Merge "Start to use importFile to file descriptor."
diff --git a/api/current.txt b/api/current.txt
index b034c86..d7fce79 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -32483,7 +32483,7 @@
     method public static boolean isDigitsOnly(java.lang.CharSequence);
     method public static boolean isEmpty(java.lang.CharSequence);
     method public static boolean isGraphic(java.lang.CharSequence);
-    method public static boolean isGraphic(char);
+    method public static deprecated boolean isGraphic(char);
     method public static java.lang.String join(java.lang.CharSequence, java.lang.Object[]);
     method public static java.lang.String join(java.lang.CharSequence, java.lang.Iterable);
     method public static int lastIndexOf(java.lang.CharSequence, char);
@@ -33984,6 +33984,7 @@
     field public static final int DENSITY_280 = 280; // 0x118
     field public static final int DENSITY_360 = 360; // 0x168
     field public static final int DENSITY_400 = 400; // 0x190
+    field public static final int DENSITY_420 = 420; // 0x1a4
     field public static final int DENSITY_560 = 560; // 0x230
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
     field public static final int DENSITY_HIGH = 240; // 0xf0
diff --git a/api/system-current.txt b/api/system-current.txt
index c5a4af4..ece5327 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -33484,6 +33484,7 @@
     field public static final java.lang.String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
     field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
+    field public static final java.lang.String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
     field public static final int CALL_STATE_IDLE = 0; // 0x0
     field public static final int CALL_STATE_OFFHOOK = 2; // 0x2
     field public static final int CALL_STATE_RINGING = 1; // 0x1
@@ -33500,11 +33501,15 @@
     field public static final int DATA_CONNECTING = 1; // 0x1
     field public static final int DATA_DISCONNECTED = 0; // 0x0
     field public static final int DATA_SUSPENDED = 3; // 0x3
+    field public static final java.lang.String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT";
     field public static final java.lang.String EXTRA_INCOMING_NUMBER = "incoming_number";
+    field public static final java.lang.String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT = "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+    field public static final java.lang.String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
     field public static final java.lang.String EXTRA_STATE = "state";
     field public static final java.lang.String EXTRA_STATE_IDLE;
     field public static final java.lang.String EXTRA_STATE_OFFHOOK;
     field public static final java.lang.String EXTRA_STATE_RINGING;
+    field public static final java.lang.String EXTRA_VOICEMAIL_NUMBER = "android.telephony.extra.VOICEMAIL_NUMBER";
     field public static final int NETWORK_TYPE_1xRTT = 7; // 0x7
     field public static final int NETWORK_TYPE_CDMA = 4; // 0x4
     field public static final int NETWORK_TYPE_EDGE = 2; // 0x2
@@ -34810,7 +34815,7 @@
     method public static boolean isDigitsOnly(java.lang.CharSequence);
     method public static boolean isEmpty(java.lang.CharSequence);
     method public static boolean isGraphic(java.lang.CharSequence);
-    method public static boolean isGraphic(char);
+    method public static deprecated boolean isGraphic(char);
     method public static java.lang.String join(java.lang.CharSequence, java.lang.Object[]);
     method public static java.lang.String join(java.lang.CharSequence, java.lang.Iterable);
     method public static int lastIndexOf(java.lang.CharSequence, char);
@@ -36311,6 +36316,7 @@
     field public static final int DENSITY_280 = 280; // 0x118
     field public static final int DENSITY_360 = 360; // 0x168
     field public static final int DENSITY_400 = 400; // 0x190
+    field public static final int DENSITY_420 = 420; // 0x1a4
     field public static final int DENSITY_560 = 560; // 0x230
     field public static final int DENSITY_DEFAULT = 160; // 0xa0
     field public static final int DENSITY_HIGH = 240; // 0xf0
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index ff7705b..5b88c8e 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -415,7 +415,8 @@
     public boolean isRunning() {
         int size = mNodes.size();
         for (int i = 0; i < size; i++) {
-            if (mNodes.get(i).mAnimation.isRunning()) {
+            Node node = mNodes.get(i);
+            if (node != mRootNode && node.mAnimation.isRunning()) {
                 return true;
             }
         }
@@ -512,7 +513,9 @@
         int size = mNodes.size();
         for (int i = 0; i < size; i++) {
             Node node = mNodes.get(i);
-            node.mAnimation.setupStartValues();
+            if (node != mRootNode) {
+                node.mAnimation.setupStartValues();
+            }
         }
     }
 
@@ -521,7 +524,9 @@
         int size = mNodes.size();
         for (int i = 0; i < size; i++) {
             Node node = mNodes.get(i);
-            node.mAnimation.setupEndValues();
+            if (node != mRootNode) {
+                node.mAnimation.setupEndValues();
+            }
         }
     }
 
@@ -536,7 +541,9 @@
                 int size = mNodes.size();
                 for (int i = 0; i < size; i++) {
                     Node node = mNodes.get(i);
-                    node.mAnimation.pause();
+                    if (node != mRootNode) {
+                        node.mAnimation.pause();
+                    }
                 }
             }
         }
@@ -553,7 +560,9 @@
                 int size = mNodes.size();
                 for (int i = 0; i < size; i++) {
                     Node node = mNodes.get(i);
-                    node.mAnimation.resume();
+                    if (node != mRootNode) {
+                        node.mAnimation.resume();
+                    }
                 }
             }
         }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fe79629..a2f2e73 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -4316,11 +4316,6 @@
 
             configDiff = mConfiguration.updateFrom(config);
             config = applyCompatConfiguration(mCurDefaultDisplayDpi);
-
-            final Theme systemTheme = getSystemContext().getTheme();
-            if ((systemTheme.getChangingConfigurations() & configDiff) != 0) {
-                systemTheme.rebase();
-            }
         }
 
         ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config);
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index abe12dc..7824072 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -1082,7 +1082,8 @@
          * create and display the dialog.
          */
         public AlertDialog create() {
-            final AlertDialog dialog = new AlertDialog(P.mContext);
+            // Context has already been wrapped with the appropriate theme.
+            final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
             P.apply(dialog.mAlert);
             dialog.setCancelable(P.mCancelable);
             if (P.mCancelable) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index c505b0b..e3414d9 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -3204,8 +3204,13 @@
      * Called by a profile or device owner to set the application restrictions for a given target
      * application running in the profile.
      *
-     * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be
-     * boolean, int, String, or String[].
+     * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be:
+     * <ul>
+     * <li>{@code boolean}
+     * <li>{@code int}
+     * <li>{@code String} or {@code String[]}
+     * <li>From {@link android.os.Build.VERSION_CODES#M}, {@code Bundle} or {@code Bundle[]}
+     * </ul>
      *
      * <p>The application restrictions are only made visible to the target application and the
      * profile or device owner.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bcce33b..9b860515e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5712,6 +5712,13 @@
         public static final String ASSISTANT = "assistant";
 
         /**
+         * Whether the camera launch gesture should be disabled.
+         *
+         * @hide
+         */
+        public static final String CAMERA_GESTURE_DISABLED = "camera_gesture_disabled";
+
+        /**
          * This are the settings to be backed up.
          *
          * NOTE: Settings are backed up and restored in the order they appear
@@ -5768,6 +5775,7 @@
             UI_NIGHT_MODE,
             SLEEP_TIMEOUT,
             DOUBLE_TAP_TO_WAKE,
+            CAMERA_GESTURE_DISABLED,
         };
 
         /**
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index ae2c0c7..4d8a7d0 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1430,8 +1430,9 @@
      */
     public static boolean isGraphic(CharSequence str) {
         final int len = str.length();
-        for (int i=0; i<len; i++) {
-            int gc = Character.getType(str.charAt(i));
+        for (int cp, i=0; i<len; i+=Character.charCount(cp)) {
+            cp = Character.codePointAt(str, i);
+            int gc = Character.getType(cp);
             if (gc != Character.CONTROL
                     && gc != Character.FORMAT
                     && gc != Character.SURROGATE
@@ -1447,7 +1448,12 @@
 
     /**
      * Returns whether this character is a printable character.
+     *
+     * This does not support non-BMP characters and should not be used.
+     *
+     * @deprecated Use {@link #isGraphic(CharSequence)} instead.
      */
+    @Deprecated
     public static boolean isGraphic(char c) {
         int gc = Character.getType(c);
         return     gc != Character.CONTROL
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index a36e66c..9a69600 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -90,6 +90,14 @@
     public static final int DENSITY_400 = 400;
 
     /**
+     * Intermediate density for screens that sit somewhere between
+     * {@link #DENSITY_XHIGH} (320 dpi) and {@link #DENSITY_XXHIGH} (480 dpi).
+     * This is not a density that applications should target, instead relying
+     * on the system to scale their {@link #DENSITY_XXHIGH} assets for them.
+     */
+    public static final int DENSITY_420 = 420;
+
+    /**
      * Standard quantized DPI for extra-extra-high-density screens.
      */
     public static final int DENSITY_XXHIGH = 480;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1c8a79b..ee06806 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -26,7 +26,6 @@
 
 import android.annotation.RequiresPermission;
 import android.content.Context;
-import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -377,8 +376,8 @@
      */
     private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
 
-    final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
-    final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
+    final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
+    final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
 
     // -----------------------------------------------------------
     
@@ -2033,8 +2032,7 @@
      */
     public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
         synchronized (mH) {
-            HashMap<InputMethodInfo, List<InputMethodSubtype>> ret =
-                    new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
+            HashMap<InputMethodInfo, List<InputMethodSubtype>> ret = new HashMap<>();
             try {
                 // TODO: We should change the return type from List<Object> to List<Parcelable>
                 List<Object> info = mService.getShortcutInputMethodsAndSubtypes();
@@ -2049,7 +2047,7 @@
                                 Log.e(TAG, "IMI list already contains the same InputMethod.");
                                 break;
                             }
-                            subtypes = new ArrayList<InputMethodSubtype>();
+                            subtypes = new ArrayList<>();
                             ret.put((InputMethodInfo)o, subtypes);
                         } else if (subtypes != null && o instanceof InputMethodSubtype) {
                             subtypes.add((InputMethodSubtype)o);
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index 742173b..d53efa0 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -428,7 +428,7 @@
     }
 
     public static ArrayList<InputMethodSubtype> getSubtypes(InputMethodInfo imi) {
-        ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
         final int subtypeCount = imi.getSubtypeCount();
         for (int i = 0; i < subtypeCount; ++i) {
             subtypes.add(imi.getSubtypeAt(i));
@@ -438,7 +438,7 @@
 
     public static ArrayList<InputMethodSubtype> getOverridingImplicitlyEnabledSubtypes(
             InputMethodInfo imi, String mode) {
-        ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
         final int subtypeCount = imi.getSubtypeCount();
         for (int i = 0; i < subtypeCount; ++i) {
             final InputMethodSubtype subtype = imi.getSubtypeAt(i);
@@ -496,10 +496,9 @@
             Resources res, InputMethodInfo imi) {
         final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
         final String systemLocale = res.getConfiguration().locale.toString();
-        if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
+        if (TextUtils.isEmpty(systemLocale)) return new ArrayList<>();
         final String systemLanguage = res.getConfiguration().locale.getLanguage();
-        final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
-                new HashMap<String, InputMethodSubtype>();
+        final HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap = new HashMap<>();
         final int N = subtypes.size();
         for (int i = 0; i < N; ++i) {
             // scan overriding implicitly enabled subtypes.
@@ -512,7 +511,7 @@
             }
         }
         if (applicableModeAndSubtypesMap.size() > 0) {
-            return new ArrayList<InputMethodSubtype>(applicableModeAndSubtypesMap.values());
+            return new ArrayList<>(applicableModeAndSubtypesMap.values());
         }
         for (int i = 0; i < N; ++i) {
             final InputMethodSubtype subtype = subtypes.get(i);
@@ -545,7 +544,7 @@
         }
         final InputMethodSubtype keyboardSubtype
                 = applicableModeAndSubtypesMap.get(SUBTYPE_MODE_KEYBOARD);
-        final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<InputMethodSubtype>(
+        final ArrayList<InputMethodSubtype> applicableSubtypes = new ArrayList<>(
                 applicableModeAndSubtypesMap.values());
         if (keyboardSubtype != null && !keyboardSubtype.containsExtraValueKey(TAG_ASCII_CAPABLE)) {
             for (int i = 0; i < N; ++i) {
@@ -818,8 +817,7 @@
                 String enabledInputMethodsStr,
                 TextUtils.SimpleStringSplitter inputMethodSplitter,
                 TextUtils.SimpleStringSplitter subtypeSplitter) {
-            ArrayList<Pair<String, ArrayList<String>>> imsList =
-                    new ArrayList<Pair<String, ArrayList<String>>>();
+            ArrayList<Pair<String, ArrayList<String>>> imsList = new ArrayList<>();
             if (TextUtils.isEmpty(enabledInputMethodsStr)) {
                 return imsList;
             }
@@ -828,13 +826,13 @@
                 String nextImsStr = inputMethodSplitter.next();
                 subtypeSplitter.setString(nextImsStr);
                 if (subtypeSplitter.hasNext()) {
-                    ArrayList<String> subtypeHashes = new ArrayList<String>();
+                    ArrayList<String> subtypeHashes = new ArrayList<>();
                     // The first element is ime id.
                     String imeId = subtypeSplitter.next();
                     while (subtypeSplitter.hasNext()) {
                         subtypeHashes.add(subtypeSplitter.next());
                     }
-                    imsList.add(new Pair<String, ArrayList<String>>(imeId, subtypeHashes));
+                    imsList.add(new Pair<>(imeId, subtypeHashes));
                 }
             }
             return imsList;
@@ -880,12 +878,6 @@
                     getEnabledInputMethodsAndSubtypeListLocked());
         }
 
-        public List<Pair<InputMethodInfo, ArrayList<String>>>
-                getEnabledInputMethodAndSubtypeHashCodeListLocked() {
-            return createEnabledInputMethodAndSubtypeHashCodeListLocked(
-                    getEnabledInputMethodsAndSubtypeListLocked());
-        }
-
         public List<InputMethodSubtype> getEnabledInputMethodSubtypeListLocked(
                 Context context, InputMethodInfo imi, boolean allowsImplicitlySelectedSubtypes) {
             List<InputMethodSubtype> enabledSubtypes =
@@ -901,8 +893,7 @@
                 InputMethodInfo imi) {
             List<Pair<String, ArrayList<String>>> imsList =
                     getEnabledInputMethodsAndSubtypeListLocked();
-            ArrayList<InputMethodSubtype> enabledSubtypes =
-                    new ArrayList<InputMethodSubtype>();
+            ArrayList<InputMethodSubtype> enabledSubtypes = new ArrayList<>();
             if (imi != null) {
                 for (Pair<String, ArrayList<String>> imsPair : imsList) {
                     InputMethodInfo info = mMethodMap.get(imsPair.first);
@@ -991,7 +982,7 @@
 
         private List<InputMethodInfo> createEnabledInputMethodListLocked(
                 List<Pair<String, ArrayList<String>>> imsList) {
-            final ArrayList<InputMethodInfo> res = new ArrayList<InputMethodInfo>();
+            final ArrayList<InputMethodInfo> res = new ArrayList<>();
             for (Pair<String, ArrayList<String>> ims: imsList) {
                 InputMethodInfo info = mMethodMap.get(ims.first);
                 if (info != null) {
@@ -1001,20 +992,6 @@
             return res;
         }
 
-        private List<Pair<InputMethodInfo, ArrayList<String>>>
-                createEnabledInputMethodAndSubtypeHashCodeListLocked(
-                        List<Pair<String, ArrayList<String>>> imsList) {
-            final ArrayList<Pair<InputMethodInfo, ArrayList<String>>> res
-                    = new ArrayList<Pair<InputMethodInfo, ArrayList<String>>>();
-            for (Pair<String, ArrayList<String>> ims : imsList) {
-                InputMethodInfo info = mMethodMap.get(ims.first);
-                if (info != null) {
-                    res.add(new Pair<InputMethodInfo, ArrayList<String>>(info, ims.second));
-                }
-            }
-            return res;
-        }
-
         private void putEnabledInputMethodsStr(String str) {
             Settings.Secure.putStringForUser(
                     mResolver, Settings.Secure.ENABLED_INPUT_METHODS, str, mCurrentUserId);
@@ -1118,7 +1095,7 @@
                         if (DEBUG) {
                             Slog.d(TAG, "Enabled subtype found in the history: " + subtypeHashCode);
                         }
-                        return new Pair<String, String>(imeInTheHistory, subtypeHashCode);
+                        return new Pair<>(imeInTheHistory, subtypeHashCode);
                     }
                 }
             }
@@ -1179,7 +1156,7 @@
         }
 
         private List<Pair<String, String>> loadInputMethodAndSubtypeHistoryLocked() {
-            ArrayList<Pair<String, String>> imsList = new ArrayList<Pair<String, String>>();
+            ArrayList<Pair<String, String>> imsList = new ArrayList<>();
             final String subtypeHistoryStr = getSubtypeHistoryStr();
             if (TextUtils.isEmpty(subtypeHistoryStr)) {
                 return imsList;
@@ -1196,7 +1173,7 @@
                         subtypeId = mSubtypeSplitter.next();
                         break;
                     }
-                    imsList.add(new Pair<String, String>(imeId, subtypeId));
+                    imsList.add(new Pair<>(imeId, subtypeId));
                 }
             }
             return imsList;
@@ -1229,11 +1206,6 @@
                     subtypeId, mCurrentUserId);
         }
 
-        public String getDisabledSystemInputMethods() {
-            return Settings.Secure.getStringForUser(
-                    mResolver, Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, mCurrentUserId);
-        }
-
         public String getSelectedInputMethod() {
             if (DEBUG) {
                 Slog.d(TAG, "getSelectedInputMethodStr: " + Settings.Secure.getStringForUser(
@@ -1294,7 +1266,7 @@
         public HashMap<InputMethodInfo, List<InputMethodSubtype>>
                 getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(Context context) {
             HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledInputMethodAndSubtypes =
-                    new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
+                    new HashMap<>();
             for (InputMethodInfo imi: getEnabledInputMethodListLocked()) {
                 enabledInputMethodAndSubtypes.put(
                         imi, getEnabledInputMethodSubtypeListLocked(context, imi, true));
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index eccf5fa..1068b51 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -16,8 +16,10 @@
 
 package com.android.internal.policy;
 
-import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.FIRST_DYNAMIC_STACK_ID;
 import static android.app.ActivityManager.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.HOME_STACK_ID;
 import static android.view.View.MeasureSpec.AT_MOST;
 import static android.view.View.MeasureSpec.EXACTLY;
 import static android.view.View.MeasureSpec.getMode;
@@ -4011,8 +4013,10 @@
         boolean isApplication = attrs.type == TYPE_BASE_APPLICATION ||
                 attrs.type == TYPE_APPLICATION;
         mWorkspaceId = getWorkspaceId();
-        // Only a non floating application window can get a non client decor.
-        if (!isFloating() && isApplication) {
+        // Only a non floating application window on one of the allowed worksapces can get a non
+        // client decor.
+        if (!isFloating() && isApplication && mWorkspaceId != HOME_STACK_ID &&
+                mWorkspaceId < FIRST_DYNAMIC_STACK_ID) {
             // Dependent on the brightness of the used title we either use the
             // dark or the light button frame.
             TypedValue value = new TypedValue();
diff --git a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
index af0c9cd..c66fd15 100644
--- a/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
+++ b/core/tests/coretests/src/android/animation/AnimatorSetActivityTest.java
@@ -3,6 +3,7 @@
 import com.android.frameworks.coretests.R;
 
 import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
@@ -18,6 +19,32 @@
         super(AnimatorSetActivity.class);
     }
 
+    static class MyListener implements Animator.AnimatorListener {
+        boolean startIsCalled = false;
+        boolean endIsCalled = false;
+        boolean cancelIsCalled = false;
+
+        @Override
+        public void onAnimationStart(Animator animation) {
+            startIsCalled = true;
+        }
+
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            endIsCalled = true;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            cancelIsCalled = true;
+        }
+
+        @Override
+        public void onAnimationRepeat(Animator animation) {
+
+        }
+    }
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -86,12 +113,7 @@
 
     @SmallTest
     public void testTotalDuration() {
-        ArrayList<Animator> list = new ArrayList<>(5);
-        list.add(a1);
-        list.add(a2);
-        list.add(a3);
-        list.add(a4);
-        list.add(a5);
+        ArrayList<Animator> list = getAnimatorList();
 
         // Run animations sequentially and test the total duration against sum of durations.
         AnimatorSet s1 = new AnimatorSet();
@@ -152,4 +174,328 @@
 
     }
 
+    @SmallTest
+    public void testGetDuration() {
+        AnimatorSet s = new AnimatorSet();
+        assertTrue(s.getDuration() < 0);
+        s.play(a1).before(a2).before(a3).after(a4).after(a5);
+        assertTrue(s.getDuration() < 0);
+
+        long duration = 200;
+        s.setDuration(duration);
+        assertEquals(duration, s.getDuration());
+
+    }
+
+    @SmallTest
+    @UiThreadTest
+    public void testSetDuration() {
+        AnimatorSet s = getSequentialSet();
+        assertTrue(s.getDuration() < 0);
+
+        long duration = 300;
+        s.setDuration(duration);
+        assertEquals(duration, s.getDuration());
+
+        s.start();
+        assertEquals(duration, s.getDuration());
+        assertEquals(duration, a1.getDuration());
+        assertEquals(duration, a2.getDuration());
+        assertEquals(duration, a3.getDuration());
+        assertEquals(duration, a4.getDuration());
+        assertEquals(duration, a5.getDuration());
+    }
+
+    @SmallTest
+    public void testAddListener() throws InterruptedException {
+        // Verify that the listener is added to the list of listeners in the AnimatorSet
+        // and that newly added listener gets callback for lifecycle events of the animator
+        final AnimatorSet s = new AnimatorSet();
+        s.play(a1).before(a2).before(a3).after(a4).after(a5);
+        final MyListener listener = new MyListener();
+        if (s.getListeners() != null) {
+            assertFalse(s.getListeners().contains(listener));
+        }
+        s.addListener(listener);
+        assertTrue(s.getListeners().contains(listener));
+
+        assertFalse(listener.startIsCalled);
+        assertFalse(listener.endIsCalled);
+
+        try {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    s.start();
+                    assertTrue(listener.startIsCalled);
+                    assertFalse(listener.endIsCalled);
+                }
+            });
+        } catch (Throwable throwable) {
+            throwable.printStackTrace();
+        }
+
+        Thread.sleep(s.getTotalDuration() + 200);
+        assertTrue(listener.startIsCalled);
+        assertTrue(listener.endIsCalled);
+    }
+
+    @SmallTest
+    public void testRemoveListener() throws Throwable {
+        final AnimatorSet s = new AnimatorSet();
+        s.playTogether(a1, a2, a3, a4);
+        MyListener listener = new MyListener();
+        s.addListener(listener);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.start();
+            }
+        });
+
+        Thread.sleep(s.getTotalDuration() + 100);
+        assertTrue(listener.startIsCalled);
+        assertTrue(listener.endIsCalled);
+
+        s.removeListener(listener);
+        if (s.getListeners() != null) {
+            assertFalse(s.getListeners().contains(listener));
+        }
+        listener.startIsCalled = false;
+        listener.endIsCalled = false;
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.start();
+            }
+        });
+        Thread.sleep(s.getTotalDuration() + 100);
+        assertFalse(listener.startIsCalled);
+        assertFalse(listener.endIsCalled);
+    }
+
+    @SmallTest
+    public void testEnd() throws Throwable {
+        // End animator set
+        final AnimatorSet s = new AnimatorSet();
+        s.play(a1).before(a2).after(a3).with(a4);
+        final MyListener listener = new MyListener();
+        s.addListener(listener);
+        assertFalse(listener.endIsCalled);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.start();
+                assertTrue(s.isStarted());
+                assertTrue(listener.startIsCalled);
+                assertFalse(listener.endIsCalled);
+            }
+        });
+
+        Thread.sleep(a2.getTotalDuration());
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.end();
+                assertTrue(listener.startIsCalled);
+                assertTrue(listener.endIsCalled);
+                assertFalse(s.isRunning());
+                assertFalse(s.isStarted());
+
+                assertFalse(a1.isStarted());
+                assertFalse(a2.isStarted());
+                assertFalse(a3.isStarted());
+                assertFalse(a4.isStarted());
+            }
+        });
+
+    }
+
+    @SmallTest
+    public void testStart() throws Throwable {
+        final AnimatorSet s = new AnimatorSet();
+        ArrayList<Animator> animators = getAnimatorList();
+
+        s.playSequentially(animators);
+        final MyListener l = new MyListener();
+        s.addListener(l);
+
+        ArrayList<MyListener> listeners = new ArrayList<>(animators.size());
+        for (int i = 0; i < animators.size(); i++) {
+            MyListener listener = new MyListener();
+            listeners.add(listener);
+            animators.get(i).addListener(listener);
+        }
+
+        // Check the state before calling start()
+        assertFalse(l.startIsCalled);
+        assertFalse(l.endIsCalled);
+        for (int i = 0; i < listeners.size(); i++) {
+            assertFalse(l.startIsCalled);
+            assertFalse(l.endIsCalled);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.start();
+                assertTrue(l.startIsCalled);
+            }
+        });
+
+        long timeout = s.getTotalDuration() * 2;
+        long wait = 0;
+
+        while (wait < timeout) {
+            if (l.endIsCalled) {
+                break;
+            }
+            Thread.sleep(200);
+            wait += 200;
+        }
+
+        // Now the set should finished
+        assertTrue(l.startIsCalled);
+        assertTrue(l.endIsCalled);
+        for (int i = 0; i < listeners.size(); i++) {
+            assertTrue(listeners.get(i).startIsCalled);
+            assertTrue(listeners.get(i).endIsCalled);
+        }
+    }
+
+    @SmallTest
+    public void testCancel() throws Throwable {
+        // Check whether cancel would trigger onAnimationCanceled and cancel all the unfinished
+        // animations
+        final AnimatorSet s = new AnimatorSet();
+        final ArrayList<Animator> animators = getAnimatorList();
+
+        s.playTogether(animators);
+        final MyListener l = new MyListener();
+        s.addListener(l);
+
+        final ArrayList<MyListener> listeners = new ArrayList<>(5);
+        for (int i = 0; i < animators.size(); i++) {
+            MyListener listener = new MyListener();
+            listeners.add(listener);
+            animators.get(i).addListener(listener);
+        }
+
+        // Check the state before calling start()
+        assertFalse(l.startIsCalled);
+        assertFalse(l.cancelIsCalled);
+        assertFalse(l.endIsCalled);
+        for (int i = 0; i < listeners.size(); i++) {
+            assertFalse(l.startIsCalled);
+            assertFalse(l.cancelIsCalled);
+            assertFalse(l.endIsCalled);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.start();
+            }
+        });
+
+        Thread.sleep(a1.getTotalDuration());
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(s.isStarted());
+                ArrayList<Integer> runningAnimIds = new ArrayList<Integer>();
+                for (int i = 0; i < animators.size(); i++) {
+                    if (animators.get(i).isStarted()) {
+                        runningAnimIds.add(i);
+                    }
+                }
+                s.cancel();
+                assertTrue(l.startIsCalled);
+                assertTrue(l.cancelIsCalled);
+                assertTrue(l.endIsCalled);
+
+                for (int i = 0; i < listeners.size(); i++) {
+                    assertTrue(listeners.get(i).startIsCalled);
+                    if (runningAnimIds.contains(i)) {
+                        assertTrue(listeners.get(i).cancelIsCalled);
+                    }
+                    assertTrue(listeners.get(i).endIsCalled);
+                }
+            }
+        });
+
+    }
+
+    @SmallTest
+    public void testIsRunning() throws Throwable {
+        final AnimatorSet s = new AnimatorSet();
+        final long startDelay = 500;
+        s.play(a1).before(a2).after(a3).with(a4);
+        s.play(a3).after(a5);
+        s.setStartDelay(startDelay);
+        MyListener listener = new MyListener();
+        s.addListener(listener);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                s.start();
+            }
+        });
+
+        while (!listener.endIsCalled) {
+            boolean passedStartDelay = a1.isStarted() || a2.isStarted() || a3.isStarted() ||
+                    a4.isStarted() || a5.isStarted();
+            assertEquals(passedStartDelay, s.isRunning());
+            Thread.sleep(50);
+        }
+        assertFalse(s.isRunning());
+    }
+
+    @SmallTest
+    public void testPauseAndResume() throws Throwable {
+        final AnimatorSet set = getSequentialSet();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Calling pause before start should have no effect, per documentation
+                set.pause();
+                set.start();
+                assertFalse(set.isPaused());
+            }
+        });
+
+        while (!a2.isStarted()) {
+            Thread.sleep(50);
+        }
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(set.isPaused());
+                set.pause();
+                assertTrue(set.isPaused());
+                set.resume();
+                assertFalse(set.isPaused());
+            }
+        });
+    }
+
+    // Create an AnimatorSet with all the animators running sequentially
+    private AnimatorSet getSequentialSet() {
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(a1, a2, a3, a4, a5);
+        return set;
+    }
+
+    private ArrayList<Animator> getAnimatorList() {
+        ArrayList<Animator> list = new ArrayList<>();
+        list.add(a1);
+        list.add(a2);
+        list.add(a3);
+        list.add(a4);
+        list.add(a5);
+        return list;
+    }
+
 }
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index bf069d3..32f6a89 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -786,12 +786,16 @@
             mMaskColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_IN);
         }
 
-        // Draw the appropriate mask.
+        // Draw the appropriate mask anchored to (0,0).
+        final int left = bounds.left;
+        final int top = bounds.top;
+        mMaskCanvas.translate(-left, -top);
         if (maskType == MASK_EXPLICIT) {
             drawMask(mMaskCanvas);
         } else if (maskType == MASK_CONTENT) {
             drawContent(mMaskCanvas);
         }
+        mMaskCanvas.translate(left, top);
     }
 
     private int getMaskType() {
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 7605231..f42d750 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -38,27 +38,35 @@
 /**
  * {@link AlgorithmParameterSpec} for initializing a {@link KeyPairGenerator} or a
  * {@link KeyGenerator} of the <a href="{@docRoot}training/articles/keystore.html">Android Keystore
- * system</a>. The spec determines whether user authentication is required for using the key, what
- * uses the key is authorized for (e.g., only for signing -- decryption not permitted), the key's
- * validity start and end dates.
+ * system</a>. The spec determines authorized uses of the key, such as whether user authentication
+ * is required for using the key, what operations are authorized (e.g., signing, but not
+ * decryption) and with what parameters (e.g., only with a particular padding scheme or digest), the
+ * key's validity start and end dates. Key use authorizations expressed in the spec apply only to
+ * secret keys and private keys -- public keys can be used for any supported operations.
  *
  * <p>To generate an asymmetric key pair or a symmetric key, create an instance of this class using
  * the {@link Builder}, initialize a {@code KeyPairGenerator} or a {@code KeyGenerator} of the
  * desired key type (e.g., {@code EC} or {@code AES} -- see
  * {@link KeyProperties}.{@code KEY_ALGORITHM} constants) from the {@code AndroidKeyStore} provider
- * with the {@code KeyPairGeneratorSpec} instance, and then generate a key or key pair using
- * {@link KeyPairGenerator#generateKeyPair()}.
+ * with the {@code KeyGenParameterSpec} instance, and then generate a key or key pair using
+ * {@link KeyGenerator#generateKey()} or {@link KeyPairGenerator#generateKeyPair()}.
  *
  * <p>The generated key pair or key will be returned by the generator and also stored in the Android
- * Keystore system under the alias specified in this spec. To obtain the secret or private key from
- * the Android KeyStore use {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)}
+ * Keystore under the alias specified in this spec. To obtain the secret or private key from the
+ * Android Keystore use {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)}
  * or {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
- * To obtain the public key from the Android Keystore system use
+ * To obtain the public key from the Android Keystore use
  * {@link java.security.KeyStore#getCertificate(String)} and then
  * {@link Certificate#getPublicKey()}.
  *
+ * <p>To help obtain algorithm-specific public parameters of key pairs stored in the Android
+ * Keystore, generated private keys implement {@link java.security.interfaces.ECKey} or
+ * {@link java.security.interfaces.RSAKey} interfaces whereas public keys implement
+ * {@link java.security.interfaces.ECPublicKey} or {@link java.security.interfaces.RSAPublicKey}
+ * interfaces.
+ *
  * <p>For asymmetric key pairs, a self-signed X.509 certificate will be also generated and stored in
- * the Android KeyStore. This is because the {@link java.security.KeyStore} abstraction does not
+ * the Android Keystore. This is because the {@link java.security.KeyStore} abstraction does not
  * support storing key pairs without a certificate. The subject, serial number, and validity dates
  * of the certificate can be customized in this spec. The self-signed certificate may be replaced at
  * a later time by a certificate signed by a Certificate Authority (CA).
@@ -82,27 +90,33 @@
  *
  * <p>Instances of this class are immutable.
  *
- * <p><h3>Example: Asymmetric key pair</h3>
- * The following example illustrates how to generate an EC key pair in the Android KeyStore system
- * under alias {@code key1} authorized to be used only for signing using SHA-256, SHA-384,
- * or SHA-512 digest and only if the user has been authenticated within the last five minutes.
+ * <p><h3>Example: NIST P-256 EC key pair for signing/verification using ECDSA</h3>
+ * This example illustrates how to generate a NIST P-256 (aka secp256r1 aka prime256v1) EC key pair
+ * in the Android KeyStore system under alias {@code key1} where the private key is authorized to be
+ * used only for signing using SHA-256, SHA-384, or SHA-512 digest and only if the user has been
+ * authenticated within the last five minutes. The use of public key is unrestricted, thus
+ * permitting signature verification using any padding schemes and digests, and without user
+ * authentication.
  * <pre> {@code
  * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
- *         KeyProperties.KEY_ALGORITHM_EC,
- *         "AndroidKeyStore");
+ *         KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore");
  * keyPairGenerator.initialize(
  *         new KeyGenParameterSpec.Builder(
  *                 "key1",
- *                 KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY)
+ *                 KeyProperties.PURPOSE_SIGN)
+ *                 .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
  *                 .setDigests(KeyProperties.DIGEST_SHA256,
  *                         KeyProperties.DIGEST_SHA384,
  *                         KeyProperties.DIGEST_SHA512)
- *                 // Only permit this key to be used if the user authenticated
+ *                 // Only permit the private key to be used if the user authenticated
  *                 // within the last five minutes.
  *                 .setUserAuthenticationRequired(true)
  *                 .setUserAuthenticationValidityDurationSeconds(5 * 60)
  *                 .build());
  * KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ * Signature signature = Signature.getInstance("SHA256withECDSA");
+ * signature.initSign(keyPair.getPrivate());
+ * ...
  *
  * // The key pair can also be obtained from the Android Keystore any time as follows:
  * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
@@ -111,14 +125,67 @@
  * PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
  * }</pre>
  *
- * <p><h3>Example: Symmetric key</h3>
+ * <p><h3>Example: RSA key pair for signing/verification using RSA-PSS</h3>
+ * This example illustrates how to generate an RSA key pair in the Android KeyStore system under
+ * alias {@code key1} authorized to be used only for signing using the RSA-PSS signature padding
+ * scheme with SHA-256 or SHA-512 digests. The use of public key is unrestricted, thus permitting
+ * signature verification using any padding schemes and digests.
+ * <pre> {@code
+ * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
+ *         KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
+ * keyPairGenerator.initialize(
+ *         new KeyGenParameterSpec.Builder(
+ *                 "key1",
+ *                 KeyProperties.PURPOSE_SIGN)
+ *                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
+ *                 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PSS)
+ *                 .build());
+ * KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ * Signature signature = Signature.getInstance("SHA256withRSA/PSS");
+ * signature.initSign(keyPair.getPrivate());
+ * ...
+ *
+ * // The key pair can also be obtained from the Android Keystore any time as follows:
+ * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ * keyStore.load(null);
+ * PrivateKey privateKey = (PrivateKey) keyStore.getKey("key1", null);
+ * PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
+ * }</pre>
+ *
+ * <p><h3>Example: RSA key pair for encryption/decryption using RSA OAEP</h3>
+ * This example illustrates how to generate an RSA key pair in the Android KeyStore system under
+ * alias {@code key1} where the private key is authorized to be used only for decryption using RSA
+ * OAEP encryption padding scheme with SHA-256 or SHA-512 digests. The use of public key is
+ * unrestricted, thus permitting encryption using any padding schemes and digests.
+ * <pre> {@code
+ * KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
+ *         KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
+ * keyPairGenerator.initialize(
+ *         new KeyGenParameterSpec.Builder(
+ *                 "key1",
+ *                 KeyProperties.PURPOSE_DECRYPT)
+ *                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
+ *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_OAEP)
+ *                 .build());
+ * KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ * Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
+ * cipher.init(Cipher.DECRYPT_MODE, keyPair.getPrivate());
+ * ...
+ *
+ * // The key pair can also be obtained from the Android Keystore any time as follows:
+ * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ * keyStore.load(null);
+ * PrivateKey privateKey = (PrivateKey) keyStore.getKey("key1", null);
+ * PublicKey publicKey = keyStore.getCertificate("key1").getPublicKey();
+ * }</pre>
+ *
+ * <p><h3>Example: AES key for encryption/decryption in GCM mode</h3>
  * The following example illustrates how to generate an AES key in the Android KeyStore system under
  * alias {@code key2} authorized to be used only for encryption/decryption in GCM mode with no
  * padding.
  * <pre> {@code
  * KeyGenerator keyGenerator = KeyGenerator.getInstance(
- *         KeyProperties.KEY_ALGORITHM_AES,
- *         "AndroidKeyStore");
+ *         KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
  * keyGenerator.initialize(
  *         new KeyGenParameterSpec.Builder("key2",
  *                 KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
@@ -127,6 +194,29 @@
  *                 .build());
  * SecretKey key = keyGenerator.generateKey();
  *
+ * Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ * cipher.init(Cipher.ENCRYPT_MODE, key);
+ * ...
+ *
+ * // The key can also be obtained from the Android Keystore any time as follows:
+ * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ * keyStore.load(null);
+ * key = (SecretKey) keyStore.getKey("key2", null);
+ * }</pre>
+ *
+ * <p><h3>Example: HMAC key for generating a MAC using SHA-256</h3>
+ * This example illustrates how to generate an HMAC key in the Android KeyStore system under alias
+ * {@code key2} authorized to be used only for generating an HMAC using SHA-256.
+ * <pre> {@code
+ * KeyGenerator keyGenerator = KeyGenerator.getInstance(
+ *         KeyProperties.KEY_ALGORITHM_HMAC_SHA256, "AndroidKeyStore");
+ * keyGenerator.initialize(
+ *         new KeyGenParameterSpec.Builder("key2", KeyProperties.PURPOSE_SIGN).build());
+ * SecretKey key = keyGenerator.generateKey();
+ * Mac mac = Mac.getInstance("HmacSHA256");
+ * mac.init(key);
+ * ...
+ *
  * // The key can also be obtained from the Android Keystore any time as follows:
  * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
  * keyStore.load(null);
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index b71dc82..c984439 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -33,28 +33,36 @@
 
 /**
  * Specification of how a key or key pair is secured when imported into the
- * <a href="{@docRoot}training/articles/keystore.html">Android KeyStore facility</a>. This class
- * specifies parameters such as whether user authentication is required for using the key, what uses
- * the key is authorized for (e.g., only in {@code GCM} mode, or only for signing -- decryption not
- * permitted), the key's and validity start and end dates.
+ * <a href="{@docRoot}training/articles/keystore.html">Android Keystore system</a>. This class
+ * specifies authorized uses of the imported key, such as whether user authentication is required
+ * for using the key, what operations the key is authorized for (e.g., decryption, but not signing)
+ * and with what parameters (e.g., only with a particular padding scheme or digest), the key's and
+ * validity start and end dates. Key use authorizations expressed in this class apply only to secret
+ * keys and private keys -- public keys can be used for any supported operations.
  *
- * <p>To import a key or key pair into the Android KeyStore, create an instance of this class using
+ * <p>To import a key or key pair into the Android Keystore, create an instance of this class using
  * the {@link Builder} and pass the instance into {@link java.security.KeyStore#setEntry(String, java.security.KeyStore.Entry, ProtectionParameter) KeyStore.setEntry}
  * with the key or key pair being imported.
  *
- * <p>To obtain the secret/symmetric or private key from the Android KeyStore use
+ * <p>To obtain the secret/symmetric or private key from the Android Keystore use
  * {@link java.security.KeyStore#getKey(String, char[]) KeyStore.getKey(String, null)} or
  * {@link java.security.KeyStore#getEntry(String, java.security.KeyStore.ProtectionParameter) KeyStore.getEntry(String, null)}.
- * To obtain the public key from the Android KeyStore use
+ * To obtain the public key from the Android Keystore use
  * {@link java.security.KeyStore#getCertificate(String)} and then
  * {@link Certificate#getPublicKey()}.
  *
- * <p>NOTE: The key material of keys stored in the Android KeyStore is not accessible.
+ * <p>To help obtain algorithm-specific public parameters of key pairs stored in the Android
+ * Keystore, its private keys implement {@link java.security.interfaces.ECKey} or
+ * {@link java.security.interfaces.RSAKey} interfaces whereas its public keys implement
+ * {@link java.security.interfaces.ECPublicKey} or {@link java.security.interfaces.RSAPublicKey}
+ * interfaces.
+ *
+ * <p>NOTE: The key material of keys stored in the Android Keystore is not accessible.
  *
  * <p>Instances of this class are immutable.
  *
- * <p><h3>Example: Symmetric Key</h3>
- * The following example illustrates how to import an AES key into the Android KeyStore under alias
+ * <p><h3>Example: AES key for encryption/decryption in GCM mode</h3>
+ * This example illustrates how to import an AES key into the Android KeyStore under alias
  * {@code key1} authorized to be used only for encryption/decryption in GCM mode with no padding.
  * The key must export its key material via {@link Key#getEncoded()} in {@code RAW} format.
  * <pre> {@code
@@ -71,15 +79,41 @@
  *                 .build());
  * // Key imported, obtain a reference to it.
  * SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
- * // The original key can now be thrown away.
+ * // The original key can now be discarded.
+ *
+ * Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
+ * cipher.init(Cipher.ENCRYPT_MODE, keyStoreKey);
+ * ...
  * }</pre>
  *
- * <p><h3>Example: Asymmetric Key Pair</h3>
- * The following example illustrates how to import an EC key pair into the Android KeyStore under
- * alias {@code key2} authorized to be used only for signing with SHA-256 digest and only if
- * the user has been authenticated within the last ten minutes. Both the private and the public key
- * must export their key material via {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509}
- * format respectively.
+ * <p><h3>Example: HMAC key for generating MACs using SHA-512</h3>
+ * This example illustrates how to import an HMAC key into the Android KeyStore under alias
+ * {@code key1} authorized to be used only for generating MACs using SHA-512 digest. The key must
+ * export its key material via {@link Key#getEncoded()} in {@code RAW} format.
+ * <pre> {@code
+ * SecretKey key = ...; // HMAC key of algorithm "HmacSHA512".
+ *
+ * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ * keyStore.load(null);
+ * keyStore.setEntry(
+ *         "key1",
+ *         new KeyStore.SecretKeyEntry(key),
+ *         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN).build());
+ * // Key imported, obtain a reference to it.
+ * SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
+ * // The original key can now be discarded.
+ *
+ * Mac mac = Mac.getInstance("HmacSHA512");
+ * mac.init(keyStoreKey);
+ * ...
+ * }</pre>
+ *
+ * <p><h3>Example: EC key pair for signing/verification using ECDSA</h3>
+ * This example illustrates how to import an EC key pair into the Android KeyStore under alias
+ * {@code key2} with the private key authorized to be used only for signing with SHA-256 or SHA-512
+ * digests. The use of public key is unrestricted, thus permitting signature verification using any
+ * digests. Both the private and the public key must export their key material via
+ * {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509} format respectively.
  * <pre> {@code
  * PrivateKey privateKey = ...;   // EC private key
  * Certificate[] certChain = ...; // Certificate chain with the first certificate
@@ -91,7 +125,39 @@
  *         "key2",
  *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
  *         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
+ *                 .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512)
+ *                 .build());
+ * // Key pair imported, obtain a reference to it.
+ * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
+ * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
+ * // The original private key can now be discarded.
+ *
+ * Signature signature = Signature.getInstance("SHA256withECDSA");
+ * signature.initSign(keyStorePrivateKey);
+ * ...
+ * }</pre>
+ *
+ * <p><h3>Example: RSA key pair for signing/verification using PKCS#1 padding</h3>
+ * This example illustrates how to import an RSA key pair into the Android KeyStore under alias
+ * {@code key2} with the private key authorized to be used only for signing using the PKCS#1
+ * signature padding scheme with SHA-256 digest and only if the user has been authenticated within
+ * the last ten minutes. The use of public key is unrestricted, thus permitting signature
+ * verification using any padding schemes and digests, and without user authentication. Both the
+ * private and the public key must export their key material via {@link Key#getEncoded()} in
+ * {@code PKCS#8} and {@code X.509} format respectively.
+ * <pre> {@code
+ * PrivateKey privateKey = ...;   // RSA private key
+ * Certificate[] certChain = ...; // Certificate chain with the first certificate
+ *                                // containing the corresponding RSA public key.
+ *
+ * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ * keyStore.load(null);
+ * keyStore.setEntry(
+ *         "key2",
+ *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
+ *         new KeyProtection.Builder(KeyProperties.PURPOSE_SIGN)
  *                 .setDigests(KeyProperties.DIGEST_SHA256)
+ *                 .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
  *                 // Only permit this key to be used if the user
  *                 // authenticated within the last ten minutes.
  *                 .setUserAuthenticationRequired(true)
@@ -100,7 +166,40 @@
  * // Key pair imported, obtain a reference to it.
  * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
  * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
- * // The original private key can now be thrown away.
+ * // The original private key can now be discarded.
+ *
+ * Signature signature = Signature.getInstance("SHA256withRSA");
+ * signature.initSign(keyStorePrivateKey);
+ * ...
+ * }</pre>
+ *
+ * <p><h3>Example: RSA key pair for encryption/decryption using PKCS#1 padding</h3>
+ * This example illustrates how to import an RSA key pair into the Android KeyStore under alias
+ * {@code key2} with the private key authorized to be used only for decryption using the PKCS#1
+ * encryption padding scheme. The use of public key is unrestricted, thus permitting encryption
+ * using any padding schemes and digests. Both the private and the public key must export their key
+ * material via {@link Key#getEncoded()} in {@code PKCS#8} and {@code X.509} format respectively.
+ * <pre> {@code
+ * PrivateKey privateKey = ...;   // RSA private key
+ * Certificate[] certChain = ...; // Certificate chain with the first certificate
+ *                                // containing the corresponding RSA public key.
+ *
+ * KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
+ * keyStore.load(null);
+ * keyStore.setEntry(
+ *         "key2",
+ *         new KeyStore.PrivateKeyEntry(privateKey, certChain),
+ *         new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
+ *                 .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
+ *                 .build());
+ * // Key pair imported, obtain a reference to it.
+ * PrivateKey keyStorePrivateKey = (PrivateKey) keyStore.getKey("key2", null);
+ * PublicKey publicKey = keyStore.getCertificate("key2").getPublicKey();
+ * // The original private key can now be discarded.
+ *
+ * Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+ * cipher.init(Cipher.DECRYPT_MODE, keyStorePrivateKey);
+ * ...
  * }</pre>
  */
 public final class KeyProtection implements ProtectionParameter {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 8f792de..dfc31ab 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -234,6 +234,12 @@
         }
     }
 
+    @Override
+    public void showMessage(String message, int color) {
+        mSecurityMessageDisplay.setNextMessageColor(color);
+        mSecurityMessageDisplay.setMessage(message, true /* important */);
+    }
+
     protected abstract int getPromtReasonStringRes(int reason);
 
     // Cause a VIRTUAL_KEY vibration
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index ff4e815..32892cf 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -170,6 +170,10 @@
         mSecurityContainer.showPromptReason(reason);
     }
 
+    public void showMessage(String message, int color) {
+        mSecurityContainer.showMessage(message, color);
+    }
+
     /**
      *  Dismisses the keyguard by going to the next screen or making it gone.
      *
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
index 2951af9..c8adf64 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
@@ -39,15 +39,18 @@
      * lift-to-type from interrupting itself.
      */
     private static final long ANNOUNCEMENT_DELAY = 250;
+    private static final int DEFAULT_COLOR = -1;
 
     private static final int SECURITY_MESSAGE_DURATION = 5000;
 
     private final KeyguardUpdateMonitor mUpdateMonitor;
     private final Handler mHandler;
+    private final int mDefaultColor;
 
     // Timeout before we reset the message to show charging/owner info
     long mTimeout = SECURITY_MESSAGE_DURATION;
     CharSequence mMessage;
+    private int mNextMessageColor = DEFAULT_COLOR;
 
     private final Runnable mClearMessageRunnable = new Runnable() {
         @Override
@@ -78,10 +81,16 @@
         mUpdateMonitor.registerCallback(mInfoCallback);
         mHandler = new Handler(Looper.myLooper());
 
+        mDefaultColor = getCurrentTextColor();
         update();
     }
 
     @Override
+    public void setNextMessageColor(int color) {
+        mNextMessageColor = color;
+    }
+
+    @Override
     public void setMessage(CharSequence msg, boolean important) {
         if (!TextUtils.isEmpty(msg) && important) {
             securityMessageChanged(msg);
@@ -151,6 +160,12 @@
         CharSequence status = mMessage;
         setVisibility(TextUtils.isEmpty(status) ? INVISIBLE : VISIBLE);
         setText(status);
+        int color = mDefaultColor;
+        if (mNextMessageColor != DEFAULT_COLOR) {
+            color = mNextMessageColor;
+            mNextMessageColor = DEFAULT_COLOR;
+        }
+        setTextColor(color);
     }
 
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 4bd1a2e..a96c79f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -15,10 +15,6 @@
  */
 package com.android.keyguard;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.AsyncTask;
@@ -28,7 +24,6 @@
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.MotionEvent;
-import android.view.RenderNodeAnimator;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.animation.AnimationUtils;
@@ -342,6 +337,12 @@
     }
 
     @Override
+    public void showMessage(String message, int color) {
+        mSecurityMessageDisplay.setNextMessageColor(color);
+        mSecurityMessageDisplay.setMessage(message, true /* important */);
+    }
+
+    @Override
     public void startAppearAnimation() {
         enableClipping(false);
         setAlpha(1f);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 85da298..8fc3cde 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -518,6 +518,13 @@
         }
     }
 
+
+    public void showMessage(String message, int color) {
+        if (mCurrentSecuritySelection != SecurityMode.None) {
+            getSecurityView(mCurrentSecuritySelection).showMessage(message, color);
+        }
+    }
+
     @Override
     public void showUsabilityHint() {
         mSecurityViewFlipper.showUsabilityHint();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
index 5658a74..7e82c63 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityView.java
@@ -77,6 +77,14 @@
     void showPromptReason(int reason);
 
     /**
+     * Show a message on the security view with a specified color
+     *
+     * @param message the message to show
+     * @param color the color to use
+     */
+    void showMessage(String message, int color);
+
+    /**
      * Instruct the view to show usability hints, if any.
      *
      */
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index a0ff21b..6012c45 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -139,6 +139,14 @@
     }
 
     @Override
+    public void showMessage(String message, int color) {
+        KeyguardSecurityView ksv = getSecurityView();
+        if (ksv != null) {
+            ksv.showMessage(message, color);
+        }
+    }
+
+    @Override
     public void showUsabilityHint() {
         KeyguardSecurityView ksv = getSecurityView();
         if (ksv != null) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 55d85206..0ee68fd 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -118,7 +118,13 @@
      * Mode in which we wake up the device, but play the normal dismiss animation. Active when we
      * acquire a fingerprint pulsing in doze mode.
      * */
-    private static final int FP_WAKE_WAKE_TO_BOUNCER = 2;
+    private static final int FP_WAKE_TO_BOUNCER = 2;
+
+    /**
+     * Mode in which we only wake up the device, and keyguard was not showing when we acquired a
+     * fingerprint.
+     * */
+    private static final int FP_ONLY_WAKE = 3;
 
     // Callback messages
     private static final int MSG_TIME_UPDATE = 301;
@@ -401,14 +407,14 @@
             mWakeLock = mPowerManager.newWakeLock(
                     PowerManager.PARTIAL_WAKE_LOCK, FINGERPRINT_WAKE_LOCK_NAME);
             mWakeLock.acquire();
-            mFpWakeMode = FP_WAKE_DIRECT_UNLOCK;
+            mFpWakeMode = mKeyguardIsVisible ? FP_WAKE_DIRECT_UNLOCK : FP_ONLY_WAKE;
             if (DEBUG_FP_WAKELOCK) {
                 Log.i(TAG, "fingerprint acquired, grabbing fp wakelock");
             }
             mHandler.postDelayed(mReleaseFingerprintWakeLockRunnable,
                     FINGERPRINT_WAKELOCK_TIMEOUT_MS);
         } else if (!mDeviceInteractive) {
-            mFpWakeMode = FP_WAKE_WAKE_TO_BOUNCER;
+            mFpWakeMode = FP_WAKE_TO_BOUNCER;
         } else {
             mFpWakeMode = FP_WAKE_NONE;
         }
@@ -436,7 +442,8 @@
     }
 
     private void handleFingerprintAuthenticated() {
-        if (mFpWakeMode == FP_WAKE_WAKE_TO_BOUNCER || mFpWakeMode == FP_WAKE_DIRECT_UNLOCK) {
+        if (mFpWakeMode == FP_WAKE_TO_BOUNCER || mFpWakeMode == FP_WAKE_DIRECT_UNLOCK
+                || mFpWakeMode == FP_ONLY_WAKE) {
             if (DEBUG_FP_WAKELOCK) {
                 Log.i(TAG, "fp wakelock: Authenticated, waking up...");
             }
@@ -942,9 +949,7 @@
     }
 
     private boolean shouldListenForFingerprint() {
-        return mKeyguardIsVisible && !mSwitchingUser &&
-                mTrustManager.hasUserAuthenticatedSinceBoot(
-                        ActivityManager.getCurrentUser());
+        return (mKeyguardIsVisible || !mDeviceInteractive) && !mSwitchingUser;
     }
 
     private void startListeningForFingerprint() {
diff --git a/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java b/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java
index b38cfd5..ddb1f6e 100644
--- a/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java
+++ b/packages/Keyguard/src/com/android/keyguard/SecurityMessageDisplay.java
@@ -17,11 +17,14 @@
 package com.android.keyguard;
 
 public interface SecurityMessageDisplay {
-    public void setMessage(CharSequence msg, boolean important);
 
-    public void setMessage(int resId, boolean important);
+    void setNextMessageColor(int color);
 
-    public void setMessage(int resId, boolean important, Object... formatArgs);
+    void setMessage(CharSequence msg, boolean important);
 
-    public void setTimeout(int timeout_ms);
+    void setMessage(int resId, boolean important);
+
+    void setMessage(int resId, boolean important, Object... formatArgs);
+
+    void setTimeout(int timeout_ms);
 }
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_land.png
new file mode 100644
index 0000000..165ef4f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_ime_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
index d6e2065..f95f09f 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
index 6be4161..860a906 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
index b031273..bab268e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_land.png
new file mode 100644
index 0000000..0feb405
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
index 12ceb90..cabab0d 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
index dc8809e..16e1bf5 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
index 5178ac5..40375de 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_land.png
new file mode 100644
index 0000000..b7b8f98
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_ime_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
index 98be526..69b7449 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
index eed3f54..57d243c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
index 22ae09d..e53eaff 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_land.png
new file mode 100644
index 0000000..695e7a4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_ime_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
index c819545..88294c0 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
index 6075caf..09d684a 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
index bccda1b..e31ea32 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_land.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_land.png
new file mode 100644
index 0000000..24f12d7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_ime_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_land.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_land.png
new file mode 100644
index 0000000..51482f5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_back_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_land.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_land.png
new file mode 100644
index 0000000..46c7b18
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_home_land.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_land.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_land.png
new file mode 100644
index 0000000..396ad7d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_recent_land.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 42c4e12..a6cea62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -42,6 +42,7 @@
 import android.database.ContentObserver;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
@@ -1816,10 +1817,16 @@
                 sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
         iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
+        final Icon smallIcon = n.getSmallIcon();
+        if (smallIcon == null) {
+            handleNotificationError(sbn,
+                    "No small icon in notification from " + sbn.getPackageName());
+            return null;
+        }
         final StatusBarIcon ic = new StatusBarIcon(
                 sbn.getUser(),
                 sbn.getPackageName(),
-                n.getSmallIcon(),
+                smallIcon,
                 n.iconLevel,
                 n.number,
                 n.tickerText);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 46b00c7..ac4dee2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -16,18 +16,13 @@
 
 package com.android.systemui.statusbar;
 
-import com.android.internal.app.IBatteryStats;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
-
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.Color;
+import android.hardware.fingerprint.FingerprintManager;
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Handler;
@@ -40,8 +35,16 @@
 import android.util.Log;
 import android.view.View;
 
+import com.android.internal.app.IBatteryStats;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
+import com.android.systemui.statusbar.phone.LockIcon;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+
 /**
- * Controls the little text indicator on the keyguard.
+ * Controls the indications and error messages shown on the Keyguard
  */
 public class KeyguardIndicationController {
 
@@ -49,6 +52,8 @@
     private static final boolean DEBUG_CHARGING_CURRENT = false;
 
     private static final int MSG_HIDE_TRANSIENT = 1;
+    private static final int MSG_CLEAR_FP_MSG = 2;
+    private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
 
     private final Context mContext;
     private final KeyguardIndicationTextView mTextView;
@@ -56,6 +61,8 @@
 
     private final int mSlowThreshold;
     private final int mFastThreshold;
+    private final LockIcon mLockIcon;
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     private String mRestingIndication;
     private String mTransientIndication;
@@ -66,10 +73,13 @@
     private boolean mPowerCharged;
     private int mChargingSpeed;
     private int mChargingCurrent;
+    private String mMessageToShowOnScreenOn;
 
-    public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView) {
+    public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView,
+                                        LockIcon lockIcon) {
         mContext = context;
         mTextView = textView;
+        mLockIcon = lockIcon;
 
         Resources res = context.getResources();
         mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
@@ -216,6 +226,64 @@
             mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
             updateIndication();
         }
+
+        @Override
+        public void onFingerprintHelp(int msgId, String helpString) {
+            KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+            if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
+                return;
+            }
+            int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+            if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+                mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
+            } else if (updateMonitor.isDeviceInteractive()) {
+                mLockIcon.setTransientFpError(true);
+                showTransientIndication(helpString, errorColor);
+                mHandler.removeMessages(MSG_CLEAR_FP_MSG);
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_FP_MSG),
+                        TRANSIENT_FP_ERROR_TIMEOUT);
+            }
+        }
+
+        @Override
+        public void onFingerprintError(int msgId, String errString) {
+            KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+            if (!updateMonitor.isUnlockingWithFingerprintAllowed()
+                    || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+                return;
+            }
+            int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
+            if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
+                mStatusBarKeyguardViewManager.showBouncerMessage(errString, errorColor);
+            } else if (updateMonitor.isDeviceInteractive()) {
+                    showTransientIndication(errString, errorColor);
+                    // We want to keep this message around in case the screen was off
+                    mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+                    hideTransientIndicationDelayed(5000);
+             } else {
+                    mMessageToShowOnScreenOn = errString;
+            }
+        }
+
+        @Override
+        public void onScreenTurnedOn() {
+            if (mMessageToShowOnScreenOn != null) {
+                int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
+                        null);
+                showTransientIndication(mMessageToShowOnScreenOn, errorColor);
+                // We want to keep this message around in case the screen was off
+                mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+                hideTransientIndicationDelayed(5000);
+                mMessageToShowOnScreenOn = null;
+            }
+        }
+
+        @Override
+        public void onFingerprintRunningStateChanged(boolean running) {
+            if (running) {
+                mMessageToShowOnScreenOn = null;
+            }
+        }
     };
 
     BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -233,7 +301,15 @@
             if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) {
                 mTransientIndication = null;
                 updateIndication();
+            } else if (msg.what == MSG_CLEAR_FP_MSG) {
+                mLockIcon.setTransientFpError(false);
+                hideTransientIndication();
             }
         }
     };
+
+    public void setStatusBarKeyguardViewManager(
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+    }
 }
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 7b67c6c..4878cd92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -29,7 +29,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
-import android.hardware.fingerprint.FingerprintManager;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -86,7 +85,6 @@
     private static final Intent PHONE_INTENT = new Intent(Intent.ACTION_DIAL);
     private static final int DOZE_ANIMATION_STAGGER_DELAY = 48;
     private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250;
-    private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
 
     private KeyguardAffordanceView mCameraImageView;
     private KeyguardAffordanceView mLeftAffordanceView;
@@ -528,7 +526,7 @@
         return mCameraPreview;
     }
 
-    public KeyguardAffordanceView getLockIcon() {
+    public LockIcon getLockIcon() {
         return mLockIcon;
     }
 
@@ -613,21 +611,6 @@
         }
     };
 
-    private final Runnable mTransientFpErrorClearRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mLockIcon.setTransientFpError(false);
-            mIndicationController.hideTransientIndication();
-        }
-    };
-
-    private final Runnable mHideTransientIndicationRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mIndicationController.hideTransientIndication();
-        }
-    };
-
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
             new KeyguardUpdateMonitorCallback() {
         @Override
@@ -661,38 +644,9 @@
         }
 
         @Override
-        public void onFingerprintAuthenticated(int userId, boolean wakeAndUnlocking) {
-        }
-
-        @Override
         public void onFingerprintRunningStateChanged(boolean running) {
             mLockIcon.update();
         }
-
-        @Override
-        public void onFingerprintHelp(int msgId, String helpString) {
-            if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()) {
-                return;
-            }
-            mLockIcon.setTransientFpError(true);
-            mIndicationController.showTransientIndication(helpString,
-                    getResources().getColor(R.color.system_warning_color, null));
-            removeCallbacks(mTransientFpErrorClearRunnable);
-            postDelayed(mTransientFpErrorClearRunnable, TRANSIENT_FP_ERROR_TIMEOUT);
-        }
-
-        @Override
-        public void onFingerprintError(int msgId, String errString) {
-            if (!KeyguardUpdateMonitor.getInstance(mContext).isUnlockingWithFingerprintAllowed()
-                    || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
-                return;
-            }
-            // TODO: Go to bouncer if this is "too many attempts" (lockout) error.
-            mIndicationController.showTransientIndication(errString,
-                    getResources().getColor(R.color.system_warning_color, null));
-            removeCallbacks(mHideTransientIndicationRunnable);
-            postDelayed(mHideTransientIndicationRunnable, 5000);
-        }
     };
 
     public void setKeyguardIndicationController(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index e9b2c61..37f563e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.view.Choreographer;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -103,6 +102,10 @@
         mKeyguardView.showPromptReason(reason);
     }
 
+    public void showMessage(String message, int color) {
+        mKeyguardView.showMessage(message, color);
+    }
+
     private void cancelShowRunnable() {
         DejankUtils.removeCallbacks(mShowRunnable);
         mShowingSoon = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 367ff1a..1649acb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -262,7 +262,7 @@
         mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back);
         mBackLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_land);
         mBackAltIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
-        mBackAltLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime);
+        mBackAltLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_ime_land);
         mRecentIcon = res.getDrawable(R.drawable.ic_sysbar_recent);
         mRecentLandIcon = res.getDrawable(R.drawable.ic_sysbar_recent_land);
     }
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 400f167..453b268 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -785,7 +785,8 @@
         mKeyguardBottomArea.setAssistManager(mAssistManager);
         mKeyguardIndicationController = new KeyguardIndicationController(mContext,
                 (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
-                        R.id.keyguard_indication_text));
+                        R.id.keyguard_indication_text),
+                mKeyguardBottomArea.getLockIcon());
         mKeyguardBottomArea.setKeyguardIndicationController(mKeyguardIndicationController);
 
         // set the inital view visibility
@@ -1031,6 +1032,8 @@
         KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
                 mStatusBarWindow, mStatusBarWindowManager, mScrimController);
+        mKeyguardIndicationController.setStatusBarKeyguardViewManager(
+                mStatusBarKeyguardViewManager);
         mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 44aa780..1bdcf03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -491,4 +491,8 @@
             mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
         }
     }
+
+    public void showBouncerMessage(String message, int color) {
+        mBouncer.showMessage(message, color);
+    }
 }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 30680ed..fa87270 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -2905,9 +2905,9 @@
                             }
                             // Now that we've told the host, push out an update.
                             sendUpdateIntentLocked(provider, appWidgetIds);
-                            providersUpdated = true;
                         }
                     }
+                    providersUpdated = true;
                 }
             }
         }
diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java
index e17ff5c..1f3d61c 100644
--- a/services/core/java/com/android/server/GestureLauncherService.java
+++ b/services/core/java/com/android/server/GestureLauncherService.java
@@ -16,21 +16,26 @@
 
 package com.android.server;
 
+import android.app.ActivityManager;
 import android.app.KeyguardManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.SensorEvent;
 import android.hardware.SensorEventListener;
 import android.hardware.SensorManager;
+import android.os.Handler;
 import android.os.PowerManager;
-import android.os.Vibrator;
 import android.os.PowerManager.WakeLock;
 import android.os.SystemProperties;
+import android.os.Vibrator;
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.util.Slog;
@@ -56,6 +61,8 @@
 
     /** The wake lock held when a gesture is detected. */
     private WakeLock mWakeLock;
+    private boolean mRegistered;
+    private int mUserId;
 
     public GestureLauncherService(Context context) {
         super(context);
@@ -81,9 +88,35 @@
             mWakeLock = powerManager.newWakeLock(
                     PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
                     "GestureLauncherService");
-            if (isCameraLaunchEnabled(resources)) {
-                registerCameraLaunchGesture(resources);
-            }
+            updateCameraRegistered();
+
+            mUserId = ActivityManager.getCurrentUser();
+            mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
+            registerContentObserver();
+        }
+    }
+
+    private void registerContentObserver() {
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.CAMERA_GESTURE_DISABLED),
+                false, mSettingObserver, mUserId);
+    }
+
+    private void updateCameraRegistered() {
+        Resources resources = mContext.getResources();
+        if (isCameraLaunchSettingEnabled(mContext, mUserId)) {
+            registerCameraLaunchGesture(resources);
+        } else {
+            unregisterCameraLaunchGesture();
+        }
+    }
+
+    private void unregisterCameraLaunchGesture() {
+        if (mRegistered) {
+            mRegistered = false;
+            SensorManager sensorManager = (SensorManager) mContext.getSystemService(
+                    Context.SENSOR_SERVICE);
+            sensorManager.unregisterListener(mGestureListener);
         }
     }
 
@@ -91,12 +124,15 @@
      * Registers for the camera launch gesture.
      */
     private void registerCameraLaunchGesture(Resources resources) {
+        if (mRegistered) {
+            return;
+        }
         SensorManager sensorManager = (SensorManager) mContext.getSystemService(
                 Context.SENSOR_SERVICE);
         int cameraLaunchGestureId = resources.getInteger(
                 com.android.internal.R.integer.config_cameraLaunchGestureSensorType);
         if (cameraLaunchGestureId != -1) {
-            boolean registered = false;
+            mRegistered = false;
             String sensorName = resources.getString(
                 com.android.internal.R.string.config_cameraLaunchGestureSensorStringType);
             mCameraLaunchSensor = sensorManager.getDefaultSensor(
@@ -108,7 +144,7 @@
             // makes the code more robust.
             if (mCameraLaunchSensor != null) {
                 if (sensorName.equals(mCameraLaunchSensor.getStringType())) {
-                    registered = sensorManager.registerListener(mGestureListener,
+                    mRegistered = sensorManager.registerListener(mGestureListener,
                             mCameraLaunchSensor, 0);
                 } else {
                     String message = String.format("Wrong configuration. Sensor type and sensor "
@@ -117,12 +153,18 @@
                     throw new RuntimeException(message);
                 }
             }
-            if (DBG) Slog.d(TAG, "Camera launch sensor registered: " + registered);
+            if (DBG) Slog.d(TAG, "Camera launch sensor registered: " + mRegistered);
         } else {
             if (DBG) Slog.d(TAG, "Camera launch sensor is not specified.");
         }
     }
 
+    public static boolean isCameraLaunchSettingEnabled(Context context, int userId) {
+        return isCameraLaunchEnabled(context.getResources())
+                && (Settings.Secure.getIntForUser(context.getContentResolver(),
+                        Settings.Secure.CAMERA_GESTURE_DISABLED, 0, userId) == 0);
+    }
+
     /**
      * Whether to enable the camera launch gesture.
      */
@@ -142,6 +184,26 @@
         return isCameraLaunchEnabled(resources);
     }
 
+    private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
+                mUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                mContext.getContentResolver().unregisterContentObserver(mSettingObserver);
+                registerContentObserver();
+                updateCameraRegistered();
+            }
+        }
+    };
+
+    private final ContentObserver mSettingObserver = new ContentObserver(new Handler()) {
+        public void onChange(boolean selfChange, android.net.Uri uri, int userId) {
+            if (userId == mUserId) {
+                updateCameraRegistered();
+            }
+        }
+    };
+
     private final class GestureEventListener implements SensorEventListener {
         @Override
         public void onSensorChanged(SensorEvent event) {
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4e11070..f9f617e 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -32,7 +32,6 @@
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.InputBindResult;
-import com.android.server.pm.UserManagerService;
 import com.android.server.statusbar.StatusBarManagerService;
 import com.android.server.wm.WindowManagerService;
 
@@ -134,7 +133,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 
@@ -197,10 +195,10 @@
 
     // All known input methods.  mMethodMap also serves as the global
     // lock for this class.
-    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
-    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
+    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<>();
+    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<>();
     private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
-            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
+            new LruCache<>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
     private final InputMethodSubtypeSwitchingController mSwitchingController;
 
     // Used to bring IME service up to visible adjustment while it is being shown.
@@ -277,8 +275,7 @@
         }
     }
 
-    final HashMap<IBinder, ClientState> mClients
-            = new HashMap<IBinder, ClientState>();
+    final HashMap<IBinder, ClientState> mClients = new HashMap<>();
 
     /**
      * Set once the system is ready to run third party code.
@@ -329,8 +326,7 @@
 
     // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
     private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
-            mShortcutInputMethodsAndSubtypes =
-                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
+            mShortcutInputMethodsAndSubtypes = new HashMap<>();
 
     // Was the keyguard locked when this client became current?
     private boolean mCurClientInKeyguard;
@@ -540,7 +536,7 @@
             final String imeId = entry.getKey();
             ArraySet<String> prevSubtypes = prevMap.get(imeId);
             if (prevSubtypes == null) {
-                prevSubtypes = new ArraySet<String>(2);
+                prevSubtypes = new ArraySet<>(2);
                 prevMap.put(imeId, prevSubtypes);
             }
             prevSubtypes.addAll(entry.getValue());
@@ -559,16 +555,15 @@
     static String buildInputMethodsAndSubtypesString(ArrayMap<String, ArraySet<String>> map) {
         // we want to use the canonical InputMethodSettings implementation,
         // so we convert data structures first.
-        List<Pair<String, ArrayList<String>>> imeMap =
-                new ArrayList<Pair<String, ArrayList<String>>>(4);
+        List<Pair<String, ArrayList<String>>> imeMap = new ArrayList<>(4);
         for (ArrayMap.Entry<String, ArraySet<String>> entry : map.entrySet()) {
             final String imeName = entry.getKey();
             final ArraySet<String> subtypeSet = entry.getValue();
-            final ArrayList<String> subtypes = new ArrayList<String>(2);
+            final ArrayList<String> subtypes = new ArrayList<>(2);
             if (subtypeSet != null) {
                 subtypes.addAll(subtypeSet);
             }
-            imeMap.add(new Pair<String, ArrayList<String>>(imeName, subtypes));
+            imeMap.add(new Pair<>(imeName, subtypes));
         }
         return InputMethodSettings.buildInputMethodsSettingString(imeMap);
     }
@@ -576,8 +571,7 @@
     // TODO: Move this method to InputMethodUtils with adding unit tests.
     static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString(
             final String inputMethodsAndSubtypesString) {
-        final ArrayMap<String, ArraySet<String>> imeMap =
-                new ArrayMap<String, ArraySet<String>>();
+        final ArrayMap<String, ArraySet<String>> imeMap = new ArrayMap<>();
         if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
             return imeMap;
         }
@@ -591,7 +585,7 @@
                         typeSplitter,
                         subtypeSplitter);
         for (Pair<String, ArrayList<String>> ime : allImeSettings) {
-            ArraySet<String> subtypes = new ArraySet<String>();
+            ArraySet<String> subtypes = new ArraySet<>();
             if (ime.second != null) {
                 subtypes.addAll(ime.second);
             }
@@ -1166,7 +1160,7 @@
             return Collections.emptyList();
         }
         synchronized (mMethodMap) {
-            return new ArrayList<InputMethodInfo>(mMethodList);
+            return new ArrayList<>(mMethodList);
         }
     }
 
@@ -1190,7 +1184,7 @@
             boolean allowsImplicitlySelectedSubtypes) {
         // TODO: Make this work even for non-current users?
         if (!calledFromValidUser()) {
-            return Collections.<InputMethodSubtype>emptyList();
+            return Collections.emptyList();
         }
         synchronized (mMethodMap) {
             final InputMethodInfo imi;
@@ -1200,7 +1194,7 @@
                 imi = mMethodMap.get(imiId);
             }
             if (imi == null) {
-                return Collections.<InputMethodSubtype>emptyList();
+                return Collections.emptyList();
             }
             return mSettings.getEnabledInputMethodSubtypeListLocked(
                     mContext, imi, allowsImplicitlySelectedSubtypes);
@@ -2898,8 +2892,6 @@
 
         // Use for queryIntentServicesAsUser
         final PackageManager pm = mContext.getPackageManager();
-        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
-        if (disabledSysImes == null) disabledSysImes = "";
 
         final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                 new Intent(InputMethod.SERVICE_INTERFACE),
@@ -2931,10 +2923,7 @@
                 if (DEBUG) {
                     Slog.d(TAG, "Found an input method " + p);
                 }
-
-            } catch (XmlPullParserException e) {
-                Slog.w(TAG, "Unable to load input method " + compName, e);
-            } catch (IOException e) {
+            } catch (XmlPullParserException | IOException e) {
                 Slog.w(TAG, "Unable to load input method " + compName, e);
             }
         }
@@ -3408,8 +3397,7 @@
             }
         }
         if (mostApplicableIMI != null) {
-            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
-                    mostApplicableSubtype);
+            return new Pair<> (mostApplicableIMI, mostApplicableSubtype);
         } else {
             return null;
         }
@@ -3468,23 +3456,12 @@
         return mCurrentSubtype;
     }
 
-    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
-            InputMethodSubtype subtype) {
-        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
-            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
-        } else {
-            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
-            subtypes.add(subtype);
-            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
-        }
-    }
-
     // TODO: We should change the return type from List to List<Parcelable>
     @SuppressWarnings("rawtypes")
     @Override
     public List getShortcutInputMethodsAndSubtypes() {
         synchronized (mMethodMap) {
-            ArrayList<Object> ret = new ArrayList<Object>();
+            ArrayList<Object> ret = new ArrayList<>();
             if (mShortcutInputMethodsAndSubtypes.size() == 0) {
                 // If there are no selected shortcut subtypes, the framework will try to find
                 // the most applicable subtype from all subtypes whose mode is
@@ -3545,7 +3522,7 @@
         private final AtomicFile mAdditionalInputMethodSubtypeFile;
         private final HashMap<String, InputMethodInfo> mMethodMap;
         private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
-                new HashMap<String, List<InputMethodSubtype>>();
+                new HashMap<>();
         public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
             if (methodMap == null) {
                 throw new NullPointerException("methodMap is null");
@@ -3581,7 +3558,7 @@
         public void addInputMethodSubtypes(
                 InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
             synchronized (mMethodMap) {
-                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<>();
                 final int N = additionalSubtypes.length;
                 for (int i = 0; i < N; ++i) {
                     final InputMethodSubtype subtype = additionalSubtypes[i];
@@ -3655,9 +3632,7 @@
                 HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
             if (allSubtypes == null || subtypesFile == null) return;
             allSubtypes.clear();
-            FileInputStream fis = null;
-            try {
-                fis = subtypesFile.openRead();
+            try (final FileInputStream fis = subtypesFile.openRead()) {
                 final XmlPullParser parser = Xml.newPullParser();
                 parser.setInput(fis, StandardCharsets.UTF_8.name());
                 int type = parser.getEventType();
@@ -3682,7 +3657,7 @@
                             Slog.w(TAG, "Invalid imi id found in subtypes.xml");
                             continue;
                         }
-                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
+                        tempSubtypesArray = new ArrayList<>();
                         allSubtypes.put(currentImiId, tempSubtypesArray);
                     } else if (NODE_SUBTYPE.equals(nodeName)) {
                         if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
@@ -3712,23 +3687,9 @@
                         tempSubtypesArray.add(subtype);
                     }
                 }
-            } catch (XmlPullParserException e) {
-                Slog.w(TAG, "Error reading subtypes: " + e);
+            } catch (XmlPullParserException | IOException | NumberFormatException e) {
+                Slog.w(TAG, "Error reading subtypes", e);
                 return;
-            } catch (java.io.IOException e) {
-                Slog.w(TAG, "Error reading subtypes: " + e);
-                return;
-            } catch (NumberFormatException e) {
-                Slog.w(TAG, "Error reading subtypes: " + e);
-                return;
-            } finally {
-                if (fis != null) {
-                    try {
-                        fis.close();
-                    } catch (java.io.IOException e1) {
-                        Slog.w(TAG, "Failed to close.");
-                    }
-                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index aab6374..8b0e6f2 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -283,7 +283,22 @@
                 // Don't delete accounts when updating a authenticator's
                 // package.
                 if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
-                    purgeOldGrantsAll();
+                    /* Purging data requires file io, don't block the main thread. This is probably
+                     * less than ideal because we are introducing a race condition where old grants
+                     * could be exercised until they are purged. But that race condition existed
+                     * anyway with the broadcast receiver.
+                     *
+                     * Ideally, we would completely clear the cache, purge data from the database,
+                     * and then rebuild the cache. All under the cache lock. But that change is too
+                     * large at this point.
+                     */
+                    Runnable r = new Runnable() {
+                        @Override
+                        public void run() {
+                            purgeOldGrantsAll();
+                        }
+                    };
+                    new Thread(r).start();
                 }
             }
         }, intentFilter);
@@ -329,52 +344,6 @@
         return mUserManager;
     }
 
-    /* Caller should lock mUsers */
-    private UserAccounts initUserLocked(int userId) {
-        UserAccounts accounts = mUsers.get(userId);
-        if (accounts == null) {
-            accounts = new UserAccounts(mContext, userId);
-            initializeDebugDbSizeAndCompileSqlStatementForLogging(
-                    accounts.openHelper.getWritableDatabase(), accounts);
-            mUsers.append(userId, accounts);
-            purgeOldGrants(accounts);
-            validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
-        }
-        return accounts;
-    }
-
-    private void purgeOldGrantsAll() {
-        synchronized (mUsers) {
-            for (int i = 0; i < mUsers.size(); i++) {
-                purgeOldGrants(mUsers.valueAt(i));
-            }
-        }
-    }
-
-    private void purgeOldGrants(UserAccounts accounts) {
-        synchronized (accounts.cacheLock) {
-            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
-            final Cursor cursor = db.query(TABLE_GRANTS,
-                    new String[]{GRANTS_GRANTEE_UID},
-                    null, null, GRANTS_GRANTEE_UID, null, null);
-            try {
-                while (cursor.moveToNext()) {
-                    final int uid = cursor.getInt(0);
-                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
-                    if (packageExists) {
-                        continue;
-                    }
-                    Log.d(TAG, "deleting grants for UID " + uid
-                            + " because its package is no longer installed");
-                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
-                            new String[]{Integer.toString(uid)});
-                }
-            } finally {
-                cursor.close();
-            }
-        }
-    }
-
     /**
      * Validate internal set of accounts against installed authenticators for
      * given user. Clears cached authenticators before validating.
@@ -469,13 +438,49 @@
         synchronized (mUsers) {
             UserAccounts accounts = mUsers.get(userId);
             if (accounts == null) {
-                accounts = initUserLocked(userId);
+                accounts = new UserAccounts(mContext, userId);
+                initializeDebugDbSizeAndCompileSqlStatementForLogging(
+                        accounts.openHelper.getWritableDatabase(), accounts);
                 mUsers.append(userId, accounts);
+                purgeOldGrants(accounts);
+                validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */);
             }
             return accounts;
         }
     }
 
+    private void purgeOldGrantsAll() {
+        synchronized (mUsers) {
+            for (int i = 0; i < mUsers.size(); i++) {
+                purgeOldGrants(mUsers.valueAt(i));
+            }
+        }
+    }
+
+    private void purgeOldGrants(UserAccounts accounts) {
+        synchronized (accounts.cacheLock) {
+            final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
+            final Cursor cursor = db.query(TABLE_GRANTS,
+                    new String[]{GRANTS_GRANTEE_UID},
+                    null, null, GRANTS_GRANTEE_UID, null, null);
+            try {
+                while (cursor.moveToNext()) {
+                    final int uid = cursor.getInt(0);
+                    final boolean packageExists = mPackageManager.getPackagesForUid(uid) != null;
+                    if (packageExists) {
+                        continue;
+                    }
+                    Log.d(TAG, "deleting grants for UID " + uid
+                            + " because its package is no longer installed");
+                    db.delete(TABLE_GRANTS, GRANTS_GRANTEE_UID + "=?",
+                            new String[]{Integer.toString(uid)});
+                }
+            } finally {
+                cursor.close();
+            }
+        }
+    }
+
     private void onUserRemoved(Intent intent) {
         int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
         if (userId < 1) return;
@@ -2510,8 +2515,9 @@
         }
         long identityToken = clearCallingIdentity();
         try {
+            UserAccounts accounts = getUserAccounts(userId);
             return getAccountsInternal(
-                    userId,
+                    accounts,
                     callingUid,
                     null,  // packageName
                     visibleAccountTypes);
@@ -2609,8 +2615,9 @@
 
         long identityToken = clearCallingIdentity();
         try {
+            UserAccounts accounts = getUserAccounts(userId);
             return getAccountsInternal(
-                    userId,
+                    accounts,
                     callingUid,
                     callingPackage,
                     visibleAccountTypes);
@@ -2620,13 +2627,11 @@
     }
 
     private Account[] getAccountsInternal(
-            int userId,
+            UserAccounts userAccounts,
             int callingUid,
             String callingPackage,
             List<String> visibleAccountTypes) {
-        UserAccounts accounts = getUserAccounts(userId);
-        synchronized (accounts.cacheLock) {
-            UserAccounts userAccounts = getUserAccounts(userId);
+        synchronized (userAccounts.cacheLock) {
             ArrayList<Account> visibleAccounts = new ArrayList<>();
             for (String visibleType : visibleAccountTypes) {
                 Account[] accountsForType = getAccountsFromCacheLocked(
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b997926..0c6c067 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3800,7 +3800,12 @@
         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId);
 
         boolean prevIsHome = false;
-        if (tr.isOverHomeStack()) {
+
+        // If true, we should resume the home activity next if the task we are moving to the
+        // back is over the home stack. We force to false if the task we are moving to back
+        // is the home task and we don't want it resumed after moving to the back.
+        final boolean canGoHome = !tr.isHomeTask() && tr.isOverHomeStack();
+        if (canGoHome) {
             final TaskRecord nextTask = getNextTask(tr);
             if (nextTask != null) {
                 nextTask.setTaskToReturnTo(tr.getTaskToReturnTo());
@@ -3834,8 +3839,7 @@
         }
 
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
-        if (prevIsHome || task == tr && tr.isOverHomeStack()
-                || numTasks <= 1 && isOnHomeDisplay()) {
+        if (prevIsHome || (task == tr && canGoHome) || (numTasks <= 1 && isOnHomeDisplay())) {
             if (!mService.mBooting && !mService.mBooted) {
                 // Not ready yet!
                 return false;
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index c705fbf..2c9d82b 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -454,6 +454,18 @@
                 "Must have " + permission + " permission.");
     }
 
+    int getEffectiveUserId(int userId) {
+        UserManager um = UserManager.get(mContext);
+        if (um != null) {
+            final long callingIdentity = Binder.clearCallingIdentity();
+            userId = um.getCredentialOwnerProfile(userId);
+            Binder.restoreCallingIdentity(callingIdentity);
+        } else {
+            Slog.e(TAG, "Unable to acquire UserManager");
+        }
+        return userId;
+    }
+
     boolean isCurrentUserOrProfile(int userId) {
         UserManager um = UserManager.get(mContext);
 
@@ -686,11 +698,15 @@
             }
             final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length);
 
+            // Group ID is arbitrarily set to parent profile user ID. It just represents
+            // the default fingerprints for the user.
+            final int effectiveGroupId = getEffectiveUserId(groupId);
+
             final boolean restricted = isRestricted();
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted);
+                    startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted);
                 }
             });
         }
@@ -724,11 +740,16 @@
                 Slog.w(TAG, "Calling not granted permission to use fingerprint");
                 return;
             }
+
+            // Group ID is arbitrarily set to parent profile user ID. It just represents
+            // the default fingerprints for the user.
+            final int effectiveGroupId = getEffectiveUserId(groupId);
+
             final boolean restricted = isRestricted();
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startAuthentication(token, opId, groupId, receiver, flags, restricted);
+                    startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted);
                 }
             });
         }
@@ -751,10 +772,14 @@
                 final IFingerprintServiceReceiver receiver) {
             checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
             final boolean restricted = isRestricted();
+
+            // Group ID is arbitrarily set to parent profile user ID. It just represents
+            // the default fingerprints for the user.
+            final int effectiveGroupId = getEffectiveUserId(groupId);
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    startRemove(token, fingerId, groupId, receiver, restricted);
+                    startRemove(token, fingerId, effectiveGroupId, receiver, restricted);
                 }
             });
 
@@ -771,10 +796,15 @@
         @Override // Binder call
         public void rename(final int fingerId, final int groupId, final String name) {
             checkPermission(MANAGE_FINGERPRINT);
+
+            // Group ID is arbitrarily set to parent profile user ID. It just represents
+            // the default fingerprints for the user.
+            final int effectiveGroupId = getEffectiveUserId(groupId);
             mHandler.post(new Runnable() {
                 @Override
                 public void run() {
-                    mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, groupId, name);
+                    mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
+                            effectiveGroupId, name);
                 }
             });
         }
@@ -784,15 +814,19 @@
             if (!canUseFingerprint(opPackageName)) {
                 return Collections.emptyList();
             }
-            return FingerprintService.this.getEnrolledFingerprints(userId);
+            int effectiveUserId = getEffectiveUserId(userId);
+
+            return FingerprintService.this.getEnrolledFingerprints(effectiveUserId);
         }
 
         @Override // Binder call
-        public boolean hasEnrolledFingerprints(int groupId, String opPackageName) {
+        public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
             if (!canUseFingerprint(opPackageName)) {
                 return false;
             }
-            return FingerprintService.this.hasEnrolledFingerprints(groupId);
+
+            int effectiveUserId  = getEffectiveUserId(userId);
+            return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId);
         }
 
         @Override // Binder call
@@ -829,8 +863,7 @@
         IFingerprintDaemon daemon = getFingerprintDaemon();
         if (daemon != null) {
             try {
-                // TODO: if this is a managed profile, use the profile parent's directory for
-                // storage.
+                userId = getEffectiveUserId(userId);
                 final File systemDir = Environment.getUserSystemDirectory(userId);
                 final File fpDir = new File(systemDir, FP_DATA_DIR);
                 if (!fpDir.exists()) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fcf743e..2b26b42 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -208,7 +208,9 @@
     }
 
     void moveStack(TaskStack stack, boolean toTop) {
-        mStacks.remove(stack);
+        if (!mStacks.remove(stack)) {
+            Slog.wtf(TAG, "moving stack that was not added: " + stack, new Throwable());
+        }
         mStacks.add(toTop ? mStacks.size() : 0, stack);
     }
 
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 90d2593..1c65c27 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -318,8 +318,6 @@
         }
 
         close();
-
-        mDisplayContent = null;
     }
 
     void resetAnimationBackgroundAnimator() {
@@ -358,6 +356,7 @@
         for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
             mTasks.get(taskNdx).close();
         }
+        mDisplayContent = null;
     }
 
     public void dump(String prefix, PrintWriter pw) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6e6c71f..eb64a9d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1022,12 +1022,6 @@
         w.getDefaultDisplay().getMetrics(metrics);
         context.getResources().updateConfiguration(config, metrics);
 
-        // The system context's theme may be configuration-dependent.
-        final Theme systemTheme = context.getTheme();
-        if (systemTheme.getChangingConfigurations() != 0) {
-            systemTheme.rebase();
-        }
-
         try {
             // TODO: use boot phase
             mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 2d40291..9ee9cf4 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -603,7 +603,10 @@
         @Override
         public void exit() {
             cancelOneshotTimeout();
-            mReceiveThread.halt();  // Also closes sockets.
+            if (mReceiveThread != null) {
+                mReceiveThread.halt();  // Also closes sockets.
+                mReceiveThread = null;
+            }
             clearDhcpState();
         }
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 303a492..80515cf 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -220,6 +220,8 @@
     private int mCdmaEriIconIndex;
     private int mCdmaEriIconMode;
 
+    private boolean mIsDataRoamingFromRegistration;
+
     /**
      * get String description of roaming type
      * @hide
@@ -297,6 +299,7 @@
         mCdmaEriIconIndex = s.mCdmaEriIconIndex;
         mCdmaEriIconMode = s.mCdmaEriIconMode;
         mIsEmergencyOnly = s.mIsEmergencyOnly;
+        mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
     }
 
     /**
@@ -324,6 +327,7 @@
         mCdmaEriIconIndex = in.readInt();
         mCdmaEriIconMode = in.readInt();
         mIsEmergencyOnly = in.readInt() != 0;
+        mIsDataRoamingFromRegistration = in.readInt() != 0;
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -348,6 +352,7 @@
         out.writeInt(mCdmaEriIconIndex);
         out.writeInt(mCdmaEriIconMode);
         out.writeInt(mIsEmergencyOnly ? 1 : 0);
+        out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0);
     }
 
     public int describeContents() {
@@ -439,6 +444,26 @@
     }
 
     /**
+     * Set whether data network registration state is roaming
+     *
+     * This should only be set to the roaming value received
+     * once the data registration phase has completed.
+     * @hide
+     */
+    public void setDataRoamingFromRegistration(boolean dataRoaming) {
+        mIsDataRoamingFromRegistration = dataRoaming;
+    }
+
+    /**
+     * Get whether data network registration state is roaming
+     * @return true if registration indicates roaming, false otherwise
+     * @hide
+     */
+    public boolean getDataRoamingFromRegistration() {
+        return mIsDataRoamingFromRegistration;
+    }
+
+    /**
      * Get current data network roaming type
      * @return roaming type
      * @hide
@@ -599,7 +624,8 @@
                 + ((null == mDataOperatorNumeric) ? 0 : mDataOperatorNumeric.hashCode())
                 + mCdmaRoamingIndicator
                 + mCdmaDefaultRoamingIndicator
-                + (mIsEmergencyOnly ? 1 : 0));
+                + (mIsEmergencyOnly ? 1 : 0)
+                + (mIsDataRoamingFromRegistration ? 1 : 0));
     }
 
     @Override
@@ -635,7 +661,8 @@
                 && equalsHandlesNulls(mCdmaRoamingIndicator, s.mCdmaRoamingIndicator)
                 && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
                         s.mCdmaDefaultRoamingIndicator)
-                && mIsEmergencyOnly == s.mIsEmergencyOnly);
+                && mIsEmergencyOnly == s.mIsEmergencyOnly
+                && mIsDataRoamingFromRegistration == s.mIsDataRoamingFromRegistration);
     }
 
     /**
@@ -736,7 +763,8 @@
                 + " " + mSystemId
                 + " RoamInd=" + mCdmaRoamingIndicator
                 + " DefRoamInd=" + mCdmaDefaultRoamingIndicator
-                + " EmergOnly=" + mIsEmergencyOnly);
+                + " EmergOnly=" + mIsEmergencyOnly
+                + " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration);
     }
 
     private void setNullState(int state) {
@@ -762,6 +790,7 @@
         mCdmaEriIconIndex = -1;
         mCdmaEriIconMode = -1;
         mIsEmergencyOnly = false;
+        mIsDataRoamingFromRegistration = false;
     }
 
     public void setStateOutOfService() {
@@ -934,6 +963,7 @@
         mCdmaRoamingIndicator = m.getInt("cdmaRoamingIndicator");
         mCdmaDefaultRoamingIndicator = m.getInt("cdmaDefaultRoamingIndicator");
         mIsEmergencyOnly = m.getBoolean("emergencyOnly");
+        mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
     }
 
     /**
@@ -962,6 +992,7 @@
         m.putInt("cdmaRoamingIndicator", mCdmaRoamingIndicator);
         m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
         m.putBoolean("emergencyOnly", Boolean.valueOf(mIsEmergencyOnly));
+        m.putBoolean("isDataRoamingFromRegistration", Boolean.valueOf(mIsDataRoamingFromRegistration));
     }
 
     /** @hide */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 88612e9..e104b38 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -602,6 +602,46 @@
     public static final String EXTRA_DATA_FAILURE_CAUSE = PhoneConstants.DATA_FAILURE_CAUSE_KEY;
 
     /**
+     * Broadcast intent action for letting custom component know to show voicemail notification.
+     * @hide
+     */
+    @SystemApi
+    public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION =
+            "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
+
+    /**
+     * The number of voice messages associated with the notification.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_NOTIFICATION_COUNT =
+            "android.telephony.extra.NOTIFICATION_COUNT";
+
+    /**
+     * The voicemail number.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_VOICEMAIL_NUMBER =
+            "android.telephony.extra.VOICEMAIL_NUMBER";
+
+    /**
+     * The intent to call voicemail.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_CALL_VOICEMAIL_INTENT =
+            "android.telephony.extra.CALL_VOICEMAIL_INTENT";
+
+    /**
+     * The intent to launch voicemail settings.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_LAUNCH_VOICEMAIL_SETTINGS_INTENT =
+            "android.telephony.extra.LAUNCH_VOICEMAIL_SETTINGS_INTENT";
+
+    /**
      * Response codes for sim activation. Activation completed successfully.
      * @hide
      */
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
index 47258b6..baf2e2e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/DelegateManager.java
@@ -97,13 +97,13 @@
      * @return the delegate or null if not found.
      */
     @Nullable
-    public T getDelegate(long native_object) {
+    public synchronized T getDelegate(long native_object) {
         if (native_object > 0) {
-            T delegate =  mDelegates.get(native_object);
+            T delegate = mDelegates.get(native_object);
 
             if (Debug.DEBUG) {
                 if (delegate == null) {
-                    System.out.println("Unknown " + mClass.getSimpleName() + " with int " +
+                    System.err.println("Unknown " + mClass.getSimpleName() + " with int " +
                             native_object);
                 }
             }
@@ -119,14 +119,18 @@
      * @param newDelegate the delegate to add
      * @return a unique native int to identify the delegate
      */
-    public long addNewDelegate(T newDelegate) {
+    public synchronized long addNewDelegate(T newDelegate) {
         long native_object = ++mDelegateCounter;
+
         mDelegates.put(native_object, newDelegate);
         assert !mJavaReferences.contains(newDelegate);
         mJavaReferences.add(newDelegate);
 
         if (Debug.DEBUG) {
-            System.out.println("New " + mClass.getSimpleName() + " with int " + native_object);
+            System.out.println(
+                    "New " + mClass.getSimpleName() + " " +
+                            "with int " +
+                            native_object);
         }
 
         return native_object;
@@ -136,7 +140,7 @@
      * Removes the main reference on the given delegate.
      * @param native_object the native integer representing the delegate.
      */
-    public void removeJavaReferenceFor(long native_object) {
+    public synchronized void removeJavaReferenceFor(long native_object) {
         T delegate = getDelegate(native_object);
 
         if (Debug.DEBUG) {