Merge "Ensure that we are removing recent tasks for a user including their profiles" into qt-dev
diff --git a/api/current.txt b/api/current.txt
index dc249eb..6253dfd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24656,7 +24656,7 @@
   public class MediaController2 implements java.lang.AutoCloseable {
     method public void cancelSessionCommand(@NonNull Object);
     method public void close();
-    method @Nullable public android.media.Session2Token getConnectedSessionToken();
+    method @Nullable public android.media.Session2Token getConnectedToken();
     method public boolean isPlaybackActive();
     method @NonNull public Object sendSessionCommand(@NonNull android.media.Session2Command, @Nullable android.os.Bundle);
   }
@@ -25821,8 +25821,8 @@
     method public void cancelSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull Object);
     method public void close();
     method @NonNull public java.util.List<android.media.MediaSession2.ControllerInfo> getConnectedControllers();
-    method @NonNull public String getSessionId();
-    method @NonNull public android.media.Session2Token getSessionToken();
+    method @NonNull public String getId();
+    method @NonNull public android.media.Session2Token getToken();
     method public boolean isPlaybackActive();
     method @NonNull public Object sendSessionCommand(@NonNull android.media.MediaSession2.ControllerInfo, @NonNull android.media.Session2Command, @Nullable android.os.Bundle);
     method public void setPlaybackActive(boolean);
@@ -25831,7 +25831,7 @@
   public static final class MediaSession2.Builder {
     ctor public MediaSession2.Builder(@NonNull android.content.Context);
     method @NonNull public android.media.MediaSession2 build();
-    method @NonNull public android.media.MediaSession2.Builder setExtras(@Nullable android.os.Bundle);
+    method @NonNull public android.media.MediaSession2.Builder setExtras(@NonNull android.os.Bundle);
     method @NonNull public android.media.MediaSession2.Builder setId(@NonNull String);
     method @NonNull public android.media.MediaSession2.Builder setSessionActivity(@Nullable android.app.PendingIntent);
     method @NonNull public android.media.MediaSession2.Builder setSessionCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.MediaSession2.SessionCallback);
@@ -34595,6 +34595,7 @@
     method @Nullable public java.util.Locale getFirstMatch(String[]);
     method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale);
     method public boolean isEmpty();
+    method public static boolean isPseudoLocale(@Nullable android.icu.util.ULocale);
     method public static void setDefault(@NonNull @Size(min=1) android.os.LocaleList);
     method @IntRange(from=0) public int size();
     method @NonNull public String toLanguageTags();
diff --git a/api/system-current.txt b/api/system-current.txt
index b60e850..d08039d 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5373,10 +5373,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.os.IncidentReportArgs> CREATOR;
   }
 
-  public final class LocaleList implements android.os.Parcelable {
-    method public static boolean isPseudoLocale(@Nullable android.icu.util.ULocale);
-  }
-
   public final class NativeHandle implements java.io.Closeable {
     ctor public NativeHandle();
     ctor public NativeHandle(@NonNull java.io.FileDescriptor, boolean);
diff --git a/api/test-current.txt b/api/test-current.txt
index 49fa558..63c8df0 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2010,6 +2010,7 @@
     field public static final int EFFECT_STRENGTH_LIGHT = 0; // 0x0
     field public static final int EFFECT_STRENGTH_MEDIUM = 1; // 0x1
     field public static final int EFFECT_STRENGTH_STRONG = 2; // 0x2
+    field public static final int EFFECT_TEXTURE_TICK = 21; // 0x15
     field public static final int EFFECT_THUD = 3; // 0x3
     field public static final int[] RINGTONES;
   }
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index 351df1b..011810b 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Size;
-import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.LocaleProto;
 import android.icu.util.ULocale;
@@ -328,9 +327,7 @@
 
     /**
      * Returns true if locale is a pseudo-locale, false otherwise.
-     * {@hide}
      */
-    @SystemApi
     public static boolean isPseudoLocale(@Nullable ULocale locale) {
         return isPseudoLocale(locale != null ? locale.toLocale() : null);
     }
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 7958ddd..035061b 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -104,6 +104,7 @@
      * @see #get(int)
      * @hide
      */
+    @TestApi
     public static final int EFFECT_TEXTURE_TICK = Effect.TEXTURE_TICK;
 
     /** {@hide} */
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d317df0..b52fdb8 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -187,8 +187,10 @@
 
     /**
      * Cancel the current drag operation.
+     * skipAnimation is 'true' when it should skip the drag cancel animation which brings the drag
+     * shadow image back to the drag start position.
      */
-    void cancelDragAndDrop(IBinder dragToken);
+    void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation);
 
     /**
      * Tell the OS that we've just dragged into a View that is willing to accept the drop
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 10f9d38..5929c1b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -25456,7 +25456,7 @@
         }
         if (mAttachInfo.mDragToken != null) {
             try {
-                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
+                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
             } catch (Exception e) {
                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
             }
diff --git a/core/java/com/android/internal/app/AbstractResolverComparator.java b/core/java/com/android/internal/app/AbstractResolverComparator.java
index e091aac..b7276a0 100644
--- a/core/java/com/android/internal/app/AbstractResolverComparator.java
+++ b/core/java/com/android/internal/app/AbstractResolverComparator.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2018 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.internal.app;
 
 import android.app.usage.UsageStatsManager;
@@ -20,7 +36,7 @@
 
     private static final int NUM_OF_TOP_ANNOTATIONS_TO_USE = 3;
 
-    protected AfterCompute mAfterCompute;
+    private AfterCompute mAfterCompute;
     protected final PackageManager mPm;
     protected final UsageStatsManager mUsm;
     protected String[] mAnnotations;
@@ -72,6 +88,13 @@
         mAfterCompute = afterCompute;
     }
 
+    protected final void afterCompute() {
+        final AfterCompute afterCompute = mAfterCompute;
+        if (afterCompute != null) {
+            afterCompute.afterCompute();
+        }
+    }
+
     @Override
     public final int compare(ResolvedComponentInfo lhsp, ResolvedComponentInfo rhsp) {
         final ResolveInfo lhs = lhsp.getResolveInfoAt(0);
diff --git a/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
new file mode 100644
index 0000000..cb44c67
--- /dev/null
+++ b/core/java/com/android/internal/app/AppPredictionServiceResolverComparator.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2018 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.internal.app;
+
+import static android.app.prediction.AppTargetEvent.ACTION_LAUNCH;
+
+import android.app.prediction.AppPredictor;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetEvent;
+import android.app.prediction.AppTargetId;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.view.textclassifier.Log;
+
+import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Uses an {@link AppPredictor} to sort Resolver targets.
+ */
+class AppPredictionServiceResolverComparator extends AbstractResolverComparator {
+
+    private static final String TAG = "APSResolverComparator";
+
+    private final AppPredictor mAppPredictor;
+    private final Context mContext;
+    private final Map<ComponentName, Integer> mTargetRanks = new HashMap<>();
+    private final UserHandle mUser;
+
+    AppPredictionServiceResolverComparator(
+                Context context, Intent intent, AppPredictor appPredictor, UserHandle user) {
+        super(context, intent);
+        mContext = context;
+        mAppPredictor = appPredictor;
+        mUser = user;
+    }
+
+    @Override
+    int compare(ResolveInfo lhs, ResolveInfo rhs) {
+        Integer lhsRank = mTargetRanks.get(new ComponentName(lhs.activityInfo.packageName,
+                lhs.activityInfo.name));
+        Integer rhsRank = mTargetRanks.get(new ComponentName(rhs.activityInfo.packageName,
+                rhs.activityInfo.name));
+        if (lhsRank == null && rhsRank == null) {
+            return 0;
+        } else if (lhsRank == null) {
+            return -1;
+        } else if (rhsRank == null) {
+            return 1;
+        }
+        return lhsRank - rhsRank;
+    }
+
+    @Override
+    void compute(List<ResolvedComponentInfo> targets) {
+        List<AppTarget> appTargets = new ArrayList<>();
+        for (ResolvedComponentInfo target : targets) {
+            appTargets.add(new AppTarget.Builder(new AppTargetId(target.name.flattenToString()))
+                    .setTarget(target.name.getPackageName(), mUser)
+                    .setClassName(target.name.getClassName()).build());
+        }
+        mAppPredictor.sortTargets(appTargets, mContext.getMainExecutor(),
+                sortedAppTargets -> {
+                    for (int i = 0; i < sortedAppTargets.size(); i++) {
+                        mTargetRanks.put(new ComponentName(sortedAppTargets.get(i).getPackageName(),
+                                sortedAppTargets.get(i).getClassName()), i);
+                    }
+                    afterCompute();
+                });
+    }
+
+    @Override
+    float getScore(ComponentName name) {
+        Integer rank = mTargetRanks.get(name);
+        if (rank == null) {
+            Log.w(TAG, "Score requested for unknown component.");
+            return 0f;
+        }
+        int consecutiveSumOfRanks = (mTargetRanks.size() - 1) * (mTargetRanks.size()) / 2;
+        return 1.0f - (((float) rank) / consecutiveSumOfRanks);
+    }
+
+    @Override
+    void updateModel(ComponentName componentName) {
+        mAppPredictor.notifyAppTargetEvent(
+                new AppTargetEvent.Builder(
+                    new AppTarget.Builder(
+                        new AppTargetId(componentName.toString()),
+                        componentName.getPackageName(), mUser)
+                        .setClassName(componentName.getClassName()).build(),
+                    ACTION_LAUNCH).build());
+    }
+
+    @Override
+    void destroy() {
+        // Do nothing. App Predictor destruction is handled by caller.
+    }
+}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 54338bf..59e867f 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -150,6 +150,7 @@
      */
     // TODO(b/123089490): Replace with system flag
     private static final boolean USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS = false;
+    private static final boolean USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES = false;
     // TODO(b/123088566) Share these in a better way.
     private static final String APP_PREDICTION_SHARE_UI_SURFACE = "share";
     public static final String LAUNCH_LOCATON_DIRECT_SHARE = "direct_share";
@@ -1387,6 +1388,15 @@
         return USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS ? getAppPredictor() : null;
     }
 
+    /**
+     * This will return an app predictor if it is enabled for share activity sorting
+     * and if one exists. Otherwise, it returns null.
+     */
+    @Nullable
+    private AppPredictor getAppPredictorForShareActivitesIfEnabled() {
+        return USE_PREDICTION_MANAGER_FOR_SHARE_ACTIVITIES ? getAppPredictor() : null;
+    }
+
     void onRefinementResult(TargetInfo selectedTarget, Intent matchingIntent) {
         if (mRefinementResultReceiver != null) {
             mRefinementResultReceiver.destroy();
@@ -1491,8 +1501,10 @@
                 PackageManager pm,
                 Intent targetIntent,
                 String referrerPackageName,
-                int launchedFromUid) {
-            super(context, pm, targetIntent, referrerPackageName, launchedFromUid);
+                int launchedFromUid,
+                AbstractResolverComparator resolverComparator) {
+            super(context, pm, targetIntent, referrerPackageName, launchedFromUid,
+                    resolverComparator);
         }
 
         @Override
@@ -1520,13 +1532,24 @@
 
     @VisibleForTesting
     protected ResolverListController createListController() {
+        AppPredictor appPredictor = getAppPredictorForShareActivitesIfEnabled();
+        AbstractResolverComparator resolverComparator;
+        if (appPredictor != null) {
+            resolverComparator = new AppPredictionServiceResolverComparator(this, getTargetIntent(),
+                    appPredictor, getUser());
+        } else {
+            resolverComparator =
+                    new ResolverRankerServiceResolverComparator(this, getTargetIntent(),
+                        getReferrerPackageName(), null);
+        }
+
         return new ChooserListController(
                 this,
                 mPm,
                 getTargetIntent(),
                 getReferrerPackageName(),
-                mLaunchedFromUid
-                );
+                mLaunchedFromUid,
+                resolverComparator);
     }
 
     @VisibleForTesting
diff --git a/core/java/com/android/internal/app/ResolverListController.java b/core/java/com/android/internal/app/ResolverListController.java
index a3cfa87..5f92cdd 100644
--- a/core/java/com/android/internal/app/ResolverListController.java
+++ b/core/java/com/android/internal/app/ResolverListController.java
@@ -63,14 +63,24 @@
             Intent targetIntent,
             String referrerPackage,
             int launchedFromUid) {
+        this(context, pm, targetIntent, referrerPackage, launchedFromUid,
+                    new ResolverRankerServiceResolverComparator(
+                        context, targetIntent, referrerPackage, null));
+    }
+
+    public ResolverListController(
+            Context context,
+            PackageManager pm,
+            Intent targetIntent,
+            String referrerPackage,
+            int launchedFromUid,
+            AbstractResolverComparator resolverComparator) {
         mContext = context;
         mpm = pm;
         mLaunchedFromUid = launchedFromUid;
         mTargetIntent = targetIntent;
         mReferrerPackage = referrerPackage;
-        mResolverComparator =
-                new ResolverRankerServiceResolverComparator(
-                    mContext, mTargetIntent, mReferrerPackage, null);
+        mResolverComparator = resolverComparator;
     }
 
     @VisibleForTesting
diff --git a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
index 9bf4f01..726b186 100644
--- a/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
+++ b/core/java/com/android/internal/app/ResolverRankerServiceResolverComparator.java
@@ -126,7 +126,7 @@
                             Log.e(TAG, "Receiving null prediction results.");
                         }
                         mHandler.removeMessages(RESOLVER_RANKER_RESULT_TIMEOUT);
-                        mAfterCompute.afterCompute();
+                        afterCompute();
                     }
                     break;
 
@@ -135,7 +135,7 @@
                         Log.d(TAG, "RESOLVER_RANKER_RESULT_TIMEOUT; unbinding services");
                     }
                     mHandler.removeMessages(RESOLVER_RANKER_SERVICE_RESULT);
-                    mAfterCompute.afterCompute();
+                    afterCompute();
                     break;
 
                 default:
@@ -149,7 +149,6 @@
         super(context, intent);
         mCollator = Collator.getInstance(context.getResources().getConfiguration().locale);
         mReferrerPackage = referrerPackage;
-        mAfterCompute = afterCompute;
         mContext = context;
 
         mCurrentTime = System.currentTimeMillis();
@@ -157,6 +156,7 @@
         mStats = mUsm.queryAndAggregateUsageStats(mSinceTime, mCurrentTime);
         mAction = intent.getAction();
         mRankerServiceName = new ComponentName(mContext, this.getClass());
+        setCallBack(afterCompute);
     }
 
     // compute features for each target according to usage stats of targets.
@@ -328,9 +328,7 @@
             mContext.unbindService(mConnection);
             mConnection.destroy();
         }
-        if (mAfterCompute != null) {
-            mAfterCompute.afterCompute();
-        }
+        afterCompute();
         if (DEBUG) {
             Log.d(TAG, "Unbinded Resolver Ranker.");
         }
@@ -513,9 +511,7 @@
                 Log.e(TAG, "Error in Predict: " + e);
             }
         }
-        if (mAfterCompute != null) {
-            mAfterCompute.afterCompute();
-        }
+        afterCompute();
     }
 
     // adds select prob as the default values, according to a pre-trained Logistic Regression model.
diff --git a/core/res/res/anim/lock_in.xml b/core/res/res/anim/lock_in.xml
index cd4effd..e687f9f 100755
--- a/core/res/res/anim/lock_in.xml
+++ b/core/res/res/anim/lock_in.xml
@@ -34,7 +34,7 @@
                                       android:trimPathOffset="0"
                                       android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
                                 <path android:name="_R_G_L_2_G_D_1_P_0"
-                                      android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+                                      android:strokeColor="#000" android:strokeLineCap="round"
                                       android:strokeLineJoin="round" android:strokeWidth="16"
                                       android:strokeAlpha="1" android:trimPathStart="0.14"
                                       android:trimPathEnd="0.89" android:trimPathOffset="0"
@@ -48,7 +48,7 @@
                     <group android:name="_R_G_L_1_G" android:translateX="-8.25"
                            android:translateY="-4.25" android:pivotX="8.25" android:pivotY="7.25"
                            android:scaleX="0" android:scaleY="0">
-                        <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+                        <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000"
                               android:fillAlpha="1" android:fillType="nonZero"
                               android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
                     </group>
@@ -58,7 +58,7 @@
                     <group android:name="_R_G_L_0_G" android:translateX="-2.25"
                            android:translateY="0.75" android:pivotX="2.25" android:pivotY="2.25"
                            android:scaleX="0" android:scaleY="0">
-                        <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="?attr/textColor"
+                        <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000"
                               android:fillAlpha="1" android:fillType="nonZero"
                               android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
                     </group>
diff --git a/core/res/res/anim/lock_lock.xml b/core/res/res/anim/lock_lock.xml
index ce9c8e8..8fc4f05 100755
--- a/core/res/res/anim/lock_lock.xml
+++ b/core/res/res/anim/lock_lock.xml
@@ -25,7 +25,7 @@
                            android:translateY="3">
                         <group android:name="_R_G_L_2_G" android:translateX="-8.25"
                                android:translateY="-7.25">
-                            <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+                            <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
                                   android:fillAlpha="1" android:fillType="nonZero"
                                   android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
                         </group>
@@ -40,7 +40,7 @@
                             <group android:name="_R_G_L_1_G" android:translateX="6"
                                    android:translateY="5" android:pivotX="2.25"
                                    android:pivotY="2.25" android:scaleX="1" android:scaleY="1">
-                                <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+                                <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000"
                                       android:fillAlpha="1" android:fillType="nonZero"
                                       android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
                             </group>
@@ -61,7 +61,7 @@
                                       android:fillAlpha="0" android:fillType="nonZero"
                                       android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/>
                                 <path android:name="_R_G_L_0_G_D_1_P_0"
-                                      android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+                                      android:strokeColor="#000" android:strokeLineCap="round"
                                       android:strokeLineJoin="round" android:strokeWidth="16"
                                       android:strokeAlpha="1"
                                       android:pathData=" M79.79 -48.55 C79.79,-48.55 79.75,-53.75 79.78,-55.48 C79.83,-57.62 79.08,-78.36 53.07,-78.83 C29.5,-79.25 25.2,-59.38 25.22,-58.27 C25.25,-56.25 24.97,-31.17 24.97,-31.17 "/>
diff --git a/core/res/res/anim/lock_scanning.xml b/core/res/res/anim/lock_scanning.xml
index 998c965..8ced02b 100644
--- a/core/res/res/anim/lock_scanning.xml
+++ b/core/res/res/anim/lock_scanning.xml
@@ -28,7 +28,7 @@
                         <group android:name="_R_G_L_2_G" android:translateX="6"
                                android:translateY="5" android:pivotX="2.25" android:pivotY="2.25"
                                android:scaleX="1" android:scaleY="1">
-                            <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+                            <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
                                   android:fillAlpha="1" android:fillType="nonZero"
                                   android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
                         </group>
@@ -45,7 +45,7 @@
                                android:scaleY="0.125">
                             <group android:name="_R_G_L_1_G" android:translateY="25.029">
                                 <path android:name="_R_G_L_1_G_D_0_P_0"
-                                      android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+                                      android:strokeColor="#000" android:strokeLineCap="round"
                                       android:strokeLineJoin="round" android:strokeWidth="16"
                                       android:strokeAlpha="1"
                                       android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
@@ -62,7 +62,7 @@
                         <group android:name="_R_G_L_0_G" android:translateY="0.04699999999999971"
                                android:pivotX="8.25" android:pivotY="7.25" android:scaleX="1.01562"
                                android:scaleY="1.01563">
-                            <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="?attr/textColor"
+                            <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000"
                                   android:fillAlpha="1" android:fillType="nonZero"
                                   android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
                         </group>
diff --git a/core/res/res/anim/lock_to_error.xml b/core/res/res/anim/lock_to_error.xml
index ddef96b..afe2290 100755
--- a/core/res/res/anim/lock_to_error.xml
+++ b/core/res/res/anim/lock_to_error.xml
@@ -26,7 +26,7 @@
                     <group android:name="_R_G_L_2_G" android:translateX="6"
                            android:translateY="4.954" android:pivotX="2.25" android:pivotY="2.25"
                            android:scaleX="0.98462" android:scaleY="0.98462">
-                        <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+                        <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
                               android:fillAlpha="1" android:fillType="nonZero"
                               android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
                     </group>
@@ -38,7 +38,7 @@
                     <group android:name="_R_G_L_1_G" android:translateX="-16.273"
                            android:translateY="32.312" android:pivotX="27.965" android:pivotY="-32"
                            android:scaleX="0.12308" android:scaleY="0.12308">
-                        <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="?attr/textColor"
+                        <path android:name="_R_G_L_1_G_D_0_P_0" android:strokeColor="#000"
                               android:strokeLineCap="round" android:strokeLineJoin="round"
                               android:strokeWidth="16" android:strokeAlpha="1"
                               android:pathData=" M-28.21 -25.03 C-28.21,-25.03 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.93,-26.15 27.93,-26.15 "/>
@@ -48,7 +48,7 @@
                        android:translateY="12.649999999999999" android:pivotX="8.25"
                        android:pivotY="7.25" android:rotation="0" android:scaleX="1.3"
                        android:scaleY="1.3">
-                    <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="?attr/textColor"
+                    <path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#000"
                           android:fillAlpha="1" android:fillType="nonZero"
                           android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
                 </group>
diff --git a/core/res/res/anim/lock_unlock.xml b/core/res/res/anim/lock_unlock.xml
index 0e85c9d..c8b2608 100755
--- a/core/res/res/anim/lock_unlock.xml
+++ b/core/res/res/anim/lock_unlock.xml
@@ -24,7 +24,7 @@
                     <group android:name="_R_G_L_2_G_T_1" android:translateY="3">
                         <group android:name="_R_G_L_2_G" android:translateX="-8.25"
                                android:translateY="-7.25">
-                            <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="?attr/textColor"
+                            <path android:name="_R_G_L_2_G_D_0_P_0" android:fillColor="#000"
                                   android:fillAlpha="1" android:fillType="nonZero"
                                   android:pathData=" M14.25 0.25 C14.25,0.25 12.75,0.25 12.75,0.25 C12.75,0.25 10.75,0.25 10.75,0.25 C10.75,0.25 5.75,0.25 5.75,0.25 C5.75,0.25 3.75,0.25 3.75,0.25 C3.75,0.25 2.25,0.25 2.25,0.25 C1.15,0.25 0.25,1.15 0.25,2.25 C0.25,2.25 0.25,12.25 0.25,12.25 C0.25,13.35 1.15,14.25 2.25,14.25 C2.25,14.25 14.25,14.25 14.25,14.25 C15.35,14.25 16.25,13.35 16.25,12.25 C16.25,12.25 16.25,2.25 16.25,2.25 C16.25,1.15 15.35,0.25 14.25,0.25c  M14.25 12.25 C14.25,12.25 2.25,12.25 2.25,12.25 C2.25,12.25 2.25,2.25 2.25,2.25 C2.25,2.25 3.75,2.25 3.75,2.25 C3.75,2.25 12.75,2.25 12.75,2.25 C12.75,2.25 14.25,2.25 14.25,2.25 C14.25,2.25 14.25,12.25 14.25,12.25c "/>
                         </group>
@@ -38,7 +38,7 @@
                             <group android:name="_R_G_L_1_G" android:translateX="6"
                                    android:translateY="5" android:pivotX="2.25"
                                    android:pivotY="2.25" android:scaleX="1" android:scaleY="1">
-                                <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="?attr/textColor"
+                                <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#000"
                                       android:fillAlpha="1" android:fillType="nonZero"
                                       android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c "/>
                             </group>
@@ -58,7 +58,7 @@
                                       android:fillAlpha="0" android:fillType="nonZero"
                                       android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
                                 <path android:name="_R_G_L_0_G_D_1_P_0"
-                                      android:strokeColor="?attr/textColor" android:strokeLineCap="round"
+                                      android:strokeColor="#000" android:strokeLineCap="round"
                                       android:strokeLineJoin="round" android:strokeWidth="16"
                                       android:strokeAlpha="1"
                                       android:pathData=" M-28.21 -31.92 C-28.21,-31.92 -27.85,-48.38 -27.97,-55.48 C-28,-57.63 -23.5,-79.87 -0.75,-79.82 C22.77,-79.76 27.75,-59.37 27.72,-58.27 C27.55,-52.88 27.97,-31.67 27.97,-31.67 "/>
diff --git a/core/res/res/drawable/ic_lock.xml b/core/res/res/drawable/ic_lock.xml
index 8d7143b..fed0e0d 100644
--- a/core/res/res/drawable/ic_lock.xml
+++ b/core/res/res/drawable/ic_lock.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="32"
         android:viewportHeight="32">
     <path
-        android:fillColor="?attr/textColor"
+        android:fillColor="#000"
         android:pathData="M16,20m-2.7,0a2.7,2.7 0,1 1,5.4 0a2.7,2.7 0,1 1,-5.4 0"/>
     <path
-        android:fillColor="?attr/textColor"
+        android:fillColor="#000"
         android:pathData="M24,10.7h-2V7.3c0,-3.3 -2.7,-6 -6,-6s-6,2.7 -6,6v3.3H8c-1.5,0 -2.7,1.2 -2.7,2.7v13.3c0,1.5 1.2,2.7 2.7,2.7h16c1.5,0 2.7,-1.2 2.7,-2.7V13.3C26.7,11.9 25.5,10.7 24,10.7zM12.7,7.3C12.7,5.5 14.2,4 16,4s3.3,1.5 3.3,3.3v3.3h-6.7V7.3zM24,26.7H8V13.3h2h12h2V26.7z"/>
 </vector>
diff --git a/core/res/res/drawable/ic_lock_open.xml b/core/res/res/drawable/ic_lock_open.xml
index 3a6bf93..494fd6a 100644
--- a/core/res/res/drawable/ic_lock_open.xml
+++ b/core/res/res/drawable/ic_lock_open.xml
@@ -19,9 +19,9 @@
         android:viewportWidth="32"
         android:viewportHeight="32">
     <path
-        android:fillColor="?attr/textColor"
+        android:fillColor="#000"
         android:pathData="M16,20m-2.67,0a2.67,2.67 0,1 1,5.34 0a2.67,2.67 0,1 1,-5.34 0"/>
     <path
-        android:fillColor="?attr/textColor"
+        android:fillColor="#000"
         android:pathData="M24.67,1.33a6,6 0,0 0,-6 6v3.34L8,10.67a2.67,2.67 0,0 0,-2.67 2.66L5.33,26.67A2.67,2.67 0,0 0,8 29.33L24,29.33a2.67,2.67 0,0 0,2.67 -2.66L26.67,13.33A2.67,2.67 0,0 0,24 10.67L21.33,10.67L21.33,7.33a3.34,3.34 0,0 1,6.67 0L28,8h2.67L30.67,7.33A6,6 0,0 0,24.67 1.33ZM24,13.33L24,26.67L8,26.67L8,13.33Z"/>
 </vector>
\ No newline at end of file
diff --git a/media/apex/java/android/media/MediaController2.java b/media/apex/java/android/media/MediaController2.java
index fb4e6ac..9848f1a 100644
--- a/media/apex/java/android/media/MediaController2.java
+++ b/media/apex/java/android/media/MediaController2.java
@@ -175,7 +175,7 @@
      * @return Session2Token of the connected session, or {@code null} if not connected
      */
     @Nullable
-    public Session2Token getConnectedSessionToken() {
+    public Session2Token getConnectedToken() {
         synchronized (mLock) {
             return mConnectedToken;
         }
diff --git a/media/apex/java/android/media/MediaSession2.java b/media/apex/java/android/media/MediaSession2.java
index 6b56ae0..0819118 100644
--- a/media/apex/java/android/media/MediaSession2.java
+++ b/media/apex/java/android/media/MediaSession2.java
@@ -153,7 +153,7 @@
      * Returns the session ID
      */
     @NonNull
-    public String getSessionId() {
+    public String getId() {
         return mSessionId;
     }
 
@@ -161,7 +161,7 @@
      * Returns the {@link Session2Token} for creating {@link MediaController2}.
      */
     @NonNull
-    public Session2Token getSessionToken() {
+    public Session2Token getToken() {
         return mSessionToken;
     }
 
@@ -522,7 +522,10 @@
          * @see Session2Token#getExtras()
          */
         @NonNull
-        public Builder setExtras(@Nullable Bundle extras) {
+        public Builder setExtras(@NonNull Bundle extras) {
+            if (extras == null) {
+                throw new NullPointerException("extras shouldn't be null");
+            }
             mExtras = extras;
             return this;
         }
@@ -553,7 +556,7 @@
             try {
                 MediaSessionManager manager = (MediaSessionManager) mContext.getSystemService(
                         Context.MEDIA_SESSION_SERVICE);
-                manager.notifySession2Created(session2.getSessionToken());
+                manager.notifySession2Created(session2.getToken());
             } catch (Exception e) {
                 session2.close();
                 throw e;
diff --git a/media/apex/java/android/media/MediaSession2Service.java b/media/apex/java/android/media/MediaSession2Service.java
index 3f392d2..b8bf384 100644
--- a/media/apex/java/android/media/MediaSession2Service.java
+++ b/media/apex/java/android/media/MediaSession2Service.java
@@ -195,15 +195,15 @@
             throw new IllegalArgumentException("session is already closed");
         }
         synchronized (mLock) {
-            MediaSession2 previousSession = mSessions.get(session.getSessionId());
+            MediaSession2 previousSession = mSessions.get(session.getId());
             if (previousSession != null) {
                 if (previousSession != session) {
-                    Log.w(TAG, "Session ID should be unique, ID=" + session.getSessionId()
+                    Log.w(TAG, "Session ID should be unique, ID=" + session.getId()
                             + ", previous=" + previousSession + ", session=" + session);
                 }
                 return;
             }
-            mSessions.put(session.getSessionId(), session);
+            mSessions.put(session.getId(), session);
             session.setForegroundServiceEventCallback(mForegroundServiceEventCallback);
         }
     }
@@ -220,11 +220,11 @@
         }
         MediaNotification notification;
         synchronized (mLock) {
-            if (mSessions.get(session.getSessionId()) != session) {
+            if (mSessions.get(session.getId()) != session) {
                 // Session isn't added or removed already.
                 return;
             }
-            mSessions.remove(session.getSessionId());
+            mSessions.remove(session.getId());
             notification = mNotifications.remove(session);
         }
         session.setForegroundServiceEventCallback(null);
diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index 2a66db1..9bd5be7 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -1,38 +1,38 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <!-- application name [CHAR LIMIT=32] -->
-    <string name="app_name">AndroidOnTap Installer</string>
+    <string name="app_name">Dynamic System Updates</string>
 
     <!-- notification channel name [CHAR LIMIT=32] -->
-    <string name="notification_channel_name">AndroidOnTap Installer</string>
+    <string name="notification_channel_name">Dynamic System Updates</string>
 
     <!-- password page title [CHAR LIMIT=32] -->
-    <string name="keyguard_title">AndroidOnTap Installer</string>
+    <string name="keyguard_title">Dynamic System Updates</string>
 
     <!-- password page description [CHAR LIMIT=128] -->
-    <string name="keyguard_description">Please enter your password and continue to AndroidOnTap installation</string>
+    <string name="keyguard_description">Please enter your password and continue to Dynamic System Updates</string>
 
-    <!-- Displayed on notification: AndroidOnTap installation is completed [CHAR LIMIT=128] -->
-    <string name="notification_install_completed">System update is ready. To finish installing, restart your device.</string>
-    <!-- Displayed on notification: AndroidOnTap installation is in progress [CHAR LIMIT=128] -->
+    <!-- Displayed on notification: Dynamic System is ready [CHAR LIMIT=128] -->
+    <string name="notification_install_completed">Dynamic system is ready. To start using it, restart your device.</string>
+    <!-- Displayed on notification: Dynamic System Updates is in progress [CHAR LIMIT=128] -->
     <string name="notification_install_inprogress">Install in progress</string>
-    <!-- Displayed on notification: AndroidOnTap installation is in progress [CHAR LIMIT=128] -->
-    <string name="notification_install_failed">Install Failed</string>
-    <!-- Displayed on notification: We are running in AndroidOnTap [CHAR LIMIT=128] -->
-    <string name="notification_dynsystem_in_use">We are running in AndroidOnTap.</string>
+    <!-- Displayed on notification: Dynamic System installation failed [CHAR LIMIT=128] -->
+    <string name="notification_install_failed">Install failed</string>
+    <!-- Displayed on notification: We are running in Dynamic System [CHAR LIMIT=128] -->
+    <string name="notification_dynsystem_in_use">Currently running a dynamic system. Restart to use the original Android version.</string>
 
     <!-- Action on notification: Cancel installation [CHAR LIMIT=16] -->
     <string name="notification_action_cancel">Cancel</string>
     <!-- Action on notification: Discard installation [CHAR LIMIT=16] -->
     <string name="notification_action_discard">Discard</string>
-    <!-- Action on notification: Uninstall AndroidOnTap [CHAR LIMIT=16] -->
+    <!-- Action on notification: Uninstall Dynamic System [CHAR LIMIT=16] -->
     <string name="notification_action_uninstall">Uninstall</string>
-    <!-- Action on notification: Restart to AndroidOnTap [CHAR LIMIT=16] -->
+    <!-- Action on notification: Restart to Dynamic System [CHAR LIMIT=16] -->
     <string name="notification_action_reboot_to_dynsystem">Restart</string>
 
-    <!-- Toast when installed AndroidOnTap is discarded [CHAR LIMIT=64] -->
-    <string name="toast_dynsystem_discarded">Installed AndroidOnTap is discarded.</string>
-    <!-- Toast when we fail to launch into AndroidOnTap [CHAR LIMIT=64] -->
-    <string name="toast_failed_to_reboot_to_dynsystem">Failed to restart to AndroidOnTap.</string>
+    <!-- Toast when installed Dynamic System is discarded [CHAR LIMIT=64] -->
+    <string name="toast_dynsystem_discarded">Discarded dynamic system</string>
+    <!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=64] -->
+    <string name="toast_failed_to_reboot_to_dynsystem">Can\u2019t restart or load dynamic system</string>
 
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index 93f6a94..9a41f1d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -38,7 +38,6 @@
 import android.text.Spanned;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.ImageSpan;
-import android.util.Log;
 import android.view.MenuItem;
 import android.widget.TextView;
 
@@ -47,7 +46,6 @@
 import com.android.internal.widget.LockPatternUtils;
 
 import java.util.List;
-import java.util.Set;
 
 /**
  * Utility class to host methods usable in adding a restricted padlock icon and showing admin
@@ -310,43 +308,6 @@
         return null;
     }
 
-    /**
-     * @param userId user id of a managed profile.
-     * @return profile owner admin if cross profile calendar is disallowed.
-     */
-    public static EnforcedAdmin getCrossProfileCalendarEnforcingAdmin(Context context, int userId) {
-        final Context managedProfileContext = createPackageContextAsUser(
-                context, userId);
-        final DevicePolicyManager dpm = managedProfileContext.getSystemService(
-                DevicePolicyManager.class);
-        if (dpm == null) {
-            return null;
-        }
-        final EnforcedAdmin admin = getProfileOwner(context, userId);
-        if (admin == null) {
-            return null;
-        }
-        final Set<String> packages = dpm.getCrossProfileCalendarPackages();
-        if (packages != null && packages.isEmpty()) {
-            return admin;
-        }
-        return null;
-    }
-
-    /**
-     * @param userId user id of a managed profile.
-     * @return a context created from the given context for the given user, or null if it fails.
-     */
-    private static Context createPackageContextAsUser(Context context, int userId) {
-        try {
-            return context.createPackageContextAsUser(
-                    context.getPackageName(), 0 /* flags */, UserHandle.of(userId));
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(LOG_TAG, "Failed to create user context", e);
-        }
-        return null;
-    }
-
     public static EnforcedAdmin checkIfAccessibilityServiceDisallowed(Context context,
             String packageName, int userId) {
         DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml b/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
index a2404b0..65f7a0e 100644
--- a/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
@@ -1,9 +1,10 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="350dp"
-    android:width="350dp"
-    android:viewportHeight="254.66145"
-    android:viewportWidth="254.66145">
+    android:height="340dp"
+    android:width="340dp"
+    android:viewportHeight="340"
+    android:viewportWidth="340">
     <path
-        android:fillColor="#000000"
-        android:pathData="M127.331,40.481m-10.914,0a10.914,10.914 0,1 1,21.828 0a10.914,10.914 0,1 1,-21.828 0"/>
+        android:pathData="M170,40m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0"
+        android:strokeColor="#000000"
+        android:strokeWidth="2"/>
 </vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml b/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
index be10b5d..95b4b1a 100644
--- a/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
@@ -1,11 +1,10 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="350dp"
-    android:width="350dp"
-    android:viewportHeight="254.66145"
-    android:viewportWidth="254.66145" >
+    android:height="340dp"
+    android:width="340dp"
+    android:viewportHeight="340"
+    android:viewportWidth="340">
     <path
+        android:pathData="M170,1L170,1A39,39 0,0 1,209 40L209,130A39,39 0,0 1,170 169L170,169A39,39 0,0 1,131 130L131,40A39,39 0,0 1,170 1z"
         android:strokeColor="#000000"
-        android:strokeWidth="5"
-        android:pathData="M125.923,29.692L128.739,29.692A27.108,30.579 0,0 1,155.847 60.271L155.847,125.268A27.108,30.579 0,0 1,128.739 155.847L125.923,155.847A27.108,30.579 0,0 1,98.815 125.268L98.815,60.271A27.108,30.579 0,0 1,125.923 29.692z"/>
+        android:strokeWidth="2"/>
 </vector>
-
diff --git a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
index b44faa9..a6ad254 100644
--- a/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
+++ b/packages/SystemUI/res-keyguard/layout/bubble_clock.xml
@@ -26,15 +26,15 @@
   >
     <ImageView
         android:id="@+id/minute_hand"
-        android:layout_width="350dp"
-        android:layout_height="350dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:src="@drawable/bubble_minute_hand"
         android:tint="@color/bubbleMinuteHandColor"
     />
     <ImageView
         android:id="@+id/hour_hand"
-        android:layout_width="350dp"
-        android:layout_height="350dp"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:src="@drawable/bubble_hour_hand"
         android:tint="@color/bubbleHourHandColor"
     />
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml
deleted file mode 100644
index 5da7611..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_message_area.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- This contains error message field and padlock shared by pin/pattern/password screens -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:orientation="vertical"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content" >
-    <FrameLayout
-        android:id="@+id/lock_icon_container"
-        android:layout_gravity="center"
-        android:layout_marginBottom="@dimen/keyguard_lock_padding"
-        android:layout_width="@dimen/keyguard_lock_width"
-        android:layout_height="@dimen/keyguard_lock_height" />
-    <com.android.keyguard.KeyguardMessageArea
-        android:id="@+id/keyguard_message_area"
-        style="@style/Keyguard.TextView"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:singleLine="true"
-        android:ellipsize="marquee"
-        android:focusable="true" />
-</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_message_area_large.xml b/packages/SystemUI/res-keyguard/layout/keyguard_message_area_large.xml
deleted file mode 100644
index ab6246d..0000000
--- a/packages/SystemUI/res-keyguard/layout/keyguard_message_area_large.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- This contains emergency call button and carrier as shared by pin/pattern/password screens -->
-<com.android.keyguard.KeyguardMessageArea
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:gravity="center"
-    android:id="@+id/keyguard_message_area"
-    android:maxLines="4"
-    android:textAppearance="?android:attr/textAppearance"
-    android:textSize="@dimen/kg_status_line_font_size"
-    android:textColor="?android:attr/textColorSecondary" />
-
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 11bd98f..b06d6a9 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -34,10 +34,6 @@
         android:layout_weight="7"
         />
 
-    <include layout="@layout/keyguard_message_area"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content" />
-
     <!-- Password entry field -->
       <FrameLayout
          android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
index ccb9af9..dc2d11d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml
@@ -48,11 +48,6 @@
             android:clipChildren="false"
             android:clipToPadding="false">
 
-            <include layout="@layout/keyguard_message_area"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-               />
-
             <com.android.internal.widget.LockPatternView
                 android:id="@+id/lockPatternView"
                 android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 9c41fca..a75b35d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -27,10 +27,6 @@
         androidprv:layout_maxHeight="@dimen/keyguard_security_max_height"
         android:orientation="vertical"
         >
-    <include layout="@layout/keyguard_message_area"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-            />
     <LinearLayout
             android:id="@+id/container"
             android:layout_width="match_parent"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index bfb5bf9..cd61a37 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -35,10 +35,6 @@
             android:tint="@color/background_protected"
             android:src="@drawable/ic_lockscreen_sim"/>
 
-    <include layout="@layout/keyguard_message_area"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-            />
     <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="0dp"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 9f3ae3a..bb75735 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -36,10 +36,6 @@
             android:tint="@color/background_protected"
             android:src="@drawable/ic_lockscreen_sim"/>
 
-    <include layout="@layout/keyguard_message_area"
-             android:layout_width="match_parent"
-             android:layout_height="wrap_content"
-            />
     <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="0dp"
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 1e98189..09a5295 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -65,7 +65,7 @@
     <string name="keyguard_charged">Fully charged</string>
 
     <!-- When the lock screen is showing and the phone plugged in, and the battery is not fully charged, say that it's wirelessly charging. [CHAR LIMIT=50]  -->
-    <string name="keyguard_plugged_in_wireless"><xliff:g id="percentage" example="20%">%s</xliff:g> • Wirelessly Charging</string>
+    <string name="keyguard_plugged_in_wireless"><xliff:g id="percentage" example="20%">%s</xliff:g> • Charging wirelessly</string>
 
     <!-- When the lock screen is showing and the phone plugged in, and the battery
          is not fully charged, say that it's charging.  -->
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 636b929..cdef09d 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -78,21 +78,6 @@
         android:tint="?attr/wallpaperTextColor" />
 
     <FrameLayout
-        android:id="@+id/lock_icon_container"
-        android:layout_width="@dimen/keyguard_lock_width"
-        android:layout_height="@dimen/keyguard_lock_height"
-        android:layout_gravity="bottom|center_horizontal"
-        android:layout_marginBottom="@dimen/keyguard_lock_padding">
-        <com.android.systemui.statusbar.phone.LockIcon
-            android:id="@+id/lock_icon"
-            android:layout_width="@dimen/keyguard_lock_width"
-            android:layout_height="@dimen/keyguard_lock_height"
-            android:src="@*android:drawable/ic_lock"
-            android:contentDescription="@string/accessibility_unlock_button"
-            android:scaleType="center" />
-    </FrameLayout>
-
-    <FrameLayout
         android:id="@+id/overlay_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 34c208a..4cf5f85 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -71,4 +71,31 @@
         sysui:ignoreRightInset="true"
         />
 
+    <LinearLayout
+        android:id="@+id/lock_icon_container"
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="@dimen/status_bar_height"
+        android:layout_gravity="top|center_horizontal">
+        <com.android.systemui.statusbar.phone.LockIcon
+            android:id="@+id/lock_icon"
+            android:layout_width="@dimen/keyguard_lock_width"
+            android:layout_height="@dimen/keyguard_lock_height"
+            android:layout_gravity="center_horizontal"
+            android:layout_marginTop="@dimen/keyguard_lock_padding"
+            android:contentDescription="@string/accessibility_unlock_button"
+            android:src="@*android:drawable/ic_lock"
+            android:scaleType="center" />
+        <com.android.keyguard.KeyguardMessageArea
+            android:id="@+id/keyguard_message_area"
+            style="@style/Keyguard.TextView"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/keyguard_lock_padding"
+            android:gravity="center"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:focusable="true" />
+    </LinearLayout>
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bfdb218..5d8b9e6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -717,9 +717,9 @@
     <!-- The width/height of the unlock icon view on keyguard. -->
     <dimen name="keyguard_lock_height">42dp</dimen>
     <dimen name="keyguard_lock_width">42dp</dimen>
-    <dimen name="keyguard_lock_padding">19dp</dimen>
+    <dimen name="keyguard_lock_padding">20dp</dimen>
 
-    <dimen name="keyguard_indication_margin_bottom">65dp</dimen>
+    <dimen name="keyguard_indication_margin_bottom">44dp</dimen>
 
     <!-- The text size for battery level -->
     <dimen name="battery_level_text_size">12sp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 256f725..0b0822c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -277,8 +277,6 @@
     <string name="accessibility_send_smart_reply">Send</string>
     <!-- Content description of the manage notification button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_manage_notification">Manage notifications</string>
-    <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
-    <string name="unlock_label">unlock</string>
     <!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
     <string name="phone_label">open phone</string>
     <!-- Click action label for accessibility for the voice assist button. This is not shown on-screen and is an accessibility label for the icon which launches the voice assist from the lock screen.[CHAR LIMIT=NONE] -->
@@ -974,7 +972,7 @@
     <string name="interruption_level_alarms_twoline">Alarms\nonly</string>
 
     <!-- Indication on the keyguard that is shown when the device is wirelessly charging. [CHAR LIMIT=80]-->
-    <string name="keyguard_indication_charging_time_wireless"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Wirelessly Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
+    <string name="keyguard_indication_charging_time_wireless"><xliff:g id="percentage" example="20%">%2$s</xliff:g> • Charging wirelessly (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
 
     <!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=50]-->
     <string name="keyguard_indication_charging_time"><xliff:g id="percentage">%2$s</xliff:g> • Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%1$s</xliff:g> until full)</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index b36a88b..4054784 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -51,6 +51,7 @@
     public static final int SYSUI_STATE_SCREEN_PINNING = 1 << 0;
     public static final int SYSUI_STATE_NAV_BAR_HIDDEN = 1 << 1;
     public static final int SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED = 1 << 2;
+    public static final int SYSUI_STATE_BOUNCER_SHOWING = 1 << 3;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({SYSUI_STATE_SCREEN_PINNING,
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 4cb8d90..2ff7266 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -100,7 +100,6 @@
     @Override
     protected void onFinishInflate() {
         mLockPatternUtils = new LockPatternUtils(mContext);
-        mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
 
         EmergencyButton button = findViewById(R.id.emergency_call_button);
@@ -110,6 +109,12 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
+    }
+
+    @Override
     public void onEmergencyButtonClickedWhenInCall() {
         mCallback.reset();
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
index 010ec7c..ace6f6f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
@@ -16,8 +16,12 @@
 
 package com.android.keyguard;
 
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.graphics.Color;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
@@ -26,12 +30,18 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.systemui.statusbar.policy.ConfigurationController;
+
 import java.lang.ref.WeakReference;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 /***
  * Manages a number of views inside of the given layout. See below for a list of widgets.
  */
-class KeyguardMessageArea extends TextView implements SecurityMessageDisplay {
+public class KeyguardMessageArea extends TextView implements SecurityMessageDisplay,
+        ConfigurationController.ConfigurationListener {
     /** Handler token posted with accessibility announcement runnables. */
     private static final Object ANNOUNCE_TOKEN = new Object();
 
@@ -43,8 +53,9 @@
     private static final int DEFAULT_COLOR = -1;
 
     private final Handler mHandler;
-    private final ColorStateList mDefaultColorState;
+    private final ConfigurationController mConfigurationController;
 
+    private ColorStateList mDefaultColorState;
     private CharSequence mMessage;
     private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
 
@@ -58,30 +69,58 @@
     };
 
     public KeyguardMessageArea(Context context) {
-        this(context, null);
+        super(context, null);
+        throw new IllegalStateException("This constructor should never be invoked");
     }
 
-    public KeyguardMessageArea(Context context, AttributeSet attrs) {
-        this(context, attrs, KeyguardUpdateMonitor.getInstance(context));
+    @Inject
+    public KeyguardMessageArea(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+            ConfigurationController configurationController) {
+        this(context, attrs, KeyguardUpdateMonitor.getInstance(context), configurationController);
     }
 
-    public KeyguardMessageArea(Context context, AttributeSet attrs, KeyguardUpdateMonitor monitor) {
+    public KeyguardMessageArea(Context context, AttributeSet attrs, KeyguardUpdateMonitor monitor,
+            ConfigurationController configurationController) {
         super(context, attrs);
         setLayerType(LAYER_TYPE_HARDWARE, null); // work around nested unclipped SaveLayer bug
 
         monitor.registerCallback(mInfoCallback);
         mHandler = new Handler(Looper.myLooper());
+        mConfigurationController = configurationController;
 
-        mDefaultColorState = getTextColors();
+        onThemeChanged();
         update();
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mConfigurationController.addCallback(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mConfigurationController.removeCallback(this);
+    }
+
+    @Override
     public void setNextMessageColor(ColorStateList colorState) {
         mNextMessageColorState = colorState;
     }
 
     @Override
+    public void onThemeChanged() {
+        TypedArray array = mContext.obtainStyledAttributes(new int[] {
+                R.attr.wallpaperTextColor
+        });
+        ColorStateList newTextColors = ColorStateList.valueOf(array.getColor(0, Color.RED));
+        array.recycle();
+        setTextColor(newTextColors);
+        mDefaultColorState = newTextColors;
+    }
+
+    @Override
     public void setMessage(CharSequence msg) {
         if (!TextUtils.isEmpty(msg)) {
             securityMessageChanged(msg);
@@ -108,9 +147,11 @@
         setMessage(message);
     }
 
-    public static SecurityMessageDisplay findSecurityMessageDisplay(View v) {
-        KeyguardMessageArea messageArea = (KeyguardMessageArea) v.findViewById(
-                R.id.keyguard_message_area);
+    public static KeyguardMessageArea findSecurityMessageDisplay(View v) {
+        KeyguardMessageArea messageArea = v.findViewById(R.id.keyguard_message_area);
+        if (messageArea == null) {
+            messageArea = v.getRootView().findViewById(R.id.keyguard_message_area);
+        }
         if (messageArea == null) {
             throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass());
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
index a543d17..6808c0f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java
@@ -67,7 +67,9 @@
     @Override
     protected void resetState() {
         super.resetState();
-        mSecurityMessageDisplay.setMessage("");
+        if (mSecurityMessageDisplay != null) {
+            mSecurityMessageDisplay.setMessage("");
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 185edbf..96392156 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -81,7 +81,9 @@
     @Override
     protected void resetState() {
         mPasswordEntry.setTextOperationUser(UserHandle.of(KeyguardUpdateMonitor.getCurrentUser()));
-        mSecurityMessageDisplay.setMessage("");
+        if (mSecurityMessageDisplay != null) {
+            mSecurityMessageDisplay.setMessage("");
+        }
         final boolean wasDisabled = mPasswordEntry.isEnabled();
         // Don't set enabled password entry & showSoftInput when PasswordEntry is invisible or in
         // pausing stage.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
index 112e067..8899bd9 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java
@@ -34,6 +34,7 @@
 import android.view.animation.Interpolator;
 import android.widget.LinearLayout;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternChecker;
 import com.android.internal.widget.LockPatternUtils;
@@ -92,7 +93,8 @@
         }
     };
     private Rect mTempRect = new Rect();
-    private KeyguardMessageArea mSecurityMessageDisplay;
+    @VisibleForTesting
+    KeyguardMessageArea mSecurityMessageDisplay;
     private View mEcaView;
     private ViewGroup mContainer;
     private int mDisappearYTranslation;
@@ -151,8 +153,6 @@
         // vibrate mode will be the same for the life of this screen
         mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());
 
-        mSecurityMessageDisplay =
-                (KeyguardMessageArea) KeyguardMessageArea.findSecurityMessageDisplay(this);
         mEcaView = findViewById(R.id.keyguard_selector_fade_container);
         mContainer = findViewById(R.id.container);
 
@@ -171,6 +171,12 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this);
+    }
+
+    @Override
     public void onEmergencyButtonClickedWhenInCall() {
         mCallback.reset();
     }
@@ -201,6 +207,10 @@
         mLockPatternView.setEnabled(true);
         mLockPatternView.clearPattern();
 
+        if (mSecurityMessageDisplay == null) {
+            return;
+        }
+
         // if the user is currently locked out, enforce it.
         long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
                 KeyguardUpdateMonitor.getCurrentUser());
@@ -212,7 +222,9 @@
     }
 
     private void displayDefaultSecurityMessage() {
-        mSecurityMessageDisplay.setMessage("");
+        if (mSecurityMessageDisplay != null) {
+            mSecurityMessageDisplay.setMessage("");
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
index fb4fe81..0d8a3db 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java
@@ -24,6 +24,7 @@
 import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -104,7 +105,9 @@
         int count = TelephonyManager.getDefault().getSimCount();
         Resources rez = getResources();
         String msg;
-        int color = Color.WHITE;
+        TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
+        int color = array.getColor(0, Color.WHITE);
+        array.recycle();
         if (count < 2) {
             msg = rez.getString(R.string.kg_sim_pin_instructions);
         } else {
@@ -120,7 +123,9 @@
             msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
         }
 
-        mSecurityMessageDisplay.setMessage(msg);
+        if (mSecurityMessageDisplay != null) {
+            mSecurityMessageDisplay.setMessage(msg);
+        }
         mSimImageView.setImageTintList(ColorStateList.valueOf(color));
     }
 
@@ -214,6 +219,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
+        resetState();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
index b17d117..27f71d1 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.graphics.Color;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -164,7 +165,9 @@
         int count = TelephonyManager.getDefault().getSimCount();
         Resources rez = getResources();
         String msg;
-        int color = Color.WHITE;
+        TypedArray array = mContext.obtainStyledAttributes(new int[] { R.attr.wallpaperTextColor });
+        int color = array.getColor(0, Color.WHITE);
+        array.recycle();
         if (count < 2) {
             msg = rez.getString(R.string.kg_puk_enter_puk_hint);
         } else {
@@ -179,7 +182,9 @@
         if (isEsimLocked) {
             msg = rez.getString(R.string.kg_sim_lock_esim_instructions, msg);
         }
-        mSecurityMessageDisplay.setMessage(msg);
+        if (mSecurityMessageDisplay != null) {
+            mSecurityMessageDisplay.setMessage(msg);
+        }
         mSimImageView.setImageTintList(ColorStateList.valueOf(color));
 
         // Sending empty PUK here to query the number of remaining PIN attempts
@@ -267,6 +272,7 @@
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mUpdateMonitorCallback);
+        resetState();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index cadfb79..fbbf64c 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -167,9 +167,9 @@
             return;
         }
         final int length = colorPalette.length;
-        mLockClock.setTextColor(colorPalette[Math.max(0, length - 3)]);
-        mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 6)],
-                colorPalette[Math.max(0, length - 3)]);
+        final int color = colorPalette[Math.max(0, length - 3)];
+        mLockClock.setTextColor(color);
+        mAnalogClock.setClockColors(color, color);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index d70d0d8..6af7ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2074,9 +2074,9 @@
 
     public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar,
             ViewGroup container, NotificationPanelView panelView,
-            BiometricUnlockController biometricUnlockController) {
+            BiometricUnlockController biometricUnlockController, ViewGroup lockIconContainer) {
         mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView,
-                biometricUnlockController, mDismissCallbackRegistry);
+                biometricUnlockController, mDismissCallbackRegistry, lockIconContainer);
         return mStatusBarKeyguardViewManager;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 56dbe2b..b2302cc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -28,6 +28,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SUPPORTS_WINDOW_CORNERS;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_WINDOW_CORNER_RADIUS;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
@@ -489,12 +490,17 @@
         }
     }
 
+    public int getSystemUiStateFlags() {
+        return mSysUiStateFlags;
+    }
+
     private void updateSystemUiStateFlags() {
         final NavigationBarController navBar = Dependency.get(NavigationBarController.class);
         final NavigationBarFragment navBarFragment = navBar.getDefaultNavigationBarFragment();
         final StatusBar statusBar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
         final boolean panelExpanded = statusBar != null && statusBar.getPanel() != null
                 && statusBar.getPanel().isFullyExpanded();
+        final boolean bouncerShowing = statusBar != null && statusBar.isBouncerShowing();
         mSysUiStateFlags = 0;
         mSysUiStateFlags |= ActivityManagerWrapper.getInstance().isScreenPinningActive()
                 ? SYSUI_STATE_SCREEN_PINNING : 0;
@@ -502,6 +508,8 @@
                 ? SYSUI_STATE_NAV_BAR_HIDDEN : 0;
         mSysUiStateFlags |= panelExpanded
                 ? SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED : 0;
+        mSysUiStateFlags |= bouncerShowing
+                ? SYSUI_STATE_BOUNCER_SHOWING : 0;
         notifySystemUiStateFlags(mSysUiStateFlags);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 25436a9..7d4cf75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -41,6 +41,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.settingslib.Utils;
@@ -51,6 +53,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
 import com.android.systemui.statusbar.phone.LockIcon;
+import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.util.wakelock.SettableWakeLock;
@@ -80,11 +83,13 @@
     private final UserManager mUserManager;
     private final IBatteryStats mBatteryInfo;
     private final SettableWakeLock mWakeLock;
+    private final LockPatternUtils mLockPatternUtils;
 
     private final int mSlowThreshold;
     private final int mFastThreshold;
     private final LockIcon mLockIcon;
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
 
     private String mRestingIndication;
     private CharSequence mTransientIndication;
@@ -104,14 +109,13 @@
 
     private final DevicePolicyManager mDevicePolicyManager;
     private boolean mDozing;
-    private float mDarkAmount;
 
     /**
      * Creates a new KeyguardIndicationController and registers callbacks.
      */
     public KeyguardIndicationController(Context context, ViewGroup indicationArea,
             LockIcon lockIcon) {
-        this(context, indicationArea, lockIcon,
+        this(context, indicationArea, lockIcon, new LockPatternUtils(context),
                 WakeLock.createPartial(context, "Doze:KeyguardIndication"));
 
         registerCallbacks(KeyguardUpdateMonitor.getInstance(context));
@@ -122,7 +126,7 @@
      */
     @VisibleForTesting
     KeyguardIndicationController(Context context, ViewGroup indicationArea, LockIcon lockIcon,
-                WakeLock wakeLock) {
+            LockPatternUtils lockPatternUtils, WakeLock wakeLock) {
         mContext = context;
         mIndicationArea = indicationArea;
         mTextView = indicationArea.findViewById(R.id.keyguard_indication_text);
@@ -130,7 +134,9 @@
                 mTextView.getTextColors() : ColorStateList.valueOf(Color.WHITE);
         mDisclosure = indicationArea.findViewById(R.id.keyguard_indication_enterprise_disclosure);
         mLockIcon = lockIcon;
+        mLockIcon.setOnLongClickListener(this::handleTrustCircleClick);
         mWakeLock = new SettableWakeLock(wakeLock, TAG);
+        mLockPatternUtils = lockPatternUtils;
 
         Resources res = context.getResources();
         mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
@@ -164,6 +170,15 @@
         Dependency.get(StatusBarStateController.class).removeCallback(this);
     }
 
+    private boolean handleTrustCircleClick(View view) {
+        mLockscreenGestureLogger.write(MetricsProto.MetricsEvent.ACTION_LS_LOCK,
+                0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
+        showTransientIndication(R.string.keyguard_indication_trust_disabled);
+        mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
+
+        return true;
+    }
+
     /**
      * Gets the {@link KeyguardUpdateMonitorCallback} instance associated with this
      * {@link KeyguardIndicationController}.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 1927f22..8028200 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -17,6 +17,10 @@
 
 import static android.view.Display.INVALID_DISPLAY;
 
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.content.res.Resources;
@@ -127,7 +131,7 @@
 
     private final PointF mDownPoint = new PointF();
     private boolean mThresholdCrossed = false;
-    private boolean mIgnoreThisGesture = false;
+    private boolean mAllowGesture = false;
     private boolean mIsOnLeftEdge;
 
     private int mImeHeight = 0;
@@ -285,9 +289,14 @@
 
     private void onMotionEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            // Verify if this is in within the touch region
-            mIgnoreThisGesture = !isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
-            if (!mIgnoreThisGesture) {
+            // Verify if this is in within the touch region and we aren't in immersive mode, and
+            // either the bouncer is showing or the notification panel is hidden
+            int stateFlags = mOverviewProxyService.getSystemUiStateFlags();
+            mAllowGesture = (stateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
+                    && ((stateFlags & SYSUI_STATE_BOUNCER_SHOWING) == SYSUI_STATE_BOUNCER_SHOWING
+                            || (stateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0)
+                    && isWithinTouchRegion((int) ev.getX(), (int) ev.getY());
+            if (mAllowGesture) {
                 mIsOnLeftEdge = ev.getX() < mEdgeWidth;
                 mEdgePanelLp.gravity = mIsOnLeftEdge
                         ? (Gravity.LEFT | Gravity.TOP)
@@ -302,13 +311,13 @@
                 mThresholdCrossed = false;
                 mEdgePanel.handleTouch(ev);
             }
-        } else if (!mIgnoreThisGesture) {
+        } else if (mAllowGesture) {
             if (!mThresholdCrossed && ev.getAction() == MotionEvent.ACTION_MOVE) {
                 float dx = Math.abs(ev.getX() - mDownPoint.x);
                 float dy = Math.abs(ev.getY() - mDownPoint.y);
                 if (dy > dx && dy > mTouchSlop) {
                     // Send action cancel to reset all the touch events
-                    mIgnoreThisGesture = true;
+                    mAllowGesture = false;
                     MotionEvent cancelEv = MotionEvent.obtain(ev);
                     cancelEv.setAction(MotionEvent.ACTION_CANCEL);
                     mEdgePanel.handleTouch(cancelEv);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 49d421b..cd0a43e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -56,7 +56,6 @@
     private int mMinFlingVelocity;
     private int mHintGrowAmount;
     private KeyguardAffordanceView mLeftIcon;
-    private KeyguardAffordanceView mCenterIcon;
     private KeyguardAffordanceView mRightIcon;
     private Animator mSwipeAnimator;
     private FalsingManager mFalsingManager;
@@ -85,7 +84,6 @@
         mCallback = callback;
         initIcons();
         updateIcon(mLeftIcon, 0.0f, mLeftIcon.getRestingAlpha(), false, false, true, false);
-        updateIcon(mCenterIcon, 0.0f, mCenterIcon.getRestingAlpha(), false, false, true, false);
         updateIcon(mRightIcon, 0.0f, mRightIcon.getRestingAlpha(), false, false, true, false);
         initDimens();
     }
@@ -108,7 +106,6 @@
 
     private void initIcons() {
         mLeftIcon = mCallback.getLeftIcon();
-        mCenterIcon = mCallback.getCenterIcon();
         mRightIcon = mCallback.getRightIcon();
         updatePreviews();
     }
@@ -398,8 +395,6 @@
             }
             updateIcon(otherView, 0.0f, fadeOutAlpha * otherView.getRestingAlpha(),
                     animateIcons, slowAnimation, isReset, forceNoCircleAnimation);
-            updateIcon(mCenterIcon, 0.0f, fadeOutAlpha * mCenterIcon.getRestingAlpha(),
-                    animateIcons, slowAnimation, isReset, forceNoCircleAnimation);
 
             mTranslation = translation;
         }
@@ -417,7 +412,6 @@
         KeyguardAffordanceView otherView = targetView == mRightIcon ? mLeftIcon : mRightIcon;
         updateIconAlpha(targetView, alpha + fadeOutAlpha * targetView.getRestingAlpha(), false);
         updateIconAlpha(otherView, fadeOutAlpha * otherView.getRestingAlpha(), false);
-        updateIconAlpha(mCenterIcon, fadeOutAlpha * mCenterIcon.getRestingAlpha(), false);
     }
 
     private float getTranslationFromRadius(float circleSize) {
@@ -538,12 +532,10 @@
         if (animate) {
             fling(0, false, !left);
             updateIcon(otherView, 0.0f, 0, true, false, true, false);
-            updateIcon(mCenterIcon, 0.0f, 0, true, false, true, false);
         } else {
             mCallback.onAnimationToSideStarted(!left, mTranslation, 0);
             mTranslation = left ? mCallback.getMaxTranslationDistance()
                     : mCallback.getMaxTranslationDistance();
-            updateIcon(mCenterIcon, 0.0f, 0.0f, false, false, true, false);
             updateIcon(otherView, 0.0f, 0.0f, false, false, true, false);
             targetView.instantFinishAnimation();
             mFlingEndListener.onAnimationEnd(null);
@@ -575,8 +567,6 @@
 
         KeyguardAffordanceView getLeftIcon();
 
-        KeyguardAffordanceView getCenterIcon();
-
         KeyguardAffordanceView getRightIcon();
 
         View getLeftPreview();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index a924680..cb64f10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -40,7 +40,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.graphics.drawable.Drawable;
-import android.hardware.biometrics.BiometricSourceType;
 import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -64,7 +63,6 @@
 import android.widget.TextView;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
@@ -77,7 +75,6 @@
 import com.android.systemui.plugins.IntentButtonProvider;
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton;
 import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState;
-import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
@@ -94,7 +91,7 @@
  */
 public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickListener,
         UnlockMethodCache.OnUnlockMethodChangedListener,
-        AccessibilityController.AccessibilityStateChangedCallback, View.OnLongClickListener {
+        AccessibilityController.AccessibilityStateChangedCallback {
 
     final static String TAG = "StatusBar/KeyguardBottomAreaView";
 
@@ -122,8 +119,6 @@
 
     private KeyguardAffordanceView mRightAffordanceView;
     private KeyguardAffordanceView mLeftAffordanceView;
-    private LockIcon mLockIcon;
-    private ViewGroup mLockIconContainer;
     private ViewGroup mIndicationArea;
     private TextView mEnterpriseDisclosure;
     private TextView mIndicationText;
@@ -169,7 +164,6 @@
     private IntentButton mLeftButton = new DefaultLeftButton();
     private Extension<IntentButton> mLeftExtension;
     private String mLeftButtonStr;
-    private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
     private boolean mDozing;
     private int mIndicationBottomMargin;
     private float mDarkAmount;
@@ -199,9 +193,7 @@
         public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
             super.onInitializeAccessibilityNodeInfo(host, info);
             String label = null;
-            if (host == mLockIcon) {
-                label = getResources().getString(R.string.unlock_label);
-            } else if (host == mRightAffordanceView) {
+            if (host == mRightAffordanceView) {
                 label = getResources().getString(R.string.camera_label);
             } else if (host == mLeftAffordanceView) {
                 if (mLeftIsVoiceAssist) {
@@ -216,11 +208,7 @@
         @Override
         public boolean performAccessibilityAction(View host, int action, Bundle args) {
             if (action == ACTION_CLICK) {
-                if (host == mLockIcon) {
-                    mStatusBar.animateCollapsePanels(
-                            CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
-                    return true;
-                } else if (host == mRightAffordanceView) {
+                if (host == mRightAffordanceView) {
                     launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
                     return true;
                 } else if (host == mLeftAffordanceView) {
@@ -247,8 +235,6 @@
         mOverlayContainer = findViewById(R.id.overlay_container);
         mRightAffordanceView = findViewById(R.id.camera_button);
         mLeftAffordanceView = findViewById(R.id.left_button);
-        mLockIcon = findViewById(R.id.lock_icon);
-        mLockIconContainer = findViewById(R.id.lock_icon_container);
         mIndicationArea = findViewById(R.id.keyguard_indication_area);
         mEnterpriseDisclosure = findViewById(
                 R.id.keyguard_indication_enterprise_disclosure);
@@ -260,14 +246,9 @@
         updateCameraVisibility();
         mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
         mUnlockMethodCache.addListener(this);
-        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-        mLockIcon.setScreenOn(updateMonitor.isScreenOn());
-        mLockIcon.update();
         setClipChildren(false);
         setClipToPadding(false);
         inflateCameraPreview();
-        mLockIcon.setOnClickListener(this);
-        mLockIcon.setOnLongClickListener(this);
         mRightAffordanceView.setOnClickListener(this);
         mLeftAffordanceView.setOnClickListener(this);
         initAccessibility();
@@ -275,7 +256,6 @@
         mFlashlightController = Dependency.get(FlashlightController.class);
         mAccessibilityController = Dependency.get(AccessibilityController.class);
         mAssistManager = Dependency.get(AssistManager.class);
-        mLockIcon.setAccessibilityController(mAccessibilityController);
         mActivityIntentHelper = new ActivityIntentHelper(getContext());
         updateLeftAffordance();
     }
@@ -316,7 +296,6 @@
     }
 
     private void initAccessibility() {
-        mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
         mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
         mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
     }
@@ -348,13 +327,6 @@
         mRightAffordanceView.setLayoutParams(lp);
         updateRightAffordanceIcon();
 
-        lp = mLockIcon.getLayoutParams();
-        lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width);
-        lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_lock_height);
-        mLockIcon.setLayoutParams(lp);
-        mLockIcon.setContentDescription(getContext().getText(R.string.accessibility_unlock_button));
-        mLockIcon.update(true /* force */);
-
         lp = mLeftAffordanceView.getLayoutParams();
         lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width);
         lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height);
@@ -437,7 +409,6 @@
         mLeftAffordanceView.setClickable(touchExplorationEnabled);
         mRightAffordanceView.setFocusable(accessibilityEnabled);
         mLeftAffordanceView.setFocusable(accessibilityEnabled);
-        mLockIcon.update();
     }
 
     @Override
@@ -446,30 +417,9 @@
             launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE);
         } else if (v == mLeftAffordanceView) {
             launchLeftAffordance();
-        } if (v == mLockIcon) {
-            if (!mAccessibilityController.isAccessibilityEnabled()) {
-                handleTrustCircleClick();
-            } else {
-                mStatusBar.animateCollapsePanels(
-                        CommandQueue.FLAG_EXCLUDE_NONE, true /* force */);
-            }
         }
     }
 
-    @Override
-    public boolean onLongClick(View v) {
-        handleTrustCircleClick();
-        return true;
-    }
-
-    private void handleTrustCircleClick() {
-        mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_LOCK, 0 /* lengthDp - N/A */,
-                0 /* velocityDp - N/A */);
-        mIndicationController.showTransientIndication(
-                R.string.keyguard_indication_trust_disabled);
-        mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
-    }
-
     public void bindCameraPrewarmService() {
         Intent intent = getCameraIntent();
         ActivityInfo targetInfo = mActivityIntentHelper.getTargetActivityInfo(intent,
@@ -571,19 +521,9 @@
             return;
         }
         mDarkAmount = darkAmount;
-        mLockIcon.setDarkAmount(darkAmount);
         dozeTimeTick();
     }
 
-    /**
-     * When keyguard is in pulsing (AOD2) state.
-     * @param pulsing {@code true} when pulsing.
-     * @param animated if transition should be animated.
-     */
-    public void setPulsing(boolean pulsing, boolean animated) {
-        mLockIcon.setPulsing(pulsing, animated);
-    }
-
     private static boolean isSuccessfulLaunch(int result) {
         return result == ActivityManager.START_SUCCESS
                 || result == ActivityManager.START_DELIVERED_TO_TOP
@@ -641,7 +581,6 @@
     protected void onVisibilityChanged(View changedView, int visibility) {
         super.onVisibilityChanged(changedView, visibility);
         if (changedView == this && visibility == VISIBLE) {
-            mLockIcon.update();
             updateCameraVisibility();
         }
     }
@@ -662,14 +601,6 @@
         return mCameraPreview;
     }
 
-    public LockIcon getLockIcon() {
-        return mLockIcon;
-    }
-
-    public ViewGroup getLockIconContainer() {
-        return mLockIconContainer;
-    }
-
     public View getIndicationArea() {
         return mIndicationArea;
     }
@@ -681,7 +612,6 @@
 
     @Override
     public void onUnlockMethodStateChanged() {
-        mLockIcon.update();
         updateCameraVisibility();
     }
 
@@ -764,32 +694,6 @@
                 }
 
                 @Override
-                public void onScreenTurnedOn() {
-                    mLockIcon.setScreenOn(true);
-                }
-
-                @Override
-                public void onScreenTurnedOff() {
-                    mLockIcon.setScreenOn(false);
-                }
-
-                @Override
-                public void onKeyguardVisibilityChanged(boolean showing) {
-                    mLockIcon.update();
-                }
-
-                @Override
-                public void onBiometricRunningStateChanged(boolean running,
-                        BiometricSourceType biometricSourceType) {
-                    mLockIcon.update();
-                }
-
-                @Override
-                public void onStrongAuthStateChanged(int userId) {
-                    mLockIcon.update();
-        }
-
-                @Override
                 public void onUserUnlocked() {
                     inflateCameraPreview();
                     updateCameraVisibility();
@@ -836,7 +740,6 @@
 
         updateCameraVisibility();
         updateLeftAffordanceIcon();
-        mLockIcon.setDozing(dozing);
 
         if (dozing) {
             mOverlayContainer.setVisibility(INVISIBLE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 1d2ca9f..b00d874 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -167,6 +167,7 @@
         DejankUtils.postAfterTraversal(mShowRunnable);
 
         mCallback.onBouncerVisiblityChanged(true /* shown */);
+        mExpansionCallback.onStartingToShow();
     }
 
     public boolean isScrimmed() {
@@ -429,8 +430,6 @@
         mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
                 com.android.systemui.R.dimen.status_bar_height);
         mRoot.setVisibility(View.INVISIBLE);
-        mRoot.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
-                oldBottom) -> mExpansionCallback.onLayout());
         mRoot.setAccessibilityPaneTitle(mKeyguardView.getAccessibilityTitleForCurrentMode());
 
         final WindowInsets rootInsets = mRoot.getRootWindowInsets();
@@ -510,7 +509,7 @@
     public interface BouncerExpansionCallback {
         void onFullyShown();
         void onStartingToHide();
+        void onStartingToShow();
         void onFullyHidden();
-        void onLayout();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index d59f248..0171d7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -99,11 +99,6 @@
      */
     private float mDarkAmount;
 
-    /**
-     * If keyguard will require a password or just fade away.
-     */
-    private boolean mCurrentlySecure;
-
     private float mEmptyDragAmount;
 
     /**
@@ -122,7 +117,7 @@
 
     public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
             float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
-            float dark, boolean secure, float emptyDragAmount) {
+            float dark, float emptyDragAmount) {
         mMinTopMargin = minTopMargin + mContainerTopPadding;
         mMaxShadeBottom = maxShadeBottom;
         mNotificationStackHeight = notificationStackHeight;
@@ -131,7 +126,6 @@
         mKeyguardStatusHeight = keyguardStatusHeight;
         mClockPreferredY = clockPreferredY;
         mDarkAmount = dark;
-        mCurrentlySecure = secure;
         mEmptyDragAmount = emptyDragAmount;
     }
 
@@ -204,13 +198,8 @@
      * @return Alpha from 0 to 1.
      */
     private float getClockAlpha(int y) {
-        float alphaKeyguard;
-        if (mCurrentlySecure) {
-            alphaKeyguard = 1;
-        } else {
-            alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedClockPosition()));
-            alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
-        }
+        float alphaKeyguard = Math.max(0, y / Math.max(1f, getExpandedClockPosition()));
+        alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard);
         return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 3cc4a7b..971e5b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -16,29 +16,40 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.Color;
-import android.graphics.PorterDuff;
 import android.graphics.drawable.Animatable2;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
+import android.hardware.biometrics.BiometricSourceType;
 import android.util.AttributeSet;
-import android.view.ContextThemeWrapper;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.graphics.ColorUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.KeyguardAffordanceView;
 import com.android.systemui.statusbar.policy.AccessibilityController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 /**
  * Manages the different states and animations of the unlock icon.
  */
-public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener {
+public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
+        StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
+        UnlockMethodCache.OnUnlockMethodChangedListener {
 
     private static final int FP_DRAW_OFF_TIMEOUT = 800;
 
@@ -46,13 +57,16 @@
     private static final int STATE_LOCK_OPEN = 1;
     private static final int STATE_SCANNING_FACE = 2;
     private static final int STATE_BIOMETRICS_ERROR = 3;
+    private final ConfigurationController mConfigurationController;
+    private final StatusBarStateController mStatusBarStateController;
+    private final UnlockMethodCache mUnlockMethodCache;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final AccessibilityController mAccessibilityController;
 
     private int mLastState = 0;
     private boolean mTransientBiometricsError;
     private boolean mScreenOn;
     private boolean mLastScreenOn;
-    private final UnlockMethodCache mUnlockMethodCache;
-    private AccessibilityController mAccessibilityController;
     private boolean mIsFaceUnlockState;
     private int mDensity;
     private boolean mPulsing;
@@ -61,18 +75,82 @@
     private boolean mLastDozing;
     private boolean mLastPulsing;
     private boolean mLastBouncerVisible;
+    private int mIconColor;
 
     private final Runnable mDrawOffTimeout = () -> update(true /* forceUpdate */);
-    private float mDarkAmount;
+    private float mDozeAmount;
 
-    public LockIcon(Context context, AttributeSet attrs) {
+    private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onScreenTurnedOn() {
+                    mScreenOn = true;
+                    update();
+                }
+
+                @Override
+                public void onScreenTurnedOff() {
+                    mScreenOn = false;
+                    update();
+                }
+
+                @Override
+                public void onKeyguardVisibilityChanged(boolean showing) {
+                    update();
+                }
+
+                @Override
+                public void onBiometricRunningStateChanged(boolean running,
+                        BiometricSourceType biometricSourceType) {
+                    update();
+                }
+
+                @Override
+                public void onStrongAuthStateChanged(int userId) {
+                    update();
+                }
+    };
+
+    @Inject
+    public LockIcon(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+            StatusBarStateController statusBarStateController,
+            ConfigurationController configurationController,
+            AccessibilityController accessibilityController) {
         super(context, attrs);
-        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
-                attrs, new int[]{ R.attr.backgroundProtectedStyle }, 0, 0);
-        mContext = new ContextThemeWrapper(context,
-                typedArray.getResourceId(0, R.style.BackgroundProtectedStyle));
-        typedArray.recycle();
+        mContext = context;
         mUnlockMethodCache = UnlockMethodCache.getInstance(context);
+        mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
+        mAccessibilityController = accessibilityController;
+        mConfigurationController = configurationController;
+        mStatusBarStateController = statusBarStateController;
+        onThemeChanged();
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mStatusBarStateController.addCallback(this);
+        mConfigurationController.addCallback(this);
+        mKeyguardUpdateMonitor.registerCallback(mUpdateMonitorCallback);
+        mUnlockMethodCache.addListener(this);
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        mStatusBarStateController.removeCallback(this);
+        mConfigurationController.removeCallback(this);
+        mKeyguardUpdateMonitor.removeCallback(mUpdateMonitorCallback);
+        mUnlockMethodCache.removeListener(this);
+    }
+
+    @Override
+    public void onThemeChanged() {
+        TypedArray typedArray = mContext.getTheme().obtainStyledAttributes(
+                null, new int[]{ R.attr.wallpaperTextColor }, 0, 0);
+        mIconColor = typedArray.getColor(0, Color.WHITE);
+        typedArray.recycle();
+        updateDarkTint();
     }
 
     @Override
@@ -88,11 +166,6 @@
         update();
     }
 
-    public void setScreenOn(boolean screenOn) {
-        mScreenOn = screenOn;
-        update();
-    }
-
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
@@ -164,7 +237,7 @@
             mLastBouncerVisible = mBouncerVisible;
         }
 
-        setVisibility(mDozing && !mPulsing ? GONE : VISIBLE);
+        setVisibility(mDozing && !mPulsing ? INVISIBLE : VISIBLE);
         updateClickability();
     }
 
@@ -185,9 +258,8 @@
     @Override
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
-        KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
-        boolean fingerprintRunning = updateMonitor.isFingerprintDetectionRunning();
-        boolean unlockingAllowed = updateMonitor.isUnlockingWithBiometricAllowed();
+        boolean fingerprintRunning = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
+        boolean unlockingAllowed = mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed();
         if (fingerprintRunning && unlockingAllowed) {
             AccessibilityNodeInfo.AccessibilityAction unlock
                     = new AccessibilityNodeInfo.AccessibilityAction(
@@ -204,10 +276,6 @@
         }
     }
 
-    public void setAccessibilityController(AccessibilityController accessibilityController) {
-        mAccessibilityController = accessibilityController;
-    }
-
     private Drawable getIconForState(int state) {
         int iconRes;
         switch (state) {
@@ -273,17 +341,17 @@
         }
     }
 
-    public void setDarkAmount(float darkAmount) {
-        mDarkAmount = darkAmount;
+    @Override
+    public void onDozeAmountChanged(float linear, float eased) {
+        mDozeAmount = eased;
         updateDarkTint();
     }
 
     /**
      * When keyguard is in pulsing (AOD2) state.
      * @param pulsing {@code true} when pulsing.
-     * @param animated if transition should be animated.
      */
-    public void setPulsing(boolean pulsing, boolean animated) {
+    public void setPulsing(boolean pulsing) {
         mPulsing = pulsing;
         update();
     }
@@ -291,15 +359,15 @@
     /**
      * Sets the dozing state of the keyguard.
      */
-    public void setDozing(boolean dozing) {
+    @Override
+    public void onDozingChanged(boolean dozing) {
         mDozing = dozing;
         update();
     }
 
     private void updateDarkTint() {
-        Drawable drawable = getDrawable().mutate();
-        int color = ColorUtils.blendARGB(Color.TRANSPARENT, Color.WHITE, mDarkAmount);
-        drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
+        int color = ColorUtils.blendARGB(mIconColor, Color.WHITE, mDozeAmount);
+        setImageTintList(ColorStateList.valueOf(color));
     }
 
     /**
@@ -312,4 +380,27 @@
         mBouncerVisible = bouncerVisible;
         update();
     }
+
+    @Override
+    public void onDensityOrFontScaleChanged() {
+        ViewGroup.LayoutParams lp = getLayoutParams();
+        if (lp == null) {
+            return;
+        }
+        lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_lock_width);
+        lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_lock_height);
+        setLayoutParams(lp);
+        update(true /* force */);
+    }
+
+    @Override
+    public void onLocaleListChanged() {
+        setContentDescription(getContext().getText(R.string.accessibility_unlock_button));
+        update(true /* force */);
+    }
+
+    @Override
+    public void onUnlockMethodStateChanged() {
+        update();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index ab13149..57b2ee9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -204,7 +204,6 @@
     private ValueAnimator mQsExpansionAnimator;
     private FlingAnimationUtils mFlingAnimationUtils;
     private int mStatusBarMinHeight;
-    private boolean mUnlockIconActive;
     private int mNotificationsHeaderCollideDistance;
     private int mUnlockMoveDistance;
     private float mEmptyDragAmount;
@@ -330,7 +329,6 @@
     private final ShadeController mShadeController =
             Dependency.get(ShadeController.class);
     private int mDisplayId;
-    private KeyguardBouncer mBouncer;
 
     /**
      * Cache the resource id of the theme to avoid unnecessary work in onThemeChanged.
@@ -640,7 +638,6 @@
                     mKeyguardStatusView.getHeight(),
                     clockPreferredY,
                     mInterpolatedDarkAmount,
-                    mStatusBar.isKeyguardCurrentlySecure(),
                     mEmptyDragAmount);
             mClockPositionAlgorithm.run(mClockPositionResult);
             PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X,
@@ -736,7 +733,6 @@
     public void resetViews(boolean animate) {
         mIsLaunchTransitionFinished = false;
         mBlockTouches = false;
-        mUnlockIconActive = false;
         if (!mLaunchingAffordance) {
             mAffordanceHelper.reset(false);
             mLastCameraLaunchSource = KeyguardBottomAreaView.CAMERA_LAUNCH_SOURCE_AFFORDANCE;
@@ -1518,6 +1514,10 @@
             mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */,
                     false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */);
         }
+        if (mExpansionListener != null) {
+            mExpansionListener.onQsExpansionChanged(mQsMaxExpansionHeight != 0
+                    ? mQsExpansionHeight / mQsMaxExpansionHeight : 0);
+        }
         if (DEBUG) {
             invalidate();
         }
@@ -1837,6 +1837,9 @@
                 !mHeadsUpManager.hasPinnedHeadsUp()) {
             alpha = getFadeoutAlpha();
         }
+        if (mBarState == StatusBarState.KEYGUARD && !mHintAnimationRunning) {
+            alpha *= mClockPositionResult.clockAlpha;
+        }
         mNotificationStackScroller.setAlpha(alpha);
     }
 
@@ -2292,11 +2295,6 @@
     }
 
     @Override
-    public KeyguardAffordanceView getCenterIcon() {
-        return mKeyguardBottomArea.getLockIcon();
-    }
-
-    @Override
     public KeyguardAffordanceView getRightIcon() {
         return getLayoutDirection() == LAYOUT_DIRECTION_RTL
                 ? mKeyguardBottomArea.getLeftView()
@@ -2723,7 +2721,6 @@
     private void setLaunchingAffordance(boolean launchingAffordance) {
         getLeftIcon().setLaunchingAffordance(launchingAffordance);
         getRightIcon().setLaunchingAffordance(launchingAffordance);
-        getCenterIcon().setLaunchingAffordance(launchingAffordance);
     }
 
     /**
@@ -2872,7 +2869,6 @@
         }
         mNotificationStackScroller.setPulsing(pulsing, animatePulse);
         mKeyguardStatusView.setPulsing(pulsing);
-        mKeyguardBottomArea.setPulsing(pulsing, animatePulse);
     }
 
     public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
@@ -2910,10 +2906,6 @@
         mKeyguardBottomArea.setUserSetupComplete(userSetupComplete);
     }
 
-    public LockIcon getLockIcon() {
-        return mKeyguardBottomArea.getLockIcon();
-    }
-
     public void applyExpandAnimationParams(ExpandAnimationParameters params) {
         mExpandOffset = params != null ? params.getTopChange() : 0;
         updateQsExpansion();
@@ -2957,7 +2949,6 @@
     public void onBouncerPreHideAnimation() {
         setKeyguardStatusViewVisibility(mBarState, true /* keyguardFadingAway */,
                 false /* goingToFullShade */);
-        updateLockIcon();
     }
 
     /**
@@ -3056,71 +3047,29 @@
         mKeyguardBottomArea.showTransientIndication(id);
     }
 
-    /**
-     * Sets the reference to the {@link KeyguardBouncer}.
-     */
-    public void setBouncer(KeyguardBouncer bouncer) {
-        mBouncer = bouncer;
-        updateLockIcon();
-    }
-
-    public void updateLockIcon() {
-        if (mBouncer == null) {
-            return;
-        }
-
-        ViewGroup bouncerContainer = mBouncer.getLockIconContainer();
-        ViewGroup bottomContainer = mKeyguardBottomArea.getLockIconContainer();
-        LockIcon lockIcon = mKeyguardBottomArea.getLockIcon();
-
-        if (mBouncer.isAnimatingAway()) {
-            if (!lockIcon.isAnimatingAlpha() && lockIcon.getAlpha() != 0) {
-                lockIcon.setImageAlpha(0, true /* animate */);
-            }
-            // Let's not re-apply the translation if the bouncer is animating, its
-            // animation also includes translation and transition would be jarring.
-            return;
-        }
-
-        // Lock icon needs to be re-parented in case of a scrimmed bouncer,
-        // otherwise it would be under the scrim.
-        if (mBouncer.isScrimmed() && bouncerContainer != null
-                && lockIcon.getParent() != bouncerContainer) {
-            ((ViewGroup) lockIcon.getParent()).removeView(lockIcon);
-            bouncerContainer.addView(lockIcon);
-        } else if (!mBouncer.isScrimmed() && bottomContainer != null
-                && lockIcon.getParent() != bottomContainer) {
-            ((ViewGroup) lockIcon.getParent()).removeView(lockIcon);
-            bottomContainer.addView(lockIcon);
-        }
-
-        float translation = 0;
-        if (bouncerContainer != null && bottomContainer != null && !mBouncer.isScrimmed()) {
-            float bottomAreaContainerY = getCommonTop(bottomContainer);
-            float bouncerLockY = getCommonTop(bouncerContainer);
-            if (bouncerLockY < bottomAreaContainerY) {
-                translation = bouncerLockY - bottomAreaContainerY;
-            }
-        }
-        lockIcon.setTranslationY(translation);
-
-        if (lockIcon.getAlpha() != 1) {
-            lockIcon.setImageAlpha(1, false /* animate */);
-        }
-    }
-
-    private static float getCommonTop(View view) {
-        float y = view.getTop();
-        ViewGroup parent = (ViewGroup) view.getParent();
-        while (!(parent instanceof StatusBarWindowView) && parent != null) {
-            y += parent.getY();
-            parent = (ViewGroup) parent.getParent();
-        }
-        return y;
-    }
-
     @Override
     public void onDynamicPrivacyChanged() {
         mAnimateNextPositionUpdate = true;
     }
+
+    /**
+     * Panel and QS expansion callbacks.
+     */
+    public interface PanelExpansionListener {
+        /**
+         * Invoked whenever the notification panel expansion changes, at every animation frame.
+         * This is the main expansion that happens when the user is swiping up to dismiss the
+         * lock screen.
+         *
+         * @param expansion 0 when collapsed, 1 when expanded.
+         * @param tracking {@code true} when the user is actively dragging the panel.
+         */
+        void onPanelExpansionChanged(float expansion, boolean tracking);
+
+        /**
+         * Invoked whenever the QS expansion changes, at every animation frame.
+         * @param expansion 0 when collapsed, 1 when expanded.
+         */
+        void onQsExpansionChanged(float expansion);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 99345d2..24389f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -49,11 +49,11 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.phone.NotificationPanelView.PanelExpansionListener;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.function.BiConsumer;
 
 public abstract class PanelView extends FrameLayout {
     public static final boolean DEBUG = PanelBar.DEBUG;
@@ -68,7 +68,7 @@
     private boolean mVibrateOnOpening;
     protected boolean mLaunchingNotification;
     private int mFixedDuration = NO_FIXED_DURATION;
-    private BiConsumer<Float, Boolean> mExpansionListener;
+    protected PanelExpansionListener mExpansionListener;
 
     private final void logf(String fmt, Object... args) {
         Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -1115,7 +1115,6 @@
 
         View[] viewsToAnimate = {
                 mKeyguardBottomArea.getIndicationArea(),
-                mKeyguardBottomArea.getLockIcon(),
                 mStatusBar.getAmbientIndicationContainer()};
         for (View v : viewsToAnimate) {
             if (v == null) {
@@ -1163,28 +1162,25 @@
 
     private ValueAnimator createHeightAnimator(float targetHeight) {
         ValueAnimator animator = ValueAnimator.ofFloat(mExpandedHeight, targetHeight);
-        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                setExpandedHeightInternal((Float) animation.getAnimatedValue());
-            }
-        });
+        animator.addUpdateListener(
+                animation -> setExpandedHeightInternal((float) animation.getAnimatedValue()));
         return animator;
     }
 
     protected void notifyBarPanelExpansionChanged() {
+        float fraction = mInstantExpanding ? 1 : mExpandedFraction;
         if (mBar != null) {
-            mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f
+            mBar.panelExpansionChanged(fraction, fraction > 0f
                     || mPeekAnimator != null || mInstantExpanding
                     || isPanelVisibleBecauseOfHeadsUp() || mTracking || mHeightAnimator != null);
         }
         if (mExpansionListener != null) {
-            mExpansionListener.accept(mExpandedFraction, mTracking);
+            mExpansionListener.onPanelExpansionChanged(fraction, mTracking);
         }
     }
 
-    public void setExpansionListener(BiConsumer<Float, Boolean> consumer) {
-        mExpansionListener = consumer;
+    public void setExpansionListener(PanelExpansionListener panelExpansionListener) {
+        mExpansionListener = panelExpansionListener;
     }
 
     protected abstract boolean isPanelVisibleBecauseOfHeadsUp();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9fccf91..a381bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -30,6 +30,7 @@
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_INVALID;
 import static com.android.systemui.shared.system.WindowManagerWrapper.NAV_BAR_POS_LEFT;
 import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
@@ -166,6 +167,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanel;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -879,7 +881,7 @@
         mKeyguardIndicationController =
                 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                         mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
-                        mNotificationPanel.getLockIcon());
+                        mStatusBarWindow.findViewById(R.id.lock_icon));
         mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);
 
         mAmbientIndicationContainer = mStatusBarWindow.findViewById(
@@ -1171,7 +1173,7 @@
         mKeyguardIndicationController =
                 SystemUIFactory.getInstance().createKeyguardIndicationController(mContext,
                         mStatusBarWindow.findViewById(R.id.keyguard_indication_area),
-                        mNotificationPanel.getLockIcon());
+                        mStatusBarWindow.findViewById(R.id.lock_icon));
         mNotificationPanel.setKeyguardIndicationController(mKeyguardIndicationController);
         mKeyguardIndicationController
                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -1222,7 +1224,8 @@
                 mScrimController, this, UnlockMethodCache.getInstance(mContext),
                 new Handler(), mKeyguardUpdateMonitor, Dependency.get(TunerService.class));
         mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
-                getBouncerContainer(), mNotificationPanel, mBiometricUnlockController);
+                getBouncerContainer(), mNotificationPanel, mBiometricUnlockController,
+                mStatusBarWindow.findViewById(R.id.lock_icon_container));
         mKeyguardIndicationController
                 .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
@@ -1231,7 +1234,6 @@
         mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
         mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
         mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
-        mNotificationPanel.setBouncer(mStatusBarKeyguardViewManager.getBouncer());
         Dependency.get(KeyguardDismissUtil.class).setDismissHandler(this::executeWhenUnlocked);
         Trace.endSection();
     }
@@ -3582,6 +3584,10 @@
         if (!mBouncerShowing) {
             updatePanelExpansionForKeyguard();
         }
+
+        // Notify overview proxy service of the new states
+        Dependency.get(OverviewProxyService.class).setSystemUiStateFlag(SYSUI_STATE_BOUNCER_SHOWING,
+                isBouncerShowing());
     }
 
     /**
@@ -3947,6 +3953,7 @@
                     mKeyguardViewMediator.setPulsing(pulsing);
                     mNotificationPanel.setPulsing(pulsing);
                     mVisualStabilityManager.setPulsing(pulsing);
+                    mStatusBarWindow.setPulsing(pulsing);
                     mIgnoreTouchWhilePulsing = false;
                     if (mKeyguardUpdateMonitor != null && passiveAuthInterrupt) {
                         mKeyguardUpdateMonitor.onAuthInterruptDetected(pulsing /* active */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index e3cc3d4..09fa9ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -25,6 +25,8 @@
 import android.content.res.ColorStateList;
 import android.os.Bundle;
 import android.os.SystemClock;
+import android.transition.Fade;
+import android.transition.TransitionManager;
 import android.util.StatsLog;
 import android.view.KeyEvent;
 import android.view.View;
@@ -32,14 +34,16 @@
 import android.view.ViewRootImpl;
 import android.view.WindowManagerGlobal;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.LatencyTracker;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
+import com.android.settingslib.animation.AppearAnimationUtils;
+import com.android.settingslib.animation.DisappearAnimationUtils;
 import com.android.systemui.DejankUtils;
 import com.android.systemui.Dependency;
+import com.android.systemui.Interpolators;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.dock.DockManager;
@@ -49,6 +53,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.KeyguardBouncer.BouncerExpansionCallback;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -65,7 +70,8 @@
  * {@link com.android.keyguard.KeyguardViewBase}.
  */
 public class StatusBarKeyguardViewManager implements RemoteInputController.Callback,
-        StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener {
+        StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
+        NotificationPanelView.PanelExpansionListener {
 
     // When hiding the Keyguard with timing supplied from WindowManager, better be early than late.
     private static final long HIDE_TIMING_CORRECTION_MS = - 16 * 3;
@@ -90,7 +96,7 @@
         public void onFullyShown() {
             updateStates();
             mStatusBar.wakeUpIfDozing(SystemClock.uptimeMillis(), mContainer, "BOUNCER_VISIBLE");
-            mNotificationPanelView.updateLockIcon();
+            updateLockIcon();
         }
 
         @Override
@@ -99,14 +105,14 @@
         }
 
         @Override
-        public void onFullyHidden() {
-            updateStates();
-            mNotificationPanelView.updateLockIcon();
+        public void onStartingToShow() {
+            updateLockIcon();
         }
 
         @Override
-        public void onLayout() {
-            mNotificationPanelView.updateLockIcon();
+        public void onFullyHidden() {
+            updateStates();
+            updateLockIcon();
         }
     };
     private final DockManager.DockEventListener mDockEventListener =
@@ -129,6 +135,7 @@
     private BiometricUnlockController mBiometricUnlockController;
 
     private ViewGroup mContainer;
+    private ViewGroup mLockIconContainer;
 
     protected KeyguardBouncer mBouncer;
     protected boolean mShowing;
@@ -151,6 +158,7 @@
     private boolean mLastPulsing;
     private int mLastBiometricMode;
     private boolean mGoingToSleepVisibleNotOccluded;
+    private int mLastLockVisibility = -1;
 
     private OnDismissAction mAfterKeyguardGoneAction;
     private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
@@ -161,6 +169,8 @@
             (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
     private final NotificationMediaManager mMediaManager =
             Dependency.get(NotificationMediaManager.class);
+    private final StatusBarStateController mStatusBarStateController =
+            Dependency.get(StatusBarStateController.class);
     private final DockManager mDockManager;
 
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
@@ -184,7 +194,7 @@
         mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mGesturalNav = QuickStepContract.isGesturalMode(context);
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
-        Dependency.get(StatusBarStateController.class).addCallback(this);
+        mStatusBarStateController.addCallback(this);
         Dependency.get(ConfigurationController.class).addCallback(this);
         mDockManager = SysUiServiceProvider.getComponent(context, DockManager.class);
         if (mDockManager != null) {
@@ -197,19 +207,21 @@
             ViewGroup container,
             NotificationPanelView notificationPanelView,
             BiometricUnlockController biometricUnlockController,
-            DismissCallbackRegistry dismissCallbackRegistry) {
+            DismissCallbackRegistry dismissCallbackRegistry,
+            ViewGroup lockIconContainer) {
         mStatusBar = statusBar;
         mContainer = container;
+        mLockIconContainer = lockIconContainer;
         mBiometricUnlockController = biometricUnlockController;
         mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext,
                 mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry,
                 mExpansionCallback);
         mNotificationPanelView = notificationPanelView;
-        notificationPanelView.setExpansionListener(this::onPanelExpansionChanged);
+        notificationPanelView.setExpansionListener(this);
     }
 
-    @VisibleForTesting
-    void onPanelExpansionChanged(float expansion, boolean tracking) {
+    @Override
+    public void onPanelExpansionChanged(float expansion, boolean tracking) {
         // We don't want to translate the bounce when:
         // • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to
         //   conserve the original animation.
@@ -230,7 +242,32 @@
                 mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
             }
         }
-        mNotificationPanelView.updateLockIcon();
+    }
+
+    @Override
+    public void onQsExpansionChanged(float expansion) {
+        updateLockIcon();
+    }
+
+    private void updateLockIcon() {
+        boolean keyguardWithoutQs = mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+                && !mNotificationPanelView.isQsExpanded();
+        int lockVisibility = (mBouncer.isShowing() || keyguardWithoutQs)
+                && !mBouncer.isAnimatingAway() ? View.VISIBLE : View.INVISIBLE;
+
+        if (mLastLockVisibility != lockVisibility) {
+            mLastLockVisibility = lockVisibility;
+
+            Fade transition = new Fade();
+            boolean appearing = lockVisibility == View.VISIBLE;
+            transition.setDuration(appearing ? AppearAnimationUtils.DEFAULT_APPEAR_DURATION
+                    : DisappearAnimationUtils.DEFAULT_APPEAR_DURATION / 2);
+            transition.setInterpolator(appearing ? Interpolators.ALPHA_IN
+                    : Interpolators.ALPHA_OUT);
+            TransitionManager.beginDelayedTransition((ViewGroup) mLockIconContainer.getParent(),
+                    transition);
+            mLockIconContainer.setVisibility(lockVisibility);
+        }
     }
 
     /**
@@ -463,6 +500,7 @@
             finishRunnable.run();
         }
         mNotificationPanelView.blockExpansionForCurrentTouch();
+        updateLockIcon();
     }
 
     /**
@@ -849,7 +887,7 @@
 
     @Override
     public void onStateChanged(int newState) {
-        // Nothing
+        updateLockIcon();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 9609057..28db28c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -87,6 +87,7 @@
     private NotificationStackScrollLayout mStackScrollLayout;
     private NotificationPanelView mNotificationPanel;
     private View mBrightnessMirror;
+    private LockIcon mLockIcon;
     private PhoneStatusBarView mStatusBarView;
 
     private int mRightInset = 0;
@@ -241,10 +242,10 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
-                R.id.notification_stack_scroller);
-        mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
+        mStackScrollLayout = findViewById(R.id.notification_stack_scroller);
+        mNotificationPanel = findViewById(R.id.notification_panel);
         mBrightnessMirror = findViewById(R.id.brightness_mirror);
+        mLockIcon = findViewById(R.id.lock_icon);
     }
 
     @Override
@@ -255,6 +256,13 @@
         }
     }
 
+    /**
+     * Propagate {@link StatusBar} pulsing state.
+     */
+    public void setPulsing(boolean pulsing) {
+        mLockIcon.setPulsing(pulsing);
+    }
+
     public void setStatusBarView(PhoneStatusBarView statusBarView) {
         mStatusBarView = statusBarView;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 376c328..1e486c0 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -24,12 +24,14 @@
 import android.view.View;
 
 import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardMessageArea;
 import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.qs.QSCarrierGroup;
 import com.android.systemui.qs.QSFooterImpl;
 import com.android.systemui.qs.QuickStatusBarHeader;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
 
 import java.lang.reflect.InvocationTargetException;
@@ -142,6 +144,16 @@
          * Creates the KeyguardSliceView.
          */
         KeyguardSliceView createKeyguardSliceView();
+
+        /**
+         * Creates the KeyguardMessageArea.
+         */
+        KeyguardMessageArea createKeyguardMessageArea();
+
+        /**
+         * Creates the keyguard LockIcon.
+         */
+        LockIcon createLockIcon();
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaTest.java
index f8ca262..fc7b9a4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaTest.java
@@ -18,32 +18,50 @@
 
 import static junit.framework.Assert.assertEquals;
 
-import static org.mockito.Mockito.mock;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper
 public class KeyguardMessageAreaTest extends SysuiTestCase {
+    @Mock
+    private ConfigurationController mConfigurationController;
+    @Mock
+    private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private KeyguardMessageArea mMessageArea;
 
     @Before
     public void setUp() throws Exception {
-        KeyguardUpdateMonitor monitor = mock(KeyguardUpdateMonitor.class);
-        mMessageArea = new KeyguardMessageArea(mContext, null, monitor);
+        MockitoAnnotations.initMocks(this);
+        mMessageArea = new KeyguardMessageArea(mContext, null, mKeyguardUpdateMonitor,
+                mConfigurationController);
         waitForIdleSync();
     }
 
     @Test
+    public void onAttachedToWindow_registersConfigurationCallback() {
+        mMessageArea.onAttachedToWindow();
+        verify(mConfigurationController).addCallback(eq(mMessageArea));
+
+        mMessageArea.onDetachedFromWindow();
+        verify(mConfigurationController).removeCallback(eq(mMessageArea));
+    }
+
+    @Test
     public void clearFollowedByMessage_keepsMessage() {
         mMessageArea.setMessage("");
         mMessageArea.setMessage("test");
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
index e7469c3..5f03bdb 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewTest.kt
@@ -22,11 +22,13 @@
 import android.view.LayoutInflater
 
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.ConfigurationController
 import com.google.common.truth.Truth.assertThat
 
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -41,8 +43,9 @@
         val inflater = LayoutInflater.from(context)
         mKeyguardPatternView = inflater.inflate(R.layout.keyguard_pattern_view, null)
                 as KeyguardPatternView
-        mSecurityMessage = KeyguardMessageArea.findSecurityMessageDisplay(mKeyguardPatternView)
-                as KeyguardMessageArea
+        mSecurityMessage = KeyguardMessageArea(mContext, null,
+                mock(KeyguardUpdateMonitor::class.java), mock(ConfigurationController::class.java))
+        mKeyguardPatternView.mSecurityMessageDisplay = mSecurityMessage
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 18ffbb5..80c51cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -40,10 +40,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
+import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.util.wakelock.WakeLockFake;
 
 import org.junit.Before;
@@ -66,6 +68,10 @@
     private ViewGroup mIndicationArea;
     @Mock
     private KeyguardIndicationTextView mDisclosure;
+    @Mock
+    private LockIcon mLockIcon;
+    @Mock
+    private LockPatternUtils mLockPatternUtils;
     private KeyguardIndicationTextView mTextView;
 
     private KeyguardIndicationController mController;
@@ -95,7 +101,8 @@
         if (Looper.myLooper() == null) {
             Looper.prepare();
         }
-        mController = new KeyguardIndicationController(mContext, mIndicationArea, null, mWakeLock);
+        mController = new KeyguardIndicationController(mContext, mIndicationArea, mLockIcon,
+                mLockPatternUtils, mWakeLock);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
index 3010996..b95bb0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
@@ -42,6 +42,5 @@
 
         other.initFrom(mKeyguardBottomArea)
         other.launchVoiceAssist()
-        other.onLongClick(null)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index c2e60d9..575ff16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -132,6 +132,7 @@
     public void testShow_notifiesVisibility() {
         mBouncer.show(true);
         verify(mViewMediatorCallback).onBouncerVisiblityChanged(eq(true));
+        verify(mExpansionCallback).onStartingToShow();
 
         // Not called again when visible
         reset(mViewMediatorCallback);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 3f4d96c..9354648 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -38,7 +38,6 @@
     private static final int PREFERRED_CLOCK_Y = SCREEN_HEIGHT / 2;
     private static final int EMPTY_MARGIN = 0;
     private static final int EMPTY_HEIGHT = 0;
-    private static final boolean SECURE_LOCKED = false;
     private static final float ZERO_DRAG = 0.f;
     private static final float OPAQUE = 1.f;
     private static final float TRANSPARENT = 0.f;
@@ -307,7 +306,7 @@
     private void positionClock() {
         mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
                 mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, PREFERRED_CLOCK_Y, mDark,
-                SECURE_LOCKED, ZERO_DRAG);
+                ZERO_DRAG);
         mClockPositionAlgorithm.run(mClockPosition);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 7d347d5..d09cea5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -19,6 +19,7 @@
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -27,6 +28,7 @@
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
+import android.view.View;
 import android.view.ViewGroup;
 
 import androidx.test.filters.SmallTest;
@@ -36,6 +38,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.StatusBarState;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -64,16 +68,23 @@
     private BiometricUnlockController mBiometrucUnlockController;
     @Mock
     private DismissCallbackRegistry mDismissCallbackRegistry;
+    @Mock
+    private ViewGroup mLockIconContainer;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mDependency.injectMockDependency(StatusBarWindowController.class);
+        mDependency.injectTestDependency(StatusBarStateController.class, mStatusBarStateController);
+        when(mLockIconContainer.getParent()).thenReturn(mock(ViewGroup.class));
         mStatusBarKeyguardViewManager = new TestableStatusBarKeyguardViewManager(getContext(),
                 mViewMediatorCallback, mLockPatternUtils);
         mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
-                mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry);
+                mNotificationPanelView, mBiometrucUnlockController, mDismissCallbackRegistry,
+                mLockIconContainer);
         mStatusBarKeyguardViewManager.show(null);
     }
 
@@ -187,6 +198,29 @@
         verify(mBouncer, never()).setExpansion(anyFloat());
     }
 
+    @Test
+    public void onQsExpansionChanged_lockVisibleOnlyWhenCollapsed() {
+        when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
+        mStatusBarKeyguardViewManager.onQsExpansionChanged(0);
+        verify(mLockIconContainer).setVisibility(eq(View.VISIBLE));
+
+        reset(mNotificationPanelView);
+        when(mNotificationPanelView.isQsExpanded()).thenReturn(true);
+        mStatusBarKeyguardViewManager.onQsExpansionChanged(1f);
+        verify(mLockIconContainer).setVisibility(eq(View.INVISIBLE));
+    }
+
+    @Test
+    public void onQsExpansionChanged_lockInvisibleWhenAnimatingAway() {
+        when(mBouncer.isShowing()).thenReturn(true);
+        mStatusBarKeyguardViewManager.onQsExpansionChanged(0);
+        verify(mLockIconContainer).setVisibility(eq(View.VISIBLE));
+
+        when(mBouncer.isAnimatingAway()).thenReturn(true);
+        mStatusBarKeyguardViewManager.onQsExpansionChanged(0f);
+        verify(mLockIconContainer).setVisibility(eq(View.INVISIBLE));
+    }
+
     private class TestableStatusBarKeyguardViewManager extends StatusBarKeyguardViewManager {
 
         public TestableStatusBarKeyguardViewManager(Context context,
@@ -199,9 +233,10 @@
         public void registerStatusBar(StatusBar statusBar, ViewGroup container,
                 NotificationPanelView notificationPanelView,
                 BiometricUnlockController fingerprintUnlockController,
-                DismissCallbackRegistry dismissCallbackRegistry) {
+                DismissCallbackRegistry dismissCallbackRegistry,
+                ViewGroup lockIconContainer) {
             super.registerStatusBar(statusBar, container, notificationPanelView,
-                    fingerprintUnlockController, dismissCallbackRegistry);
+                    fingerprintUnlockController, dismissCallbackRegistry, lockIconContainer);
             mBouncer = StatusBarKeyguardViewManagerTest.this.mBouncer;
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 5f7f422..43bc21b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -170,6 +170,8 @@
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock
     private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
+    @Mock
+    private StatusBarWindowView mStatusBarWindowView;
 
     private TestableStatusBar mStatusBar;
     private FakeMetricsLogger mMetricsLogger;
@@ -261,7 +263,7 @@
                 mDozeScrimController, mock(NotificationShelf.class),
                 mLockscreenUserManager, mCommandQueue, mNotificationPresenter,
                 mock(BubbleController.class), mock(NavigationBarController.class),
-                mock(AutoHideController.class), mKeyguardUpdateMonitor);
+                mock(AutoHideController.class), mKeyguardUpdateMonitor, mStatusBarWindowView);
         mStatusBar.mContext = mContext;
         mStatusBar.mComponents = mContext.getComponents();
         SystemUIFactory.getInstance().getRootComponent()
@@ -767,7 +769,8 @@
                 BubbleController bubbleController,
                 NavigationBarController navBarController,
                 AutoHideController autoHideController,
-                KeyguardUpdateMonitor keyguardUpdateMonitor) {
+                KeyguardUpdateMonitor keyguardUpdateMonitor,
+                StatusBarWindowView statusBarWindow) {
             mStatusBarKeyguardViewManager = man;
             mUnlockMethodCache = unlock;
             mKeyguardIndicationController = key;
@@ -801,6 +804,7 @@
             mNavigationBarController = navBarController;
             mAutoHideController = autoHideController;
             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+            mStatusBarWindow = statusBarWindow;
         }
 
         private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 5d0fa26..ba56261 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -236,6 +236,7 @@
                     case VibrationEffect.EFFECT_CLICK:
                     case VibrationEffect.EFFECT_DOUBLE_CLICK:
                     case VibrationEffect.EFFECT_HEAVY_CLICK:
+                    case VibrationEffect.EFFECT_TEXTURE_TICK:
                     case VibrationEffect.EFFECT_TICK:
                     case VibrationEffect.EFFECT_POP:
                     case VibrationEffect.EFFECT_THUD:
@@ -379,6 +380,9 @@
         mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect);
         mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect);
 
+        mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK,
+                VibrationEffect.get(VibrationEffect.EFFECT_TICK, false));
+
         mScaleLevels = new SparseArray<>();
         mScaleLevels.put(SCALE_VERY_LOW,
                 new ScaleLevel(SCALE_VERY_LOW_GAMMA, SCALE_VERY_LOW_MAX_AMPLITUDE));
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 881a4ae..0b60282 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -544,6 +544,7 @@
     private static final int NATIVE_DUMP_TIMEOUT_MS = 2000; // 2 seconds;
 
     final OomAdjuster mOomAdjuster;
+    final LowMemDetector mLowMemDetector;
 
     /** All system services */
     SystemServiceManager mSystemServiceManager;
@@ -2294,6 +2295,7 @@
                 ? new ActivityManagerConstants(mContext, this, mHandler) : null;
         final ActiveUids activeUids = new ActiveUids(this, false /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
+        mLowMemDetector = null;
         mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
 
         mIntentFirewall = hasHandlerThread
@@ -2342,6 +2344,7 @@
         mConstants = new ActivityManagerConstants(mContext, this, mHandler);
         final ActiveUids activeUids = new ActiveUids(this, true /* postChangesToAtm */);
         mProcessList.init(this, activeUids);
+        mLowMemDetector = new LowMemDetector(this);
         mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids);
 
         // Broadcast policy parameters
@@ -16524,25 +16527,29 @@
     final boolean updateLowMemStateLocked(int numCached, int numEmpty, int numTrimming) {
         final int N = mProcessList.getLruSizeLocked();
         final long now = SystemClock.uptimeMillis();
-        // Now determine the memory trimming level of background processes.
-        // Unfortunately we need to start at the back of the list to do this
-        // properly.  We only do this if the number of background apps we
-        // are managing to keep around is less than half the maximum we desire;
-        // if we are keeping a good number around, we'll let them use whatever
-        // memory they want.
-        final int numCachedAndEmpty = numCached + numEmpty;
         int memFactor;
-        if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
-                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
-            if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
-                memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
-            } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
-                memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
-            } else {
-                memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
-            }
+        if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
+            memFactor = mLowMemDetector.getMemFactor();
         } else {
-            memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+            // Now determine the memory trimming level of background processes.
+            // Unfortunately we need to start at the back of the list to do this
+            // properly.  We only do this if the number of background apps we
+            // are managing to keep around is less than half the maximum we desire;
+            // if we are keeping a good number around, we'll let them use whatever
+            // memory they want.
+            if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
+                && numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
+                final int numCachedAndEmpty = numCached + numEmpty;
+                if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
+                    memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
+                } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
+                    memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
+                } else {
+                    memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
+                }
+            } else {
+                memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
+            }
         }
         // We always allow the memory level to go up (better).  We only allow it to go
         // down if we are in a state where that is allowed, *and* the total number of processes
diff --git a/services/core/java/com/android/server/am/LowMemDetector.java b/services/core/java/com/android/server/am/LowMemDetector.java
new file mode 100644
index 0000000..e82a207
--- /dev/null
+++ b/services/core/java/com/android/server/am/LowMemDetector.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 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.server.am;
+
+import com.android.internal.annotations.GuardedBy;
+
+/**
+ * Detects low memory using PSI.
+ *
+ * If the kernel doesn't support PSI, then this class is not available.
+ */
+public final class LowMemDetector {
+    private static final String TAG = "LowMemDetector";
+    private final ActivityManagerService mAm;
+    private final LowMemThread mLowMemThread;
+    private boolean mAvailable;
+
+    private final Object mPressureStateLock = new Object();
+
+    @GuardedBy("mPressureStateLock")
+    private int mPressureState = MEM_PRESSURE_NONE;
+
+    /* getPressureState return values */
+    public static final int MEM_PRESSURE_NONE = 0;
+    public static final int MEM_PRESSURE_LOW = 1;
+    public static final int MEM_PRESSURE_MEDIUM = 2;
+    public static final int MEM_PRESSURE_HIGH = 3;
+
+    LowMemDetector(ActivityManagerService am) {
+        mAm = am;
+        mLowMemThread = new LowMemThread();
+        if (init() != 0) {
+            mAvailable = false;
+        } else {
+            mAvailable = true;
+            mLowMemThread.start();
+        }
+    }
+
+    public boolean isAvailable() {
+        return mAvailable;
+    }
+
+    /**
+     * Returns the current mem factor.
+     * Note that getMemFactor returns LowMemDetector.MEM_PRESSURE_XXX
+     * which match ProcessStats.ADJ_MEM_FACTOR_XXX values. If they deviate
+     * there should be conversion performed here to translate pressure state
+     * into memFactor.
+     */
+    public int getMemFactor() {
+        synchronized (mPressureStateLock) {
+            return mPressureState;
+        }
+    }
+
+    private native int init();
+    private native int waitForPressure();
+
+    private final class LowMemThread extends Thread {
+        public void run() {
+
+            while (true) {
+                // sleep waiting for a PSI event
+                int newPressureState = waitForPressure();
+                if (newPressureState == -1) {
+                    // epoll broke, tear this down
+                    mAvailable = false;
+                    break;
+                }
+                // got a PSI event? let's update lowmem info
+                synchronized (mPressureStateLock) {
+                    mPressureState = newPressureState;
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 716e4ef..f8f6334 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -236,7 +236,7 @@
         }
     }
 
-    void cancelDragAndDrop(IBinder dragToken) {
+    void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) {
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "cancelDragAndDrop");
         }
@@ -257,7 +257,7 @@
                 }
 
                 mDragState.mDragResult = false;
-                mDragState.cancelDragLocked();
+                mDragState.cancelDragLocked(skipAnimation);
             }
         } finally {
             mCallback.get().postCancelDragAndDrop();
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index c438966..6127303 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -475,15 +475,16 @@
         closeLocked();
     }
 
-    void cancelDragLocked() {
+    void cancelDragLocked(boolean skipAnimation) {
         if (mAnimator != null) {
             return;
         }
-        if (!mDragInProgress) {
-            // This can happen if an app invokes Session#cancelDragAndDrop before
+        if (!mDragInProgress || skipAnimation) {
+            // mDragInProgress is false if an app invokes Session#cancelDragAndDrop before
             // Session#performDrag. Reset the drag state without playing the cancel animation
             // because H.DRAG_START_TIMEOUT may be sent to WindowManagerService, which will cause
             // DragState#reset() while playing the cancel animation.
+            // skipAnimation is true when a caller requests to skip the drag cancel animation.
             closeLocked();
             return;
         }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 22b030d..b33f8c7 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -283,10 +283,10 @@
     }
 
     @Override
-    public void cancelDragAndDrop(IBinder dragToken) {
+    public void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) {
         final long ident = Binder.clearCallingIdentity();
         try {
-            mDragDropController.cancelDragAndDrop(dragToken);
+            mDragDropController.cancelDragAndDrop(dragToken, skipAnimation);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java
index 7714458..7f1b4c0 100644
--- a/services/core/java/com/android/server/wm/TaskPositioner.java
+++ b/services/core/java/com/android/server/wm/TaskPositioner.java
@@ -34,6 +34,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Binder;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
@@ -56,7 +57,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
-class TaskPositioner {
+class TaskPositioner implements IBinder.DeathRecipient {
     private static final boolean DEBUG_ORIENTATION_VIOLATIONS = false;
     private static final String TAG_LOCAL = "TaskPositioner";
     private static final String TAG = TAG_WITH_CLASS_NAME ? TAG_LOCAL : TAG_WM;
@@ -116,7 +117,9 @@
     private float mStartDragY;
     @CtrlType
     private int mCtrlType = CTRL_NONE;
-    private boolean mDragEnded = false;
+    @VisibleForTesting
+    boolean mDragEnded;
+    private IBinder mClientCallback;
 
     InputChannel mServerChannel;
     InputChannel mClientChannel;
@@ -346,6 +349,7 @@
         }
         mDisplayContent.resumeRotationLocked();
         mDisplayContent = null;
+        mClientCallback.unlinkToDeath(this, 0 /* flags */);
     }
 
     void startDrag(WindowState win, boolean resize, boolean preserveOrientation, float startX,
@@ -355,6 +359,14 @@
                     + ", preserveOrientation=" + preserveOrientation + ", {" + startX + ", "
                     + startY + "}");
         }
+        try {
+            mClientCallback = win.mClient.asBinder();
+            mClientCallback.linkToDeath(this, 0 /* flags */);
+        } catch (RemoteException e) {
+            // The caller has died, so clean up TaskPositioningController.
+            mService.mTaskPositioningController.finishTaskPositioning();
+            return;
+        }
         mTask = win.getTask();
         // Use the bounds of the task which accounts for
         // multiple app windows. Don't use any bounds from win itself as it
@@ -651,6 +663,11 @@
         return sFactory.create(service);
     }
 
+    @Override
+    public void binderDied() {
+        mService.mTaskPositioningController.finishTaskPositioning();
+    }
+
     interface Factory {
         default TaskPositioner create(WindowManagerService service) {
             return new TaskPositioner(service);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index e1318af..6218498 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -51,6 +51,7 @@
         "com_android_server_PersistentDataBlockService.cpp",
         "com_android_server_GraphicsStatsService.cpp",
         "com_android_server_am_AppCompactor.cpp",
+        "com_android_server_am_LowMemDetector.cpp",
         "onload.cpp",
         ":lib_networkStatsFactory_native",
     ],
@@ -104,6 +105,7 @@
         "libbpf_android",
         "libnetdbpf",
         "libnetdutils",
+        "libpsi",
         "android.hardware.audio.common@2.0",
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
diff --git a/services/core/jni/com_android_server_am_LowMemDetector.cpp b/services/core/jni/com_android_server_am_LowMemDetector.cpp
new file mode 100644
index 0000000..e41de4d
--- /dev/null
+++ b/services/core/jni/com_android_server_am_LowMemDetector.cpp
@@ -0,0 +1,156 @@
+/**
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "LowMemDetector"
+
+#include <errno.h>
+#include <psi/psi.h>
+#include <string.h>
+#include <sys/epoll.h>
+
+#include <jni.h>
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+
+namespace android {
+
+enum pressure_levels {
+    PRESSURE_NONE,
+    PRESSURE_LOW,
+    PRESSURE_MEDIUM,
+    PRESSURE_HIGH,
+    PRESSURE_LEVEL_COUNT = PRESSURE_HIGH
+};
+
+// amount of stall in us for each level
+static constexpr int PSI_LOW_STALL_US = 15000;
+static constexpr int PSI_MEDIUM_STALL_US = 30000;
+static constexpr int PSI_HIGH_STALL_US = 50000;
+
+// stall tracking window size in us
+static constexpr int PSI_WINDOW_SIZE_US = 1000000;
+
+static int psi_epollfd = -1;
+
+static jint android_server_am_LowMemDetector_init(JNIEnv*, jobject) {
+    int epollfd;
+    int low_psi_fd;
+    int medium_psi_fd;
+    int high_psi_fd;
+
+    epollfd = epoll_create(PRESSURE_LEVEL_COUNT);
+    if (epollfd == -1) {
+        ALOGE("epoll_create failed: %s", strerror(errno));
+        return -1;
+    }
+
+    low_psi_fd = init_psi_monitor(PSI_SOME, PSI_LOW_STALL_US, PSI_WINDOW_SIZE_US);
+    if (low_psi_fd < 0 ||
+        register_psi_monitor(epollfd, low_psi_fd, (void*)PRESSURE_LOW) != 0) {
+        goto low_fail;
+    }
+
+    medium_psi_fd =
+        init_psi_monitor(PSI_FULL, PSI_MEDIUM_STALL_US, PSI_WINDOW_SIZE_US);
+    if (medium_psi_fd < 0 || register_psi_monitor(epollfd, medium_psi_fd,
+                                                  (void*)PRESSURE_MEDIUM) != 0) {
+        goto medium_fail;
+    }
+
+    high_psi_fd =
+        init_psi_monitor(PSI_FULL, PSI_HIGH_STALL_US, PSI_WINDOW_SIZE_US);
+    if (high_psi_fd < 0 ||
+        register_psi_monitor(epollfd, high_psi_fd, (void*)PRESSURE_HIGH) != 0) {
+        goto high_fail;
+    }
+
+    psi_epollfd = epollfd;
+    return 0;
+
+high_fail:
+    unregister_psi_monitor(epollfd, medium_psi_fd);
+medium_fail:
+    unregister_psi_monitor(epollfd, low_psi_fd);
+low_fail:
+    ALOGE("Failed to register psi trigger");
+    close(epollfd);
+    return -1;
+}
+
+static jint android_server_am_LowMemDetector_waitForPressure(JNIEnv*, jobject) {
+    static uint32_t pressure_level = PRESSURE_NONE;
+    struct epoll_event events[PRESSURE_LEVEL_COUNT];
+    int nevents = 0;
+
+    if (psi_epollfd < 0) {
+        ALOGE("Memory pressure detector is not initialized");
+        return -1;
+    }
+
+    do {
+        if (pressure_level == PRESSURE_NONE) {
+            /* Wait for events with no timeout */
+            nevents = epoll_wait(psi_epollfd, events, PRESSURE_LEVEL_COUNT, -1);
+        } else {
+            // This is simpler than lmkd. Assume that the memory pressure
+            // state will stay high for at least 1s. Within that 1s window,
+            // the memory pressure state can go up due to a different FD
+            // becoming available or it can go down when that window expires.
+            // Accordingly, there's no polling: just epoll_wait with a 1s timeout.
+            nevents = epoll_wait(psi_epollfd, events, PRESSURE_LEVEL_COUNT, 1000);
+            if (nevents == 0) {
+                pressure_level = PRESSURE_NONE;
+                return pressure_level;
+            }
+        }
+        // keep waiting if interrupted
+    } while (nevents == -1 && errno == EINTR);
+
+    if (nevents == -1) {
+        ALOGE("epoll_wait failed while waiting for psi events: %s", strerror(errno));
+        return -1;
+    }
+
+    // reset pressure_level and raise it based on received events
+    pressure_level = PRESSURE_NONE;
+    for (int i = 0; i < nevents; i++) {
+        if (events[i].events & (EPOLLERR | EPOLLHUP)) {
+            // should never happen unless psi got disabled in kernel
+            ALOGE("Memory pressure events are not available anymore");
+            return -1;
+        }
+        // record the highest reported level
+        if (events[i].data.u32 > pressure_level) {
+            pressure_level = events[i].data.u32;
+        }
+    }
+
+    return pressure_level;
+}
+
+static const JNINativeMethod sMethods[] = {
+    /* name, signature, funcPtr */
+    {"init", "()I", (void*)android_server_am_LowMemDetector_init},
+    {"waitForPressure", "()I",
+     (void*)android_server_am_LowMemDetector_waitForPressure},
+};
+
+int register_android_server_am_LowMemDetector(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/server/am/LowMemDetector",
+                                    sMethods, NELEM(sMethods));
+}
+
+} // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index cce96ff..efffa6c 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -56,6 +56,7 @@
 int register_android_server_net_NetworkStatsService(JNIEnv* env);
 int register_android_server_security_VerityUtils(JNIEnv* env);
 int register_android_server_am_AppCompactor(JNIEnv* env);
+int register_android_server_am_LowMemDetector(JNIEnv* env);
 };
 
 using namespace android;
@@ -105,5 +106,6 @@
     register_android_server_net_NetworkStatsService(env);
     register_android_server_security_VerityUtils(env);
     register_android_server_am_AppCompactor(env);
+    register_android_server_am_LowMemDetector(env);
     return JNI_VERSION_1_4;
 }
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 782196d..2baa4d8 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -34,6 +34,7 @@
 
     jni_libs: [
         "libdexmakerjvmtiagent",
+        "libpsi",
         "libstaticjvmtiagent",
     ],
 
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 4ee9551..1522a60 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -69,6 +69,7 @@
         "liblog",
         "liblzma",
         "libnativehelper",
+        "libpsi",
         "libui",
         "libunwindstack",
         "libutils",
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 68d8bc0..196cc21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -137,7 +137,7 @@
                 return;
             }
             if (mToken != null) {
-                mTarget.cancelDragAndDrop(mToken);
+                mTarget.cancelDragAndDrop(mToken, false);
             }
             latch = new CountDownLatch(1);
             mTarget.setOnClosedCallbackLocked(latch::countDown);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 9cdb465..df55b39 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -20,6 +20,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.server.wm.TaskPositioner.MIN_ASPECT;
 import static com.android.server.wm.WindowManagerService.dipToPixel;
 import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP;
@@ -29,6 +30,8 @@
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 
 import android.app.IActivityTaskManager;
 import android.graphics.Rect;
@@ -37,6 +40,7 @@
 import android.util.Log;
 import android.view.Display;
 
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
@@ -494,4 +498,15 @@
         assertEquals("top", expected.top, actual.top);
         assertEquals("bottom", expected.bottom, actual.bottom);
     }
+
+    @FlakyTest(bugId = 129492888)
+    @Test
+    public void testFinishingMovingWhenBinderDied() {
+        spyOn(mWm.mTaskPositioningController);
+
+        mPositioner.startDrag(mWindow, false, false, 0 /* startX */, 0 /* startY */);
+        verify(mWm.mTaskPositioningController, never()).finishTaskPositioning();
+        mPositioner.binderDied();
+        verify(mWm.mTaskPositioningController).finishTaskPositioning();
+    }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 18b9fbb..0edf08ed 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -64,6 +64,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.telecom.TelecomManager;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
+import android.telephony.data.ApnSetting;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories;
 import android.telephony.ims.aidl.IImsConfig;
@@ -10949,26 +10950,31 @@
         return new Pair<Integer, Integer>(-1, -1);
     }
 
-
     /**
-     * Return whether MMS data is enabled. This will tell if framework will accept a MMS network
-     * request on a subId.
+     * Return whether data is enabled for certain APN type. This will tell if framework will accept
+     * corresponding network requests on a subId.
      *
-     *  Mms is enabled if:
-     *  1) user data is turned on, or
-     *  2) MMS is un-metered for this subscription, or
-     *  3) alwaysAllowMms setting {@link SubscriptionManager#setAlwaysAllowMmsData} is turned on.
+     * {@link #isDataEnabled()} is directly associated with users' Mobile data toggle on / off. If
+     * {@link #isDataEnabled()} returns false, it means in general all meter-ed data are disabled.
      *
-     * @return whether MMS data is allowed.
+     * This per APN type API gives a better idea whether data is allowed on a specific APN type.
+     * It will return true if:
+     *
+     *  1) User data is turned on, or
+     *  2) APN is un-metered for this subscription, or
+     *  3) APN type is whitelisted. E.g. MMS is whitelisted if
+     *  {@link SubscriptionManager#setAlwaysAllowMmsData} is turned on.
+     *
+     * @return whether data is enabled for a apn type.
      *
      * @hide
      */
-    public boolean isMmsDataEnabled() {
+    public boolean isDataEnabledForApn(@ApnSetting.ApnType int apnType) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.isMmsDataEnabled(getSubId(), pkgForDebug);
+                return service.isDataEnabledForApn(apnType, getSubId(), pkgForDebug);
             }
         } catch (RemoteException ex) {
             if (!isSystemProcess()) {
@@ -10977,4 +10983,24 @@
         }
         return false;
     }
+
+    /**
+     * Whether an APN type is metered or not. It will be evaluated with the subId associated
+     * with the TelephonyManager instance.
+     *
+     * @hide
+     */
+    public boolean isApnMetered(@ApnSetting.ApnType int apnType) {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.isApnMetered(apnType, getSubId());
+            }
+        } catch (RemoteException ex) {
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+        return true;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 536c514..0169c26 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1967,5 +1967,7 @@
 
     boolean isModemEnabledForSlot(int slotIndex, String callingPackage);
 
-    boolean isMmsDataEnabled(int subId, String callingPackage);
+    boolean isDataEnabledForApn(int apnType, int subId, String callingPackage);
+
+    boolean isApnMetered(int apnType, int subId);
 }