Merge "DO NOT MERGE Add 'bluetooth' user to the 'system' group." into cw-e-dev
diff --git a/Android.mk b/Android.mk
index 6f5f8f9..41190be 100644
--- a/Android.mk
+++ b/Android.mk
@@ -160,6 +160,7 @@
 	core/java/android/hardware/fingerprint/IFingerprintDaemon.aidl \
 	core/java/android/hardware/fingerprint/IFingerprintDaemonCallback.aidl \
 	core/java/android/hardware/fingerprint/IFingerprintService.aidl \
+	core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl \
 	core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl \
 	core/java/android/hardware/hdmi/IHdmiControlCallback.aidl \
 	core/java/android/hardware/hdmi/IHdmiControlService.aidl \
@@ -172,6 +173,7 @@
 	core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl \
 	core/java/android/hardware/input/IInputManager.aidl \
 	core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
+	core/java/android/hardware/input/ITabletModeChangedListener.aidl \
 	core/java/android/hardware/location/IActivityRecognitionHardware.aidl \
 	core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl \
 	core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl \
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 3b026d2..132ffef 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -2196,6 +2196,7 @@
             fragment.mTag = tag;
             fragment.mInLayout = true;
             fragment.mFragmentManager = this;
+            fragment.mHost = mHost;
             fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
             addFragment(fragment, true);
         } else if (fragment.mInLayout) {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 7cff11b..1f23c0a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -392,6 +392,18 @@
     };
 
     /**
+     * @hide
+     */
+    public static abstract class LockoutResetCallback {
+
+        /**
+         * Called when lockout period expired and clients are allowed to listen for fingerprint
+         * again.
+         */
+        public void onLockoutReset() { }
+    };
+
+    /**
      * Request authentication of a crypto object. This call warms up the fingerprint hardware
      * and starts scanning for a fingerprint. It terminates when
      * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
@@ -680,10 +692,37 @@
             try {
                 mService.resetTimeout(token);
             } catch (RemoteException e) {
-                Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
+                Log.v(TAG, "Remote exception in resetTimeout(): ", e);
             }
         } else {
-            Log.w(TAG, "getAuthenticatorId(): Service not connected!");
+            Log.w(TAG, "resetTimeout(): Service not connected!");
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void addLockoutResetCallback(final LockoutResetCallback callback) {
+        if (mService != null) {
+            try {
+                mService.addLockoutResetCallback(
+                        new IFingerprintServiceLockoutResetCallback.Stub() {
+
+                    @Override
+                    public void onLockoutReset(long deviceId) throws RemoteException {
+                        mHandler.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                callback.onLockoutReset();
+                            }
+                        });
+                    }
+                });
+            } catch (RemoteException e) {
+                Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
+            }
+        } else {
+            Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
         }
     }
 
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 3356354..690a751 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,6 +17,7 @@
 
 import android.os.Bundle;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
 import android.hardware.fingerprint.Fingerprint;
 import java.util.List;
 
@@ -71,4 +72,7 @@
 
     // Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
     void resetTimeout(in byte [] cryptoToken);
+
+    // Add a callback which gets notified when the fingerprint lockout period expired.
+    void addLockoutResetCallback(IFingerprintServiceLockoutResetCallback callback);
 }
diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl
new file mode 100644
index 0000000..c9a5d59
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.fingerprint;
+
+import android.hardware.fingerprint.Fingerprint;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+/**
+ * Callback when lockout period expired and clients are allowed to authenticate again.
+ * @hide
+ */
+oneway interface IFingerprintServiceLockoutResetCallback {
+    void onLockoutReset(long deviceId);
+}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 465d142..c8b45c7 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -19,6 +19,7 @@
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.KeyboardLayout;
 import android.hardware.input.IInputDevicesChangedListener;
+import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.TouchCalibration;
 import android.os.IBinder;
 import android.view.InputDevice;
@@ -60,6 +61,9 @@
     // Registers an input devices changed listener.
     void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
 
+    // Registers a tablet mode change listener
+    void registerTabletModeChangedListener(ITabletModeChangedListener listener);
+
     // Input device vibrator control.
     void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
     void cancelVibrate(int deviceId, IBinder token);
diff --git a/core/java/android/hardware/input/ITabletModeChangedListener.aidl b/core/java/android/hardware/input/ITabletModeChangedListener.aidl
new file mode 100644
index 0000000..a8559a7
--- /dev/null
+++ b/core/java/android/hardware/input/ITabletModeChangedListener.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.input;
+
+/** @hide */
+interface ITabletModeChangedListener {
+    /* Called when the device enters or exits tablet mode. */
+    oneway void onTabletModeChanged(long whenNanos, boolean inTabletMode);
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 444f020..a754d6b 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,6 +16,7 @@
 
 package android.hardware.input;
 
+import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 
 import android.annotation.SdkConstant;
@@ -29,6 +30,7 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
@@ -38,6 +40,7 @@
 import android.view.InputEvent;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Provides information about input devices and available key layouts.
@@ -67,6 +70,11 @@
     private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
             new ArrayList<InputDeviceListenerDelegate>();
 
+    // Guarded by mTabletModeLock
+    private final Object mTabletModeLock = new Object();
+    private TabletModeChangedListener mTabletModeChangedListener;
+    private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
+
     /**
      * Broadcast Action: Query available keyboard layouts.
      * <p>
@@ -331,6 +339,72 @@
     }
 
     /**
+     * Register a tablet mode changed listener.
+     *
+     * @param listener The listener to register.
+     * @param handler The handler on which the listener should be invoked, or null
+     * if the listener should be invoked on the calling thread's looper.
+     * @hide
+     */
+    public void registerOnTabletModeChangedListener(
+            OnTabletModeChangedListener listener, Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        synchronized (mTabletModeLock) {
+            if (mOnTabletModeChangedListeners == null) {
+                initializeTabletModeListenerLocked();
+            }
+            int idx = findOnTabletModeChangedListenerLocked(listener);
+            if (idx < 0) {
+                OnTabletModeChangedListenerDelegate d =
+                    new OnTabletModeChangedListenerDelegate(listener, handler);
+                mOnTabletModeChangedListeners.add(d);
+            }
+        }
+    }
+
+    /**
+     * Unregister a tablet mode changed listener.
+     *
+     * @param listener The listener to unregister.
+     * @hide
+     */
+    public void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+        synchronized (mTabletModeLock) {
+            int idx = findOnTabletModeChangedListenerLocked(listener);
+            if (idx >= 0) {
+                OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
+                d.removeCallbacksAndMessages(null);
+            }
+        }
+    }
+
+    private void initializeTabletModeListenerLocked() {
+        final TabletModeChangedListener listener = new TabletModeChangedListener();
+        try {
+            mIm.registerTabletModeChangedListener(listener);
+        } catch (RemoteException ex) {
+            throw new RuntimeException("Could not register tablet mode changed listener", ex);
+        }
+        mTabletModeChangedListener = listener;
+        mOnTabletModeChangedListeners = new ArrayList<>();
+    }
+
+    private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
+        final int N = mOnTabletModeChangedListeners.size();
+        for (int i = 0; i < N; i++) {
+            if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
      * Gets information about all supported keyboard layouts.
      * <p>
      * The input manager consults the built-in keyboard layouts as well
@@ -769,6 +843,22 @@
         return false;
     }
 
+
+    private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+        if (DEBUG) {
+            Log.d(TAG, "Received tablet mode changed: "
+                    + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
+        }
+        synchronized (mTabletModeLock) {
+            final int N = mOnTabletModeChangedListeners.size();
+            for (int i = 0; i < N; i++) {
+                OnTabletModeChangedListenerDelegate listener =
+                        mOnTabletModeChangedListeners.get(i);
+                listener.sendTabletModeChanged(whenNanos, inTabletMode);
+            }
+        }
+    }
+
     /**
      * Gets a vibrator service associated with an input device, assuming it has one.
      * @return The vibrator, never null.
@@ -838,6 +928,57 @@
         }
     }
 
+    /** @hide */
+    public interface OnTabletModeChangedListener {
+        /**
+         * Called whenever the device goes into or comes out of tablet mode.
+         *
+         * @param whenNanos The time at which the device transitioned into or
+         * out of tablet mode. This is given in nanoseconds in the
+         * {@link SystemClock#uptimeMillis} time base.
+         */
+        void onTabletModeChanged(long whenNanos, boolean inTabletMode);
+    }
+
+    private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
+        @Override
+        public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+            InputManager.this.onTabletModeChanged(whenNanos, inTabletMode);
+        }
+    }
+
+    private static final class OnTabletModeChangedListenerDelegate extends Handler {
+        private static final int MSG_TABLET_MODE_CHANGED = 0;
+
+        public final OnTabletModeChangedListener mListener;
+
+        public OnTabletModeChangedListenerDelegate(
+                OnTabletModeChangedListener listener, Handler handler) {
+            super(handler != null ? handler.getLooper() : Looper.myLooper());
+            mListener = listener;
+        }
+
+        public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
+            args.argi2 = (int) (whenNanos >> 32);
+            args.arg1 = (Boolean) inTabletMode;
+            obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_TABLET_MODE_CHANGED:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
+                    boolean inTabletMode = (boolean) args.arg1;
+                    mListener.onTabletModeChanged(whenNanos, inTabletMode);
+                    break;
+            }
+        }
+    }
+
     private final class InputDeviceVibrator extends Vibrator {
         private final int mDeviceId;
         private final Binder mToken;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ec0cc6d..d4e6c82 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -100,6 +100,16 @@
     public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
 
     /**
+     * A temporary hack until SUPL system can get off the legacy APIS.
+     * They do too many network requests and the long list of apps listening
+     * and waking due to the CONNECTIVITY_ACTION bcast makes it expensive.
+     * Use this bcast intent instead for SUPL requests.
+     * @hide
+     */
+    public static final String CONNECTIVITY_ACTION_SUPL =
+            "android.net.conn.CONNECTIVITY_CHANGE_SUPL";
+
+    /**
      * The device has connected to a network that has presented a captive
      * portal, which is blocking Internet connectivity. The user was presented
      * with a notification that network sign in is required,
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 9761661..44df0ce 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -76,6 +76,15 @@
         mMenu = new MenuBuilder(context).setDefaultShowAsAction(
                 MenuItem.SHOW_AS_ACTION_IF_ROOM);
         setType(ActionMode.TYPE_FLOATING);
+        mMenu.setCallback(new MenuBuilder.Callback() {
+            @Override
+            public void onMenuModeChange(MenuBuilder menu) {}
+
+            @Override
+            public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
+                return mCallback.onActionItemClicked(FloatingActionMode.this, item);
+            }
+        });
         mContentRect = new Rect();
         mContentRectOnScreen = new Rect();
         mPreviousContentRectOnScreen = new Rect();
@@ -99,7 +108,7 @@
                 .setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                         @Override
                     public boolean onMenuItemClick(MenuItem item) {
-                        return mCallback.onActionItemClicked(FloatingActionMode.this, item);
+                        return mMenu.performItemAction(item, 0);
                     }
                 });
         mFloatingToolbarVisibilityHelper = new FloatingToolbarVisibilityHelper(mFloatingToolbar);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index d24b10b..4ac2958 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -232,7 +232,7 @@
     public void reportFailedPasswordAttempt(int userId) {
         getDevicePolicyManager().reportFailedPasswordAttempt(userId);
         getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
-        requireCredentialEntry(userId);
+        requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL, userId);
     }
 
     public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1174,7 +1174,7 @@
      * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
      */
     public void requireCredentialEntry(int userId) {
-        requireStrongAuth(StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
+        requireStrongAuth(StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
     }
 
     /**
@@ -1251,7 +1251,7 @@
                 value = { STRONG_AUTH_NOT_REQUIRED,
                         STRONG_AUTH_REQUIRED_AFTER_BOOT,
                         STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
-                        SOME_AUTH_REQUIRED_AFTER_USER_REQUEST})
+                        STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST})
         @Retention(RetentionPolicy.SOURCE)
         public @interface StrongAuthFlags {}
 
@@ -1266,14 +1266,14 @@
         public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
 
         /**
-         * Strong authentication is required because a device admin has requested it.
+         * Strong authentication is required because a device admin has temporarily requested it.
          */
         public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
 
         /**
-         * Some authentication is required because the user has temporarily disabled trust.
+         * Strong authentication is required because the user has temporarily requested it.
          */
-        public static final int SOME_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
+        public static final int STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
 
         /**
          * Strong authentication is required because the user has been locked out after too many
@@ -1281,11 +1281,17 @@
          */
         public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
 
+        /**
+         * Some authentication is required because the user has entered a wrong credential.
+         */
+        public static final int SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL = 0x10;
+
         public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
-        private static final int ALLOWING_FINGERPRINT = SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 
-        final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
+        private static final int ALLOWING_FINGERPRINT = STRONG_AUTH_NOT_REQUIRED
+                | SOME_AUTH_REQUIRED_AFTER_WRONG_CREDENTIAL;
 
+        private final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
         private final H mHandler;
 
         public StrongAuthTracker() {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index dce2ecb..1d1685a 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -83,6 +83,14 @@
   pid_t pid;
   int status;
 
+  // It's necessary to save and restore the errno during this function.
+  // Since errno is stored per thread, changing it here modifies the errno
+  // on the thread on which this signal handler executes. If a signal occurs
+  // between a call and an errno check, it's possible to get the errno set
+  // here.
+  // See b/23572286 for extra information.
+  int saved_errno = errno;
+
   while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
      // Log process-death status that we care about.  In general it is
      // not safe to call LOG(...) from a signal handler because of
@@ -118,6 +126,8 @@
   if (pid < 0 && errno != ECHILD) {
     ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
   }
+
+  errno = saved_errno;
 }
 
 // Configures the SIGCHLD handler for the zygote process. This is configured
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 86659ae..02fb8f4 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2061,6 +2061,12 @@
     <permission android:name="android.permission.SET_KEYBOARD_LAYOUT"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to monitor changes in tablet mode.
+         <p>Not for use by third-party applications.
+         @hide -->
+    <permission android:name="android.permission.TABLET_MODE_LISTENER"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to request installing packages. Apps
          targeting APIs greater than 22 must hold this permission in
          order to use {@link android.content.Intent#ACTION_INSTALL_PACKAGE}.
diff --git a/core/res/res/values-mcc204-mnc12/config.xml b/core/res/res/values-mcc204-mnc12/config.xml
new file mode 100644
index 0000000..80432d7
--- /dev/null
+++ b/core/res/res/values-mcc204-mnc12/config.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2015, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Don't use roaming icon for considered operators -->
+    <string-array translatable="false" name="config_operatorConsideredNonRoaming">
+        <item>20408</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values-mcc450-mnc06/config.xml b/core/res/res/values-mcc450-mnc06/config.xml
index 63f9823..819c2a5 100644
--- a/core/res/res/values-mcc450-mnc06/config.xml
+++ b/core/res/res/values-mcc450-mnc06/config.xml
@@ -25,4 +25,7 @@
     -->
     <integer name="config_mobile_mtu">1428</integer>
 
+    <!-- Do not set the system language as value of EF LI/EF PL -->
+    <bool name="config_use_sim_language_file">false</bool>
+
 </resources>
diff --git a/core/res/res/values-mcc450-mnc08/config.xml b/core/res/res/values-mcc450-mnc08/config.xml
index 950c62b..ca26ec1 100644
--- a/core/res/res/values-mcc450-mnc08/config.xml
+++ b/core/res/res/values-mcc450-mnc08/config.xml
@@ -25,4 +25,7 @@
     -->
     <integer name="config_mobile_mtu">1450</integer>
 
+    <!-- Do not set the system language as value of EF LI/EF PL -->
+    <bool name="config_use_sim_language_file">false</bool>
+
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 694d263..77d79ad 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -166,6 +166,21 @@
          so that applications can still use their own mechanisms. -->
     <bool name="config_enableAutoPowerModes">false</bool>
 
+    <!-- The threshold angle for any motion detection in auto-power save modes.
+         In hundreths of a degree. -->
+    <integer name="config_autoPowerModeThresholdAngle">200</integer>
+
+    <!-- The sensor id of an "any motion" sensor used in auto-power save modes.
+         0 indicates this sensor is not available. -->
+    <integer name="config_autoPowerModeAnyMotionSensor">0</integer>
+
+    <!-- If an any motion sensor is not available, prefer the wrist tilt detector over the
+         SMD. -->
+    <bool name="config_autoPowerModePreferWristTilt">false</bool>
+
+    <!-- If a location should be pre-fetched when going into device idle. -->
+    <bool name="config_autoPowerModePrefetchLocation">true</bool>
+
     <!-- The duration (in milliseconds) that the radio will scan for a signal
          when there's no network connection. If the scan doesn't timeout, use zero -->
     <integer name="config_radioScanningTimeout">0</integer>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4e94a64..35443fe 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -253,6 +253,10 @@
   <java-symbol type="bool" name="config_cellBroadcastAppLinks" />
   <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
   <java-symbol type="bool" name="config_enableAutoPowerModes" />
+  <java-symbol type="integer" name="config_autoPowerModeThresholdAngle" />
+  <java-symbol type="integer" name="config_autoPowerModeAnyMotionSensor" />
+  <java-symbol type="bool" name="config_autoPowerModePreferWristTilt" />
+  <java-symbol type="bool" name="config_autoPowerModePrefetchLocation" />
   <java-symbol type="bool" name="config_enable_emergency_call_while_sim_locked" />
   <java-symbol type="bool" name="config_enable_puk_unlock_screen" />
   <java-symbol type="bool" name="config_enableBurnInProtection" />
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
index e43ba12..7f9d874 100644
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ b/core/tests/bluetoothtests/AndroidManifest.xml
@@ -21,6 +21,7 @@
     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
     <uses-permission android:name="android.permission.BROADCAST_STICKY" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.LOCAL_MAC_ADDRESS" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
index ce2d11a..f51e10f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -64,7 +64,7 @@
 
     @Override
     protected void resetState() {
-        mPasswordEntry.setEnabled(true);
+        setPasswordEntryEnabled(true);
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fc6117f..b752c9b 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -29,6 +29,7 @@
 import android.content.IntentFilter;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
+import android.hardware.fingerprint.Fingerprint;
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
 import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -472,6 +473,10 @@
         }
     }
 
+    private void handleFingerprintLockoutReset() {
+        updateFingerprintListeningState();
+    }
+
     private void setFingerprintRunningState(int fingerprintRunningState) {
         boolean wasRunning = mFingerprintRunningState == FINGERPRINT_STATE_RUNNING;
         boolean isRunning = fingerprintRunningState == FINGERPRINT_STATE_RUNNING;
@@ -681,6 +686,14 @@
         }
     };
 
+    private final FingerprintManager.LockoutResetCallback mLockoutResetCallback
+            = new FingerprintManager.LockoutResetCallback() {
+        @Override
+        public void onLockoutReset() {
+            handleFingerprintLockoutReset();
+        }
+    };
+
     private FingerprintManager.AuthenticationCallback mAuthenticationCallback
             = new AuthenticationCallback() {
 
@@ -1003,6 +1016,9 @@
 
         mFpm = (FingerprintManager) context.getSystemService(Context.FINGERPRINT_SERVICE);
         updateFingerprintListeningState();
+        if (mFpm != null) {
+            mFpm.addLockoutResetCallback(mLockoutResetCallback);
+        }
     }
 
     private void updateFingerprintListeningState() {
@@ -1332,9 +1348,7 @@
      */
     private void handleKeyguardReset() {
         if (DEBUG) Log.d(TAG, "handleKeyguardReset");
-        if (!isUnlockingWithFingerprintAllowed()) {
-            updateFingerprintListeningState();
-        }
+        updateFingerprintListeningState();
     }
 
     /**
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index d785cca..b9daf59 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -39,6 +39,7 @@
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
     <uses-permission android:name="android.permission.BLUETOOTH" />
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <!-- System tool permissions granted to the shell. -->
     <uses-permission android:name="android.permission.REAL_GET_TASKS" />
     <uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d520072..da4ffa4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1046,6 +1046,7 @@
             // Without this, settings is not enabled until the lock screen first appears
             setShowingLocked(false);
             hideLocked();
+            mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index c14f2159..eecac63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1636,11 +1636,13 @@
     protected void handleVisibleToUserChanged(boolean visibleToUser) {
         try {
             if (visibleToUser) {
-                boolean clearNotificationEffects = !isPanelFullyCollapsed() &&
-                    (mShowLockscreenNotifications ||
-                        (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED));
+                boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
+                boolean clearNotificationEffects =
+                    ((mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD) ||
+                            (!pinnedHeadsUp && (mState == StatusBarState.SHADE
+                                    || mState == StatusBarState.SHADE_LOCKED)));
                 int notificationLoad = mNotificationData.getActiveNotifications().size();
-                if (mHeadsUpManager.hasPinnedHeadsUp() && isPanelFullyCollapsed())  {
+                if (pinnedHeadsUp && isPanelFullyCollapsed())  {
                     notificationLoad = 1;
                 } else {
                     MetricsLogger.histogram(mContext, "note_load", notificationLoad);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 4e69999..84082db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -227,7 +227,7 @@
                 return MODE_DISMISS_BOUNCER;
             } else if (unlockingAllowed) {
                 return MODE_UNLOCK;
-            } else {
+            } else if (!mStatusBarKeyguardViewManager.isBouncerShowing()) {
                 return MODE_SHOW_BOUNCER;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index d30411a..f4439bf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -262,14 +262,21 @@
         return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT;
     }
 
+    /**
+     * Resolves the intent to launch the camera application.
+     */
+    public ResolveInfo resolveCameraIntent() {
+        return mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
+                PackageManager.MATCH_DEFAULT_ONLY,
+                KeyguardUpdateMonitor.getCurrentUser());
+    }
+
     private void updateCameraVisibility() {
         if (mCameraImageView == null) {
             // Things are not set up yet; reply hazy, ask again later
             return;
         }
-        ResolveInfo resolved = mContext.getPackageManager().resolveActivityAsUser(getCameraIntent(),
-                PackageManager.MATCH_DEFAULT_ONLY,
-                KeyguardUpdateMonitor.getCurrentUser());
+        ResolveInfo resolved = resolveCameraIntent();
         boolean visible = !isCameraDisabledByDpm() && resolved != null
                 && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance)
                 && mUserSetupComplete;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 93ecb06..030501b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -166,10 +166,13 @@
         if (mAccessibilityController == null) {
             return;
         }
+        boolean trustManagedOrFingerprintAllowed = mUnlockMethodCache.isTrustManaged()
+                || KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed();
+
         boolean clickToUnlock = mAccessibilityController.isTouchExplorationEnabled();
-        boolean clickToForceLock = mUnlockMethodCache.isTrustManaged()
+        boolean clickToForceLock = trustManagedOrFingerprintAllowed
                 && !mAccessibilityController.isAccessibilityEnabled();
-        boolean longClickToForceLock = mUnlockMethodCache.isTrustManaged()
+        boolean longClickToForceLock = trustManagedOrFingerprintAllowed
                 && !clickToForceLock;
         setClickable(clickToForceLock || clickToUnlock);
         setLongClickable(longClickToForceLock);
@@ -245,10 +248,10 @@
             return STATE_FINGERPRINT_ERROR;
         } else if (mUnlockMethodCache.canSkipBouncer()) {
             return STATE_LOCK_OPEN;
-        } else if (fingerprintRunning && unlockingAllowed) {
-            return STATE_FINGERPRINT;
         } else if (mUnlockMethodCache.isFaceUnlockRunning()) {
             return STATE_FACE_UNLOCK;
+        } else if (fingerprintRunning && unlockingAllowed) {
+            return STATE_FINGERPRINT;
         } else {
             return STATE_LOCKED;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index 950b162..310625e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -78,6 +78,13 @@
         Notification notif = sbn.getNotification();
         String groupKey = sbn.getGroupKey();
         final NotificationGroup group = mGroupMap.get(groupKey);
+        if (group == null) {
+            // When an app posts 2 different notifications as summary of the same group, then a
+            // cancellation of the first notification removes this group.
+            // This situation is not supported and we will not allow such notifications anymore in
+            // the close future. See b/23676310 for reference.
+            return;
+        }
         if (notif.isGroupSummary()) {
             group.summary = null;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5557f9c..b93586e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -21,7 +21,10 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -61,6 +64,8 @@
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 
+import java.util.List;
+
 public class NotificationPanelView extends PanelView implements
         ExpandableView.OnHeightChangedListener, ObservableScrollView.Listener,
         View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
@@ -2425,7 +2430,28 @@
         getCenterIcon().setLaunchingAffordance(launchingAffordance);
     }
 
-    public boolean canCameraGestureBeLaunched() {
-        return !mAfforanceHelper.isSwipingInProgress();
+    /**
+     * Whether the camera application can be launched for the camera launch gesture.
+     *
+     * @param keyguardIsShowing whether keyguard is being shown
+     */
+    public boolean canCameraGestureBeLaunched(boolean keyguardIsShowing) {
+        ResolveInfo resolveInfo = mKeyguardBottomArea.resolveCameraIntent();
+        String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null)
+                ? null : resolveInfo.activityInfo.packageName;
+        return packageToLaunch != null &&
+               (keyguardIsShowing || !isForegroundApp(packageToLaunch)) &&
+               !mAfforanceHelper.isSwipingInProgress();
+    }
+
+    /**
+     * Return true if the applications with the package name is running in foreground.
+     *
+     * @param pkgName application package name.
+     */
+    private boolean isForegroundApp(String pkgName) {
+        ActivityManager am = getContext().getSystemService(ActivityManager.class);
+        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+        return !tasks.isEmpty() && pkgName.equals(tasks.get(0).topActivity.getPackageName());
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 8063bbe..55b1127 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3742,12 +3742,9 @@
         // down on the lockscreen), clear notification LED, vibration,
         // ringing.
         // Other transitions are covered in handleVisibleToUserChanged().
-        if (state != mState && mVisible && state == StatusBarState.SHADE_LOCKED) {
-            try {
-                mBarService.clearNotificationEffects();
-            } catch (RemoteException e) {
-                // Ignore.
-            }
+        if (state != mState && mVisible && (state == StatusBarState.SHADE_LOCKED
+                || (state == StatusBarState.SHADE && isGoingToNotificationShade()))) {
+            clearNotificationEffects();
         }
         mState = state;
         mGroupManager.setStatusBarState(state);
@@ -4090,7 +4087,8 @@
 
     @Override
     public void onCameraLaunchGestureDetected() {
-        if (!mNotificationPanel.canCameraGestureBeLaunched()) {
+        if (!mNotificationPanel.canCameraGestureBeLaunched(
+                mStatusBarKeyguardViewManager.isShowing() && mExpandedVisible)) {
             return;
         }
         if (!mDeviceInteractive) {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index d58d3721..e3d5d38 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -177,7 +177,7 @@
 
         private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
         private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
-        private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = 60*1000;
+        private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
         private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
         private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10*1000;
 
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java
index 6a67316..a0b5c15 100644
--- a/services/core/java/com/android/server/AnyMotionDetector.java
+++ b/services/core/java/com/android/server/AnyMotionDetector.java
@@ -58,9 +58,6 @@
     /** Current measurement state. */
     private int mState;
 
-    /** Threshold angle in degrees beyond which the device is considered moving. */
-    private final float THRESHOLD_ANGLE = 2f;
-
     /** Threshold energy above which the device is considered moving. */
     private final float THRESHOLD_ENERGY = 5f;
 
@@ -88,6 +85,9 @@
     private SensorManager mSensorManager;
     private PowerManager.WakeLock mWakeLock;
 
+    /** Threshold angle in degrees beyond which the device is considered moving. */
+    private final float mThresholdAngle;
+
     /** The minimum number of samples required to detect AnyMotion. */
     private int mNumSufficientSamples;
 
@@ -106,7 +106,7 @@
     private DeviceIdleCallback mCallback = null;
 
     public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
-            DeviceIdleCallback callback) {
+            DeviceIdleCallback callback, float thresholdAngle) {
         if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(false);
@@ -116,6 +116,7 @@
         mMeasurementInProgress = false;
         mState = STATE_INACTIVE;
         mCallback = callback;
+        mThresholdAngle = thresholdAngle;
         mRunningStats = new RunningSignalStats();
         mNumSufficientSamples = (int) Math.ceil(
                 ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS));
@@ -224,8 +225,9 @@
         Vector3 previousGravityVectorNormalized = mPreviousGravityVector.normalized();
         Vector3 currentGravityVectorNormalized = mCurrentGravityVector.normalized();
         float angle = previousGravityVectorNormalized.angleBetween(currentGravityVectorNormalized);
-        if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle);
-        if ((angle < THRESHOLD_ANGLE) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) {
+        if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle
+                + " energy = " + mRunningStats.getEnergy());
+        if ((angle < mThresholdAngle) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) {
             return RESULT_STATIONARY;
         } else if (Float.isNaN(angle)) {
           /**
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index e19447d..2bcee91 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1524,10 +1524,14 @@
 
             final long ident = Binder.clearCallingIdentity();
             if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
+                final NetworkInfo ni = intent.getParcelableExtra(
+                        ConnectivityManager.EXTRA_NETWORK_INFO);
+                if (ni.getType() == ConnectivityManager.TYPE_MOBILE_SUPL) {
+                    intent.setAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                }
                 final IBatteryStats bs = BatteryStatsService.getService();
                 try {
-                    NetworkInfo ni = intent.getParcelableExtra(
-                            ConnectivityManager.EXTRA_NETWORK_INFO);
                     bs.noteConnectivityChanged(intent.getIntExtra(
                             ConnectivityManager.EXTRA_NETWORK_TYPE, ConnectivityManager.TYPE_NONE),
                             ni != null ? ni.getState().toString() : "?");
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 80fd441..80e8d1c 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -98,7 +98,7 @@
         implements AnyMotionDetector.DeviceIdleCallback {
     private static final String TAG = "DeviceIdleController";
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = true;  // STOPSHIP
 
     private static final boolean COMPRESS_TIME = false;
 
@@ -128,7 +128,8 @@
     private boolean mNotMoving;
     private boolean mLocating;
     private boolean mLocated;
-    private boolean mHaveGps;
+    private boolean mHasGps;
+    private boolean mHasNetworkLocation;
     private Location mLastGenericLocation;
     private Location mLastGpsLocation;
 
@@ -882,17 +883,37 @@
                 mDisplayManager = (DisplayManager) getContext().getSystemService(
                         Context.DISPLAY_SERVICE);
                 mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
-                mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
-                mLocationManager = (LocationManager) getContext().getSystemService(
-                        Context.LOCATION_SERVICE);
-                mLocationRequest = new LocationRequest()
-                    .setQuality(LocationRequest.ACCURACY_FINE)
-                    .setInterval(0)
-                    .setFastestInterval(0)
-                    .setNumUpdates(1);
+                int sigMotionSensorId = getContext().getResources().getInteger(
+                        com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
+                if (sigMotionSensorId > 0) {
+                    mSigMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
+                }
+                if (mSigMotionSensor == null && getContext().getResources().getBoolean(
+                        com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
+                    mSigMotionSensor = mSensorManager.getDefaultSensor(
+                            Sensor.TYPE_WRIST_TILT_GESTURE);
+                }
+                if (mSigMotionSensor == null) {
+                    // As a last ditch, fall back to SMD.
+                    mSigMotionSensor = mSensorManager.getDefaultSensor(
+                            Sensor.TYPE_SIGNIFICANT_MOTION);
+                }
+                if (getContext().getResources().getBoolean(
+                        com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
+                    mLocationManager = (LocationManager) getContext().getSystemService(
+                            Context.LOCATION_SERVICE);
+                    mLocationRequest = new LocationRequest()
+                        .setQuality(LocationRequest.ACCURACY_FINE)
+                        .setInterval(0)
+                        .setFastestInterval(0)
+                        .setNumUpdates(1);
+                }
+
+                float angleThreshold = getContext().getResources().getInteger(
+                        com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
                 mAnyMotionDetector = new AnyMotionDetector(
                         (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
-                        mHandler, mSensorManager, this);
+                        mHandler, mSensorManager, this, angleThreshold);
 
                 Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
                         .setPackage("android")
@@ -1279,17 +1300,30 @@
                 EventLogTags.writeDeviceIdle(mState, "step");
                 cancelSensingAlarmLocked();
                 scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
-                mLocating = true;
-                mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener,
-                        mHandler.getLooper());
-                if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
-                    mHaveGps = true;
+                if (mLocationManager != null
+                        && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
+                    mLocationManager.requestLocationUpdates(mLocationRequest,
+                            mGenericLocationListener, mHandler.getLooper());
+                    mLocating = true;
+                } else {
+                    mHasNetworkLocation = false;
+                }
+                if (mLocationManager != null
+                        && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
+                    mHasGps = true;
                     mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
                             mGpsLocationListener, mHandler.getLooper());
+                    mLocating = true;
                 } else {
-                    mHaveGps = false;
+                    mHasGps = false;
                 }
-                break;
+                // If we have a location provider, we're all set, the listeners will move state
+                // forward.
+                if (mLocating) {
+                    break;
+                }
+
+                // Otherwise, we have to move from locating into idle maintenance.
             case STATE_LOCATING:
                 cancelSensingAlarmLocked();
                 cancelLocatingLocked();
@@ -1346,7 +1380,7 @@
         }
         if (DEBUG) Slog.d(TAG, "Generic location: " + location);
         mLastGenericLocation = new Location(location);
-        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) {
+        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
             return;
         }
         mLocated = true;
@@ -1413,9 +1447,9 @@
     void scheduleAlarmLocked(long delay, boolean idleUntil) {
         if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
         if (mSigMotionSensor == null) {
-            // If there is no significant motion sensor on this device, then we won't schedule
+            // If there is no motion sensor on this device, then we won't schedule
             // alarms, because we can't determine if the device is not moving.  This effectively
-            // turns off normal exeuction of device idling, although it is still possible to
+            // turns off normal execution of device idling, although it is still possible to
             // manually poke it by pretending like the alarm is going off.
             return;
         }
@@ -1902,8 +1936,9 @@
             pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
             pw.print("  mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
                     pw.println(mNotMoving);
-            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHaveGps=");
-                    pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated);
+            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
+                    pw.print(mHasGps); pw.print(" mHasNetwork=");
+                    pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
             if (mLastGenericLocation != null) {
                 pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
             }
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 899139f..b87e109 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2085,7 +2085,8 @@
     }
 
     private boolean collectPackageServicesLocked(String packageName, Set<String> filterByClasses,
-            boolean evenPersistent, boolean doit, ArrayMap<ComponentName, ServiceRecord> services) {
+            boolean evenPersistent, boolean doit, boolean killProcess,
+            ArrayMap<ComponentName, ServiceRecord> services) {
         boolean didSomething = false;
         for (int i = services.size() - 1; i >= 0; i--) {
             ServiceRecord service = services.valueAt(i);
@@ -2101,7 +2102,7 @@
                 didSomething = true;
                 Slog.i(TAG, "  Force stopping service " + service);
                 if (service.app != null) {
-                    service.app.removed = true;
+                    service.app.removed = killProcess;
                     if (!service.app.persistent) {
                         service.app.services.remove(service);
                     }
@@ -2118,7 +2119,7 @@
     }
 
     boolean bringDownDisabledPackageServicesLocked(String packageName, Set<String> filterByClasses,
-            int userId, boolean evenPersistent, boolean doit) {
+            int userId, boolean evenPersistent, boolean killProcess, boolean doit) {
         boolean didSomething = false;
 
         if (mTmpCollectionResults != null) {
@@ -2128,7 +2129,7 @@
         if (userId == UserHandle.USER_ALL) {
             for (int i = mServiceMap.size() - 1; i >= 0; i--) {
                 didSomething |= collectPackageServicesLocked(packageName, filterByClasses,
-                        evenPersistent, doit, mServiceMap.valueAt(i).mServicesByName);
+                        evenPersistent, doit, killProcess, mServiceMap.valueAt(i).mServicesByName);
                 if (!doit && didSomething) {
                     return true;
                 }
@@ -2138,7 +2139,7 @@
             if (smap != null) {
                 ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName;
                 didSomething = collectPackageServicesLocked(packageName, filterByClasses,
-                        evenPersistent, doit, items);
+                        evenPersistent, doit, killProcess, items);
             }
         }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 191bf99..525aac7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -400,6 +400,17 @@
     private static final int PERSISTENT_MASK =
             ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT;
 
+
+    // Delay to disable app launch boost
+    static final int APP_BOOST_MESSAGE_DELAY = 3000;
+    // Lower delay than APP_BOOST_MESSAGE_DELAY to disable the boost
+    static final int APP_BOOST_TIMEOUT = 2500;
+
+    private static native int nativeMigrateToBoost();
+    private static native int nativeMigrateFromBoost();
+    private boolean mIsBoosted = false;
+    private long mBoostStartTime = 0;
+
     /** All system services */
     SystemServiceManager mSystemServiceManager;
 
@@ -1356,6 +1367,7 @@
     static final int REPORT_TIME_TRACKER_MSG = 55;
     static final int REPORT_USER_SWITCH_COMPLETE_MSG = 56;
     static final int SHUTDOWN_UI_AUTOMATION_CONNECTION_MSG = 57;
+    static final int APP_BOOST_DEACTIVATE_MSG = 58;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -2031,6 +2043,20 @@
                 // it is finished we make sure it is reset to its default.
                 mUserIsMonkey = false;
             } break;
+            case APP_BOOST_DEACTIVATE_MSG : {
+                synchronized(ActivityManagerService.this) {
+                    if (mIsBoosted) {
+                        if (mBoostStartTime < (SystemClock.uptimeMillis() - APP_BOOST_TIMEOUT)) {
+                            nativeMigrateFromBoost();
+                            mIsBoosted = false;
+                            mBoostStartTime = 0;
+                        } else {
+                            Message newmsg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
+                            mHandler.sendMessageDelayed(newmsg, APP_BOOST_TIMEOUT);
+                        }
+                    }
+                }
+            } break;
             }
         }
     };
@@ -3114,6 +3140,16 @@
             app = null;
         }
 
+        // app launch boost for big.little configurations
+        // use cpusets to migrate freshly launched tasks to big cores
+        synchronized(ActivityManagerService.this) {
+            nativeMigrateToBoost();
+            mIsBoosted = true;
+            mBoostStartTime = SystemClock.uptimeMillis();
+            Message msg = mHandler.obtainMessage(APP_BOOST_DEACTIVATE_MSG);
+            mHandler.sendMessageDelayed(msg, APP_BOOST_MESSAGE_DELAY);
+        }
+
         // We don't have to do anything more if:
         // (1) There is an existing application record; and
         // (2) The caller doesn't think it is dead, OR there is no thread
@@ -5562,7 +5598,7 @@
     }
 
     private void cleanupDisabledPackageComponentsLocked(
-            String packageName, int userId, String[] changedClasses) {
+            String packageName, int userId, boolean killProcess, String[] changedClasses) {
 
         Set<String> disabledClasses = null;
         boolean packageDisabled = false;
@@ -5632,7 +5668,7 @@
 
         // Clean-up disabled services.
         mServices.bringDownDisabledPackageServicesLocked(
-                packageName, disabledClasses, userId, false, true);
+                packageName, disabledClasses, userId, false, killProcess, true);
 
         // Clean-up disabled providers.
         ArrayList<ContentProviderRecord> providers = new ArrayList<>();
@@ -5717,7 +5753,7 @@
         }
 
         if (mServices.bringDownDisabledPackageServicesLocked(
-                packageName, null, userId, evenPersistent, doit)) {
+                packageName, null, userId, evenPersistent, true, doit)) {
             if (!doit) {
                 return true;
             }
@@ -16590,7 +16626,9 @@
                                 boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
                                 boolean fullUninstall = removed &&
                                         !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-                                if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
+                                final boolean killProcess =
+                                        !intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false);
+                                if (killProcess) {
                                     forceStopPackageLocked(ssp, UserHandle.getAppId(
                                             intent.getIntExtra(Intent.EXTRA_UID, -1)),
                                             false, true, true, false, fullUninstall, userId,
@@ -16610,7 +16648,7 @@
                                         mBatteryStatsService.notePackageUninstalled(ssp);
                                     }
                                 } else {
-                                    cleanupDisabledPackageComponentsLocked(ssp, userId,
+                                    cleanupDisabledPackageComponentsLocked(ssp, userId, killProcess,
                                             intent.getStringArrayExtra(
                                                     Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST));
                                 }
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index a956c56..960cbf1 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -509,7 +509,7 @@
                     break;
                 }
                 int appOp = AppOpsManager.permissionToOpCode(requiredPermission);
-                if (appOp != r.appOp
+                if (appOp != AppOpsManager.OP_NONE && appOp != r.appOp
                         && mService.mAppOpsService.noteOperation(appOp,
                         filter.receiverList.uid, filter.packageName)
                         != AppOpsManager.MODE_ALLOWED) {
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 7e46db8..0023258 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -18,13 +18,18 @@
 
 import android.Manifest;
 import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
 import android.app.IUserSwitchObserver;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
 import android.os.Binder;
+import android.os.DeadObjectException;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
@@ -51,8 +56,8 @@
 import android.hardware.fingerprint.IFingerprintDaemon;
 import android.hardware.fingerprint.IFingerprintDaemonCallback;
 import android.hardware.fingerprint.IFingerprintServiceReceiver;
-import android.view.Display;
 
+import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.Manifest.permission.MANAGE_FINGERPRINT;
 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
 import static android.Manifest.permission.USE_FINGERPRINT;
@@ -60,6 +65,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -83,12 +89,15 @@
     private ClientMonitor mAuthClient = null;
     private ClientMonitor mEnrollClient = null;
     private ClientMonitor mRemoveClient = null;
+    private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
+            new ArrayList<>();
     private final AppOpsManager mAppOps;
 
     private static final long MS_PER_SEC = 1000;
     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
     private static final int MAX_FAILED_ATTEMPTS = 5;
     private static final int FINGERPRINT_ACQUIRED_GOOD = 0;
+    private final String mKeyguardPackage;
 
     Handler mHandler = new Handler() {
         @Override
@@ -121,6 +130,8 @@
     public FingerprintService(Context context) {
         super(context);
         mContext = context;
+        mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
+                com.android.internal.R.string.config_keyguardComponent)).getPackageName();
         mAppOps = context.getSystemService(AppOpsManager.class);
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
     }
@@ -248,7 +259,7 @@
     }
 
     private boolean inLockoutMode() {
-        return mFailedAttempts > MAX_FAILED_ATTEMPTS;
+        return mFailedAttempts >= MAX_FAILED_ATTEMPTS;
     }
 
     private void resetFailedAttempts() {
@@ -259,11 +270,12 @@
         // If we're asked to reset failed attempts externally (i.e. from Keyguard), the runnable
         // may still be in the queue; remove it.
         mHandler.removeCallbacks(mLockoutReset);
+        notifyLockoutResetMonitors();
     }
 
     private boolean handleFailedAttempt(ClientMonitor clientMonitor) {
         mFailedAttempts++;
-        if (mFailedAttempts > MAX_FAILED_ATTEMPTS) {
+        if (inLockoutMode()) {
             // Failing multiple times will continue to push out the lockout time.
             mHandler.removeCallbacks(mLockoutReset);
             mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS);
@@ -493,10 +505,67 @@
         return false;
     }
 
-    private boolean canUseFingerprint(String opPackageName) {
+    private boolean isForegroundActivity(int uid, int pid) {
+        try {
+            List<RunningAppProcessInfo> procs =
+                    ActivityManagerNative.getDefault().getRunningAppProcesses();
+            int N = procs.size();
+            for (int i = 0; i < N; i++) {
+                RunningAppProcessInfo proc = procs.get(i);
+                if (proc.pid == pid && proc.uid == uid
+                        && proc.importance == IMPORTANCE_FOREGROUND) {
+                    return true;
+                }
+            }
+        } catch (RemoteException e) {
+            Slog.w(TAG, "am.getRunningAppProcesses() failed");
+        }
+        return false;
+    }
+
+    /**
+     * @param opPackageName name of package for caller
+     * @param foregroundOnly only allow this call while app is in the foreground
+     * @return true if caller can use fingerprint API
+     */
+    private boolean canUseFingerprint(String opPackageName, boolean foregroundOnly) {
         checkPermission(USE_FINGERPRINT);
-        return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(),
-                opPackageName) == AppOpsManager.MODE_ALLOWED;
+        final int uid = Binder.getCallingUid();
+        final int pid = Binder.getCallingPid();
+        if (opPackageName.equals(mKeyguardPackage)) {
+            return true; // Keyguard is always allowed
+        }
+        if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {
+            Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile");
+            return false;
+        }
+        if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
+                != AppOpsManager.MODE_ALLOWED) {
+            Slog.v(TAG, "Rejecting " + opPackageName + " ; permission denied");
+            return false;
+        }
+        if (foregroundOnly && !isForegroundActivity(uid, pid)) {
+            Slog.v(TAG, "Rejecting " + opPackageName + " ; not in foreground");
+            return false;
+        }
+        return true;
+    }
+
+    private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) {
+        if (!mLockoutMonitors.contains(monitor)) {
+            mLockoutMonitors.add(monitor);
+        }
+    }
+
+    private void removeLockoutResetCallback(
+            FingerprintServiceLockoutResetMonitor monitor) {
+        mLockoutMonitors.remove(monitor);
+    }
+
+    private void notifyLockoutResetMonitors() {
+        for (int i = 0; i < mLockoutMonitors.size(); i++) {
+            mLockoutMonitors.get(i).sendLockoutReset();
+        }
     }
 
     private class ClientMonitor implements IBinder.DeathRecipient {
@@ -614,7 +683,7 @@
                     FingerprintUtils.vibrateFingerprintSuccess(getContext());
                 }
                 result |= true; // we have a valid fingerprint
-                mLockoutReset.run();
+                mHandler.post(mLockoutReset);
             }
             return result;
         }
@@ -654,6 +723,36 @@
         }
     }
 
+    private class FingerprintServiceLockoutResetMonitor {
+
+        private final IFingerprintServiceLockoutResetCallback mCallback;
+
+        public FingerprintServiceLockoutResetMonitor(
+                IFingerprintServiceLockoutResetCallback callback) {
+            mCallback = callback;
+        }
+
+        public void sendLockoutReset() {
+            if (mCallback != null) {
+                try {
+                    mCallback.onLockoutReset(mHalDeviceId);
+                } catch (DeadObjectException e) {
+                    Slog.w(TAG, "Death object while invoking onLockoutReset: ", e);
+                    mHandler.post(mRemoveCallbackRunnable);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
+                }
+            }
+        }
+
+        private final Runnable mRemoveCallbackRunnable = new Runnable() {
+            @Override
+            public void run() {
+                removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
+            }
+        };
+    }
+
     private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {
 
         @Override
@@ -782,12 +881,7 @@
         public void authenticate(final IBinder token, final long opId, final int groupId,
                 final IFingerprintServiceReceiver receiver, final int flags,
                 final String opPackageName) {
-            if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) {
-                Slog.w(TAG, "Can't authenticate non-current user");
-                return;
-            }
-            if (!canUseFingerprint(opPackageName)) {
-                Slog.w(TAG, "Calling not granted permission to use fingerprint");
+            if (!canUseFingerprint(opPackageName, true /* foregroundOnly */)) {
                 return;
             }
 
@@ -807,7 +901,7 @@
 
         @Override // Binder call
         public void cancelAuthentication(final IBinder token, String opPackageName) {
-            if (!canUseFingerprint(opPackageName)) {
+            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
                 return;
             }
             mHandler.post(new Runnable() {
@@ -838,7 +932,7 @@
 
         @Override // Binder call
         public boolean isHardwareDetected(long deviceId, String opPackageName) {
-            if (!canUseFingerprint(opPackageName)) {
+            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
                 return false;
             }
             return mHalDeviceId != 0;
@@ -862,7 +956,7 @@
 
         @Override // Binder call
         public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
-            if (!canUseFingerprint(opPackageName)) {
+            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
                 return Collections.emptyList();
             }
             int effectiveUserId = getEffectiveUserId(userId);
@@ -872,7 +966,7 @@
 
         @Override // Binder call
         public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
-            if (!canUseFingerprint(opPackageName)) {
+            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */)) {
                 return false;
             }
 
@@ -922,7 +1016,19 @@
         public void resetTimeout(byte [] token) {
             checkPermission(RESET_FINGERPRINT_LOCKOUT);
             // TODO: confirm security token when we move timeout management into the HAL layer.
-            mLockoutReset.run();
+            mHandler.post(mLockoutReset);
+        }
+
+        @Override
+        public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)
+                throws RemoteException {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    addLockoutResetMonitor(
+                            new FingerprintServiceLockoutResetMonitor(callback));
+                }
+            });
         }
     }
 
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 17b4f9c..5a13672 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.input;
 
 import android.view.Display;
+import com.android.internal.os.SomeArgs;
 import com.android.internal.R;
 import com.android.internal.util.XmlUtils;
 import com.android.server.DisplayThread;
@@ -52,6 +53,7 @@
 import android.hardware.input.InputDeviceIdentifier;
 import android.hardware.input.InputManager;
 import android.hardware.input.InputManagerInternal;
+import android.hardware.input.ITabletModeChangedListener;
 import android.hardware.input.KeyboardLayout;
 import android.hardware.input.TouchCalibration;
 import android.os.Binder;
@@ -93,6 +95,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 
 import libcore.io.Streams;
 import libcore.util.Objects;
@@ -112,6 +115,7 @@
     private static final int MSG_RELOAD_KEYBOARD_LAYOUTS = 3;
     private static final int MSG_UPDATE_KEYBOARD_LAYOUTS = 4;
     private static final int MSG_RELOAD_DEVICE_ALIASES = 5;
+    private static final int MSG_DELIVER_TABLET_MODE_CHANGED = 6;
 
     // Pointer to native input manager service object.
     private final long mPtr;
@@ -124,6 +128,13 @@
     private boolean mSystemReady;
     private NotificationManager mNotificationManager;
 
+    private final Object mTabletModeLock = new Object();
+    // List of currently registered tablet mode changed listeners by process id
+    private final SparseArray<TabletModeChangedListenerRecord> mTabletModeChangedListeners =
+            new SparseArray<>(); // guarded by mTabletModeLock
+    private final List<TabletModeChangedListenerRecord> mTempTabletModeChangedListenersToNotify =
+            new ArrayList<>();
+
     // Persistent data store.  Must be locked each time during use.
     private final PersistentDataStore mDataStore = new PersistentDataStore();
 
@@ -227,6 +238,11 @@
     /** Switch code: Lid switch.  When set, lid is shut. */
     public static final int SW_LID = 0x00;
 
+    /** Switch code: Tablet mode switch.
+     * When set, the device is in tablet mode (i.e. no keyboard is connected).
+     */
+    public static final int SW_TABLET_MODE = 0x01;
+
     /** Switch code: Keypad slide.  When set, keyboard is exposed. */
     public static final int SW_KEYPAD_SLIDE = 0x0a;
 
@@ -246,6 +262,7 @@
     public static final int SW_CAMERA_LENS_COVER = 0x09;
 
     public static final int SW_LID_BIT = 1 << SW_LID;
+    public static final int SW_TABLET_MODE_BIT = 1 << SW_TABLET_MODE;
     public static final int SW_KEYPAD_SLIDE_BIT = 1 << SW_KEYPAD_SLIDE;
     public static final int SW_HEADPHONE_INSERT_BIT = 1 << SW_HEADPHONE_INSERT;
     public static final int SW_MICROPHONE_INSERT_BIT = 1 << SW_MICROPHONE_INSERT;
@@ -774,6 +791,57 @@
         }
     }
 
+    @Override // Binder call
+    public void registerTabletModeChangedListener(ITabletModeChangedListener listener) {
+        if (!checkCallingPermission(android.Manifest.permission.TABLET_MODE_LISTENER,
+                "registerTabletModeChangedListener()")) {
+            throw new SecurityException("Requires TABLET_MODE_LISTENER permission");
+        }
+        if (listener == null) {
+            throw new IllegalArgumentException("listener must not be null");
+        }
+
+        synchronized (mTabletModeLock) {
+            final int callingPid = Binder.getCallingPid();
+            if (mTabletModeChangedListeners.get(callingPid) != null) {
+                throw new IllegalStateException("The calling process has already registered "
+                        + "a TabletModeChangedListener.");
+            }
+            TabletModeChangedListenerRecord record =
+                    new TabletModeChangedListenerRecord(callingPid, listener);
+            try {
+                IBinder binder = listener.asBinder();
+                binder.linkToDeath(record, 0);
+            } catch (RemoteException ex) {
+                throw new RuntimeException(ex);
+            }
+            mTabletModeChangedListeners.put(callingPid, record);
+        }
+    }
+
+    private void onTabletModeChangedListenerDied(int pid) {
+        synchronized (mTabletModeLock) {
+            mTabletModeChangedListeners.remove(pid);
+        }
+    }
+
+    // Must be called on handler
+    private void deliverTabletModeChanged(long whenNanos, boolean inTabletMode) {
+        mTempTabletModeChangedListenersToNotify.clear();
+        final int numListeners;
+        synchronized (mTabletModeLock) {
+            numListeners = mTabletModeChangedListeners.size();
+            for (int i = 0; i < numListeners; i++) {
+                mTempTabletModeChangedListenersToNotify.add(
+                        mTabletModeChangedListeners.valueAt(i));
+            }
+        }
+        for (int i = 0; i < numListeners; i++) {
+            mTempTabletModeChangedListenersToNotify.get(i).notifyTabletModeChanged(
+                    whenNanos, inTabletMode);
+        }
+    }
+
     // Must be called on handler.
     private void showMissingKeyboardLayoutNotification(InputDevice device) {
         if (!mKeyboardLayoutNotificationShown) {
@@ -1419,6 +1487,15 @@
             mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
                     switchMask);
         }
+
+        if ((switchMask & SW_TABLET_MODE) != 0) {
+            SomeArgs args = SomeArgs.obtain();
+            args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
+            args.argi2 = (int) (whenNanos >> 32);
+            args.arg1 = Boolean.valueOf((switchValues & SW_TABLET_MODE_BIT) != 0);
+            mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED,
+                    args).sendToTarget();
+        }
     }
 
     // Native callback.
@@ -1664,6 +1741,12 @@
                 case MSG_RELOAD_DEVICE_ALIASES:
                     reloadDeviceAliases();
                     break;
+                case MSG_DELIVER_TABLET_MODE_CHANGED:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
+                    boolean inTabletMode = (boolean) args.arg1;
+                    deliverTabletModeChanged(whenNanos, inTabletMode);
+                    break;
             }
         }
     }
@@ -1755,6 +1838,34 @@
         }
     }
 
+    private final class TabletModeChangedListenerRecord implements DeathRecipient {
+        private final int mPid;
+        private final ITabletModeChangedListener mListener;
+
+        public TabletModeChangedListenerRecord(int pid, ITabletModeChangedListener listener) {
+            mPid = pid;
+            mListener = listener;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DEBUG) {
+                Slog.d(TAG, "Tablet mode changed listener for pid " + mPid + " died.");
+            }
+            onTabletModeChangedListenerDied(mPid);
+        }
+
+        public void notifyTabletModeChanged(long whenNanos, boolean inTabletMode) {
+            try {
+                mListener.onTabletModeChanged(whenNanos, inTabletMode);
+            } catch (RemoteException ex) {
+                Slog.w(TAG, "Failed to notify process " + mPid +
+                        " that tablet mode changed, assuming it died.", ex);
+                binderDied();
+            }
+        }
+    }
+
     private final class VibratorToken implements DeathRecipient {
         public final int mDeviceId;
         public final IBinder mToken;
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 02f2c73..4f42f83 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -444,7 +444,8 @@
                 checkSmsSuplInit(intent);
             } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
                 checkWapSuplInit(intent);
-            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)
+                    || action.equals(ConnectivityManager.CONNECTIVITY_ACTION_SUPL)) {
                 // retrieve NetworkInfo result for this UID
                 NetworkInfo info =
                         intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
@@ -2049,6 +2050,7 @@
             intentFilter.addAction(ALARM_WAKEUP);
             intentFilter.addAction(ALARM_TIMEOUT);
             intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+            intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_SUPL);
             intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
             intentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
             intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 7112fc8..96c54605 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2283,16 +2283,16 @@
             }
             updatePermissionsLPw(null, null, updateFlags);
             ver.sdkVersion = mSdkVersion;
-            // clear only after permissions have been updated
-            mExistingSystemPackages.clear();
-            mPromoteSystemApps = false;
 
-            // If this is the first boot, and it is a normal boot, then
-            // we need to initialize the default preferred apps.
-            if (!mRestoredSettings && !onlyCore) {
-                mSettings.applyDefaultPreferredAppsLPw(this, UserHandle.USER_OWNER);
-                applyFactoryDefaultBrowserLPw(UserHandle.USER_OWNER);
-                primeDomainVerificationsLPw(UserHandle.USER_OWNER);
+            // If this is the first boot or an update from pre-M, and it is a normal
+            // boot, then we need to initialize the default preferred apps across
+            // all defined users.
+            if (!onlyCore && (mPromoteSystemApps || !mRestoredSettings)) {
+                for (UserInfo user : sUserManager.getUsers(true)) {
+                    mSettings.applyDefaultPreferredAppsLPw(this, user.id);
+                    applyFactoryDefaultBrowserLPw(user.id);
+                    primeDomainVerificationsLPw(user.id);
+                }
             }
 
             // If this is first boot after an OTA, and a normal boot, then
@@ -2310,6 +2310,10 @@
 
             checkDefaultBrowser();
 
+            // clear only after permissions and other defaults have been updated
+            mExistingSystemPackages.clear();
+            mPromoteSystemApps = false;
+
             // All the changes are done during package scanning.
             ver.databaseVersion = Settings.CURRENT_DATABASE_VERSION;
 
@@ -5929,12 +5933,6 @@
          */
         if (shouldHideSystemApp) {
             synchronized (mPackages) {
-                /*
-                 * We have to grant systems permissions before we hide, because
-                 * grantPermissions will assume the package update is trying to
-                 * expand its permissions.
-                 */
-                grantPermissionsLPw(pkg, true, pkg.packageName);
                 mSettings.disableSystemPackageLPw(pkg.packageName);
             }
         }
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d7c9c02..34737c1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4417,7 +4417,7 @@
                     if (mAppsToBeHidden.isEmpty()) {
                         if (dismissKeyguard && !mKeyguardSecure) {
                             mAppsThatDismissKeyguard.add(appToken);
-                        } else if (win.isDrawnLw()) {
+                        } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
                             mWinShowWhenLocked = win;
                             mHideLockScreen = true;
                             mForceStatusBarFromKeyguard = false;
@@ -4451,7 +4451,8 @@
                         mWinDismissingKeyguard = win;
                         mSecureDismissingKeyguard = mKeyguardSecure;
                         mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
-                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked && win.isDrawnLw()) {
+                    } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
+                            && (win.isDrawnLw() || win.hasAppShownWindows())) {
                         if (DEBUG_LAYOUT) Slog.v(TAG,
                                 "Setting mHideLockScreen to true by win " + win);
                         mHideLockScreen = true;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 3da9b44..ba608bd 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -375,7 +375,10 @@
             for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
                 final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
                 for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
-                    mService.removeWindowInnerLocked(appWindows.get(winNdx));
+                    // We are in the middle of changing the state of displays/stacks/tasks. We need
+                    // to finish that, before we let layout interfere with it.
+                    mService.removeWindowInnerLocked(appWindows.get(winNdx),
+                            false /* performLayout */);
                     doAnotherLayoutPass = true;
                 }
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 33d4331..a0499b7 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2793,6 +2793,10 @@
     }
 
     void removeWindowInnerLocked(WindowState win) {
+        removeWindowInnerLocked(win, true);
+    }
+
+    void removeWindowInnerLocked(WindowState win, boolean performLayout) {
         if (win.mRemoved) {
             // Nothing to do.
             return;
@@ -2890,7 +2894,9 @@
                 if (displayContent != null) {
                     displayContent.layoutNeeded = true;
                 }
-                performLayoutAndPlaceSurfacesLocked();
+                if (performLayout) {
+                    performLayoutAndPlaceSurfacesLocked();
+                }
                 if (win.mAppToken != null) {
                     win.mAppToken.updateReportedVisibilityLocked();
                 }
@@ -5193,7 +5199,9 @@
     }
 
     public void removeStack(int stackId) {
-        mStackIdToStack.remove(stackId);
+        synchronized (mWindowMap) {
+            mStackIdToStack.remove(stackId);
+        }
     }
 
     public void removeTask(int taskId) {
@@ -5267,10 +5275,12 @@
     }
 
     public void getStackBounds(int stackId, Rect bounds) {
-        final TaskStack stack = mStackIdToStack.get(stackId);
-        if (stack != null) {
-            stack.getBounds(bounds);
-            return;
+        synchronized (mWindowMap) {
+            final TaskStack stack = mStackIdToStack.get(stackId);
+            if (stack != null) {
+                stack.getBounds(bounds);
+                return;
+            }
         }
         bounds.setEmpty();
     }
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 9556b08..98d8d08 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -4,9 +4,16 @@
 
 LOCAL_CFLAGS += -Wall -Werror -Wno-unused-parameter
 
+ifneq ($(ENABLE_CPUSETS),)
+ifneq ($(ENABLE_SCHED_BOOST),)
+LOCAL_CFLAGS += -DUSE_SCHED_BOOST
+endif
+endif
+
 LOCAL_SRC_FILES += \
     $(LOCAL_REL_DIR)/com_android_server_AlarmManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_am_BatteryStatsService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_am_ActivityManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_AssetAtlasService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
     $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
diff --git a/services/core/jni/com_android_server_am_ActivityManagerService.cpp b/services/core/jni/com_android_server_am_ActivityManagerService.cpp
new file mode 100644
index 0000000..52217b9
--- /dev/null
+++ b/services/core/jni/com_android_server_am_ActivityManagerService.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ActivityManagerService"
+//#define LOG_NDEBUG 0
+
+#include <android_runtime/AndroidRuntime.h>
+#include <jni.h>
+
+#include <ScopedLocalRef.h>
+#include <ScopedPrimitiveArray.h>
+
+#include <cutils/log.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <semaphore.h>
+#include <stddef.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace android
+{
+
+    // migrate from foreground to foreground_boost
+    static jint migrateToBoost(JNIEnv *env, jobject _this)
+    {
+#ifdef USE_SCHED_BOOST
+        // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error
+        FILE* fg_cpuset_file = NULL;
+        int   boost_cpuset_fd = 0;
+        if (!access("/dev/cpuset/tasks", F_OK)) {
+            fg_cpuset_file = fopen("/dev/cpuset/foreground/tasks", "r+");
+            if (ferror(fg_cpuset_file)) {
+                return 0;
+            }
+            boost_cpuset_fd = open("/dev/cpuset/foreground/boost/tasks", O_WRONLY);
+            if (boost_cpuset_fd < 0) {
+                fclose(fg_cpuset_file);
+                return 0;
+            }
+
+        }
+        if (!fg_cpuset_file || !boost_cpuset_fd) {
+            fclose(fg_cpuset_file);
+            close(boost_cpuset_fd);
+            return 0;
+        }
+        char buf[17];
+        while (fgets(buf, 16, fg_cpuset_file)) {
+            int i = 0;
+            for (; i < 16; i++) {
+                if (buf[i] == '\n') {
+                    buf[i] = 0;
+                    break;
+                }
+            }
+            if (write(boost_cpuset_fd, buf, i) < 0) {
+                // ignore error
+            }
+            if (feof(fg_cpuset_file))
+                break;
+        }
+        fclose(fg_cpuset_file);
+        close(boost_cpuset_fd);
+#endif
+        return 0;
+    }
+
+    // migrate from foreground_boost to foreground
+    static jint migrateFromBoost(JNIEnv *env, jobject _this)
+    {
+#ifdef USE_SCHED_BOOST
+        // File descriptors open to /dev/cpuset/../tasks, setup by initialize, or -1 on error
+        int   fg_cpuset_fd = 0;
+        FILE* boost_cpuset_file = NULL;
+        if (!access("/dev/cpuset/tasks", F_OK)) {
+            boost_cpuset_file = fopen("/dev/cpuset/foreground/boost/tasks", "r+");
+            if (ferror(boost_cpuset_file)) {
+                return 0;
+            }
+            fg_cpuset_fd = open("/dev/cpuset/foreground/tasks", O_WRONLY);
+            if (fg_cpuset_fd < 0) {
+                fclose(boost_cpuset_file);
+                return 0;
+            }
+
+        }
+        if (!boost_cpuset_file || !fg_cpuset_fd) {
+            fclose(boost_cpuset_file);
+            close(fg_cpuset_fd);
+            return 0;
+        }
+        char buf[17];
+        char *curBuf = buf;
+        while (fgets(buf, 16, boost_cpuset_file)) {
+            //ALOGE("Appending FD %s to fg", buf);
+            int i = 0;
+            for (; i < 16; i++) {
+                if (buf[i] == '\n') {
+                    buf[i] = 0;
+                    break;
+                }
+            }
+            if (write(fg_cpuset_fd, buf, i) < 0) {
+                //ALOGE("Appending FD %s to fg ERROR", buf);
+                // handle error?
+            }
+            if (feof(boost_cpuset_file))
+                break;
+        }
+
+        close(fg_cpuset_fd);
+        fclose(boost_cpuset_file);
+
+#endif
+        return 0;
+
+    }
+
+
+    static JNINativeMethod method_table[] = {
+        { "nativeMigrateToBoost",   "()I", (void*)migrateToBoost },
+        { "nativeMigrateFromBoost", "()I", (void*)migrateFromBoost },
+    };
+
+    int register_android_server_ActivityManagerService(JNIEnv *env)
+    {
+        return jniRegisterNativeMethods(env, "com/android/server/am/ActivityManagerService",
+                                        method_table, NELEM(method_table));
+    }
+
+}
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 67872da..1f3fde6 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -20,6 +20,7 @@
 #include "utils/misc.h"
 
 namespace android {
+int register_android_server_ActivityManagerService(JNIEnv* env);
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_AssetAtlasService(JNIEnv* env);
 int register_android_server_BatteryStatsService(JNIEnv* env);
@@ -57,6 +58,7 @@
     }
     ALOG_ASSERT(env, "Could not retrieve the env!");
 
+    register_android_server_ActivityManagerService(env);
     register_android_server_PowerManagerService(env);
     register_android_server_SerialService(env);
     register_android_server_InputApplicationHandle(env);
@@ -80,5 +82,6 @@
     register_android_server_PersistentDataBlockService(env);
     register_android_server_Watchdog(env);
 
+
     return JNI_VERSION_1_4;
 }
diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java
index a91ddb8..cbf8fc2 100644
--- a/services/net/java/android/net/dhcp/DhcpPacket.java
+++ b/services/net/java/android/net/dhcp/DhcpPacket.java
@@ -55,6 +55,7 @@
     public static final int MIN_PACKET_LENGTH_L3 = MIN_PACKET_LENGTH_BOOTP + 20 + 8;
     public static final int MIN_PACKET_LENGTH_L2 = MIN_PACKET_LENGTH_L3 + 14;
 
+    public static final int HWADDR_LEN = 16;
     public static final int MAX_OPTION_LEN = 255;
     /**
      * IP layer definitions.
@@ -399,7 +400,7 @@
         buf.put(mRelayIp.getAddress());
         buf.put(mClientMac);
         buf.position(buf.position() +
-                     (16 - mClientMac.length) // pad addr to 16 bytes
+                     (HWADDR_LEN - mClientMac.length) // pad addr to 16 bytes
                      + 64     // empty server host name (64 bytes)
                      + 128);  // empty boot file name (128 bytes)
         buf.putInt(0x63825363); // magic number
@@ -786,7 +787,7 @@
 
         byte type = packet.get();
         byte hwType = packet.get();
-        byte addrLen = packet.get();
+        int addrLen = packet.get() & 0xff;
         byte hops = packet.get();
         transactionId = packet.getInt();
         secs = packet.getShort();
@@ -807,6 +808,16 @@
             return null;
         }
 
+        // Some DHCP servers have been known to announce invalid client hardware address values such
+        // as 0xff. The legacy DHCP client accepted these becuause it does not check the length at
+        // all but only checks that the interface MAC address matches the first bytes of the address
+        // in the packets. We're a bit stricter: if the length is obviously invalid (i.e., bigger
+        // than the size of the field), we fudge it to 6 (Ethernet). http://b/23725795
+        // TODO: evaluate whether to make this test more liberal.
+        if (addrLen > HWADDR_LEN) {
+            addrLen = ETHER_BROADCAST.length;
+        }
+
         clientMac = new byte[addrLen];
         packet.get(clientMac);
 
diff --git a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
index da1df1a..cd3b8bb 100644
--- a/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
+++ b/services/tests/servicestests/src/android/net/dhcp/DhcpPacketTest.java
@@ -333,6 +333,76 @@
     }
 
     @SmallTest
+    public void testBadHwaddrLength() throws Exception {
+        final ByteBuffer packet = ByteBuffer.wrap(HexEncoding.decode((
+            // IP header.
+            "450001518d0600004011144dc0a82b01c0a82bf7" +
+            // UDP header.
+            "00430044013d9ac7" +
+            // BOOTP header.
+            "02010600dfc23d1f0002000000000000c0a82bf7c0a82b0100000000" +
+            // MAC address.
+            "30766ff2a90c00000000000000000000" +
+            // Server name.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // File.
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            "0000000000000000000000000000000000000000000000000000000000000000" +
+            // Options
+            "638253633501023604c0a82b01330400000e103a04000007083b0400000c4e0104ffffff00" +
+            "1c04c0a82bff0304c0a82b010604c0a82b012b0f414e44524f49445f4d455445524544ff"
+        ).toCharArray(), false));
+        String expectedClientMac = "30766FF2A90C";
+
+        final int hwAddrLenOffset = 20 + 8 + 2;
+        assertEquals(6, packet.get(hwAddrLenOffset));
+
+        // Expect the expected.
+        DhcpPacket offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+        assertNotNull(offerPacket);
+        assertEquals(6, offerPacket.getClientMac().length);
+        assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
+
+        // Reduce the hardware address length and verify that it shortens the client MAC.
+        packet.flip();
+        packet.put(hwAddrLenOffset, (byte) 5);
+        offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+        assertNotNull(offerPacket);
+        assertEquals(5, offerPacket.getClientMac().length);
+        assertEquals(expectedClientMac.substring(0, 10),
+                HexDump.toHexString(offerPacket.getClientMac()));
+
+        packet.flip();
+        packet.put(hwAddrLenOffset, (byte) 3);
+        offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+        assertNotNull(offerPacket);
+        assertEquals(3, offerPacket.getClientMac().length);
+        assertEquals(expectedClientMac.substring(0, 6),
+                HexDump.toHexString(offerPacket.getClientMac()));
+
+        // Set the the hardware address length to 0xff and verify that we a) don't treat it as -1
+        // and crash, and b) hardcode it to 6.
+        packet.flip();
+        packet.put(hwAddrLenOffset, (byte) -1);
+        offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+        assertNotNull(offerPacket);
+        assertEquals(6, offerPacket.getClientMac().length);
+        assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
+
+        // Set the the hardware address length to a positive invalid value (> 16) and verify that we
+        // hardcode it to 6.
+        packet.flip();
+        packet.put(hwAddrLenOffset, (byte) 17);
+        offerPacket = DhcpPacket.decodeFullPacket(packet, ENCAP_L3);
+        assertNotNull(offerPacket);
+        assertEquals(6, offerPacket.getClientMac().length);
+        assertEquals(expectedClientMac, HexDump.toHexString(offerPacket.getClientMac()));
+    }
+
+    @SmallTest
     public void testPadAndOverloadedOptionsOffer() throws Exception {
         // A packet observed in the real world that is interesting for two reasons:
         //
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 62e532e..df8affe 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -411,7 +411,7 @@
      * @hide
      */
     public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL =
-            "allowNonEmergencyCallsInEcm";
+            "allow_non_emergency_calls_in_ecm_bool";
 
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 273cc93..b430340 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1457,10 +1457,15 @@
         String result = null;
         try {
             PhoneNumber pn = util.parseAndKeepRawInput(phoneNumber, defaultCountryIso);
+            /**
+             * Need to reformat any local Korean phone numbers (when the user is in Korea) with
+             * country code to corresponding national format which would replace the leading
+             * +82 with 0.
+             */
             if (KOREA_ISO_COUNTRY_CODE.equals(defaultCountryIso) &&
-                    (pn.getCountryCode() == util.getCountryCodeForRegion(KOREA_ISO_COUNTRY_CODE))) {
-                // Format local Korean phone numbers with country code to corresponding national
-                // format which would replace the leading +82 with 0.
+                    (pn.getCountryCode() == util.getCountryCodeForRegion(KOREA_ISO_COUNTRY_CODE)) &&
+                    (pn.getCountryCodeSource() ==
+                            PhoneNumber.CountryCodeSource.FROM_NUMBER_WITH_PLUS_SIGN)) {
                 result = util.format(pn, PhoneNumberUtil.PhoneNumberFormat.NATIONAL);
             } else {
                 result = util.formatInOriginalFormat(pn, defaultCountryIso);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 1f3802e..689e359 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -36,8 +36,8 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.annotation.Nullable;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -139,8 +139,9 @@
     private Map<StyleResourceValue, Integer> mStyleToDynamicIdMap;
     private int mDynamicIdGenerator = 0x02030000; // Base id for R.style in custom namespace
 
-    // cache for TypedArray generated from IStyleResourceValue object
-    private Map<int[], Map<Integer, BridgeTypedArray>> mTypedArrayCache;
+    // cache for TypedArray generated from StyleResourceValue object
+    private Map<int[], Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>
+            mTypedArrayCache;
     private BridgeInflater mBridgeInflater;
 
     private BridgeContentResolver mContentResolver;
@@ -621,31 +622,38 @@
             }
         }
 
+        // The map is from
+        // attrs (int[]) -> context's current themes (List<StyleRV>) -> resid (int) -> typed array.
         if (mTypedArrayCache == null) {
-            mTypedArrayCache = new HashMap<int[], Map<Integer,BridgeTypedArray>>();
-
-            Map<Integer, BridgeTypedArray> map = new HashMap<Integer, BridgeTypedArray>();
-            mTypedArrayCache.put(attrs, map);
-
-            BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs);
-            map.put(resid, ta);
-
-            return ta;
+            mTypedArrayCache = new IdentityHashMap<int[],
+                    Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>>();
         }
 
         // get the 2nd map
-        Map<Integer, BridgeTypedArray> map = mTypedArrayCache.get(attrs);
-        if (map == null) {
-            map = new HashMap<Integer, BridgeTypedArray>();
-            mTypedArrayCache.put(attrs, map);
+        Map<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>> map2 =
+                mTypedArrayCache.get(attrs);
+        if (map2 == null) {
+            map2 = new HashMap<List<StyleResourceValue>, Map<Integer, BridgeTypedArray>>();
+            mTypedArrayCache.put(attrs, map2);
         }
 
-        // get the array from the 2nd map
-        BridgeTypedArray ta = map.get(resid);
+        // get the 3rd map
+        List<StyleResourceValue> currentThemes = mRenderResources.getAllThemes();
+        Map<Integer, BridgeTypedArray> map3 = map2.get(currentThemes);
+        if (map3 == null) {
+            map3 = new HashMap<Integer, BridgeTypedArray>();
+            // Create a copy of the list before adding it to the map. This allows reusing the
+            // existing list.
+            currentThemes = new ArrayList<StyleResourceValue>(currentThemes);
+            map2.put(currentThemes, map3);
+        }
+
+        // get the array from the 3rd map
+        BridgeTypedArray ta = map3.get(resid);
 
         if (ta == null) {
             ta = createStyleBasedTypedArray(style, attrs);
-            map.put(resid, ta);
+            map3.put(resid, ta);
         }
 
         return ta;