Merge "Fix GamepadTestCase#testButtonA CTS test"
diff --git a/Android.bp b/Android.bp
index 4ab5f1f..5c059b5 100644
--- a/Android.bp
+++ b/Android.bp
@@ -28,26 +28,26 @@
             proto: {
                 type: "full",
             },
+            srcs: [
+                "core/proto/**/*.proto",
+                "libs/incident/**/*.proto",
+            ],
         },
         android: {
             proto: {
                 type: "lite",
             },
+            // We only build the protos that are optimized for the lite
+            // runtime, as well as the only protos that are actually
+            // needed by the device.
+            srcs: [
+                "core/proto/android/service/graphicsstats.proto",
+            ],
             shared: {
-                // The proto files generate full protos, but we only use
-                // them as lite on device.  This works fine for a static
-                // library, where the unused full symbols are stripped,
-                // but fails if it is linked as a standalone shared
-                // library because it is missing the full runtime.
                 enabled: false,
             },
         },
     },
-
-    srcs: [
-        "core/proto/**/*.proto",
-        "libs/incident/**/*.proto",
-    ],
 }
 
 subdirs = [
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f6aea96..5bb54c2 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1700,15 +1700,27 @@
 
     @Override
     public int installExistingPackage(String packageName) throws NameNotFoundException {
-        return installExistingPackageAsUser(packageName, mContext.getUserId());
+        return installExistingPackage(packageName, PackageManager.INSTALL_REASON_UNKNOWN);
+    }
+
+    @Override
+    public int installExistingPackage(String packageName, int installReason)
+            throws NameNotFoundException {
+        return installExistingPackageAsUser(packageName, installReason, mContext.getUserId());
     }
 
     @Override
     public int installExistingPackageAsUser(String packageName, int userId)
             throws NameNotFoundException {
+        return installExistingPackageAsUser(packageName, PackageManager.INSTALL_REASON_UNKNOWN,
+                userId);
+    }
+
+    private int installExistingPackageAsUser(String packageName, int installReason, int userId)
+            throws NameNotFoundException {
         try {
             int res = mPM.installExistingPackageAsUser(packageName, userId, 0 /*installFlags*/,
-                    PackageManager.INSTALL_REASON_UNKNOWN);
+                    installReason);
             if (res == INSTALL_FAILED_INVALID_URI) {
                 throw new NameNotFoundException("Package " + packageName + " doesn't exist");
             }
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ccbd5b4..8a15b1f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+
 import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
@@ -42,7 +44,6 @@
 import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.BadParcelableException;
-import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -72,6 +73,7 @@
 import android.widget.RemoteViews;
 
 import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.internal.util.Preconditions;
@@ -2670,6 +2672,19 @@
         private static final boolean USE_ONLY_TITLE_IN_LOW_PRIORITY_SUMMARY =
                 SystemProperties.getBoolean("notifications.only_title", true);
 
+        /**
+         * The lightness difference that has to be added to the primary text color to obtain the
+         * secondary text color when the background is light.
+         */
+        private static final int LIGHTNESS_TEXT_DIFFERENCE_LIGHT = 20;
+
+        /**
+         * The lightness difference that has to be added to the primary text color to obtain the
+         * secondary text color when the background is dark.
+         * A bit less then the above value, since it looks better on dark backgrounds.
+         */
+        private static final int LIGHTNESS_TEXT_DIFFERENCE_DARK = -10;
+
         private Context mContext;
         private Notification mN;
         private Bundle mUserExtras = new Bundle();
@@ -3836,11 +3851,26 @@
             contentView.setTextColor(id, mPrimaryTextColor);
         }
 
-        private int getPrimaryTextColor() {
+        /**
+         * @return the primary text color
+         * @hide
+         */
+        @VisibleForTesting
+        public int getPrimaryTextColor() {
             ensureColors();
             return mPrimaryTextColor;
         }
 
+        /**
+         * @return the secondary text color
+         * @hide
+         */
+        @VisibleForTesting
+        public int getSecondaryTextColor() {
+            ensureColors();
+            return mSecondaryTextColor;
+        }
+
         private int getActionBarColor() {
             ensureColors();
             return mActionBarColor;
@@ -3880,16 +3910,21 @@
                     double textLum = NotificationColorUtil.calculateLuminance(mForegroundColor);
                     double contrast = NotificationColorUtil.calculateContrast(mForegroundColor,
                             backgroundColor);
-                    boolean textDark = backLum > textLum;
+                    // We only respect the given colors if worst case Black or White still has
+                    // contrast
+                    boolean backgroundLight = backLum > textLum
+                                    && satisfiesTextContrast(backgroundColor, Color.BLACK)
+                            || backLum <= textLum
+                                    && !satisfiesTextContrast(backgroundColor, Color.WHITE);
                     if (contrast < 4.5f) {
-                        if (textDark) {
+                        if (backgroundLight) {
                             mSecondaryTextColor = NotificationColorUtil.findContrastColor(
                                     mForegroundColor,
                                     backgroundColor,
                                     true /* findFG */,
                                     4.5f);
                             mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
-                                    mSecondaryTextColor, -20);
+                                    mSecondaryTextColor, -LIGHTNESS_TEXT_DIFFERENCE_LIGHT);
                         } else {
                             mSecondaryTextColor =
                                     NotificationColorUtil.findContrastColorAgainstDark(
@@ -3898,16 +3933,17 @@
                                     true /* findFG */,
                                     4.5f);
                             mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
-                                    mSecondaryTextColor, 10);
+                                    mSecondaryTextColor, -LIGHTNESS_TEXT_DIFFERENCE_DARK);
                         }
                     } else {
                         mPrimaryTextColor = mForegroundColor;
                         mSecondaryTextColor = NotificationColorUtil.changeColorLightness(
-                                mPrimaryTextColor, textDark ? 10 : -20);
+                                mPrimaryTextColor, backgroundLight ? LIGHTNESS_TEXT_DIFFERENCE_LIGHT
+                                        : LIGHTNESS_TEXT_DIFFERENCE_DARK);
                         if (NotificationColorUtil.calculateContrast(mSecondaryTextColor,
                                 backgroundColor) < 4.5f) {
                             // oh well the secondary is not good enough
-                            if (textDark) {
+                            if (backgroundLight) {
                                 mSecondaryTextColor = NotificationColorUtil.findContrastColor(
                                         mSecondaryTextColor,
                                         backgroundColor,
@@ -3922,7 +3958,9 @@
                                         4.5f);
                             }
                             mPrimaryTextColor = NotificationColorUtil.changeColorLightness(
-                                    mSecondaryTextColor, textDark ? -20 : 10);
+                                    mSecondaryTextColor, backgroundLight
+                                            ? -LIGHTNESS_TEXT_DIFFERENCE_LIGHT
+                                            : -LIGHTNESS_TEXT_DIFFERENCE_DARK);
                         }
                     }
                 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 1d5377b..4889c86 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -656,6 +656,8 @@
 
     void deletePreloadsFileCache();
 
+    ComponentName getInstantAppResolverComponent();
+
     ComponentName getInstantAppResolverSettingsComponent();
 
     ComponentName getInstantAppInstallerComponent();
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ca15275..68f0c83 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4666,6 +4666,14 @@
 
     /**
      * If there is already an application with the given package name installed
+     * on the system for other users, also install it for the calling user.
+     * @hide
+     */
+    public abstract int installExistingPackage(String packageName, @InstallReason int installReason)
+            throws NameNotFoundException;
+
+    /**
+     * If there is already an application with the given package name installed
      * on the system for other users, also install it for the specified user.
      * @hide
      */
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index e3e0cc5..f779aeb 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -886,6 +886,11 @@
 
     /**
      * Return the max width for icons, in pixels.
+     *
+     * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
+     * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
+     * to function as {@link AcaptiveIconDrawable}, multiply
+     * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
      */
     public int getIconMaxWidth() {
         try {
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index fccc877..8e57e85 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -118,6 +118,15 @@
      * @hide
      */
     public static final int FINGERPRINT_ERROR_VENDOR = 8;
+
+    /**
+     * The operation was canceled because FINGERPRINT_ERROR_LOCKOUT occurred too many times.
+     * Fingerprint authentication is disabled until the user unlocks with strong authentication
+     * (PIN/Pattern/Password)
+     * @hide
+     */
+    public static final int FINGERPRINT_ERROR_LOCKOUT_PERMANENT = 9;
+
     /**
      * @hide
      */
@@ -871,9 +880,11 @@
                 case MSG_REMOVED:
                     sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
                             msg.arg2 /* groupId */);
+                    break;
                 case MSG_ENUMERATED:
                     sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
                             msg.arg2 /* groupId */);
+                    break;
             }
         }
 
@@ -1013,6 +1024,9 @@
                 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
             case FINGERPRINT_ERROR_LOCKOUT:
                 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
+            case FINGERPRINT_ERROR_LOCKOUT_PERMANENT:
+                return mContext.getString(
+                        com.android.internal.R.string.fingerprint_error_lockout_permanent);
             case FINGERPRINT_ERROR_VENDOR: {
                     String[] msgArray = mContext.getResources().getStringArray(
                             com.android.internal.R.array.fingerprint_error_vendor);
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 6c01b36..fa96dd3 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import com.android.internal.os.Zygote;
+
 import dalvik.annotation.optimization.FastNative;
 
 /**
@@ -94,6 +96,8 @@
     // Must be volatile to avoid word tearing.
     private static volatile long sEnabledTags = TRACE_TAG_NOT_READY;
 
+    private static int sZygoteDebugFlags = 0;
+
     private static native long nativeGetEnabledTags();
     private static native void nativeSetAppTracingAllowed(boolean allowed);
     private static native void nativeSetTracingEnabled(boolean allowed);
@@ -118,9 +122,10 @@
         // The system provides ordering through a priority level.  Callbacks made through
         // SystemProperties.addChangeCallback currently have a negative priority, while
         // our native code is using a priority of zero.
-        SystemProperties.addChangeCallback(new Runnable() {
-            @Override public void run() {
-                cacheEnabledTags();
+        SystemProperties.addChangeCallback(() -> {
+            cacheEnabledTags();
+            if ((sZygoteDebugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
+                traceCounter(TRACE_TAG_ALWAYS, "java_debuggable", 1);
             }
         });
     }
@@ -201,8 +206,9 @@
      *
      * @hide
      */
-    public static void setTracingEnabled(boolean enabled) {
+    public static void setTracingEnabled(boolean enabled, int debugFlags) {
         nativeSetTracingEnabled(enabled);
+        sZygoteDebugFlags = debugFlags;
 
         // Setting whether tracing is enabled may change the tags, so we update the cached tags
         // here.
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f2df7da..7bd3bf6 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -19,6 +19,7 @@
 import android.Manifest;
 import android.accounts.AccountManager;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
@@ -2129,7 +2130,7 @@
      * @return the list of users that were created.
      * @hide
      */
-    public List<UserInfo> getUsers(boolean excludeDying) {
+    public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
         try {
             return mService.getUsers(excludeDying);
         } catch (RemoteException re) {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 5f72fc7..290d811 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -624,8 +624,14 @@
                     return new Intent(Intent.ACTION_VIEW)
                             .setData(Uri.parse(String.format("geo:0,0?q=%s", text)));
                 case TextClassifier.TYPE_URL:
-                    if (!text.startsWith("https://") && !text.startsWith("http://")) {
-                        text = "http://" + text;
+                    final String httpPrefix = "http://";
+                    final String httpsPrefix = "https://";
+                    if (text.toLowerCase().startsWith(httpPrefix)) {
+                        text = httpPrefix + text.substring(httpPrefix.length());
+                    } else if (text.toLowerCase().startsWith(httpsPrefix)) {
+                        text = httpsPrefix + text.substring(httpsPrefix.length());
+                    } else {
+                        text = httpPrefix + text;
                     }
                     return new Intent(Intent.ACTION_VIEW, Uri.parse(text))
                             .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index bb658c1..1fef7cb 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -2016,7 +2016,7 @@
     /**
      * Asynchronously invalidates an action mode using the TextClassifier.
      */
-    private void invalidateActionModeAsync() {
+    void invalidateActionModeAsync() {
         getSelectionActionModeHelper().invalidateActionModeAsync();
     }
 
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 59fb02d..8464c6e 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1667,32 +1667,17 @@
             int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
             int displayFrameBottom, boolean allowResize) {
         final int winOffsetY = screenLocationY - drawingLocationY;
-        final int popupScreenTop = outParams.y + winOffsetY;
-        final int spaceBelow = displayFrameBottom - popupScreenTop;
-        if (popupScreenTop >= 0 && height <= spaceBelow) {
+        final int anchorTopInScreen = outParams.y + winOffsetY;
+        final int spaceBelow = displayFrameBottom - anchorTopInScreen;
+        if (anchorTopInScreen >= 0 && height <= spaceBelow) {
             return true;
         }
 
-        final int popupScreenBottom;
-        if (mOverlapAnchor) {
-            // popupScreenTop equals the anchor's top at this point.
-            // When shown above the anchor, an overlapping popup's bottom should be aligned with
-            // the anchor's bottom.
-            popupScreenBottom = popupScreenTop + anchorHeight;
-        } else {
-            // popupScreenTop equals the anchor's bottom at this point.
-            // When shown above the anchor, a non-overlapping popup's bottom is aligned with
-            // the anchor's top.
-            popupScreenBottom = popupScreenTop - anchorHeight;
-        }
-        final int spaceAbove = popupScreenBottom - displayFrameTop;
+        final int spaceAbove = anchorTopInScreen - anchorHeight - displayFrameTop;
         if (height <= spaceAbove) {
             // Move everything up.
             if (mOverlapAnchor) {
-                // Add one anchorHeight to compensate for the correction made at the start of
-                // findDropDownPosition, and another to account for being aligned to the anchor's
-                // bottom, not top.
-                yOffset += anchorHeight * 2;
+                yOffset += anchorHeight;
             }
             outParams.y = drawingLocationY - height + yOffset;
 
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 89182b0..3d54fe7 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -400,6 +400,7 @@
                 CharSequence text, int selectionStart, int selectionEnd, LocaleList locales) {
             mTextClassifier = Preconditions.checkNotNull(textClassifier);
             mText = Preconditions.checkNotNull(text).toString();
+            mLastClassificationText = null; // invalidate.
             Preconditions.checkArgument(selectionEnd > selectionStart);
             mSelectionStart = selectionStart;
             mSelectionEnd = selectionEnd;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1f54c84..77f27d9 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1639,12 +1639,21 @@
         boolean canInputOrMove = (mMovement != null || getKeyListener() != null);
         boolean clickable = canInputOrMove || isClickable();
         boolean longClickable = canInputOrMove || isLongClickable();
+        int focusable = getFocusable();
 
         n = a.getIndexCount();
         for (int i = 0; i < n; i++) {
             int attr = a.getIndex(i);
 
             switch (attr) {
+                case com.android.internal.R.styleable.View_focusable:
+                    TypedValue val = new TypedValue();
+                    if (a.getValue(attr, val)) {
+                        focusable = (val.type == TypedValue.TYPE_INT_BOOLEAN)
+                                ? (val.data == 0 ? NOT_FOCUSABLE : FOCUSABLE)
+                                : val.data;
+                    }
+
                 case com.android.internal.R.styleable.View_clickable:
                     clickable = a.getBoolean(attr, clickable);
                     break;
@@ -1656,6 +1665,13 @@
         }
         a.recycle();
 
+        // Some apps were relying on the undefined behavior of focusable winning over
+        // focusableInTouchMode != focusable in TextViews if both were specified in XML (usually
+        // when starting with EditText and setting only focusable=false). To keep those apps from
+        // breaking, re-apply the focusable attribute here.
+        if (focusable != getFocusable()) {
+            setFocusable(focusable);
+        }
         setClickable(clickable);
         setLongClickable(longClickable);
 
@@ -10756,7 +10772,11 @@
 
         switch (id) {
             case ID_SELECT_ALL:
+                final boolean hadSelection = hasSelection();
                 selectAllText();
+                if (mEditor != null && hadSelection) {
+                    mEditor.invalidateActionModeAsync();
+                }
                 return true;
 
             case ID_UNDO:
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 373f4bb..78566df 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -132,7 +132,7 @@
     void noteBleScanStarted(in WorkSource ws);
     void noteBleScanStopped(in WorkSource ws);
     void noteResetBleScan();
-    void noteBleScanResult(in WorkSource ws);
+    void noteBleScanResults(in WorkSource ws, int numNewResults);
 
     HealthStatsParceler takeUidSnapshot(int uid);
     HealthStatsParceler[] takeUidSnapshots(in int[] uid);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 5c6a1b2..20cc419 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -936,6 +936,10 @@
             mCount.incrementAndGet();
         }
 
+        void addAtomic(int delta) {
+            mCount.addAndGet(delta);
+        }
+
         /**
          * Clear state of this counter.
          */
@@ -4842,11 +4846,11 @@
         }
     }
 
-    public void noteBluetoothScanResultFromSourceLocked(WorkSource ws) {
+    public void noteBluetoothScanResultsFromSourceLocked(WorkSource ws, int numNewResults) {
         final int N = ws.size();
         for (int i = 0; i < N; i++) {
             int uid = mapUid(ws.get(i));
-            getUidStatsLocked(uid).noteBluetoothScanResultLocked();
+            getUidStatsLocked(uid).noteBluetoothScanResultsLocked(numNewResults);
         }
     }
 
@@ -6057,8 +6061,8 @@
             return mBluetoothScanResultCounter;
         }
 
-        public void noteBluetoothScanResultLocked() {
-            createBluetoothScanResultCounterLocked().stepAtomic();
+        public void noteBluetoothScanResultsLocked(int numNewResults) {
+            createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
         }
 
         @Override
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index e065843..5eca496 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -107,7 +107,7 @@
                   fdsToIgnore, instructionSet, appDataDir);
         // Enable tracing as soon as possible for the child process.
         if (pid == 0) {
-            Trace.setTracingEnabled(true);
+            Trace.setTracingEnabled(true, debugFlags);
 
             // Note that this event ends at the end of handleChildProc,
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -152,7 +152,7 @@
                 uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
         // Enable tracing as soon as we enter the system_server.
         if (pid == 0) {
-            Trace.setTracingEnabled(true);
+            Trace.setTracingEnabled(true, debugFlags);
         }
         VM_HOOKS.postForkCommon();
         return pid;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 4ce6ec5..9e61a99 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -745,7 +745,7 @@
             bootTimingsTraceLog.traceEnd(); // ZygoteInit
             // Disable tracing so that forked processes do not inherit stale tracing tags from
             // Zygote.
-            Trace.setTracingEnabled(false);
+            Trace.setTracingEnabled(false, 0);
 
             // Zygote process unmounts root storage spaces.
             Zygote.nativeUnmountStorageOnInit();
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index cd41f9e..1ba92bf 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -533,6 +533,10 @@
         return ColorUtilsFromCompat.calculateContrast(foregroundColor, backgroundColor);
     }
 
+    public static boolean satisfiesTextContrast(int backgroundColor, int foregroundColor) {
+        return NotificationColorUtil.calculateContrast(backgroundColor, foregroundColor) >= 4.5;
+    }
+
     /**
      * Composite two potentially translucent colors over each other and returns the result.
      */
@@ -540,6 +544,10 @@
         return ColorUtilsFromCompat.compositeColors(foreground, background);
     }
 
+    public static boolean isColorLight(int backgroundColor) {
+        return calculateLuminance(backgroundColor) > 0.5f;
+    }
+
     /**
      * Framework copy of functions needed from android.support.v4.graphics.ColorUtils.
      */
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 2042bf62..0ee71bd 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -22,7 +22,6 @@
 import "frameworks/base/libs/incident/proto/android/privacy.proto";
 import "frameworks/base/core/proto/android/service/appwidget.proto";
 import "frameworks/base/core/proto/android/service/battery.proto";
-import "frameworks/base/core/proto/android/service/graphicsstats.proto";
 import "frameworks/base/core/proto/android/service/fingerprint.proto";
 import "frameworks/base/core/proto/android/service/diskstats.proto";
 import "frameworks/base/core/proto/android/service/netstats.proto";
@@ -66,5 +65,4 @@
     android.service.notification.NotificationServiceDumpProto notification = 3004;
     android.service.pm.PackageServiceDumpProto package = 3008;
     android.service.power.PowerServiceDumpProto power = 3009;
-    android.service.GraphicsStatsServiceDumpProto graphicsstats = 3005;
 }
diff --git a/core/proto/android/service/fingerprint.proto b/core/proto/android/service/fingerprint.proto
index 79dba86..f88b762 100644
--- a/core/proto/android/service/fingerprint.proto
+++ b/core/proto/android/service/fingerprint.proto
@@ -54,4 +54,7 @@
 
     // Total number of lockouts.
     int32 lockout = 4;
+
+    // Total number of permanent lockouts.
+    int32 lockout_permanent = 5;
 }
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index 6dbfe48..b8679b0 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -20,6 +20,7 @@
 
 option java_multiple_files = true;
 option java_outer_classname = "GraphicsStatsServiceProto";
+option optimize_for = LITE_RUNTIME;
 
 message GraphicsStatsServiceDumpProto {
     repeated GraphicsStatsProto stats = 1;
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 21ab4c3..76310b8 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1335,6 +1335,8 @@
     <string name="fingerprint_error_canceled">Fingerprint operation canceled.</string>
     <!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
     <string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
+    <!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
+    <string name="fingerprint_error_lockout_permanent">Too many attempts. Fingerprint sensor disabled.</string>
     <!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
     <string name="fingerprint_error_unable_to_process">Try again.</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 16e933a..18c18a8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2289,6 +2289,7 @@
   <java-symbol type="array" name="fingerprint_acquired_vendor" />
   <java-symbol type="string" name="fingerprint_error_canceled" />
   <java-symbol type="string" name="fingerprint_error_lockout" />
+  <java-symbol type="string" name="fingerprint_error_lockout_permanent" />
   <java-symbol type="string" name="fingerprint_name_template" />
 
   <!-- Fingerprint config -->
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
new file mode 100644
index 0000000..ac1ac19
--- /dev/null
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.app;
+
+import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.media.session.MediaSession;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.NotificationColorUtil;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NotificationTest {
+
+    private Context mContext;
+
+    @Before
+    public void setUp() {
+        mContext = InstrumentationRegistry.getContext();
+    }
+
+    @Test
+    public void testColorSatisfiedWhenBgDarkTextDarker() {
+        Notification.Builder builder = getMediaNotification();
+        builder.build();
+
+        // An initial guess where the foreground color is actually darker than an already dark bg
+        int backgroundColor = 0xff585868;
+        int initialForegroundColor = 0xff505868;
+        builder.setColorPalette(backgroundColor, initialForegroundColor);
+        int primaryTextColor = builder.getPrimaryTextColor();
+        assertTrue(satisfiesTextContrast(primaryTextColor, backgroundColor));
+        int secondaryTextColor = builder.getSecondaryTextColor();
+        assertTrue(satisfiesTextContrast(secondaryTextColor, backgroundColor));
+    }
+
+    private Notification.Builder getMediaNotification() {
+        MediaSession session = new MediaSession(mContext, "test");
+        return new Notification.Builder(mContext, "color")
+                .setSmallIcon(com.android.internal.R.drawable.emergency_icon)
+                .setContentTitle("Title")
+                .setContentText("Text")
+                .setStyle(new Notification.MediaStyle().setMediaSession(session.getSessionToken()));
+    }
+}
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index 7b7031b..29447ed 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -124,19 +124,40 @@
         int startIndex = text.indexOf(classifiedText);
         int endIndex = startIndex + classifiedText.length();
         assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
-                isTextClassification(classifiedText, TextClassifier.TYPE_EMAIL));
+                isTextClassification(
+                        classifiedText,
+                        TextClassifier.TYPE_EMAIL,
+                        "mailto:" + classifiedText));
     }
 
     @Test
     public void testTextClassifyText_url() {
         if (isTextClassifierDisabled()) return;
 
-        String text = "Visit http://www.android.com for more information";
+        String text = "Visit www.android.com for more information";
         String classifiedText = "www.android.com";
         int startIndex = text.indexOf(classifiedText);
         int endIndex = startIndex + classifiedText.length();
         assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
-                isTextClassification(classifiedText, TextClassifier.TYPE_URL));
+                isTextClassification(
+                        classifiedText,
+                        TextClassifier.TYPE_URL,
+                        "http://" + classifiedText));
+    }
+
+    @Test
+    public void testTextClassifyText_url_inCaps() {
+        if (isTextClassifierDisabled()) return;
+
+        String text = "Visit HTTP://ANDROID.COM for more information";
+        String classifiedText = "HTTP://ANDROID.COM";
+        int startIndex = text.indexOf(classifiedText);
+        int endIndex = startIndex + classifiedText.length();
+        assertThat(mClassifier.classifyText(text, startIndex, endIndex, LOCALES),
+                isTextClassification(
+                        classifiedText,
+                        TextClassifier.TYPE_URL,
+                        "http://ANDROID.COM"));
     }
 
     @Test
@@ -149,7 +170,10 @@
         int endIndex = startIndex + classifiedText.length();
         LocaleList nullLocales = null;
         assertThat(mClassifier.classifyText(text, startIndex, endIndex, nullLocales),
-                isTextClassification(classifiedText, TextClassifier.TYPE_EMAIL));
+                isTextClassification(
+                        classifiedText,
+                        TextClassifier.TYPE_EMAIL,
+                        "mailto:" + classifiedText));
     }
 
     @Test
@@ -206,18 +230,23 @@
     }
 
     private static Matcher<TextClassification> isTextClassification(
-            final String text, final String type) {
+            final String text, final String type, final String intentUri) {
         return new BaseMatcher<TextClassification>() {
             @Override
             public boolean matches(Object o) {
                 if (o instanceof TextClassification) {
                     TextClassification result = (TextClassification) o;
                     final boolean typeRequirementSatisfied;
+                    String scheme;
                     switch (type) {
+                        case TextClassifier.TYPE_EMAIL:
+                            scheme = result.getIntent().getData().getScheme();
+                            typeRequirementSatisfied = "mailto".equals(scheme);
+                            break;
                         case TextClassifier.TYPE_URL:
-                            String scheme = result.getIntent().getData().getScheme();
-                            typeRequirementSatisfied = "http".equalsIgnoreCase(scheme)
-                                    || "https".equalsIgnoreCase(scheme);
+                            scheme = result.getIntent().getData().getScheme();
+                            typeRequirementSatisfied = "http".equals(scheme)
+                                    || "https".equals(scheme);
                             break;
                         default:
                             typeRequirementSatisfied = true;
@@ -226,7 +255,8 @@
                     return typeRequirementSatisfied
                             && text.equals(result.getText())
                             && result.getEntityCount() > 0
-                            && type.equals(result.getEntity(0));
+                            && type.equals(result.getEntity(0))
+                            && intentUri.equals(result.getIntent().getDataString());
                     // TODO: Include other properties.
                 }
                 return false;
@@ -235,7 +265,8 @@
             @Override
             public void describeTo(Description description) {
                 description.appendText("text=").appendValue(text)
-                        .appendText(", type=").appendValue(type);
+                        .appendText(", type=").appendValue(type)
+                        .appendText(", intent.data=").appendValue(intentUri);
             }
         };
     }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 1dced75..e374e11 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -29,15 +29,15 @@
     private static final int UID = 10500;
     private static final WorkSource WS = new WorkSource(UID);
 
-    /** Test that BatteryStatsImpl.Uid.noteBluetoothScanResultLocked. */
+    /** Test that BatteryStatsImpl.Uid.noteBluetoothScanResultsLocked. */
     @SmallTest
     public void testNoteBluetoothScanResultLocked() throws Exception {
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks());
         bi.updateTimeBasesLocked(true, true, 0, 0);
 
-        bi.noteBluetoothScanResultFromSourceLocked(WS);
-        bi.noteBluetoothScanResultFromSourceLocked(WS);
-        assertEquals(2,
+        bi.noteBluetoothScanResultsFromSourceLocked(WS, 1);
+        bi.noteBluetoothScanResultsFromSourceLocked(WS, 100);
+        assertEquals(101,
                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
                         .getCountLocked(STATS_SINCE_CHARGED));
     }
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index acf8883..07ff27d 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -62,7 +62,7 @@
         "libskia",
         "libui",
         "libgui",
-        "libprotobuf-cpp-full",
+        "libprotobuf-cpp-lite",
         "libharfbuzz_ng",
         "libft2",
         "libminikin",
diff --git a/libs/hwui/service/GraphicsStatsService.cpp b/libs/hwui/service/GraphicsStatsService.cpp
index ab6420e..87eaa6a 100644
--- a/libs/hwui/service/GraphicsStatsService.cpp
+++ b/libs/hwui/service/GraphicsStatsService.cpp
@@ -19,7 +19,7 @@
 #include "JankTracker.h"
 
 #include <frameworks/base/core/proto/android/service/graphicsstats.pb.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
 #include <log/log.h>
 
 #include <inttypes.h>
@@ -27,6 +27,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <sys/mman.h>
 
 namespace android {
 namespace uirenderer {
@@ -46,10 +47,74 @@
         const ProfileData* data);
 static void dumpAsTextToFd(service::GraphicsStatsProto* proto, int outFd);
 
+class FileDescriptor {
+public:
+    FileDescriptor(int fd) : mFd(fd) {}
+    ~FileDescriptor() {
+        if (mFd != -1) {
+            close(mFd);
+            mFd = -1;
+        }
+    }
+    bool valid() { return mFd != -1; }
+    operator int() { return mFd; }
+private:
+    int mFd;
+};
+
+class FileOutputStreamLite : public io::ZeroCopyOutputStream {
+public:
+    FileOutputStreamLite(int fd) : mCopyAdapter(fd), mImpl(&mCopyAdapter) {}
+    virtual ~FileOutputStreamLite() {}
+
+    int GetErrno() { return mCopyAdapter.mErrno; }
+
+    virtual bool Next(void** data, int* size) override {
+        return mImpl.Next(data, size);
+    }
+
+    virtual void BackUp(int count) override {
+        mImpl.BackUp(count);
+    }
+
+    virtual int64 ByteCount() const override {
+        return mImpl.ByteCount();
+    }
+
+    bool Flush() {
+        return mImpl.Flush();
+    }
+
+private:
+    struct FDAdapter : public io::CopyingOutputStream {
+        int mFd;
+        int mErrno = 0;
+
+        FDAdapter(int fd) : mFd(fd) {}
+        virtual ~FDAdapter() {}
+
+        virtual bool Write(const void* buffer, int size) override {
+            int ret;
+            while (size) {
+                ret = TEMP_FAILURE_RETRY( write(mFd, buffer, size) );
+                if (ret <= 0) {
+                    mErrno = errno;
+                    return false;
+                }
+                size -= ret;
+            }
+            return true;
+        }
+    };
+
+    FileOutputStreamLite::FDAdapter mCopyAdapter;
+    io::CopyingOutputStreamAdaptor mImpl;
+};
+
 bool GraphicsStatsService::parseFromFile(const std::string& path, service::GraphicsStatsProto* output) {
 
-    int fd = open(path.c_str(), O_RDONLY);
-    if (fd == -1) {
+    FileDescriptor fd{open(path.c_str(), O_RDONLY)};
+    if (!fd.valid()) {
         int err = errno;
         // The file not existing is normal for addToDump(), so only log if
         // we get an unexpected error
@@ -58,26 +123,41 @@
         }
         return false;
     }
-    uint32_t file_version;
-    ssize_t bytesRead = read(fd, &file_version, sHeaderSize);
-    if (bytesRead != sHeaderSize || file_version != sCurrentFileVersion) {
-        ALOGW("Failed to read '%s', bytesRead=%zd file_version=%d", path.c_str(), bytesRead,
-                file_version);
-        close(fd);
+    struct stat sb;
+    if (fstat(fd, &sb) || sb.st_size < sHeaderSize) {
+        int err = errno;
+        // The file not existing is normal for addToDump(), so only log if
+        // we get an unexpected error
+        if (err != ENOENT) {
+            ALOGW("Failed to fstat '%s', errno=%d (%s) (st_size %d)", path.c_str(), err,
+                    strerror(err), (int) sb.st_size);
+        }
+        return false;
+    }
+    void* addr = mmap(nullptr, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
+    if (!addr) {
+        int err = errno;
+        // The file not existing is normal for addToDump(), so only log if
+        // we get an unexpected error
+        if (err != ENOENT) {
+            ALOGW("Failed to mmap '%s', errno=%d (%s)", path.c_str(), err, strerror(err));
+        }
+        return false;
+    }
+    uint32_t file_version = *reinterpret_cast<uint32_t*>(addr);
+    if (file_version != sCurrentFileVersion) {
+        ALOGW("file_version mismatch! expected %d got %d", sCurrentFileVersion, file_version);
         return false;
     }
 
-    io::FileInputStream input(fd);
+    void* data = reinterpret_cast<uint8_t*>(addr) + sHeaderSize;
+    int dataSize = sb.st_size - sHeaderSize;
+    io::ArrayInputStream input{data, dataSize};
     bool success = output->ParseFromZeroCopyStream(&input);
-    if (input.GetErrno() != 0) {
-        ALOGW("Error reading from fd=%d, path='%s' err=%d (%s)",
-                fd, path.c_str(), input.GetErrno(), strerror(input.GetErrno()));
-        success = false;
-    } else if (!success) {
+    if (!success) {
         ALOGW("Parse failed on '%s' error='%s'",
                 path.c_str(), output->InitializationErrorString().c_str());
     }
-    close(fd);
     return success;
 }
 
@@ -212,7 +292,7 @@
         return;
     }
     {
-        io::FileOutputStream output(outFd);
+        FileOutputStreamLite output(outFd);
         bool success = statsProto.SerializeToZeroCopyStream(&output) && output.Flush();
         if (output.GetErrno() != 0) {
             ALOGW("Error writing to fd=%d, path='%s' err=%d (%s)",
@@ -277,7 +357,7 @@
 
 void GraphicsStatsService::finishDump(Dump* dump) {
     if (dump->type() == DumpType::Protobuf) {
-        io::FileOutputStream stream(dump->fd());
+        FileOutputStreamLite stream(dump->fd());
         dump->proto().SerializeToZeroCopyStream(&stream);
     }
     delete dump;
diff --git a/libs/hwui/tests/unit/FontRendererTests.cpp b/libs/hwui/tests/unit/FontRendererTests.cpp
index 773a7ea..ee20236 100644
--- a/libs/hwui/tests/unit/FontRendererTests.cpp
+++ b/libs/hwui/tests/unit/FontRendererTests.cpp
@@ -28,7 +28,7 @@
     return true;
 }
 
-RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, DISABLED_renderDropShadow) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(FontRenderer, renderDropShadow) {
     SkPaint paint;
     paint.setTextSize(10);
     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
diff --git a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
index 5383e57..8312bda 100644
--- a/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
+++ b/libs/hwui/tests/unit/TextDropShadowCacheTests.cpp
@@ -26,7 +26,7 @@
 using namespace android;
 using namespace android::uirenderer;
 
-RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, DISABLED_addRemove) {
+RENDERTHREAD_OPENGL_PIPELINE_TEST(TextDropShadowCache, addRemove) {
     SkPaint paint;
     paint.setTextSize(20);
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java b/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java
index 766c42b..d9f4c44 100644
--- a/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java
+++ b/packages/SettingsLib/src/com/android/settingslib/SecureTouchListener.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 package com.android.settingslib;
 
 import android.os.SystemClock;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index e3ef873..d43b740 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -63,6 +63,7 @@
     <uses-permission android:name="android.permission.OVERRIDE_WIFI_CONFIG" />
     <uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
     <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <uses-permission android:name="android.permission.NETWORK_SETTINGS" />
     <uses-permission android:name="android.permission.TETHER_PRIVILEGED" />
     <uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
     <uses-permission android:name="android.permission.REQUEST_NETWORK_SCORES" />
diff --git a/packages/SystemUI/res/drawable/pip_expand.xml b/packages/SystemUI/res/drawable/pip_expand.xml
new file mode 100644
index 0000000..cdb2ee5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/pip_expand.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2017 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="36dp"
+    android:height="36dp"
+    android:viewportWidth="36"
+    android:viewportHeight="36">
+
+    <path
+        android:pathData="M0 0h36v36H0z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M10 21H7v8h8v-3h-5v-5zm-3-6h3v-5h5V7H7v8zm19 11h-5v3h8v-8h-3v5zM21
+7v3h5v5h3V7h-8z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_ll.xml b/packages/SystemUI/res/drawable/pip_expand_ll.xml
deleted file mode 100644
index a8b82b5..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_ll.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="60dp"
-    android:height="60dp"
-    android:viewportWidth="60"
-    android:viewportHeight="60">
-
-    <path
-        android:fillColor="#fff"
-        android:pathData="M7.5,52h45a5,5,0,0,0,5-5V12.95A5,5,0,0,0,52.5,8H7.5a5,5,0,0,0-5,4.95V47A5,5,0,0,0,7.5,52Zm-1-5V13a1,1,0,0,1,1-1h45a1,1,0,0,1,1,1V47a1,1,0,0,1-1,1H7.5A1,1,0,0,1,6.5,47Z" />
-    <path
-        android:pathData="M0,0V60H60V0H0Z" />
-    <path
-        android:fillColor="#fff"
-        android:pathData="M35,39.14v2a1,1,0,0,0,1,1H46.5a1,1,0,0,0,1-1V30.64a1,1,0,0,0-1-1h-2a1,1,0,0,0-1,1v7.5H36A1,1,0,0,0,35,39.14Z" />
-    <path
-        android:fillColor="#fff"
-        android:pathData="M13.5,30.36h2a1,1,0,0,0,1-1v-7.5H24a1,1,0,0,0,1-1v-2a1,1,0,0,0-1-1H13.5a1,1,0,0,0-1,1v10.5A1,1,0,0,0,13.5,30.36Z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_lr.xml b/packages/SystemUI/res/drawable/pip_expand_lr.xml
deleted file mode 100644
index 44d97ef..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_lr.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="60dp"
-    android:height="60dp"
-    android:viewportWidth="60"
-    android:viewportHeight="60">
-
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M57.5,47V12.95c0-2.75-2.25-4.95-5-4.95h-45c-2.75,0-5,2.2-5,4.95V47c0,2.75,2.25,5,5,5h45
-C55.25,52,57.5,49.75,57.5,47z
-M52.5,48h-45c-0.55,0-1-0.45-1-1V13c0-0.55,0.45-1,1-1h45c0.55,0,1,0.45,1,1v34
-C53.5,47.55,53.05,48,52.5,48z" />
-    <path
-        android:pathData="M60,0v60H0L0,0L60,0z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M25,39.14v2c0,0.55-0.45,1-1,1H13.5c-0.55,0-1-0.45-1-1v-10.5c0-0.55,0.45-1,1-1h2c0.55,0,1,0.45,1,1v7.5
-H24C24.55,38.14,25,38.59,25,39.14z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M46.5,30.36h-2c-0.55,0-1-0.45-1-1v-7.5H36c-0.55,0-1-0.45-1-1v-2c0-0.55,0.45-1,1-1h10.5
-c0.55,0,1,0.45,1,1v10.5C47.5,29.91,47.05,30.36,46.5,30.36z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_pl.xml b/packages/SystemUI/res/drawable/pip_expand_pl.xml
deleted file mode 100644
index 57b9358..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_pl.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="60dp"
-    android:height="60dp"
-    android:viewportWidth="60"
-    android:viewportHeight="60">
-
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M47,2.5H12.95C10.2,2.5,8,4.75,8,7.5v45c0,2.75,2.2,5,4.95,5H47c2.75,0,5-2.25,5-5v-45
-C52,4.75,49.75,2.5,47,2.5z
-M48,7.5v45c0,0.55-0.45,1-1,1H13c-0.55,0-1-0.45-1-1v-45c0-0.55,0.45-1,1-1h34
-C47.55,6.5,48,6.95,48,7.5z" />
-    <path
-        android:pathData="M0,0l60,0v60H0L0,0z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M39.14,35h2c0.55,0,1,0.45,1,1v10.5c0,0.55-0.45,1-1,1h-10.5c-0.55,0-1-0.45-1-1v-2c0-0.55,0.45-1,1-1h7.5
-V36C38.14,35.45,38.59,35,39.14,35z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M30.36,13.5v2c0,0.55-0.45,1-1,1h-7.5V24c0,0.55-0.45,1-1,1h-2c-0.55,0-1-0.45-1-1V13.5c0-0.55,0.45-1,1-1
-h10.5C29.91,12.5,30.36,12.95,30.36,13.5z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pip_expand_pr.xml b/packages/SystemUI/res/drawable/pip_expand_pr.xml
deleted file mode 100644
index e34a95d..0000000
--- a/packages/SystemUI/res/drawable/pip_expand_pr.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-Copyright (C) 2017 The Android Open Source Project
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-    you may not use this file except in compliance with the License.
-    You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="60dp"
-    android:height="60dp"
-    android:viewportWidth="60"
-    android:viewportHeight="60">
-
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M8,7.5v45c0,2.75,2.25,5,5,5h34.05c2.75,0,4.95-2.25,4.95-5v-45c0-2.75-2.2-5-4.95-5H13
-C10.25,2.5,8,4.75,8,7.5z
-M13,6.5h34c0.55,0,1,0.45,1,1v45c0,0.55-0.45,1-1,1H13c-0.55,0-1-0.45-1-1v-45C12,6.95,12.45,6.5,13,6.5z" />
-    <path
-        android:pathData="M60,0L0,0l0,60h60V0z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M20.86,35h-2c-0.55,0-1,0.45-1,1v10.5c0,0.55,0.45,1,1,1h10.5c0.55,0,1-0.45,1-1v-2c0-0.55-0.45-1-1-1h-7.5
-V36C21.86,35.45,21.41,35,20.86,35z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M29.64,13.5v2c0,0.55,0.45,1,1,1h7.5V24c0,0.55,0.45,1,1,1h2c0.55,0,1-0.45,1-1V13.5c0-0.55-0.45-1-1-1
-h-10.5C30.09,12.5,29.64,12.95,29.64,13.5z" />
-</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 8c66bab..8b7f692 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -38,6 +38,8 @@
               android:layout_height="60dp"
               android:layout_gravity="center"
               android:contentDescription="@string/pip_phone_expand"
+              android:padding="10dp"
+              android:src="@drawable/pip_expand"
               android:background="?android:selectableItemBackgroundBorderless" />
       </FrameLayout>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 97e180c..99c6227 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -792,7 +792,7 @@
 
     <!-- The bottom margin of the expand container when there are actions.
          Equal to pip_action_size - pip_action_padding. -->
-    <dimen name="pip_expand_container_edge_margin">36dp</dimen>
+    <dimen name="pip_expand_container_edge_margin">30dp</dimen>
 
     <dimen name="default_gear_space">18dp</dimen>
     <dimen name="cell_overlay_padding">18dp</dimen>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 47290ec..dce4b61 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -512,6 +512,12 @@
             }
         }
 
+        if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+            mLockPatternUtils.requireStrongAuth(
+                    LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
+                    getCurrentUser());
+        }
+
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index 65f24cf..766914c 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -303,7 +303,6 @@
                 mMenuContainerAnimator.cancel();
             }
             notifyMenuStateChange(menuState);
-            updateExpandButtonFromBounds(stackBounds, movementBounds);
             mMenuContainerAnimator = new AnimatorSet();
             ObjectAnimator menuAnim = ObjectAnimator.ofFloat(mMenuContainer, View.ALPHA,
                     mMenuContainer.getAlpha(), 1f);
@@ -388,24 +387,6 @@
         }
     }
 
-    private void updateExpandButtonFromBounds(Rect stackBounds, Rect movementBounds) {
-        if (stackBounds == null) {
-            return;
-        }
-
-        boolean isLandscapePip = stackBounds.width() > stackBounds.height();
-        boolean left = stackBounds.left < movementBounds.centerX();
-        boolean top = stackBounds.top < movementBounds.centerY();
-        boolean expandL = (left && top) || (!left && !top);
-        int iconResId;
-        if (isLandscapePip) {
-            iconResId = expandL ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr;
-        } else {
-            iconResId = expandL ? R.drawable.pip_expand_pl : R.drawable.pip_expand_pr;
-        }
-        mExpandButton.setImageResource(iconResId);
-    }
-
     private void setActions(Rect stackBounds, List<RemoteAction> actions) {
         mActions.clear();
         mActions.addAll(actions);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
index 5b54d85..30240c3 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipNotification.java
@@ -168,8 +168,7 @@
     void onConfigurationChanged(Context context) {
         Resources res = context.getResources();
         mDefaultTitle = res.getString(R.string.pip_notification_unknown_title);
-        mDefaultIconResId = res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_LTR
-                        ? R.drawable.pip_expand_ll : R.drawable.pip_expand_lr;
+        mDefaultIconResId = R.drawable.pip_expand;
         if (mNotified) {
             // update notification
             notifyPipNotification();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
index f6bd14c..9a3de61 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/MediaNotificationProcessor.java
@@ -28,6 +28,7 @@
 import android.support.v7.graphics.Palette;
 import android.util.LayoutDirection;
 
+import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
 
 import java.util.List;
@@ -120,7 +121,7 @@
                 paletteBuilder.addFilter(mBlackWhiteFilter);
                 palette = paletteBuilder.generate();
                 int foregroundColor;
-                if (ColorUtils.calculateLuminance(backgroundColor) > 0.5) {
+                if (NotificationColorUtil.isColorLight(backgroundColor)) {
                     Palette.Swatch first = palette.getDarkVibrantSwatch();
                     Palette.Swatch second = palette.getVibrantSwatch();
                     if (first != null && second != null) {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 7a1a5f2..38db8de 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -792,6 +792,11 @@
             return false;
         }
 
+        // 4. it is an "instant" app
+        if (app.isInstantApp()) {
+            return false;
+        }
+
         // Everything else checks out; the only remaining roadblock would be if the
         // package were disabled
         return !appIsDisabled(app, pm);
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index 8ed95ee..ff5efde 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -65,6 +65,7 @@
     static final boolean DEBUG_MU = DEBUG_ALL || false;
     static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
     static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false;
+    static final boolean DEBUG_OOM_ADJ_REASON = DEBUG_ALL || false;
     static final boolean DEBUG_PAUSE = DEBUG_ALL || false;
     static final boolean DEBUG_POWER = DEBUG_ALL || false;
     static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 8398eee..e09dd25 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -118,6 +118,7 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_NETWORK;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ_REASON;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER;
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
@@ -20629,6 +20630,7 @@
         if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {
             // The max adjustment doesn't allow this app to be anything
             // below foreground, so it is not worth doing work for it.
+            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making fixed: " + app);
             app.adjType = "fixed";
             app.adjSeq = mAdjSeq;
             app.curRawAdj = app.maxAdj;
@@ -20680,12 +20682,14 @@
             app.adjType = "top-activity";
             foregroundActivities = true;
             procState = PROCESS_STATE_CUR_TOP;
+            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making top: " + app);
         } else if (app.instr != null) {
             // Don't want to kill running instrumentation.
             adj = ProcessList.FOREGROUND_APP_ADJ;
             schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
             app.adjType = "instrumentation";
             procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
+            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making instrumentation: " + app);
         } else if (isReceivingBroadcastLocked(app, mTmpBroadcastQueue)) {
             // An app that is currently receiving a broadcast also
             // counts as being in the foreground for OOM killer purposes.
@@ -20696,6 +20700,7 @@
                     ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "broadcast";
             procState = ActivityManager.PROCESS_STATE_RECEIVER;
+            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making broadcast: " + app);
         } else if (app.executingServices.size() > 0) {
             // An app that is currently executing a service callback also
             // counts as being in the foreground.
@@ -20704,6 +20709,7 @@
                     ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND;
             app.adjType = "exec-service";
             procState = ActivityManager.PROCESS_STATE_SERVICE;
+            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making exec-service: " + app);
             //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);
         } else {
             // As far as we know the process is empty.  We may change our mind later.
@@ -20715,6 +20721,7 @@
             app.cached = true;
             app.empty = true;
             app.adjType = "cch-empty";
+            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Making empty: " + app);
         }
 
         // Examine all activities if not already foreground.
@@ -20736,10 +20743,13 @@
                     // App has a visible activity; only upgrade adjustment.
                     if (adj > ProcessList.VISIBLE_APP_ADJ) {
                         adj = ProcessList.VISIBLE_APP_ADJ;
-                        app.adjType = "visible";
+                        app.adjType = "vis-activity";
+                        if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
                     }
                     if (procState > PROCESS_STATE_CUR_TOP) {
                         procState = PROCESS_STATE_CUR_TOP;
+                        app.adjType = "vis-activity";
+                        if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to vis-activity: " + app);
                     }
                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                     app.cached = false;
@@ -20756,10 +20766,13 @@
                 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {
                     if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         adj = ProcessList.PERCEPTIBLE_APP_ADJ;
-                        app.adjType = "pausing";
+                        app.adjType = "pause-activity";
+                        if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
                     }
                     if (procState > PROCESS_STATE_CUR_TOP) {
                         procState = PROCESS_STATE_CUR_TOP;
+                        app.adjType = "pause-activity";
+                        if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to pause-activity: " + app);
                     }
                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                     app.cached = false;
@@ -20768,7 +20781,8 @@
                 } else if (r.state == ActivityState.STOPPING) {
                     if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                         adj = ProcessList.PERCEPTIBLE_APP_ADJ;
-                        app.adjType = "stopping";
+                        app.adjType = "stop-activity";
+                        if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to stop-activity: " + app);
                     }
                     // For the process state, we will at this point consider the
                     // process to be cached.  It will be cached either as an activity
@@ -20780,6 +20794,8 @@
                     if (!r.finishing) {
                         if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                             procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+                            app.adjType = "stop-activity";
+                            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to stop-activity: " + app);
                         }
                     }
                     app.cached = false;
@@ -20789,6 +20805,7 @@
                     if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {
                         procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
                         app.adjType = "cch-act";
+                        if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to cached activity: " + app);
                     }
                 }
             }
@@ -20806,6 +20823,7 @@
                 app.cached = false;
                 app.adjType = "fg-service";
                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to fg service: " + app);
             } else if (app.hasOverlayUi) {
                 // The process is display an overlay UI.
                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -20813,6 +20831,7 @@
                 app.cached = false;
                 app.adjType = "has-overlay-ui";
                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to overlay ui: " + app);
             }
         }
 
@@ -20828,6 +20847,7 @@
                 app.adjType = "force-imp";
                 app.adjSource = app.forcingToImportant;
                 schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to force imp: " + app);
             }
         }
 
@@ -20838,9 +20858,12 @@
                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "heavy";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to heavy: " + app);
             }
             if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
+                app.adjType = "heavy";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to heavy: " + app);
             }
         }
 
@@ -20852,9 +20875,12 @@
                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "home";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to home: " + app);
             }
             if (procState > ActivityManager.PROCESS_STATE_HOME) {
                 procState = ActivityManager.PROCESS_STATE_HOME;
+                app.adjType = "home";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to home: " + app);
             }
         }
 
@@ -20867,9 +20893,12 @@
                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
                 app.adjType = "previous";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to prev: " + app);
             }
             if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                 procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+                app.adjType = "previous";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to prev: " + app);
             }
         }
 
@@ -20893,14 +20922,20 @@
                     procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
                 }
                 app.adjType = "backup";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to backup: " + app);
                 app.cached = false;
             }
             if (procState > ActivityManager.PROCESS_STATE_BACKUP) {
                 procState = ActivityManager.PROCESS_STATE_BACKUP;
+                app.adjType = "backup";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to backup: " + app);
             }
         }
 
         boolean mayBeTop = false;
+        String mayBeTopType = null;
+        Object mayBeTopSource = null;
+        Object mayBeTopTarget = null;
 
         for (int is = app.services.size()-1;
                 is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
@@ -20912,6 +20947,8 @@
                 app.hasStartedServices = true;
                 if (procState > ActivityManager.PROCESS_STATE_SERVICE) {
                     procState = ActivityManager.PROCESS_STATE_SERVICE;
+                    app.adjType = "started-services";
+                    if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to started service: " + app);
                 }
                 if (app.hasShownUi && app != mHomeProcess) {
                     // If this process has shown some UI, let it immediately
@@ -20929,6 +20966,7 @@
                         if (adj > ProcessList.SERVICE_ADJ) {
                             adj = ProcessList.SERVICE_ADJ;
                             app.adjType = "started-services";
+                            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to started service: " + app);
                             app.cached = false;
                         }
                     }
@@ -21010,27 +21048,35 @@
                             // memory.
                             if (app.hasShownUi && app != mHomeProcess
                                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                adjType = "cch-bound-ui-services";
+                                if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
+                                    adjType = "cch-bound-ui-services";
+                                }
                             } else {
+                                int newAdj;
                                 if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                         |Context.BIND_IMPORTANT)) != 0) {
-                                    adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
+                                    newAdj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ
                                             ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;
                                 } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
                                         && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
                                         && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                    adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+                                    newAdj = ProcessList.PERCEPTIBLE_APP_ADJ;
                                 } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
-                                    adj = clientAdj;
+                                    newAdj = clientAdj;
                                 } else {
                                     if (adj > ProcessList.VISIBLE_APP_ADJ) {
-                                        adj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
+                                        newAdj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ);
+                                    } else {
+                                        newAdj = adj;
                                     }
                                 }
                                 if (!client.cached) {
                                     app.cached = false;
                                 }
-                                adjType = "service";
+                                if (adj >  newAdj) {
+                                    adj = newAdj;
+                                    adjType = "service";
+                                }
                             }
                         }
                         if ((cr.flags & (Context.BIND_NOT_FOREGROUND
@@ -21057,6 +21103,9 @@
                                     // is more important to continue considering it to be
                                     // in the background state.
                                     mayBeTop = true;
+                                    mayBeTopType = "service";
+                                    mayBeTopSource = cr.binding.client;
+                                    mayBeTopTarget = s.name;
                                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                                 } else {
                                     // Special handling for above-top states (persistent
@@ -21093,6 +21142,9 @@
                         }
                         if (procState > clientProcState) {
                             procState = clientProcState;
+                            if (adjType == null) {
+                                adjType = "service";
+                            }
                         }
                         if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
                                 && (cr.flags&Context.BIND_SHOWING_UI) != 0) {
@@ -21105,6 +21157,9 @@
                             app.adjSource = cr.binding.client;
                             app.adjSourceProcState = clientProcState;
                             app.adjTarget = s.name;
+                            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to " + adjType
+                                    + ": " + app + ", due to " + cr.binding.client
+                                    + " adj=" + adj + " procState=" + procState);
                         }
                     }
                     if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
@@ -21130,6 +21185,8 @@
                             app.adjSource = a;
                             app.adjSourceProcState = procState;
                             app.adjTarget = s.name;
+                            if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to service w/activity: "
+                                    + app);
                         }
                     }
                 }
@@ -21160,21 +21217,17 @@
                     // we are going to consider it empty.
                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
                 }
+                String adjType = null;
                 if (adj > clientAdj) {
                     if (app.hasShownUi && app != mHomeProcess
                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
-                        app.adjType = "cch-ui-provider";
+                        adjType = "cch-ui-provider";
                     } else {
                         adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                                 ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
-                        app.adjType = "provider";
+                        adjType = "provider";
                     }
                     app.cached &= client.cached;
-                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
-                            .REASON_PROVIDER_IN_USE;
-                    app.adjSource = client;
-                    app.adjSourceProcState = clientProcState;
-                    app.adjTarget = cpr.name;
                 }
                 if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {
                     if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {
@@ -21189,6 +21242,9 @@
                         // in the background state.
                         mayBeTop = true;
                         clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;
+                        mayBeTopType = adjType = "provider-top";
+                        mayBeTopSource = client;
+                        mayBeTopTarget = cpr.name;
                     } else {
                         // Special handling for above-top states (persistent
                         // processes).  These should not bring the current process
@@ -21196,6 +21252,9 @@
                         // give them the best state after that.
                         clientProcState =
                                 ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+                        if (adjType == null) {
+                            adjType = "provider";
+                        }
                     }
                 }
                 if (procState > clientProcState) {
@@ -21204,6 +21263,17 @@
                 if (client.curSchedGroup > schedGroup) {
                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                 }
+                if (adjType != null) {
+                    app.adjType = adjType;
+                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+                            .REASON_PROVIDER_IN_USE;
+                    app.adjSource = client;
+                    app.adjSourceProcState = clientProcState;
+                    app.adjTarget = cpr.name;
+                    if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to " + adjType
+                            + ": " + app + ", due to " + client
+                            + " adj=" + adj + " procState=" + procState);
+                }
             }
             // If the provider has external (non-framework) process
             // dependencies, ensure that its adjustment is at least
@@ -21213,8 +21283,9 @@
                     adj = ProcessList.FOREGROUND_APP_ADJ;
                     schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                     app.cached = false;
-                    app.adjType = "provider";
+                    app.adjType = "ext-provider";
                     app.adjTarget = cpr.name;
+                    if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to external provider: " + app);
                 }
                 if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                     procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
@@ -21228,10 +21299,13 @@
                 adj = ProcessList.PREVIOUS_APP_ADJ;
                 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND;
                 app.cached = false;
-                app.adjType = "provider";
+                app.adjType = "recent-provider";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to recent provider: " + app);
             }
             if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
                 procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;
+                app.adjType = "recent-provider";
+                if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "Raise to recent provider: " + app);
             }
         }
 
@@ -21243,6 +21317,9 @@
             // is top (states that tend to be longer-term) and otherwise allow it to go
             // to the top state.
             switch (procState) {
+                case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
+                    // Something else is keeping it at this level, just leave it.
+                    break;
                 case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:
                 case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:
                 case ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND:
@@ -21250,10 +21327,22 @@
                     // These all are longer-term states, so pull them up to the top
                     // of the background states, but not all the way to the top state.
                     procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+                    app.adjType = mayBeTopType;
+                    app.adjSource = mayBeTopSource;
+                    app.adjTarget = mayBeTopTarget;
+                    if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "May be top raise to " + mayBeTopType
+                            + ": " + app + ", due to " + mayBeTopSource
+                            + " adj=" + adj + " procState=" + procState);
                     break;
                 default:
                     // Otherwise, top is a better choice, so take it.
                     procState = ActivityManager.PROCESS_STATE_TOP;
+                    app.adjType = mayBeTopType;
+                    app.adjSource = mayBeTopSource;
+                    app.adjTarget = mayBeTopTarget;
+                    if (DEBUG_OOM_ADJ_REASON) Slog.d(TAG, "May be top raise to " + mayBeTopType
+                            + ": " + app + ", due to " + mayBeTopSource
+                            + " adj=" + adj + " procState=" + procState);
                     break;
             }
         }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 5d8cb12..4db5c85 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -989,10 +989,10 @@
     }
 
     @Override
-    public void noteBleScanResult(WorkSource ws) {
+    public void noteBleScanResults(WorkSource ws, int numNewResults) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteBluetoothScanResultFromSourceLocked(ws);
+            mStats.noteBluetoothScanResultsFromSourceLocked(ws, numNewResults);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 80e7c75..7810c5e 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -356,7 +356,7 @@
                 procState = "PERU";
                 break;
             case ActivityManager.PROCESS_STATE_TOP:
-                procState = "TOP";
+                procState = "TOP ";
                 break;
             case ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE:
                 procState = "BFGS";
diff --git a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
index fe49813..4fc6ddd 100644
--- a/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
+++ b/services/core/java/com/android/server/fingerprint/AuthenticationClient.java
@@ -34,8 +34,13 @@
 public abstract class AuthenticationClient extends ClientMonitor {
     private long mOpId;
 
-    public abstract boolean handleFailedAttempt();
+    public abstract int handleFailedAttempt();
     public abstract void resetFailedAttempts();
+
+    public static final int LOCKOUT_NONE = 0;
+    public static final int LOCKOUT_TIMED = 1;
+    public static final int LOCKOUT_PERMANENT = 2;
+
     private boolean mAlreadyCancelled;
 
     public AuthenticationClient(Context context, long halDeviceId, IBinder token,
@@ -79,19 +84,21 @@
                 FingerprintUtils.vibrateFingerprintError(getContext());
             }
             // allow system-defined limit of number of attempts before giving up
-            boolean inLockoutMode =  handleFailedAttempt();
-            // send lockout event in case driver doesn't enforce it.
-            if (inLockoutMode) {
+            int lockoutMode =  handleFailedAttempt();
+            if (lockoutMode != LOCKOUT_NONE) {
                 try {
-                    Slog.w(TAG, "Forcing lockout (fp driver code should do this!)");
-                    stop(false); // cancel fingerprint authentication
-                    receiver.onError(getHalDeviceId(),
-                            FingerprintManager.FINGERPRINT_ERROR_LOCKOUT, 0 /* vendorCode */);
+                    Slog.w(TAG, "Forcing lockout (fp driver code should do this!), mode(" +
+                            lockoutMode + ")");
+                    stop(false);
+                    int errorCode = lockoutMode == LOCKOUT_TIMED ?
+                            FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
+                            FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+                    receiver.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "Failed to notify lockout:", e);
                 }
             }
-            result |= inLockoutMode;
+            result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
         } else {
             if (receiver != null) {
                 FingerprintUtils.vibrateFingerprintSuccess(getContext());
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index 6f5b028..6cc7071 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -108,6 +108,7 @@
         int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image
                      // acquisition in some cases (too fast, too slow, dirty sensor, etc.)
         int lockout; // total number of lockouts
+        int permanentLockout; // total number of permanent lockouts
     }
 
     private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
@@ -118,13 +119,16 @@
             Collections.synchronizedMap(new HashMap<>());
     private final AppOpsManager mAppOps;
     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
-    private static final int MAX_FAILED_ATTEMPTS = 5;
+    private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
+    private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;
+
     private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
     private final String mKeyguardPackage;
     private int mCurrentUserId = UserHandle.USER_NULL;
     private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
     private Context mContext;
     private long mHalDeviceId;
+    private boolean mTimedLockoutCleared;
     private int mFailedAttempts;
     @GuardedBy("this")
     private IBiometricsFingerprint mDaemon;
@@ -173,7 +177,7 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) {
-                resetFailedAttempts();
+                resetFailedAttempts(false /* clearAttemptCounter */);
             }
         }
     };
@@ -181,7 +185,7 @@
     private final Runnable mResetFailedAttemptsRunnable = new Runnable() {
         @Override
         public void run() {
-            resetFailedAttempts();
+            resetFailedAttempts(true /* clearAttemptCounter */);
         }
     };
 
@@ -369,6 +373,7 @@
         if (client != null && client.onError(error, vendorCode)) {
             removeClient(client);
         }
+
         if (DEBUG) Slog.v(TAG, "handleError(client="
                 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")");
         // This is the magic code that starts the next client when the old client finishes.
@@ -438,7 +443,7 @@
         if (client != null && client.onAcquired(acquiredInfo, vendorCode)) {
             removeClient(client);
         }
-        if (mPerformanceStats != null && !inLockoutMode()
+        if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE
                 && client instanceof AuthenticationClient) {
             // ignore enrollment acquisitions or acquisitions when we're locked out
             mPerformanceStats.acquire++;
@@ -482,8 +487,14 @@
         }
     }
 
-    private boolean inLockoutMode() {
-        return mFailedAttempts >= MAX_FAILED_ATTEMPTS;
+    private int getLockoutMode() {
+        if (mFailedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
+            return AuthenticationClient.LOCKOUT_PERMANENT;
+        } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false &&
+                (mFailedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
+            return AuthenticationClient.LOCKOUT_TIMED;
+        }
+        return AuthenticationClient.LOCKOUT_NONE;
     }
 
     private void scheduleLockoutReset() {
@@ -801,22 +812,27 @@
         AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
                 receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) {
             @Override
-            public boolean handleFailedAttempt() {
+            public int handleFailedAttempt() {
                 mFailedAttempts++;
-                if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
+                mTimedLockoutCleared = false;
+                final int lockoutMode = getLockoutMode();
+                if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
+                    mPerformanceStats.permanentLockout++;
+                } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
                     mPerformanceStats.lockout++;
                 }
-                if (inLockoutMode()) {
-                    // Failing multiple times will continue to push out the lockout time.
+
+                // Failing multiple times will continue to push out the lockout time
+                if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
                     scheduleLockoutReset();
-                    return true;
+                    return lockoutMode;
                 }
-                return false;
+                return AuthenticationClient.LOCKOUT_NONE;
             }
 
             @Override
             public void resetFailedAttempts() {
-                FingerprintService.this.resetFailedAttempts();
+                FingerprintService.this.resetFailedAttempts(true /* clearAttemptCounter */);
             }
 
             @Override
@@ -830,11 +846,15 @@
             }
         };
 
-        if (inLockoutMode()) {
-            Slog.v(TAG, "In lockout mode; disallowing authentication");
-            // Don't bother starting the client. Just send the error message.
-            if (!client.onError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT, 0 /* vendorCode */)) {
-                Slog.w(TAG, "Cannot send timeout message to client");
+        int lockoutMode = getLockoutMode();
+        if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
+            Slog.v(TAG, "In lockout mode(" + lockoutMode +
+                    ") ; disallowing authentication");
+            int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
+                    FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
+                    FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
+            if (!client.onError(errorCode, 0 /* vendorCode */)) {
+                Slog.w(TAG, "Cannot send permanent lockout message to client");
             }
             return;
         }
@@ -864,11 +884,16 @@
         startClient(client, true /* initiatedByClient */);
     }
 
-    protected void resetFailedAttempts() {
-        if (DEBUG && inLockoutMode()) {
-            Slog.v(TAG, "Reset fingerprint lockout");
+    // attempt counter should only be cleared when Keyguard goes away or when
+    // a fingerprint is successfully authenticated
+    protected void resetFailedAttempts(boolean clearAttemptCounter) {
+        if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
+            Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter);
         }
-        mFailedAttempts = 0;
+        if (clearAttemptCounter) {
+            mFailedAttempts = 0;
+        }
+        mTimedLockoutCleared = true;
         // If we're asked to reset failed attempts externally (i.e. from Keyguard),
         // the alarm might still be pending; remove it.
         cancelLockoutReset();
@@ -1301,6 +1326,7 @@
                 set.put("reject", (stats != null) ? stats.reject : 0);
                 set.put("acquire", (stats != null) ? stats.acquire : 0);
                 set.put("lockout", (stats != null) ? stats.lockout : 0);
+                set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0);
                 // cryptoStats measures statistics about secure fingerprint transactions
                 // (e.g. to unlock password storage, make secure purchases, etc.)
                 set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
@@ -1336,6 +1362,7 @@
                 proto.write(FingerprintActionStatsProto.REJECT, normal.reject);
                 proto.write(FingerprintActionStatsProto.ACQUIRE, normal.acquire);
                 proto.write(FingerprintActionStatsProto.LOCKOUT, normal.lockout);
+                proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.lockout);
                 proto.end(countsToken);
             }
 
@@ -1348,6 +1375,7 @@
                 proto.write(FingerprintActionStatsProto.REJECT, crypto.reject);
                 proto.write(FingerprintActionStatsProto.ACQUIRE, crypto.acquire);
                 proto.write(FingerprintActionStatsProto.LOCKOUT, crypto.lockout);
+                proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.lockout);
                 proto.end(countsToken);
             }
 
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 2e6cd3f..57b1ccc 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -807,7 +807,7 @@
             ArrayList<JobStatus> result = new ArrayList<JobStatus>();
             for (int i = mJobs.size() - 1; i >= 0; i--) {
                 if (UserHandle.getUserId(mJobs.keyAt(i)) == userId) {
-                    ArraySet<JobStatus> jobs = mJobs.get(i);
+                    ArraySet<JobStatus> jobs = mJobs.valueAt(i);
                     if (jobs != null) {
                         result.addAll(jobs);
                     }
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index 0e1f485..ef3e7bc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -20,6 +20,7 @@
 import static android.content.Intent.ACTION_PACKAGE_ADDED;
 import static android.content.Intent.ACTION_PACKAGE_CHANGED;
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
+import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
 import static android.content.pm.PackageManager.SIGNATURE_MATCH;
 
@@ -46,6 +47,7 @@
 import android.os.ShellCallback;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -243,11 +245,14 @@
                     packageFilter, null, null);
 
             final IntentFilter userFilter = new IntentFilter();
+            userFilter.addAction(ACTION_USER_ADDED);
             userFilter.addAction(ACTION_USER_REMOVED);
             getContext().registerReceiverAsUser(new UserReceiver(), UserHandle.ALL,
                     userFilter, null, null);
 
             restoreSettings();
+
+            initIfNeeded();
             onSwitchUser(UserHandle.USER_SYSTEM);
 
             publishBinderService(Context.OVERLAY_SERVICE, mService);
@@ -269,14 +274,31 @@
         }
     }
 
+    private void initIfNeeded() {
+        final UserManager um = getContext().getSystemService(UserManager.class);
+        final List<UserInfo> users = um.getUsers(true /*excludeDying*/);
+        synchronized (mLock) {
+            final int userCount = users.size();
+            for (int i = 0; i < userCount; i++) {
+                final UserInfo userInfo = users.get(i);
+                if (!userInfo.supportsSwitchTo() && userInfo.id != UserHandle.USER_SYSTEM) {
+                    // Initialize any users that can't be switched to, as there state would
+                    // never be setup in onSwitchUser(). We will switch to the system user right
+                    // after this, and its state will be setup there.
+                    final List<String> targets = mImpl.updateOverlaysForUser(users.get(i).id);
+                    updateOverlayPaths(users.get(i).id, targets);
+                }
+            }
+        }
+    }
+
     @Override
     public void onSwitchUser(final int newUserId) {
         // ensure overlays in the settings are up-to-date, and propagate
         // any asset changes to the rest of the system
-        final List<String> targets;
         synchronized (mLock) {
-            targets = mImpl.onSwitchUser(newUserId);
-            updateAssetsLocked(newUserId, targets);
+            final List<String> targets = mImpl.updateOverlaysForUser(newUserId);
+            updateAssets(newUserId, targets);
         }
         schedulePersistSettings();
     }
@@ -428,10 +450,19 @@
     private final class UserReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(@NonNull final Context context, @NonNull final Intent intent) {
+            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
             switch (intent.getAction()) {
+                case ACTION_USER_ADDED:
+                    if (userId != UserHandle.USER_NULL) {
+                        final ArrayList<String> targets;
+                        synchronized (mLock) {
+                            targets = mImpl.updateOverlaysForUser(userId);
+                        }
+                        updateOverlayPaths(userId, targets);
+                    }
+                    break;
+
                 case ACTION_USER_REMOVED:
-                    final int userId =
-                            intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                     if (userId != UserHandle.USER_NULL) {
                         synchronized (mLock) {
                             mImpl.onUserRemoved(userId);
@@ -647,9 +678,7 @@
         public void onOverlaysChanged(@NonNull final String targetPackageName, final int userId) {
             schedulePersistSettings();
             FgThread.getHandler().post(() -> {
-                synchronized (mLock) {
-                    updateAssetsLocked(userId, targetPackageName);
-                }
+                updateAssets(userId, targetPackageName);
 
                 final Intent intent = new Intent(Intent.ACTION_OVERLAY_CHANGED,
                         Uri.fromParts("package", targetPackageName, null));
@@ -670,13 +699,10 @@
         }
     }
 
-    private void updateAssetsLocked(final int userId, final String targetPackageName) {
-        final List<String> list = new ArrayList<>();
-        list.add(targetPackageName);
-        updateAssetsLocked(userId, list);
-    }
-
-    private void updateAssetsLocked(final int userId, List<String> targetPackageNames) {
+    /**
+     * Updates the target packages' set of enabled overlays in PackageManager.
+     */
+    private void updateOverlayPaths(int userId, List<String> targetPackageNames) {
         if (DEBUG) {
             Slog.d(TAG, "Updating overlay assets");
         }
@@ -706,12 +732,19 @@
             }
 
             if (!pm.setEnabledOverlayPackages(
-                        userId, targetPackageName, pendingChanges.get(targetPackageName))) {
+                    userId, targetPackageName, pendingChanges.get(targetPackageName))) {
                 Slog.e(TAG, String.format("Failed to change enabled overlays for %s user %d",
-                            targetPackageName, userId));
+                        targetPackageName, userId));
             }
         }
+    }
 
+    private void updateAssets(final int userId, final String targetPackageName) {
+        updateAssets(userId, Collections.singletonList(targetPackageName));
+    }
+
+    private void updateAssets(final int userId, List<String> targetPackageNames) {
+        updateOverlayPaths(userId, targetPackageNames);
         final IActivityManager am = ActivityManager.getService();
         try {
             am.scheduleApplicationInfoChanged(targetPackageNames, userId);
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 5196c66..261bcc5 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -68,15 +68,15 @@
         mListener = listener;
     }
 
-    /*
-     * Call this when switching to a new Android user. Will return a list of
-     * target packages that must refresh their overlays. This list is the union
+    /**
+     * Call this to synchronize the Settings for a user with what PackageManager knows about a user.
+     * Returns a list of target packages that must refresh their overlays. This list is the union
      * of two sets: the set of targets with currently active overlays, and the
      * set of targets that had, but no longer have, active overlays.
      */
-    List<String> onSwitchUser(final int newUserId) {
+    ArrayList<String> updateOverlaysForUser(final int newUserId) {
         if (DEBUG) {
-            Slog.d(TAG, "onSwitchUser newUserId=" + newUserId);
+            Slog.d(TAG, "updateOverlaysForUser newUserId=" + newUserId);
         }
 
         final Set<String> packagesToUpdateAssets = new ArraySet<>();
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index 2f83793..353b710 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -22,12 +22,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.om.OverlayInfo;
+import android.os.UserHandle;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -266,32 +268,32 @@
         return true;
     }
 
-    private static final String TAB1 = "    ";
-    private static final String TAB2 = TAB1 + TAB1;
-    private static final String TAB3 = TAB2 + TAB1;
-
-    void dump(@NonNull final PrintWriter pw) {
+    void dump(@NonNull final PrintWriter p) {
+        final IndentingPrintWriter pw = new IndentingPrintWriter(p, "  ");
         pw.println("Settings");
-        pw.println(TAB1 + "Items");
+        pw.increaseIndent();
 
         if (mItems.isEmpty()) {
-            pw.println(TAB2 + "<none>");
+            pw.println("<none>");
             return;
         }
 
         final int N = mItems.size();
         for (int i = 0; i < N; i++) {
             final SettingsItem item = mItems.get(i);
-            final StringBuilder sb = new StringBuilder();
-            sb.append(TAB2 + item.mPackageName + ":" + item.getUserId() + " {\n");
-            sb.append(TAB3 + "mPackageName.......: " + item.mPackageName + "\n");
-            sb.append(TAB3 + "mUserId............: " + item.getUserId() + "\n");
-            sb.append(TAB3 + "mTargetPackageName.: " + item.getTargetPackageName() + "\n");
-            sb.append(TAB3 + "mBaseCodePath......: " + item.getBaseCodePath() + "\n");
-            sb.append(TAB3 + "mState.............: " + OverlayInfo.stateToString(item.getState()) + "\n");
-            sb.append(TAB3 + "mIsEnabled.........: " + item.isEnabled() + "\n");
-            sb.append(TAB2 + "}");
-            pw.println(sb.toString());
+            pw.println(item.mPackageName + ":" + item.getUserId() + " {");
+            pw.increaseIndent();
+
+            pw.print("mPackageName.......: "); pw.println(item.mPackageName);
+            pw.print("mUserId............: "); pw.println(item.getUserId());
+            pw.print("mTargetPackageName.: "); pw.println(item.getTargetPackageName());
+            pw.print("mBaseCodePath......: "); pw.println(item.getBaseCodePath());
+            pw.print("mState.............: "); pw.println(OverlayInfo.stateToString(item.getState()));
+            pw.print("mIsEnabled.........: "); pw.println(item.isEnabled());
+            pw.print("mIsStatic..........: "); pw.println(item.isStatic());
+
+            pw.decreaseIndent();
+            pw.println("}");
         }
     }
 
@@ -527,12 +529,6 @@
                 .filter(item -> item.getTargetPackageName().equals(targetPackageName));
     }
 
-    private void assertNotNull(@Nullable final Object o) {
-        if (o == null) {
-            throw new AndroidRuntimeException("object must not be null");
-        }
-    }
-
     static final class BadKeyException extends RuntimeException {
         BadKeyException(@NonNull final String packageName, final int userId) {
             super("Bad key mPackageName=" + packageName + " mUserId=" + userId);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1129076..8fcfc8f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -29,7 +29,6 @@
 import static com.android.server.pm.PackageInstallerService.prepareStageDir;
 
 import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -46,7 +45,6 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.Signature;
-import android.content.pm.UserInfo;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.FileBridge;
@@ -56,7 +54,6 @@
 import android.os.Message;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
-import android.os.ProxyFileDescriptorCallback;
 import android.os.RemoteException;
 import android.os.RevocableFileDescriptor;
 import android.os.UserHandle;
@@ -1168,19 +1165,7 @@
         // Send broadcast to default launcher only if it's a new install
         final boolean isNewInstall = extras == null || !extras.getBoolean(Intent.EXTRA_REPLACING);
         if (success && isNewInstall) {
-            UserManagerService ums = UserManagerService.getInstance();
-            if (ums != null) {
-                final UserInfo parent = ums.getProfileParent(userId);
-                final int launcherUid = (parent != null) ? parent.id : userId;
-                final ComponentName launcherComponent = mPm.getDefaultHomeActivity(launcherUid);
-                if (launcherComponent != null) {
-                    Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
-                            .putExtra(PackageInstaller.EXTRA_SESSION, generateInfo())
-                            .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
-                            .setPackage(launcherComponent.getPackageName());
-                    mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
-                }
-            }
+            mPm.sendSessionCommitBroadcast(generateInfo(), userId);
         }
 
         mCallback.onSessionFinished(this, success);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9c76f84..baea5c6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3186,6 +3186,17 @@
         return null;
     }
 
+    @Override
+    public @Nullable ComponentName getInstantAppResolverComponent() {
+        synchronized (mPackages) {
+            final Pair<ComponentName, String> instantAppResolver = getInstantAppResolverLPr();
+            if (instantAppResolver == null) {
+                return null;
+            }
+            return instantAppResolver.first;
+        }
+    }
+
     private @Nullable Pair<ComponentName, String> getInstantAppResolverLPr() {
         final String[] packageArray =
                 mContext.getResources().getStringArray(R.array.config_ephemeralResolverPackage);
@@ -13681,6 +13692,12 @@
             int userId) {
         final boolean isSystem = isSystemApp(pkgSetting) || isUpdatedSystemApp(pkgSetting);
         sendPackageAddedForNewUsers(packageName, isSystem, pkgSetting.appId, userId);
+
+        // Send a session commit broadcast
+        final PackageInstaller.SessionInfo info = new PackageInstaller.SessionInfo();
+        info.installReason = pkgSetting.getInstallReason(userId);
+        info.appPackageName = packageName;
+        sendSessionCommitBroadcast(info, userId);
     }
 
     public void sendPackageAddedForNewUsers(String packageName, boolean isSystem, int appId, int... userIds) {
@@ -20197,11 +20214,27 @@
         return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
     }
 
+    public void sendSessionCommitBroadcast(PackageInstaller.SessionInfo sessionInfo, int userId) {
+        UserManagerService ums = UserManagerService.getInstance();
+        if (ums != null) {
+            final UserInfo parent = ums.getProfileParent(userId);
+            final int launcherUid = (parent != null) ? parent.id : userId;
+            final ComponentName launcherComponent = getDefaultHomeActivity(launcherUid);
+            if (launcherComponent != null) {
+                Intent launcherIntent = new Intent(PackageInstaller.ACTION_SESSION_COMMITTED)
+                        .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo)
+                        .putExtra(Intent.EXTRA_USER, UserHandle.of(userId))
+                        .setPackage(launcherComponent.getPackageName());
+                mContext.sendBroadcastAsUser(launcherIntent, UserHandle.of(launcherUid));
+            }
+        }
+    }
+
     /**
      * Report the 'Home' activity which is currently set as "always use this one". If non is set
      * then reports the most likely home activity or null if there are more than one.
      */
-    public ComponentName getDefaultHomeActivity(int userId) {
+    private ComponentName getDefaultHomeActivity(int userId) {
         List<ResolveInfo> allHomeCandidates = new ArrayList<>();
         ComponentName cn = getHomeActivitiesAsUser(allHomeCandidates, userId);
         if (cn != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 3e920d4..bf92ce7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -148,6 +148,8 @@
                     return runSetHomeActivity();
                 case "get-privapp-permissions":
                     return runGetPrivappPermissions();
+                case "get-instantapp-resolver":
+                    return runGetInstantAppResolver();
                 case "has-feature":
                     return runHasFeature();
                 default:
@@ -1272,6 +1274,21 @@
         return 0;
     }
 
+    private int runGetInstantAppResolver() {
+        final PrintWriter pw = getOutPrintWriter();
+        try {
+            final ComponentName instantAppsResolver = mInterface.getInstantAppResolverComponent();
+            if (instantAppsResolver == null) {
+                return 1;
+            }
+            pw.println(instantAppsResolver.flattenToString());
+            return 0;
+        } catch (Exception e) {
+            pw.println(e.toString());
+            return 1;
+        }
+    }
+
     private int runHasFeature() {
         final PrintWriter err = getErrPrintWriter();
         final String featureName = getNextArg();
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ac4b828..feeee3f 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -54,6 +54,7 @@
 import android.graphics.Bitmap.CompressFormat;
 import android.graphics.Canvas;
 import android.graphics.RectF;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Binder;
@@ -1356,7 +1357,7 @@
             if (icon == null) {
                 return; // has no icon
             }
-
+            int maxIconDimension = mMaxIconDimension;
             Bitmap bitmap;
             try {
                 switch (icon.getType()) {
@@ -1368,9 +1369,12 @@
                         return;
                     }
                     case Icon.TYPE_BITMAP:
-                    case Icon.TYPE_ADAPTIVE_BITMAP: {
                         bitmap = icon.getBitmap(); // Don't recycle in this case.
                         break;
+                    case Icon.TYPE_ADAPTIVE_BITMAP: {
+                        bitmap = icon.getBitmap(); // Don't recycle in this case.
+                        maxIconDimension *= (1 + 2 * AdaptiveIconDrawable.getExtraInsetFraction());
+
                     }
                     default:
                         // This shouldn't happen because we've already validated the icon, but
@@ -1378,7 +1382,7 @@
                         throw ShortcutInfo.getInvalidIconException();
                 }
                 mShortcutBitmapSaver.saveBitmapLocked(shortcut,
-                        mMaxIconDimension, mIconPersistFormat, mIconPersistQuality);
+                        maxIconDimension, mIconPersistFormat, mIconPersistQuality);
             } finally {
                 // Once saved, we won't use the original icon information, so null it out.
                 shortcut.clearIcon();
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index 82416ec..fc4ec28 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -158,19 +158,23 @@
     /**
      * Reloads all the resources for the current configuration.
      */
-    void reloadResources() {
+    private void reloadResources() {
         final Resources res = mService.mContext.getResources();
         mMinSize = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
         mDefaultAspectRatio = res.getFloat(
                 com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
-        final Size screenEdgeInsetsDp = Size.parseSize(res.getString(
-                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets));
+        final String screenEdgeInsetsDpString = res.getString(
+                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
+        final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
+                ? Size.parseSize(screenEdgeInsetsDpString)
+                : null;
         mDefaultStackGravity = res.getInteger(
                 com.android.internal.R.integer.config_defaultPictureInPictureGravity);
         mDisplayContent.getDisplay().getRealMetrics(mTmpMetrics);
-        mScreenEdgeInsets = new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
-                dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
+        mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
+                : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), mTmpMetrics),
+                        dpToPx(screenEdgeInsetsDp.getHeight(), mTmpMetrics));
         mMinAspectRatio = res.getFloat(
                 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
         mMaxAspectRatio = res.getFloat(
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a6b95d6..6cb4ddc 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1310,6 +1310,10 @@
     }
 
     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
+        if (mSurfaceController == null) {
+            return;
+        }
+
         final WindowState w = mWin;
         final LayoutParams attrs = mWin.getAttrs();
         final Task task = w.getTask();
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index 2663aaf..f4c4ea9 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -16,10 +16,10 @@
 
 package com.android.server.appwidget;
 
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
@@ -35,10 +35,8 @@
 import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.IntentSender;
 import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutServiceInternal;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
@@ -113,19 +111,18 @@
         ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
         // Set up users.
         when(mMockShortcutService.requestPinAppWidget(anyString(),
-                any(AppWidgetProviderInfo.class), any(Bundle.class), any(IntentSender.class), anyInt()))
+                any(AppWidgetProviderInfo.class), eq(null), eq(null), anyInt()))
                 .thenReturn(true);
         assertTrue(mManager.requestPinAppWidget(provider, null, null));
 
         final ArgumentCaptor<AppWidgetProviderInfo> providerCaptor =
                 ArgumentCaptor.forClass(AppWidgetProviderInfo.class);
         verify(mMockShortcutService, times(1)).requestPinAppWidget(anyString(),
-                providerCaptor.capture(), any(null), eq(null), anyInt());
+                providerCaptor.capture(), eq(null), eq(null), anyInt());
         assertEquals(provider, providerCaptor.getValue().provider);
     }
 
     public void testIsRequestPinAppWidgetSupported() {
-        ComponentName provider = new ComponentName(mTestContext, DummyAppWidget.class);
         // Set up users.
         when(mMockShortcutService.isRequestPinItemSupported(anyInt(), anyInt()))
                 .thenReturn(true, false);
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
index f124df9..45b107d 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
@@ -635,6 +635,12 @@
     }
 
     @Override
+    public int installExistingPackage(String packageName, int installReason)
+            throws NameNotFoundException {
+        return 0;
+    }
+
+    @Override
     public int installExistingPackageAsUser(String packageName, int userId)
             throws NameNotFoundException {
         return 0;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 1284b1b..0e8960e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -498,6 +498,7 @@
         pkg.mRestrictedAccountType = "foo19";
         pkg.mRequiredAccountType = "foo20";
         pkg.mOverlayTarget = "foo21";
+        pkg.mOverlayPriority = 100;
         pkg.mSigningKeys = new ArraySet<>();
         pkg.mUpgradeKeySets = new ArraySet<>();
         pkg.mKeySetMapping = new ArrayMap<>();
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 0167654..32eee84 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -120,18 +120,21 @@
     @After
     public void tearDown() throws Exception {
         final LinkedList<WindowState> nonCommonWindows = new LinkedList();
-        sWm.mRoot.forAllWindows(w -> {
-            if (!mCommonWindows.contains(w)) {
-                nonCommonWindows.addLast(w);
+
+        synchronized (sWm.mWindowMap) {
+            sWm.mRoot.forAllWindows(w -> {
+                if (!mCommonWindows.contains(w)) {
+                    nonCommonWindows.addLast(w);
+                }
+            }, true /* traverseTopToBottom */);
+
+            while (!nonCommonWindows.isEmpty()) {
+                nonCommonWindows.pollLast().removeImmediately();
             }
-        }, true /* traverseTopToBottom */);
 
-        while (!nonCommonWindows.isEmpty()) {
-            nonCommonWindows.pollLast().removeImmediately();
+            mDisplayContent.removeImmediately();
+            sWm.mInputMethodTarget = null;
         }
-
-        mDisplayContent.removeImmediately();
-        sWm.mInputMethodTarget = null;
     }
 
     private WindowState createCommonWindow(WindowState parent, int type, String name) {
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index bd8492b3..48f07d6 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -45,6 +45,8 @@
     public static final int CODE_LOCAL_IMS_SERVICE_DOWN = 106;
     // No pending incoming call exists
     public static final int CODE_LOCAL_NO_PENDING_CALL = 107;
+    // IMS Call ended during conference merge process
+    public static final int CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE = 108;
 
     // IMS -> Telephony
     // Service unavailable; by power off
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 9a03c53..3cb1f39 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -987,6 +987,15 @@
      * @hide
      */
     @Override
+    public int installExistingPackage(String packageName, int installReason)
+            throws NameNotFoundException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
     public int installExistingPackageAsUser(String packageName, int userId)
             throws NameNotFoundException {
         throw new UnsupportedOperationException();
diff --git a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
index 1156b01..1a4067f 100644
--- a/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
+++ b/tools/aapt2/integration-tests/AppOne/AndroidManifest.xml
@@ -17,4 +17,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.android.aapt.app.one" coreApp="true">
     <uses-sdk android:minSdkVersion="21" />
+
+    <uses-permission-sdk-23 android:name="android.permission.TEST" android:maxSdkVersion="22" />
 </manifest>
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index f998d31..53c66a6 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -295,6 +295,7 @@
   manifest_action["original-package"];
   manifest_action["protected-broadcast"];
   manifest_action["uses-permission"];
+  manifest_action["uses-permission-sdk-23"];
   manifest_action["permission"];
   manifest_action["permission-tree"];
   manifest_action["permission-group"];