Merge "Retire preliminary FGS deferral control API" into sc-dev
diff --git a/Android.bp b/Android.bp
index 9023a19..4d8924d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -273,6 +273,11 @@
     installable: false,
 }
 
+filegroup {
+    name: "framework-jarjar-rules",
+    srcs: ["framework-jarjar-rules.txt"],
+}
+
 java_defaults {
     name: "framework-minus-apex-defaults",
     defaults: ["framework-aidl-export-defaults"],
@@ -294,7 +299,7 @@
         "--core-library",
         "--multi-dex",
     ],
-    jarjar_rules: "framework-jarjar-rules.txt",
+    jarjar_rules: ":framework-jarjar-rules",
     javac_shard_size: 150,
     plugins: [
         "view-inspector-annotation-processor",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index ed24d43..b6c45ed 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -255,7 +255,7 @@
 
 modules_system_stubs = [
     "android.net.ipsec.ike.stubs.system",
-    "art.module.public.api.stubs", // Only has public stubs
+    "art.module.public.api.stubs.system",
     "conscrypt.module.public.api.stubs", // Only has public stubs
     "framework-appsearch.stubs.system",
     "framework-connectivity.stubs.system",
diff --git a/api/Android.bp b/api/Android.bp
index b85dc46..db1f64c 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -161,6 +161,7 @@
 genrule {
     name: "frameworks-base-api-system-current.txt",
     srcs: [
+        ":art.module.public.api{.system.api.txt}",
         ":android.net.ipsec.ike{.system.api.txt}",
         ":framework-appsearch{.system.api.txt}",
         ":framework-connectivity{.system.api.txt}",
@@ -215,6 +216,7 @@
 genrule {
     name: "frameworks-base-api-system-removed.txt",
     srcs: [
+        ":art.module.public.api{.system.removed-api.txt}",
         ":android.net.ipsec.ike{.system.removed-api.txt}",
         ":framework-appsearch{.system.removed-api.txt}",
         ":framework-connectivity{.system.removed-api.txt}",
@@ -251,6 +253,7 @@
 genrule {
     name: "frameworks-base-api-module-lib-current.txt",
     srcs: [
+        ":art.module.public.api{.module-lib.api.txt}",
         ":android.net.ipsec.ike{.module-lib.api.txt}",
         ":framework-appsearch{.module-lib.api.txt}",
         ":framework-connectivity{.module-lib.api.txt}",
@@ -307,6 +310,7 @@
 genrule {
     name: "frameworks-base-api-module-lib-removed.txt",
     srcs: [
+        ":art.module.public.api{.module-lib.removed-api.txt}",
         ":android.net.ipsec.ike{.module-lib.removed-api.txt}",
         ":framework-appsearch{.module-lib.removed-api.txt}",
         ":framework-connectivity{.module-lib.removed-api.txt}",
diff --git a/boot/Android.bp b/boot/Android.bp
index e8d88a5..3caede4 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -48,57 +48,13 @@
     // bootclasspath.
     fragments: [
         {
-            apex: "com.android.appsearch",
-            module: "com.android.appsearch-bootclasspath-fragment",
-        },
-        {
             apex: "com.android.art",
             module: "art-bootclasspath-fragment",
         },
         {
-            apex: "com.android.conscrypt",
-            module: "com.android.conscrypt-bootclasspath-fragment",
-        },
-        {
             apex: "com.android.i18n",
             module: "i18n-bootclasspath-fragment",
         },
-        {
-            apex: "com.android.ipsec",
-            module: "com.android.ipsec-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.media",
-            module: "com.android.media-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.mediaprovider",
-            module: "com.android.mediaprovider-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.os.statsd",
-            module: "com.android.os.statsd-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.permission",
-            module: "com.android.permission-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.scheduling",
-            module: "com.android.scheduling-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.sdkext",
-            module: "com.android.sdkext-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.tethering",
-            module: "com.android.tethering-bootclasspath-fragment",
-        },
-        {
-            apex: "com.android.wifi",
-            module: "com.android.wifi-bootclasspath-fragment",
-        },
     ],
 
     // Additional information needed by hidden api processing.
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index d939438..6f68e3f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1458,6 +1458,7 @@
     method public long getTimestampMillis();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.search.Query> CREATOR;
+    field public static final String EXTRA_IME_HEIGHT = "android.app.search.extra.IME_HEIGHT";
   }
 
   public final class SearchAction implements android.os.Parcelable {
@@ -1526,7 +1527,7 @@
     method @Nullable public android.content.pm.ShortcutInfo getShortcutInfo();
     method @Nullable public android.net.Uri getSliceUri();
     method @NonNull public android.os.UserHandle getUserHandle();
-    method public boolean shouldHide();
+    method public boolean isHidden();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.app.search.SearchTarget> CREATOR;
     field public static final String LAYOUT_TYPE_ICON = "icon";
@@ -1543,12 +1544,12 @@
     method @NonNull public android.app.search.SearchTarget build();
     method @NonNull public android.app.search.SearchTarget.Builder setAppWidgetProviderInfo(@NonNull android.appwidget.AppWidgetProviderInfo);
     method @NonNull public android.app.search.SearchTarget.Builder setExtras(@NonNull android.os.Bundle);
+    method @NonNull public android.app.search.SearchTarget.Builder setHidden(boolean);
     method @NonNull public android.app.search.SearchTarget.Builder setPackageName(@NonNull String);
     method @NonNull public android.app.search.SearchTarget.Builder setParentId(@NonNull String);
     method @NonNull public android.app.search.SearchTarget.Builder setScore(@FloatRange(from=0.0f, to=1.0f) float);
     method @NonNull public android.app.search.SearchTarget.Builder setSearchAction(@Nullable android.app.search.SearchAction);
     method @NonNull public android.app.search.SearchTarget.Builder setShortcutInfo(@NonNull android.content.pm.ShortcutInfo);
-    method @NonNull public android.app.search.SearchTarget.Builder setShouldHide(boolean);
     method @NonNull public android.app.search.SearchTarget.Builder setSliceUri(@NonNull android.net.Uri);
     method @NonNull public android.app.search.SearchTarget.Builder setUserHandle(@NonNull android.os.UserHandle);
   }
@@ -2246,7 +2247,7 @@
 package android.companion {
 
   public final class CompanionDeviceManager {
-    method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress);
+    method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress, @NonNull byte[]);
     method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
     method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
   }
@@ -10416,11 +10417,11 @@
     ctor public TranslationService();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public void onConnected();
-    method public void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
+    method public abstract void onCreateTranslationSession(@NonNull android.view.translation.TranslationContext, int, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method public void onDisconnected();
     method public abstract void onFinishTranslationSession(int);
     method public abstract void onTranslationCapabilitiesRequest(int, int, @NonNull java.util.function.Consumer<java.util.Set<android.view.translation.TranslationCapability>>);
-    method public void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.view.translation.TranslationResponse>);
+    method public abstract void onTranslationRequest(@NonNull android.view.translation.TranslationRequest, int, @Nullable android.os.CancellationSignal, @NonNull java.util.function.Consumer<android.view.translation.TranslationResponse>);
     method public final void updateTranslationCapability(@NonNull android.view.translation.TranslationCapability);
     field public static final String SERVICE_INTERFACE = "android.service.translation.TranslationService";
     field public static final String SERVICE_META_DATA = "android.translation_service";
@@ -10528,7 +10529,7 @@
     method @Nullable public android.media.MediaSyncEvent getMediaSyncEvent();
     method public int getPersonalizedScore();
     method public int getScore();
-    method public boolean isPersonalizedHotwordDetection();
+    method public boolean isHotwordDetectionPersonalized();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int AUDIO_CHANNEL_UNSET = -1; // 0xffffffff
     field public static final int CONFIDENCE_LEVEL_HIGH = 5; // 0x5
@@ -10548,11 +10549,11 @@
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setAudioChannel(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setConfidenceLevel(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.PersistableBundle);
+    method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDetectionPersonalized(boolean);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDurationMillis(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordOffsetMillis(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setMediaSyncEvent(@NonNull android.media.MediaSyncEvent);
-    method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedHotwordDetection(boolean);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedScore(int);
     method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
   }
diff --git a/core/api/system-removed.txt b/core/api/system-removed.txt
index 304f4fe..7cf0076 100644
--- a/core/api/system-removed.txt
+++ b/core/api/system-removed.txt
@@ -58,6 +58,14 @@
     method @Deprecated public void destroy();
   }
 
+  public final class SearchTarget implements android.os.Parcelable {
+    method @Deprecated public boolean shouldHide();
+  }
+
+  public static final class SearchTarget.Builder {
+    method @Deprecated @NonNull public android.app.search.SearchTarget.Builder setShouldHide(boolean);
+  }
+
 }
 
 package android.bluetooth {
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index be62deb7..edd6047 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -101,7 +101,7 @@
     // We also check if the image has dark pixels in it,
     // to avoid bright images with some dark spots.
     private static final float DARK_PIXEL_CONTRAST = 5.5f;
-    private static final float MAX_DARK_AREA = 0.025f;
+    private static final float MAX_DARK_AREA = 0.05f;
 
     private final List<Color> mMainColors;
     private final Map<Integer, Integer> mAllColors;
diff --git a/core/java/android/app/search/Query.java b/core/java/android/app/search/Query.java
index 34ace48..c64e107 100644
--- a/core/java/android/app/search/Query.java
+++ b/core/java/android/app/search/Query.java
@@ -37,6 +37,14 @@
 public final class Query implements Parcelable {
 
     /**
+     * The lookup key for a integer that indicates what the height of the soft keyboard
+     * (e.g., IME, also known as Input Method Editor) was on the client window
+     * in dp (density-independent pixels). This information is to be used by the consumer
+     * of the API in estimating how many search results will be visible above the keyboard.
+     */
+    public static final String EXTRA_IME_HEIGHT = "android.app.search.extra.IME_HEIGHT";
+
+    /**
      * string typed from the client.
      */
     @NonNull
@@ -45,7 +53,7 @@
     private final long mTimestampMillis;
 
     /**
-     * Contains other client UI constraints related data
+     * Contains other client UI constraints related data (e.g., {@link #EXTRA_IME_HEIGHT}.
      */
     @NonNull
     private final Bundle mExtras;
diff --git a/core/java/android/app/search/SearchTarget.java b/core/java/android/app/search/SearchTarget.java
index 6d638d4..a590a5d 100644
--- a/core/java/android/app/search/SearchTarget.java
+++ b/core/java/android/app/search/SearchTarget.java
@@ -50,7 +50,7 @@
  * can recommend which layout this target should be rendered in.
  *
  * The service can also use fields such as {@link #getScore()} to indicate
- * how confidence the search result is and {@link #shouldHide()} to indicate
+ * how confidence the search result is and {@link #isHidden()} to indicate
  * whether it is recommended to be shown by default.
  *
  * Finally, {@link #getId()} is the unique identifier of this search target and a single
@@ -125,7 +125,7 @@
 
     private final float mScore;
 
-    private final boolean mShouldHide;
+    private final boolean mHidden;
 
     @NonNull
     private final String mPackageName;
@@ -149,7 +149,7 @@
         mId = parcel.readString();
         mParentId = parcel.readString();
         mScore = parcel.readFloat();
-        mShouldHide = parcel.readBoolean();
+        mHidden = parcel.readBoolean();
 
         mPackageName = parcel.readString();
         mUserHandle = UserHandle.of(parcel.readInt());
@@ -165,7 +165,7 @@
             @NonNull String layoutType,
             @NonNull String id,
             @Nullable String parentId,
-            float score, boolean shouldHide,
+            float score, boolean hidden,
             @NonNull String packageName,
             @NonNull UserHandle userHandle,
             @Nullable SearchAction action,
@@ -178,7 +178,7 @@
         mId = Objects.requireNonNull(id);
         mParentId = parentId;
         mScore = score;
-        mShouldHide = shouldHide;
+        mHidden = hidden;
         mPackageName = Objects.requireNonNull(packageName);
         mUserHandle = Objects.requireNonNull(userHandle);
         mSearchAction = action;
@@ -238,9 +238,20 @@
 
     /**
      * Indicates whether this object should be hidden and shown only on demand.
+     *
+     * @deprecated will be removed once SDK drops
+     * @removed
      */
+    @Deprecated
     public boolean shouldHide() {
-        return mShouldHide;
+        return mHidden;
+    }
+
+    /**
+     * Indicates whether this object should be hidden and shown only on demand.
+     */
+    public boolean isHidden() {
+        return mHidden;
     }
 
     /**
@@ -311,7 +322,7 @@
         parcel.writeString(mId);
         parcel.writeString(mParentId);
         parcel.writeFloat(mScore);
-        parcel.writeBoolean(mShouldHide);
+        parcel.writeBoolean(mHidden);
         parcel.writeString(mPackageName);
         parcel.writeInt(mUserHandle.getIdentifier());
         parcel.writeTypedObject(mSearchAction, flags);
@@ -351,7 +362,7 @@
         @Nullable
         private String mParentId;
         private float mScore;
-        private boolean mShouldHide;
+        private boolean mHidden;
         @NonNull
         private String mPackageName;
         @NonNull
@@ -374,7 +385,7 @@
             mLayoutType = Objects.requireNonNull(layoutType);
             mResultType = resultType;
             mScore = 1f;
-            mShouldHide = false;
+            mHidden = false;
         }
 
         /**
@@ -473,8 +484,20 @@
          * Sets whether the result should be hidden (e.g. not visible) by default inside client.
          */
         @NonNull
+        public Builder setHidden(boolean hidden) {
+            mHidden = hidden;
+            return this;
+        }
+
+        /**
+         * Sets whether the result should be hidden by default inside client.
+         * @deprecated will be removed once SDK drops
+         * @removed
+         */
+        @NonNull
+        @Deprecated
         public Builder setShouldHide(boolean shouldHide) {
-            mShouldHide = shouldHide;
+            mHidden = shouldHide;
             return this;
         }
 
@@ -485,7 +508,7 @@
          */
         @NonNull
         public SearchTarget build() {
-            return new SearchTarget(mResultType, mLayoutType, mId, mParentId, mScore, mShouldHide,
+            return new SearchTarget(mResultType, mLayoutType, mId, mParentId, mScore, mHidden,
                     mPackageName, mUserHandle,
                     mSearchAction, mShortcutInfo, mSliceUri, mAppWidgetProviderInfo,
                     mExtras);
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index e6ffded..b99ad51 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -442,13 +442,18 @@
     /**
      * Associates given device with given app for the given user directly, without UI prompt.
      *
+     * @param packageName package name of the companion app
+     * @param macAddress mac address of the device to associate
+     * @param certificate The SHA256 digest of the companion app's signing certificate
+     *
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES)
     public void associate(
             @NonNull String packageName,
-            @NonNull MacAddress macAddress) {
+            @NonNull MacAddress macAddress,
+            @NonNull byte[] certificate) {
         if (!checkFeaturePresent()) {
             return;
         }
@@ -458,7 +463,7 @@
         UserHandle user = android.os.Process.myUserHandle();
         try {
             mService.createAssociation(
-                    packageName, macAddress.toString(), user.getIdentifier());
+                    packageName, macAddress.toString(), user.getIdentifier(), certificate);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index cc3749c..d113b92 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -52,5 +52,6 @@
 
     boolean canPairWithoutPrompt(in String packageName, in String deviceMacAddress, int userId);
 
-    void createAssociation(in String packageName, in String macAddress, int userId);
+    void createAssociation(in String packageName, in String macAddress, int userId,
+        in byte[] certificate);
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a436fa4..688483a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1983,7 +1983,7 @@
      * activities that are not properly protected.
      *
      * <p>
-     * Input: {@link android.Manifest.permission_group} specifies the permission group
+     * Input: {@link #EXTRA_PERMISSION_GROUP_NAME} specifies the permission group
      * for which the launched UI would be targeted.
      * </p>
      * <p>
@@ -2013,12 +2013,12 @@
      * Input: {@link #EXTRA_ATTRIBUTION_TAGS} specifies the attribution tags for the usage entry.
      * </p>
      * <p>
-     * Input: {@link #EXTRA_START_TIME} specifies the start time of the period. Both start time and
-     * end time are needed and start time must be <= end time.
+     * Input: {@link #EXTRA_START_TIME} specifies the start time of the period (epoch time in
+     * millis). Both start time and end time are needed and start time must be <= end time.
      * </p>
      * <p>
-     * Input: {@link #EXTRA_END_TIME} specifies the end time of the period. Both start time and end
-     * time are needed and start time must be <= end time.
+     * Input: {@link #EXTRA_END_TIME} specifies the end time of the period (epoch time in
+     * millis). Both start time and end time are needed and start time must be <= end time.
      * </p>
      * <p>
      * Output: Nothing.
diff --git a/core/java/android/hardware/biometrics/BiometricTestSession.java b/core/java/android/hardware/biometrics/BiometricTestSession.java
index 41672b7..c62680f 100644
--- a/core/java/android/hardware/biometrics/BiometricTestSession.java
+++ b/core/java/android/hardware/biometrics/BiometricTestSession.java
@@ -23,7 +23,6 @@
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
 import android.content.Context;
-import android.hardware.fingerprint.FingerprintManager;
 import android.os.RemoteException;
 import android.util.ArraySet;
 import android.util.Log;
@@ -248,6 +247,12 @@
             }
         }
 
+        if (!mUsersCleaningUp.isEmpty()) {
+            // TODO(b/186600837): this seems common on multi sensor devices
+            Log.e(getTag(), "Cleanup not finished before shutdown - pending: "
+                    + mUsersCleaningUp.size());
+        }
+
         // Disable the test HAL after the sensor becomes idle.
         setTestHalEnabled(false);
     }
diff --git a/core/java/android/service/translation/TranslationService.java b/core/java/android/service/translation/TranslationService.java
index 2f704f4..e1d4a56 100644
--- a/core/java/android/service/translation/TranslationService.java
+++ b/core/java/android/service/translation/TranslationService.java
@@ -230,12 +230,8 @@
      */
     // TODO(b/176464808): the session id won't be unique cross client/server process. Need to find
     // solution to make it's safe.
-    // TODO: make abstract once aiai is implemented.
-    public void onCreateTranslationSession(@NonNull TranslationContext translationContext,
-            int sessionId, @NonNull Consumer<Boolean> callback) {
-        onCreateTranslationSession(translationContext, sessionId);
-        callback.accept(true);
-    }
+    public abstract void onCreateTranslationSession(@NonNull TranslationContext translationContext,
+            int sessionId, @NonNull Consumer<Boolean> callback);
 
     /**
      * TODO: fill in javadoc.
@@ -285,23 +281,9 @@
      * @param callback
      * @param cancellationSignal
      */
-    //TODO: make abstract once aiai transitions.
-    public void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
+    public abstract void onTranslationRequest(@NonNull TranslationRequest request, int sessionId,
             @Nullable CancellationSignal cancellationSignal,
-            @NonNull Consumer<TranslationResponse> callback) {
-        onTranslationRequest(request, sessionId, cancellationSignal,
-                new OnTranslationResultCallback() {
-                    @Override
-                    public void onTranslationSuccess(@NonNull TranslationResponse response) {
-                        callback.accept(response);
-                    }
-
-                    @Override
-                    public void onError() {
-                        // null-op
-                    }
-                });
-    }
+            @NonNull Consumer<TranslationResponse> callback);
 
     /**
      * TODO: fill in javadoc
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index 95e43f3..846f2f9 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -118,7 +118,7 @@
      * Returns whether the trigger has happened due to model having been personalized to fit user's
      * voice.
      */
-    private boolean mPersonalizedHotwordDetection = false;
+    private boolean mHotwordDetectionPersonalized = false;
 
     /**
      * Score for the hotword trigger.
@@ -270,7 +270,7 @@
             int hotwordOffsetMillis,
             int hotwordDurationMillis,
             int audioChannel,
-            boolean personalizedHotwordDetection,
+            boolean hotwordDetectionPersonalized,
             int score,
             int personalizedScore,
             int hotwordPhraseId,
@@ -282,7 +282,7 @@
         this.mHotwordOffsetMillis = hotwordOffsetMillis;
         this.mHotwordDurationMillis = hotwordDurationMillis;
         this.mAudioChannel = audioChannel;
-        this.mPersonalizedHotwordDetection = personalizedHotwordDetection;
+        this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
         this.mScore = score;
         this.mPersonalizedScore = personalizedScore;
         this.mHotwordPhraseId = hotwordPhraseId;
@@ -334,8 +334,8 @@
      * voice.
      */
     @DataClass.Generated.Member
-    public boolean isPersonalizedHotwordDetection() {
-        return mPersonalizedHotwordDetection;
+    public boolean isHotwordDetectionPersonalized() {
+        return mHotwordDetectionPersonalized;
     }
 
     /**
@@ -400,7 +400,7 @@
                 "hotwordOffsetMillis = " + mHotwordOffsetMillis + ", " +
                 "hotwordDurationMillis = " + mHotwordDurationMillis + ", " +
                 "audioChannel = " + mAudioChannel + ", " +
-                "personalizedHotwordDetection = " + mPersonalizedHotwordDetection + ", " +
+                "hotwordDetectionPersonalized = " + mHotwordDetectionPersonalized + ", " +
                 "score = " + mScore + ", " +
                 "personalizedScore = " + mPersonalizedScore + ", " +
                 "hotwordPhraseId = " + mHotwordPhraseId + ", " +
@@ -426,7 +426,7 @@
                 && mHotwordOffsetMillis == that.mHotwordOffsetMillis
                 && mHotwordDurationMillis == that.mHotwordDurationMillis
                 && mAudioChannel == that.mAudioChannel
-                && mPersonalizedHotwordDetection == that.mPersonalizedHotwordDetection
+                && mHotwordDetectionPersonalized == that.mHotwordDetectionPersonalized
                 && mScore == that.mScore
                 && mPersonalizedScore == that.mPersonalizedScore
                 && mHotwordPhraseId == that.mHotwordPhraseId
@@ -445,7 +445,7 @@
         _hash = 31 * _hash + mHotwordOffsetMillis;
         _hash = 31 * _hash + mHotwordDurationMillis;
         _hash = 31 * _hash + mAudioChannel;
-        _hash = 31 * _hash + Boolean.hashCode(mPersonalizedHotwordDetection);
+        _hash = 31 * _hash + Boolean.hashCode(mHotwordDetectionPersonalized);
         _hash = 31 * _hash + mScore;
         _hash = 31 * _hash + mPersonalizedScore;
         _hash = 31 * _hash + mHotwordPhraseId;
@@ -460,7 +460,7 @@
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
         int flg = 0;
-        if (mPersonalizedHotwordDetection) flg |= 0x20;
+        if (mHotwordDetectionPersonalized) flg |= 0x20;
         if (mMediaSyncEvent != null) flg |= 0x2;
         dest.writeInt(flg);
         dest.writeInt(mConfidenceLevel);
@@ -486,7 +486,7 @@
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
         int flg = in.readInt();
-        boolean personalizedHotwordDetection = (flg & 0x20) != 0;
+        boolean hotwordDetectionPersonalized = (flg & 0x20) != 0;
         int confidenceLevel = in.readInt();
         MediaSyncEvent mediaSyncEvent = (flg & 0x2) == 0 ? null : (MediaSyncEvent) in.readTypedObject(MediaSyncEvent.CREATOR);
         int hotwordOffsetMillis = in.readInt();
@@ -504,7 +504,7 @@
         this.mHotwordOffsetMillis = hotwordOffsetMillis;
         this.mHotwordDurationMillis = hotwordDurationMillis;
         this.mAudioChannel = audioChannel;
-        this.mPersonalizedHotwordDetection = personalizedHotwordDetection;
+        this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
         this.mScore = score;
         this.mPersonalizedScore = personalizedScore;
         this.mHotwordPhraseId = hotwordPhraseId;
@@ -541,7 +541,7 @@
         private int mHotwordOffsetMillis;
         private int mHotwordDurationMillis;
         private int mAudioChannel;
-        private boolean mPersonalizedHotwordDetection;
+        private boolean mHotwordDetectionPersonalized;
         private int mScore;
         private int mPersonalizedScore;
         private int mHotwordPhraseId;
@@ -618,10 +618,10 @@
          * voice.
          */
         @DataClass.Generated.Member
-        public @NonNull Builder setPersonalizedHotwordDetection(boolean value) {
+        public @NonNull Builder setHotwordDetectionPersonalized(boolean value) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x20;
-            mPersonalizedHotwordDetection = value;
+            mHotwordDetectionPersonalized = value;
             return this;
         }
 
@@ -708,7 +708,7 @@
                 mAudioChannel = AUDIO_CHANNEL_UNSET;
             }
             if ((mBuilderFieldsSet & 0x20) == 0) {
-                mPersonalizedHotwordDetection = false;
+                mHotwordDetectionPersonalized = false;
             }
             if ((mBuilderFieldsSet & 0x40) == 0) {
                 mScore = defaultScore();
@@ -728,7 +728,7 @@
                     mHotwordOffsetMillis,
                     mHotwordDurationMillis,
                     mAudioChannel,
-                    mPersonalizedHotwordDetection,
+                    mHotwordDetectionPersonalized,
                     mScore,
                     mPersonalizedScore,
                     mHotwordPhraseId,
@@ -745,10 +745,10 @@
     }
 
     @DataClass.Generated(
-            time = 1621631039729L,
+            time = 1621943150502L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
-            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mPersonalizedHotwordDetection\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final  int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\nprivate static  int defaultHotwordPhraseId()\npublic static  int getMaxHotwordPhraseId()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+            inputSignatures = "public static final  int CONFIDENCE_LEVEL_NONE\npublic static final  int CONFIDENCE_LEVEL_LOW\npublic static final  int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM\npublic static final  int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final  int CONFIDENCE_LEVEL_HIGH\npublic static final  int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final  int HOTWORD_OFFSET_UNSET\npublic static final  int AUDIO_CHANNEL_UNSET\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate  int mHotwordOffsetMillis\nprivate  int mHotwordDurationMillis\nprivate  int mAudioChannel\nprivate  boolean mHotwordDetectionPersonalized\nprivate final  int mScore\nprivate final  int mPersonalizedScore\nprivate final  int mHotwordPhraseId\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static  int defaultConfidenceLevel()\nprivate static  int defaultScore()\nprivate static  int defaultPersonalizedScore()\npublic static  int getMaxScore()\nprivate static  int defaultHotwordPhraseId()\npublic static  int getMaxHotwordPhraseId()\nprivate static  android.os.PersistableBundle defaultExtras()\npublic static  int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/view/TunnelModeEnabledListener.java b/core/java/android/view/TunnelModeEnabledListener.java
new file mode 100644
index 0000000..c158da9
--- /dev/null
+++ b/core/java/android/view/TunnelModeEnabledListener.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Listens for tunnel mode enabled/disabled events from SurfaceFlinger.
+ * {@hide}
+ */
+public abstract class TunnelModeEnabledListener {
+
+    private long mNativeListener;
+    private final Executor mExecutor;
+
+    public TunnelModeEnabledListener(Executor executor) {
+        mExecutor = executor;
+        mNativeListener = nativeCreate(this);
+    }
+
+    /**
+     * Destroys the listener.
+     */
+    public void destroy() {
+        if (mNativeListener == 0) {
+            return;
+        }
+        unregister(this);
+        nativeDestroy(mNativeListener);
+        mNativeListener = 0;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            destroy();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Reports when tunnel mode has been enabled/disabled.
+     */
+    public abstract void onTunnelModeEnabledChanged(boolean tunnelModeEnabled);
+
+    /**
+     * Registers a listener.
+     */
+    public static void register(TunnelModeEnabledListener listener) {
+        if (listener.mNativeListener == 0) {
+            return;
+        }
+        nativeRegister(listener.mNativeListener);
+    }
+
+    /**
+     * Unregisters a listener.
+     */
+    public static void unregister(TunnelModeEnabledListener listener) {
+        if (listener.mNativeListener == 0) {
+            return;
+        }
+        nativeUnregister(listener.mNativeListener);
+    }
+
+    /**
+     * Dispatch tunnel mode enabled.
+     *
+     * Called from native code on a binder thread.
+     */
+    @VisibleForTesting
+    public static void dispatchOnTunnelModeEnabledChanged(TunnelModeEnabledListener listener,
+            boolean tunnelModeEnabled) {
+        listener.mExecutor.execute(() -> listener.onTunnelModeEnabledChanged(tunnelModeEnabled));
+    }
+
+    private static native long nativeCreate(TunnelModeEnabledListener thiz);
+    private static native void nativeDestroy(long ptr);
+    private static native void nativeRegister(long ptr);
+    private static native void nativeUnregister(long ptr);
+}
diff --git a/core/java/android/widget/AnalogClock.java b/core/java/android/widget/AnalogClock.java
index 5bb8a8e..40cce7c 100644
--- a/core/java/android/widget/AnalogClock.java
+++ b/core/java/android/widget/AnalogClock.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.AppGlobals;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -61,8 +62,9 @@
 @Deprecated
 public class AnalogClock extends View {
     private static final String LOG_TAG = "AnalogClock";
+
     /** How many times per second that the seconds hand advances. */
-    private static final long SECONDS_HAND_FPS = 30;
+    private final int mSecondsHandFps;
 
     private Clock mClock;
     @Nullable
@@ -106,6 +108,10 @@
     public AnalogClock(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
 
+        mSecondsHandFps = AppGlobals.getIntCoreSetting(
+                WidgetFlags.KEY_ANALOG_CLOCK_SECONDS_HAND_FPS,
+                WidgetFlags.ANALOG_CLOCK_SECONDS_HAND_FPS_DEFAULT);
+
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, com.android.internal.R.styleable.AnalogClock, defStyleAttr, defStyleRes);
         saveAttributeDataForStyleable(context, com.android.internal.R.styleable.AnalogClock,
@@ -743,7 +749,7 @@
         // n positions between two given numbers, where n is the number of ticks per second. This
         // ensures the second hand advances by a consistent distance despite our handler callbacks
         // occurring at inconsistent frequencies.
-        mSeconds = Math.round(rawSeconds * SECONDS_HAND_FPS) / (float) SECONDS_HAND_FPS;
+        mSeconds = Math.round(rawSeconds * mSecondsHandFps) / (float) mSecondsHandFps;
         mMinutes = localTime.getMinute() + mSeconds / 60.0f;
         mHour = localTime.getHour() + mMinutes / 60.0f;
         mChanged = true;
@@ -781,7 +787,7 @@
             // How many milliseconds through the second we currently are.
             long millisOfSecond = Duration.ofNanos(localTime.getNano()).toMillis();
             // How many milliseconds there are between tick positions for the seconds hand.
-            double millisPerTick = 1000 / (double) SECONDS_HAND_FPS;
+            double millisPerTick = 1000 / (double) mSecondsHandFps;
             // How many milliseconds we are past the last tick position.
             long millisPastLastTick = Math.round(millisOfSecond % millisPerTick);
             // How many milliseconds there are until the next tick position.
diff --git a/core/java/android/widget/WidgetFlags.java b/core/java/android/widget/WidgetFlags.java
index 1a49365..0971268 100644
--- a/core/java/android/widget/WidgetFlags.java
+++ b/core/java/android/widget/WidgetFlags.java
@@ -199,6 +199,17 @@
      */
     public static final float MAGNIFIER_ASPECT_RATIO_DEFAULT = 5.5f;
 
+    /** The flag of the fps of the analog clock seconds hand. */
+    public static final String ANALOG_CLOCK_SECONDS_HAND_FPS =
+            "AnalogClockFeature__analog_clock_seconds_hand_fps";
+
+    /** The key name used in app core settings for {@link #ANALOG_CLOCK_SECONDS_HAND_FPS}. */
+    public static final String KEY_ANALOG_CLOCK_SECONDS_HAND_FPS =
+            "widget__analog_clock_seconds_hand_fps";
+
+    /** Default value for the flag {@link #ANALOG_CLOCK_SECONDS_HAND_FPS}. */
+    public static final int ANALOG_CLOCK_SECONDS_HAND_FPS_DEFAULT = 1;
+
     private WidgetFlags() {
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
index d4d6125..3aaccdd 100644
--- a/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
+++ b/core/java/com/android/internal/os/BatteryUsageStatsProvider.java
@@ -180,29 +180,28 @@
     }
 
     private long getProcessForegroundTimeMs(BatteryStats.Uid uid, long realtimeUs) {
-        final long topStateDurationMs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP,
-                realtimeUs, BatteryStats.STATS_SINCE_CHARGED) / 1000;
-
-        long foregroundActivityDurationMs = 0;
+        final long topStateDurationUs = uid.getProcessStateTime(BatteryStats.Uid.PROCESS_STATE_TOP,
+                realtimeUs, BatteryStats.STATS_SINCE_CHARGED);
+        long foregroundActivityDurationUs = 0;
         final BatteryStats.Timer foregroundActivityTimer = uid.getForegroundActivityTimer();
         if (foregroundActivityTimer != null) {
-            foregroundActivityDurationMs = foregroundActivityTimer.getTotalTimeLocked(realtimeUs,
-                    BatteryStats.STATS_SINCE_CHARGED) / 1000;
+            foregroundActivityDurationUs = foregroundActivityTimer.getTotalTimeLocked(realtimeUs,
+                    BatteryStats.STATS_SINCE_CHARGED);
         }
 
         // Use the min value of STATE_TOP time and foreground activity time, since both of these
         // times are imprecise
-        final long foregroundDurationMs = Math.min(topStateDurationMs,
-                foregroundActivityDurationMs);
+        long totalForegroundDurationUs = Math.min(topStateDurationUs, foregroundActivityDurationUs);
 
-        long foregroundServiceDurationMs = 0;
-        final BatteryStats.Timer foregroundServiceTimer = uid.getForegroundServiceTimer();
-        if (foregroundServiceTimer != null) {
-            foregroundServiceDurationMs = foregroundServiceTimer.getTotalTimeLocked(realtimeUs,
-                    BatteryStats.STATS_SINCE_CHARGED) / 1000;
-        }
+        totalForegroundDurationUs += uid.getProcessStateTime(
+                BatteryStats.Uid.PROCESS_STATE_FOREGROUND, realtimeUs,
+                BatteryStats.STATS_SINCE_CHARGED);
 
-        return foregroundDurationMs + foregroundServiceDurationMs;
+        totalForegroundDurationUs += uid.getProcessStateTime(
+                BatteryStats.Uid.PROCESS_STATE_FOREGROUND_SERVICE, realtimeUs,
+                BatteryStats.STATS_SINCE_CHARGED);
+
+        return totalForegroundDurationUs / 1000;
     }
 
     private long getProcessBackgroundTimeMs(BatteryStats.Uid uid, long realtimeUs) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 1f805c9..1468633 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -128,6 +128,7 @@
                 "android_graphics_BLASTBufferQueue.cpp",
                 "android_view_SurfaceSession.cpp",
                 "android_view_TextureView.cpp",
+                "android_view_TunnelModeEnabledListener.cpp",
                 "android_view_VelocityTracker.cpp",
                 "android_view_VerifiedKeyEvent.cpp",
                 "android_view_VerifiedMotionEvent.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f76cccb..7e8fc7e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -127,6 +127,7 @@
 extern int register_android_view_SurfaceSession(JNIEnv* env);
 extern int register_android_view_CompositionSamplingListener(JNIEnv* env);
 extern int register_android_view_TextureView(JNIEnv* env);
+extern int register_android_view_TunnelModeEnabledListener(JNIEnv* env);
 extern int register_android_database_CursorWindow(JNIEnv* env);
 extern int register_android_database_SQLiteConnection(JNIEnv* env);
 extern int register_android_database_SQLiteGlobal(JNIEnv* env);
@@ -1521,6 +1522,7 @@
         REG_JNI(register_android_view_SurfaceSession),
         REG_JNI(register_android_view_CompositionSamplingListener),
         REG_JNI(register_android_view_TextureView),
+        REG_JNI(register_android_view_TunnelModeEnabledListener),
         REG_JNI(register_com_google_android_gles_jni_EGLImpl),
         REG_JNI(register_com_google_android_gles_jni_GLImpl),
         REG_JNI(register_android_opengl_jni_EGL14),
diff --git a/core/jni/android_view_TunnelModeEnabledListener.cpp b/core/jni/android_view_TunnelModeEnabledListener.cpp
new file mode 100644
index 0000000..af7bae8
--- /dev/null
+++ b/core/jni/android_view_TunnelModeEnabledListener.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2021 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 "TunnelModeEnabledListener"
+
+#include "android_util_Binder.h"
+#include "core_jni_helpers.h"
+
+#include <nativehelper/JNIHelp.h>
+
+#include <android/gui/BnTunnelModeEnabledListener.h>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <utils/Log.h>
+
+#include <gui/SurfaceComposerClient.h>
+#include <ui/Rect.h>
+
+namespace android {
+
+namespace {
+
+struct {
+    jclass mClass;
+    jmethodID mDispatchOnTunnelModeEnabledChanged;
+} gListenerClassInfo;
+
+struct TunnelModeEnabledListener : public gui::BnTunnelModeEnabledListener {
+    TunnelModeEnabledListener(JNIEnv* env, jobject listener)
+          : mListener(env->NewWeakGlobalRef(listener)) {}
+
+    binder::Status onTunnelModeEnabledChanged(bool tunnelModeEnabled) override {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        LOG_ALWAYS_FATAL_IF(env == nullptr,
+                            "Unable to retrieve JNIEnv in onTunnelModeEnabledChanged.");
+
+        jobject listener = env->NewGlobalRef(mListener);
+        if (listener == NULL) {
+            // Weak reference went out of scope
+            return binder::Status::ok();
+        }
+        env->CallStaticVoidMethod(gListenerClassInfo.mClass,
+                                  gListenerClassInfo.mDispatchOnTunnelModeEnabledChanged, listener,
+                                  static_cast<jboolean>(tunnelModeEnabled));
+        env->DeleteGlobalRef(listener);
+
+        if (env->ExceptionCheck()) {
+            ALOGE("TunnelModeEnabledListener.onTunnelModeEnabledChanged() failed.");
+            LOGE_EX(env);
+            env->ExceptionClear();
+        }
+        return binder::Status::ok();
+    }
+
+protected:
+    virtual ~TunnelModeEnabledListener() {
+        JNIEnv* env = AndroidRuntime::getJNIEnv();
+        env->DeleteWeakGlobalRef(mListener);
+    }
+
+private:
+    jweak mListener;
+};
+
+jlong nativeCreate(JNIEnv* env, jclass clazz, jobject obj) {
+    TunnelModeEnabledListener* listener = new TunnelModeEnabledListener(env, obj);
+    listener->incStrong((void*)nativeCreate);
+    return reinterpret_cast<jlong>(listener);
+}
+
+void nativeDestroy(JNIEnv* env, jclass clazz, jlong ptr) {
+    TunnelModeEnabledListener* listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
+    listener->decStrong((void*)nativeCreate);
+}
+
+void nativeRegister(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
+    if (SurfaceComposerClient::addTunnelModeEnabledListener(listener) != OK) {
+        constexpr auto error_msg = "Couldn't addTunnelModeEnabledListener";
+        ALOGE(error_msg);
+        jniThrowRuntimeException(env, error_msg);
+    }
+}
+
+void nativeUnregister(JNIEnv* env, jclass clazz, jlong ptr) {
+    sp<TunnelModeEnabledListener> listener = reinterpret_cast<TunnelModeEnabledListener*>(ptr);
+
+    if (SurfaceComposerClient::removeTunnelModeEnabledListener(listener) != OK) {
+        constexpr auto error_msg = "Couldn't removeTunnelModeEnabledListener";
+        ALOGE(error_msg);
+        jniThrowRuntimeException(env, error_msg);
+    }
+}
+
+const JNINativeMethod gMethods[] = {
+        /* name, signature, funcPtr */
+        {"nativeCreate", "(Landroid/view/TunnelModeEnabledListener;)J", (void*)nativeCreate},
+        {"nativeDestroy", "(J)V", (void*)nativeDestroy},
+        {"nativeRegister", "(J)V", (void*)nativeRegister},
+        {"nativeUnregister", "(J)V", (void*)nativeUnregister}};
+
+} // namespace
+
+int register_android_view_TunnelModeEnabledListener(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/view/TunnelModeEnabledListener", gMethods,
+                                       NELEM(gMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz = env->FindClass("android/view/TunnelModeEnabledListener");
+    gListenerClassInfo.mClass = MakeGlobalRefOrDie(env, clazz);
+    gListenerClassInfo.mDispatchOnTunnelModeEnabledChanged =
+            env->GetStaticMethodID(clazz, "dispatchOnTunnelModeEnabledChanged",
+                                   "(Landroid/view/TunnelModeEnabledListener;Z)V");
+    return 0;
+}
+
+} // namespace android
diff --git a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
index c207135..0c7218e 100644
--- a/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
+++ b/core/tests/batterystatstests/BatteryStatsViewer/src/com/android/frameworks/core/batterystatsviewer/BatteryConsumerData.java
@@ -124,7 +124,8 @@
         for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
             final String metricTitle = getPowerMetricTitle(component);
             final int powerModel = requestedBatteryConsumer.getPowerModel(component);
-            if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
+            if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE
+                    || powerModel == BatteryConsumer.POWER_MODEL_UNDEFINED) {
                 addEntry(metricTitle, EntryType.UID_POWER_MODELED,
                         requestedBatteryConsumer.getConsumedPower(component),
                         totalPowerByComponentMah[component]
@@ -202,7 +203,8 @@
         for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
             final String metricTitle = getPowerMetricTitle(component);
             final int powerModel = deviceBatteryConsumer.getPowerModel(component);
-            if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
+            if (powerModel == BatteryConsumer.POWER_MODEL_POWER_PROFILE
+                    || powerModel == BatteryConsumer.POWER_MODEL_UNDEFINED) {
                 addEntry(metricTitle, EntryType.DEVICE_POWER_MODELED,
                         deviceBatteryConsumer.getConsumedPower(component),
                         appsBatteryConsumer.getConsumedPower(component));
@@ -237,8 +239,9 @@
 
     private boolean isPowerProfileModelsOnly(BatteryConsumer batteryConsumer) {
         for (int component = 0; component < BatteryConsumer.POWER_COMPONENT_COUNT; component++) {
-            if (batteryConsumer.getPowerModel(component)
-                    != BatteryConsumer.POWER_MODEL_POWER_PROFILE) {
+            final int powerModel = batteryConsumer.getPowerModel(component);
+            if (powerModel != BatteryConsumer.POWER_MODEL_POWER_PROFILE
+                    && powerModel != BatteryConsumer.POWER_MODEL_UNDEFINED) {
                 return false;
             }
         }
diff --git a/core/tests/coretests/src/android/view/TunnelModeEnabledListenerTest.java b/core/tests/coretests/src/android/view/TunnelModeEnabledListenerTest.java
new file mode 100644
index 0000000..65dd34f
--- /dev/null
+++ b/core/tests/coretests/src/android/view/TunnelModeEnabledListenerTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@MediumTest
+@Presubmit
+public class TunnelModeEnabledListenerTest {
+    private TestableTunnelModeEnabledListener mListener;
+
+    @Before
+    public void init() {
+        mListener = new TestableTunnelModeEnabledListener();
+    }
+
+    @Test
+    public void testRegisterUnregister() {
+        TunnelModeEnabledListener.register(mListener);
+        TunnelModeEnabledListener.unregister(mListener);
+    }
+
+    @Test
+    public void testDispatchUpdatesListener() {
+        TunnelModeEnabledListener.dispatchOnTunnelModeEnabledChanged(mListener, true);
+        assertEquals(true, mListener.mTunnelModeEnabled.get());
+        TunnelModeEnabledListener.dispatchOnTunnelModeEnabledChanged(mListener, false);
+        assertEquals(false, mListener.mTunnelModeEnabled.get());
+    }
+
+    @Test
+    public void testRegisterUpdatesListener() throws Exception {
+        TunnelModeEnabledListener.register(mListener);
+        TimeUnit.SECONDS.sleep(1);
+        assertTrue(mListener.mTunnelModeEnabledUpdated.get());
+        TunnelModeEnabledListener.unregister(mListener);
+    }
+
+    private static class TestableTunnelModeEnabledListener extends TunnelModeEnabledListener {
+        AtomicBoolean mTunnelModeEnabled;
+        AtomicBoolean mTunnelModeEnabledUpdated;
+
+        TestableTunnelModeEnabledListener() {
+            super(Runnable::run);
+            mTunnelModeEnabled = new AtomicBoolean(false);
+            mTunnelModeEnabledUpdated = new AtomicBoolean();
+        }
+
+        @Override
+        public void onTunnelModeEnabledChanged(boolean tunnelModeEnabled) {
+            mTunnelModeEnabled.set(tunnelModeEnabled);
+            mTunnelModeEnabledUpdated.set(true);
+        }
+    }
+
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
index 7f0449b..d83645d 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsProviderTest.java
@@ -59,8 +59,14 @@
                 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
         batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_SERVICE,
                 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS);
-        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+        batteryStats.noteUidProcessStateLocked(APP_UID,
+                ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE,
                 40 * MINUTE_IN_MS, 40 * MINUTE_IN_MS);
+        batteryStats.noteUidProcessStateLocked(APP_UID,
+                ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE,
+                50 * MINUTE_IN_MS, 50 * MINUTE_IN_MS);
+        batteryStats.noteUidProcessStateLocked(APP_UID, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
+                80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
 
         mStatsRule.setCurrentTime(54321);
 
@@ -74,7 +80,7 @@
                 batteryUsageStats.getUidBatteryConsumers();
         final UidBatteryConsumer uidBatteryConsumer = uidBatteryConsumers.get(0);
         assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
-                .isEqualTo(20 * MINUTE_IN_MS);
+                .isEqualTo(60 * MINUTE_IN_MS);
         assertThat(uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
                 .isEqualTo(10 * MINUTE_IN_MS);
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 19332c7..8d4739d 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -473,6 +473,7 @@
         <permission name="android.permission.UPDATE_FONTS" />
         <!-- Permission required for hotword detection service CTS tests -->
         <permission name="android.permission.MANAGE_HOTWORD_DETECTION" />
+        <permission name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
         <permission name="android.permission.MANAGE_APP_HIBERNATION"/>
         <!-- Permission required for CTS test - ResourceObserverNativeTest -->
         <permission name="android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER" />
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 187e104..c37e88a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -277,8 +277,9 @@
             // waiting for setContentView before relayoutWindow
             SplashScreenView contentView = viewSupplier.get();
             final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
-            // if record == null, either the starting window added fail or removed already.
-            if (record != null) {
+            // If record == null, either the starting window added fail or removed already.
+            // Do not add this view if the token is mismatch.
+            if (record != null && appToken == record.mAppToken) {
                 // if view == null then creation of content view was failed.
                 if (contentView != null) {
                     try {
@@ -297,15 +298,16 @@
 
         try {
             final WindowManager wm = context.getSystemService(WindowManager.class);
-            postAddWindow(taskId, appToken, rootLayout, wm, params);
-
-            // We use the splash screen worker thread to create SplashScreenView while adding the
-            // window, as otherwise Choreographer#doFrame might be delayed on this thread.
-            // And since Choreographer#doFrame won't happen immediately after adding the window, if
-            // the view is not added to the PhoneWindow on the first #doFrame, the view will not be
-            // rendered on the first frame. So here we need to synchronize the view on the window
-            // before first round relayoutWindow, which will happen after insets animation.
-            mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
+            if (postAddWindow(taskId, appToken, rootLayout, wm, params)) {
+                // We use the splash screen worker thread to create SplashScreenView while adding
+                // the window, as otherwise Choreographer#doFrame might be delayed on this thread.
+                // And since Choreographer#doFrame won't happen immediately after adding the window,
+                // if the view is not added to the PhoneWindow on the first #doFrame, the view will
+                // not be rendered on the first frame. So here we need to synchronize the view on
+                // the window before first round relayoutWindow, which will happen after insets
+                // animation.
+                mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
+            }
         } catch (RuntimeException e) {
             // don't crash if something else bad happens, for example a
             // failure loading resources because we are loading from an app
@@ -347,7 +349,8 @@
         final int taskId = startingWindowInfo.taskInfo.taskId;
         final TaskSnapshotWindow surface = TaskSnapshotWindow.create(startingWindowInfo, appToken,
                 snapshot, mSplashScreenExecutor, () -> removeWindowNoAnimate(taskId));
-        final StartingWindowRecord tView = new StartingWindowRecord(null/* decorView */, surface);
+        final StartingWindowRecord tView = new StartingWindowRecord(appToken,
+                null/* decorView */, surface);
         mStartingWindowRecords.put(taskId, tView);
     }
 
@@ -382,7 +385,7 @@
         ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
     }
 
-    protected void postAddWindow(int taskId, IBinder appToken, View view, WindowManager wm,
+    protected boolean postAddWindow(int taskId, IBinder appToken, View view, WindowManager wm,
             WindowManager.LayoutParams params) {
         boolean shouldSaveView = true;
         try {
@@ -401,12 +404,13 @@
         }
         if (shouldSaveView) {
             removeWindowNoAnimate(taskId);
-            saveSplashScreenRecord(taskId, view);
+            saveSplashScreenRecord(appToken, taskId, view);
         }
+        return shouldSaveView;
     }
 
-    private void saveSplashScreenRecord(int taskId, View view) {
-        final StartingWindowRecord tView = new StartingWindowRecord(view,
+    private void saveSplashScreenRecord(IBinder appToken, int taskId, View view) {
+        final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
                 null/* TaskSnapshotWindow */);
         mStartingWindowRecords.put(taskId, tView);
     }
@@ -468,12 +472,15 @@
      * Record the view or surface for a starting window.
      */
     private static class StartingWindowRecord {
+        private final IBinder mAppToken;
         private final View mDecorView;
         private final TaskSnapshotWindow mTaskSnapshotWindow;
         private SplashScreenView mContentView;
         private boolean mSetSplashScreen;
 
-        StartingWindowRecord(View decorView, TaskSnapshotWindow taskSnapshotWindow) {
+        StartingWindowRecord(IBinder appToken, View decorView,
+                TaskSnapshotWindow taskSnapshotWindow) {
+            mAppToken = appToken;
             mDecorView = decorView;
             mTaskSnapshotWindow = taskSnapshotWindow;
         }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 2623535..4e3e133 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -83,11 +83,12 @@
         }
 
         @Override
-        protected void postAddWindow(int taskId, IBinder appToken,
+        protected boolean postAddWindow(int taskId, IBinder appToken,
                 View view, WindowManager wm, WindowManager.LayoutParams params) {
             // listen for addView
             mAddWindowForTask = taskId;
             mViewThemeResId = view.getContext().getThemeResId();
+            return true;
         }
 
         @Override
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index 859a555..db3a108 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -24,10 +24,10 @@
 #include <GrDirectContext.h>
 #include <SkCanvas.h>
 #include <SkImage.h>
+#include <gui/TraceUtils.h>
 #include <utils/GLUtils.h>
 #include <utils/NdkUtils.h>
 #include <utils/Trace.h>
-#include <utils/TraceUtils.h>
 
 #include <thread>
 
diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp
index a9b129f..8a8b418 100644
--- a/libs/hwui/Readback.cpp
+++ b/libs/hwui/Readback.cpp
@@ -19,6 +19,7 @@
 #include <sync/sync.h>
 #include <system/window.h>
 
+#include <gui/TraceUtils.h>
 #include "DeferredLayerUpdater.h"
 #include "Properties.h"
 #include "hwui/Bitmap.h"
@@ -28,7 +29,6 @@
 #include "utils/Color.h"
 #include "utils/MathUtils.h"
 #include "utils/NdkUtils.h"
-#include "utils/TraceUtils.h"
 
 using namespace android::uirenderer::renderthread;
 
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index ded7994..9a9e6d4 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -27,9 +27,9 @@
 #include "DamageAccumulator.h"
 #include "pipeline/skia/SkiaDisplayList.h"
 #endif
+#include <gui/TraceUtils.h>
 #include "utils/MathUtils.h"
 #include "utils/StringUtils.h"
-#include "utils/TraceUtils.h"
 
 #include <SkPathOps.h>
 #include <algorithm>
diff --git a/libs/hwui/VectorDrawable.cpp b/libs/hwui/VectorDrawable.cpp
index 4a21ad6..55f434f 100644
--- a/libs/hwui/VectorDrawable.cpp
+++ b/libs/hwui/VectorDrawable.cpp
@@ -30,8 +30,8 @@
 #include "renderthread/RenderThread.h"
 #endif
 
+#include <gui/TraceUtils.h>
 #include "utils/Macros.h"
-#include "utils/TraceUtils.h"
 #include "utils/VectorDrawableUtils.h"
 
 namespace android {
diff --git a/libs/hwui/hwui/AnimatedImageDrawable.cpp b/libs/hwui/hwui/AnimatedImageDrawable.cpp
index 0d3d3e3..876f5c8 100644
--- a/libs/hwui/hwui/AnimatedImageDrawable.cpp
+++ b/libs/hwui/hwui/AnimatedImageDrawable.cpp
@@ -19,7 +19,7 @@
 #include "AnimatedImageThread.h"
 #endif
 
-#include "utils/TraceUtils.h"
+#include <gui/TraceUtils.h>
 #include "pipeline/skia/SkiaUtils.h"
 
 #include <SkPicture.h>
diff --git a/libs/hwui/jni/Typeface.cpp b/libs/hwui/jni/Typeface.cpp
index f928baa..ee7b260 100644
--- a/libs/hwui/jni/Typeface.cpp
+++ b/libs/hwui/jni/Typeface.cpp
@@ -15,19 +15,19 @@
  */
 
 #define ATRACE_TAG ATRACE_TAG_VIEW
-#include "FontUtils.h"
-#include "GraphicsJNI.h"
-#include "fonts/Font.h"
-#include <nativehelper/ScopedPrimitiveArray.h>
-#include <nativehelper/ScopedUtfChars.h>
-#include "SkData.h"
-#include "SkTypeface.h"
+#include <gui/TraceUtils.h>
 #include <hwui/Typeface.h>
 #include <minikin/FontCollection.h>
 #include <minikin/FontFamily.h>
 #include <minikin/FontFileParser.h>
 #include <minikin/SystemFonts.h>
-#include <utils/TraceUtils.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
+#include "FontUtils.h"
+#include "GraphicsJNI.h"
+#include "SkData.h"
+#include "SkTypeface.h"
+#include "fonts/Font.h"
 
 #include <mutex>
 #include <unordered_map>
@@ -37,7 +37,6 @@
 #endif
 
 using namespace android;
-using android::uirenderer::TraceUtils;
 
 static inline Typeface* toTypeface(jlong ptr) {
     return reinterpret_cast<Typeface*>(ptr);
diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
index 82bc5a1..4289c45 100644
--- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp
@@ -24,6 +24,7 @@
 #include <Properties.h>
 #include <RootRenderNode.h>
 #include <dlfcn.h>
+#include <gui/TraceUtils.h>
 #include <inttypes.h>
 #include <media/NdkImage.h>
 #include <media/NdkImageReader.h>
@@ -39,7 +40,6 @@
 #include <utils/RefBase.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
-#include <utils/TraceUtils.h>
 
 #include <pthread.h>
 
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 002bd83..e1da169 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -26,8 +26,8 @@
 #endif
 #include <TreeInfo.h>
 #include <effects/StretchEffect.h>
+#include <gui/TraceUtils.h>
 #include <hwui/Paint.h>
-#include <utils/TraceUtils.h>
 
 namespace android {
 
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index c8247e7..d7546d8 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -16,11 +16,11 @@
 
 #include "RenderNodeDrawable.h"
 #include <SkPaintFilterCanvas.h>
-#include "StretchMask.h"
+#include <gui/TraceUtils.h>
 #include "RenderNode.h"
 #include "SkiaDisplayList.h"
+#include "StretchMask.h"
 #include "TransformCanvas.h"
-#include "utils/TraceUtils.h"
 
 #include <include/effects/SkImageFilters.h>
 
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index 3baff7e..c482fc1 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -16,6 +16,7 @@
 
 #include "ShaderCache.h"
 #include <GrDirectContext.h>
+#include <gui/TraceUtils.h>
 #include <log/log.h>
 #include <openssl/sha.h>
 #include <algorithm>
@@ -23,7 +24,6 @@
 #include <thread>
 #include "FileBlobCache.h"
 #include "Properties.h"
-#include "utils/TraceUtils.h"
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 50eea31..a78cd83 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -16,6 +16,7 @@
 
 #include "SkiaOpenGLPipeline.h"
 
+#include <gui/TraceUtils.h>
 #include "DeferredLayerUpdater.h"
 #include "LayerDrawable.h"
 #include "LightingInfo.h"
@@ -27,7 +28,6 @@
 #include "renderthread/EglManager.h"
 #include "renderthread/Frame.h"
 #include "utils/GLUtils.h"
-#include "utils/TraceUtils.h"
 
 #include <GLES3/gl3.h>
 
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 1f73ac9..039b0f9 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -31,13 +31,13 @@
 
 #include <sstream>
 
+#include <gui/TraceUtils.h>
 #include "LightingInfo.h"
 #include "VectorDrawable.h"
 #include "thread/CommonPool.h"
 #include "tools/SkSharingProc.h"
 #include "utils/Color.h"
 #include "utils/String8.h"
-#include "utils/TraceUtils.h"
 
 using namespace android::uirenderer::renderthread;
 
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 30a3fc5..0e4a1f9 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -16,6 +16,7 @@
 
 #include "SkiaVulkanPipeline.h"
 
+#include <gui/TraceUtils.h>
 #include "DeferredLayerUpdater.h"
 #include "LightingInfo.h"
 #include "Readback.h"
@@ -25,7 +26,6 @@
 #include "VkInteropFunctorDrawable.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/Frame.h"
-#include "utils/TraceUtils.h"
 
 #include <SkSurface.h>
 #include <SkTypes.h>
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 6efe176..8abf4534 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -21,9 +21,9 @@
 #include <SkAndroidFrameworkUtils.h>
 #include <SkImage.h>
 #include <SkM44.h>
+#include <gui/TraceUtils.h>
 #include <utils/Color.h>
 #include <utils/Trace.h>
-#include <utils/TraceUtils.h>
 #include <vk/GrVkTypes.h>
 #include <thread>
 #include "renderthread/RenderThread.h"
diff --git a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
index bae11f7..ddfb66f 100644
--- a/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkInteropFunctorDrawable.cpp
@@ -21,11 +21,11 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 #include <GLES3/gl3.h>
+#include <gui/TraceUtils.h>
 #include <private/hwui/DrawGlInfo.h>
 #include <utils/Color.h>
 #include <utils/GLUtils.h>
 #include <utils/Trace.h>
-#include <utils/TraceUtils.h>
 
 #include <thread>
 
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c1f61e08..d317305 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -26,6 +26,7 @@
 #include <cstdlib>
 #include <functional>
 
+#include <gui/TraceUtils.h>
 #include "../Properties.h"
 #include "AnimationContext.h"
 #include "Frame.h"
@@ -39,7 +40,6 @@
 #include "thread/CommonPool.h"
 #include "utils/GLUtils.h"
 #include "utils/TimeUtils.h"
-#include "utils/TraceUtils.h"
 
 #define TRIM_MEMORY_COMPLETE 80
 #define TRIM_MEMORY_UI_HIDDEN 20
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 8448b87..5c4b901 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -16,8 +16,8 @@
 
 #include "DrawFrameTask.h"
 
+#include <gui/TraceUtils.h>
 #include <utils/Log.h>
-#include <utils/TraceUtils.h>
 #include <algorithm>
 
 #include "../DeferredLayerUpdater.h"
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 95aa29d..ac19a15 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -16,6 +16,7 @@
 
 #include "RenderProxy.h"
 
+#include <gui/TraceUtils.h>
 #include "DeferredLayerUpdater.h"
 #include "DisplayList.h"
 #include "Properties.h"
@@ -27,7 +28,6 @@
 #include "renderthread/RenderThread.h"
 #include "utils/Macros.h"
 #include "utils/TimeUtils.h"
-#include "utils/TraceUtils.h"
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index a648f98..4ba7748 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -16,6 +16,7 @@
 
 #include "RenderThread.h"
 
+#include <gui/TraceUtils.h>
 #include "../HardwareBitmapUploader.h"
 #include "CanvasContext.h"
 #include "DeviceInfo.h"
@@ -29,7 +30,6 @@
 #include "pipeline/skia/SkiaVulkanPipeline.h"
 #include "renderstate/RenderState.h"
 #include "utils/TimeUtils.h"
-#include "utils/TraceUtils.h"
 
 #include <GrContextOptions.h>
 #include <gl/GrGLInterface.h>
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 07146e8..5a71833 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -29,11 +29,11 @@
 
 #include <cstring>
 
+#include <gui/TraceUtils.h>
 #include "Properties.h"
 #include "RenderThread.h"
 #include "pipeline/skia/ShaderCache.h"
 #include "renderstate/RenderState.h"
-#include "utils/TraceUtils.h"
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index c559425..01a2ec5 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -20,9 +20,9 @@
 #include <SkSurface.h>
 #include <algorithm>
 
+#include <gui/TraceUtils.h>
 #include "VulkanManager.h"
 #include "utils/Color.h"
-#include "utils/TraceUtils.h"
 
 namespace android {
 namespace uirenderer {
diff --git a/libs/hwui/tests/macrobench/TestSceneRunner.cpp b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
index b640b90..de2c621 100644
--- a/libs/hwui/tests/macrobench/TestSceneRunner.cpp
+++ b/libs/hwui/tests/macrobench/TestSceneRunner.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <gui/TraceUtils.h>
 #include "AnimationContext.h"
 #include "RenderNode.h"
 #include "renderthread/RenderProxy.h"
@@ -21,7 +22,6 @@
 #include "tests/common/TestContext.h"
 #include "tests/common/TestScene.h"
 #include "tests/common/scenes/TestSceneBase.h"
-#include "utils/TraceUtils.h"
 
 #include <benchmark/benchmark.h>
 #include <gui/Surface.h>
diff --git a/libs/hwui/utils/TraceUtils.h b/libs/hwui/utils/TraceUtils.h
deleted file mode 100644
index e61b4be..0000000
--- a/libs/hwui/utils/TraceUtils.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-#ifndef TRACE_UTILS_H
-#define TRACE_UTILS_H
-
-#include <cutils/trace.h>
-#include <utils/Trace.h>
-
-#define ATRACE_FORMAT(fmt, ...)           \
-    TraceUtils::TraceEnder __traceEnder = \
-            (TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__), TraceUtils::TraceEnder())
-
-#define ATRACE_FORMAT_BEGIN(fmt, ...) TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__)
-
-namespace android {
-namespace uirenderer {
-
-class TraceUtils {
-public:
-    class TraceEnder {
-    public:
-        ~TraceEnder() { ATRACE_END(); }
-    };
-
-    static void atraceFormatBegin(const char* fmt, ...) {
-        if (CC_LIKELY(!ATRACE_ENABLED())) return;
-
-        const int BUFFER_SIZE = 256;
-        va_list ap;
-        char buf[BUFFER_SIZE];
-
-        va_start(ap, fmt);
-        vsnprintf(buf, BUFFER_SIZE, fmt, ap);
-        va_end(ap);
-
-        ATRACE_BEGIN(buf);
-    }
-
-};  // class TraceUtils
-
-} /* namespace uirenderer */
-} /* namespace android */
-
-#endif /* TRACE_UTILS_H */
diff --git a/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java b/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java
index ed447f8..3d93964 100644
--- a/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java
+++ b/packages/SettingsLib/SettingsTransition/src/com/android/settingslib/transition/SettingsTransitionHelper.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.transition;
 
+import androidx.annotation.IntDef;
 import android.app.Activity;
 import android.content.Context;
 import android.util.Log;
@@ -29,11 +30,31 @@
 import com.google.android.material.transition.platform.MaterialSharedAxis;
 import com.google.android.material.transition.platform.SlideDistanceProvider;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A helper class to apply Settings Transition
  */
 public class SettingsTransitionHelper {
 
+    /**
+     * Flags indicating the type of the transition.
+     */
+    @IntDef({
+            TransitionType.TRANSITION_NONE,
+            TransitionType.TRANSITION_SHARED_AXIS,
+            TransitionType.TRANSITION_SLIDE,
+            TransitionType.TRANSITION_FADE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TransitionType {
+        int TRANSITION_NONE = -1;
+        int TRANSITION_SHARED_AXIS = 0;
+        int TRANSITION_SLIDE = 1;
+        int TRANSITION_FADE = 2;
+    }
+
     private static final String TAG = "SettingsTransitionHelper";
     private static final long DURATION = 450L;
     private static final float FADE_THROUGH_THRESHOLD = 0.22F;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 4558a8a..fe92e26 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1222,19 +1222,22 @@
      */
     public Pair<Drawable, String> getDrawableWithDescription() {
         Uri uri = BluetoothUtils.getUriMetaData(mDevice, BluetoothDevice.METADATA_MAIN_ICON);
+        Pair<Drawable, String> pair = BluetoothUtils.getBtClassDrawableWithDescription(
+                mContext, this);
+
         if (BluetoothUtils.isAdvancedDetailsHeader(mDevice) && uri != null) {
             BitmapDrawable drawable = mDrawableCache.get(uri.toString());
             if (drawable != null) {
                 Resources resources = mContext.getResources();
                 return new Pair<>(new AdaptiveOutlineDrawable(
-                        resources, drawable.getBitmap()),
-                        BluetoothUtils.getBtClassDrawableWithDescription(mContext, this).second);
+                        resources, drawable.getBitmap()), pair.second);
             }
 
             refresh();
         }
 
-        return BluetoothUtils.getBtRainbowDrawableWithDescription(mContext, this);
+        return new Pair<>(BluetoothUtils.buildBtRainbowDrawable(
+                        mContext, pair.first, getAddress().hashCode()), pair.second);
     }
 
     void releaseLruCache() {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 38172f7..f523354 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -31,7 +31,9 @@
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
 import android.content.Context;
+import android.graphics.drawable.BitmapDrawable;
 import android.media.AudioManager;
+import android.util.LruCache;
 
 import com.android.settingslib.R;
 import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
@@ -961,6 +963,10 @@
 
     @Test
     public void getDrawableWithDescription_isAdvancedDevice_returnAdvancedIcon() {
+        LruCache lruCache = mock(LruCache.class);
+        mCachedDevice.mDrawableCache = lruCache;
+        BitmapDrawable drawable = mock(BitmapDrawable.class);
+        when(lruCache.get("fake_uri")).thenReturn(drawable);
         when(mDevice.getMetadata(BluetoothDevice.METADATA_MAIN_ICON))
                 .thenReturn("fake_uri".getBytes());
         when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 6e256c1..d2947c6 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -528,6 +528,7 @@
 
     <!-- Permission required for hotword detection service CTS tests -->
     <uses-permission android:name="android.permission.MANAGE_HOTWORD_DETECTION" />
+    <uses-permission android:name="android.permission.BIND_HOTWORD_DETECTION_SERVICE" />
 
     <uses-permission android:name="android.permission.MANAGE_APP_HIBERNATION"/>
 
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 1cf0c5f..2b87737 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -4,12 +4,15 @@
 import android.animation.AnimatorListenerAdapter
 import android.animation.ValueAnimator
 import android.app.ActivityManager
+import android.app.ActivityTaskManager
 import android.app.PendingIntent
 import android.content.Context
 import android.graphics.Matrix
 import android.graphics.Rect
+import android.graphics.RectF
 import android.os.Looper
 import android.os.RemoteException
+import android.util.Log
 import android.util.MathUtils
 import android.view.IRemoteAnimationFinishedCallback
 import android.view.IRemoteAnimationRunner
@@ -30,6 +33,8 @@
  * nicely into the starting window.
  */
 class ActivityLaunchAnimator(context: Context) {
+    private val TAG = this::class.java.simpleName
+
     companion object {
         const val ANIMATION_DURATION = 500L
         const val ANIMATION_DURATION_FADE_OUT_CONTENT = 183L
@@ -78,29 +83,49 @@
      * If [controller] is null or [animate] is false, then the intent will be started and no
      * animation will run.
      *
+     * If possible, you should pass the [packageName] of the intent that will be started so that
+     * trampoline activity launches will also be animated.
+     *
      * This method will throw any exception thrown by [intentStarter].
      */
     @JvmOverloads
-    inline fun startIntentWithAnimation(
+    fun startIntentWithAnimation(
         controller: Controller?,
         animate: Boolean = true,
+        packageName: String? = null,
         intentStarter: (RemoteAnimationAdapter?) -> Int
     ) {
         if (controller == null || !animate) {
+            Log.d(TAG, "Starting intent with no animation")
             intentStarter(null)
             controller?.callOnIntentStartedOnMainThread(willAnimate = false)
             return
         }
 
+        Log.d(TAG, "Starting intent with a launch animation")
         val runner = Runner(controller)
         val animationAdapter = RemoteAnimationAdapter(
             runner,
             ANIMATION_DURATION,
             ANIMATION_DURATION - 150 /* statusBarTransitionDelay */
         )
+
+        // Register the remote animation for the given package to also animate trampoline
+        // activity launches.
+        if (packageName != null) {
+            try {
+                ActivityTaskManager.getService().registerRemoteAnimationForNextActivityStart(
+                    packageName, animationAdapter)
+            } catch (e: RemoteException) {
+                Log.w(TAG, "Unable to register the remote animation", e)
+            }
+        }
+
         val launchResult = intentStarter(animationAdapter)
         val willAnimate = launchResult == ActivityManager.START_TASK_TO_FRONT ||
             launchResult == ActivityManager.START_SUCCESS
+
+        Log.d(TAG, "launchResult=$launchResult willAnimate=$willAnimate")
         controller.callOnIntentStartedOnMainThread(willAnimate)
 
         // If we expect an animation, post a timeout to cancel it in case the remote animation is
@@ -110,7 +135,6 @@
         }
     }
 
-    @PublishedApi
     internal fun Controller.callOnIntentStartedOnMainThread(willAnimate: Boolean) {
         if (Looper.myLooper() != Looper.getMainLooper()) {
             this.launchContainer.context.mainExecutor.execute {
@@ -125,15 +149,21 @@
      * Same as [startIntentWithAnimation] but allows [intentStarter] to throw a
      * [PendingIntent.CanceledException] which must then be handled by the caller. This is useful
      * for Java caller starting a [PendingIntent].
+     *
+     * If possible, you should pass the [packageName] of the intent that will be started so that
+     * trampoline activity launches will also be animated.
      */
     @Throws(PendingIntent.CanceledException::class)
     @JvmOverloads
     fun startPendingIntentWithAnimation(
         controller: Controller?,
         animate: Boolean = true,
+        packageName: String? = null,
         intentStarter: PendingIntentStarter
     ) {
-        startIntentWithAnimation(controller, animate) { intentStarter.startPendingIntent(it) }
+        startIntentWithAnimation(controller, animate, packageName) {
+            intentStarter.startPendingIntent(it)
+        }
     }
 
     /** Create a new animation [Runner] controlled by [controller]. */
@@ -278,11 +308,14 @@
     @VisibleForTesting
     inner class Runner(private val controller: Controller) : IRemoteAnimationRunner.Stub() {
         private val launchContainer = controller.launchContainer
-        @PublishedApi internal val context = launchContainer.context
+        private val context = launchContainer.context
         private val transactionApplier = SyncRtSurfaceTransactionApplier(launchContainer)
         private var animator: ValueAnimator? = null
 
+        private val matrix = Matrix()
+        private val invertMatrix = Matrix()
         private var windowCrop = Rect()
+        private var windowCropF = RectF()
         private var timedOut = false
         private var cancelled = false
 
@@ -294,7 +327,6 @@
         // posting it.
         private var onTimeout = Runnable { onAnimationTimedOut() }
 
-        @PublishedApi
         internal fun postTimeout() {
             launchContainer.postDelayed(onTimeout, LAUNCH_TIMEOUT)
         }
@@ -336,11 +368,13 @@
             remoteAnimationNonAppTargets: Array<out RemoteAnimationTarget>,
             iCallback: IRemoteAnimationFinishedCallback
         ) {
+            Log.d(TAG, "Remote animation started")
             val window = remoteAnimationTargets.firstOrNull {
                 it.mode == RemoteAnimationTarget.MODE_OPENING
             }
 
             if (window == null) {
+                Log.d(TAG, "Aborting the animation as no window is opening")
                 removeTimeout()
                 invokeCallback(iCallback)
                 controller.onLaunchAnimationCancelled()
@@ -399,10 +433,12 @@
 
             animator.addListener(object : AnimatorListenerAdapter() {
                 override fun onAnimationStart(animation: Animator?, isReverse: Boolean) {
+                    Log.d(TAG, "Animation started")
                     controller.onLaunchAnimationStart(isExpandingFullyAbove)
                 }
 
                 override fun onAnimationEnd(animation: Animator?) {
+                    Log.d(TAG, "Animation ended")
                     invokeCallback(iCallback)
                     controller.onLaunchAnimationEnd(isExpandingFullyAbove)
                 }
@@ -447,19 +483,52 @@
         }
 
         private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) {
-            val m = Matrix()
-            m.postTranslate(0f, (state.top - window.sourceContainerBounds.top).toFloat())
-            windowCrop.set(state.left, 0, state.right, state.height)
+            val screenBounds = window.screenSpaceBounds
+            val centerX = (screenBounds.left + screenBounds.right) / 2f
+            val centerY = (screenBounds.top + screenBounds.bottom) / 2f
+            val width = screenBounds.right - screenBounds.left
+            val height = screenBounds.bottom - screenBounds.top
 
-            val cornerRadius = minOf(state.topCornerRadius, state.bottomCornerRadius)
+            // Scale the window. We use the max of (widthRatio, heightRatio) so that there is no
+            // blank space on any side.
+            val widthRatio = state.width.toFloat() / width
+            val heightRatio = state.height.toFloat() / height
+            val scale = maxOf(widthRatio, heightRatio)
+            matrix.reset()
+            matrix.setScale(scale, scale, centerX, centerY)
+
+            // Align it to the top and center it in the x-axis.
+            val heightChange = height * scale - height
+            val translationX = state.centerX - centerX
+            val translationY = state.top - screenBounds.top + heightChange / 2f
+            matrix.postTranslate(translationX, translationY)
+
+            // Crop it. The matrix will also be applied to the crop, so we apply the inverse
+            // operation. Given that we only scale (by factor > 0) then translate, we can assume
+            // that the matrix is invertible.
+            val cropX = state.left.toFloat() - screenBounds.left
+            val cropY = state.top.toFloat() - screenBounds.top
+            windowCropF.set(cropX, cropY, cropX + state.width, cropY + state.height)
+            matrix.invert(invertMatrix)
+            invertMatrix.mapRect(windowCropF)
+            windowCrop.set(
+                windowCropF.left.roundToInt(),
+                windowCropF.top.roundToInt(),
+                windowCropF.right.roundToInt(),
+                windowCropF.bottom.roundToInt()
+            )
+
+            // The scale will also be applied to the corner radius, so we divide by the scale to
+            // keep the original radius.
+            val cornerRadius = minOf(state.topCornerRadius, state.bottomCornerRadius) / scale
             val params = SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(window.leash)
-                    .withAlpha(1f)
-                    .withMatrix(m)
-                    .withWindowCrop(windowCrop)
-                    .withLayer(window.prefixOrderIndex)
-                    .withCornerRadius(cornerRadius)
-                    .withVisibility(true)
-                    .build()
+                .withAlpha(1f)
+                .withMatrix(matrix)
+                .withWindowCrop(windowCrop)
+                .withLayer(window.prefixOrderIndex)
+                .withCornerRadius(cornerRadius)
+                .withVisibility(true)
+                .build()
 
             transactionApplier.scheduleApply(params)
         }
@@ -474,12 +543,13 @@
 
             val params = SyncRtSurfaceTransactionApplier.SurfaceParams.Builder(navigationBar.leash)
             if (fadeInProgress > 0) {
-                val m = Matrix()
-                m.postTranslate(0f, (state.top - navigationBar.sourceContainerBounds.top).toFloat())
+                matrix.reset()
+                matrix.setTranslate(
+                    0f, (state.top - navigationBar.sourceContainerBounds.top).toFloat())
                 windowCrop.set(state.left, 0, state.right, state.height)
                 params
                         .withAlpha(NAV_FADE_IN_INTERPOLATOR.getInterpolation(fadeInProgress))
-                        .withMatrix(m)
+                        .withMatrix(matrix)
                         .withWindowCrop(windowCrop)
                         .withVisibility(true)
             } else {
@@ -496,6 +566,7 @@
                 return
             }
 
+            Log.d(TAG, "Remote animation timed out")
             timedOut = true
             controller.onLaunchAnimationCancelled()
         }
@@ -505,6 +576,7 @@
                 return
             }
 
+            Log.d(TAG, "Remote animation was cancelled")
             cancelled = true
             removeTimeout()
             context.mainExecutor.execute {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
index 044b5ed..e1f72c1 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/Interpolators.java
@@ -96,13 +96,18 @@
     /**
      * Interpolate alpha for notifications background scrim during shade expansion.
      * @param fraction Shade expansion fraction
+     * @param forNotification If we want the alpha of the notification shade or the scrim.
      */
-    public static float getNotificationScrimAlpha(float fraction) {
+    public static float getNotificationScrimAlpha(float fraction, boolean forNotification) {
+        if (!forNotification) {
+            fraction = MathUtils.saturate(1.7f * fraction);
+        }
         fraction = fraction * 1.2f - 0.2f;
         if (fraction <= 0) {
             return 0;
         } else {
-            return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * Math.pow(1f - fraction, 2f))));
+            final float oneMinusFrac = 1f - fraction;
+            return (float) (1f - 0.5f * (1f - Math.cos(3.14159f * oneMinusFrac * oneMinusFrac)));
         }
     }
 }
diff --git a/packages/SystemUI/res/drawable/ic_cake.xml b/packages/SystemUI/res/drawable/ic_cake.xml
new file mode 100644
index 0000000..9c83b43
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_cake.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M19,14v-4c0,-1.1 -0.9,-2 -2,-2h-4L13,6.55c0.15,-0.09 0.29,-0.18 0.41,-0.31 0.39,-0.39 0.59,-0.92 0.59,-1.42s-0.2,-1.02 -0.59,-1.41L12,2l-1.41,1.41c-0.39,0.39 -0.59,0.91 -0.59,1.41s0.2,1.03 0.59,1.42c0.13,0.13 0.27,0.22 0.41,0.31L11,8L7,8c-1.1,0 -2,0.9 -2,2v4c-1.1,0 -2,0.9 -2,2v4c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-4c0,-1.1 -0.9,-2 -2,-2zM7,10h10v4L7,14v-4zM19,20L5,20v-4h14v4z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_celebration.xml b/packages/SystemUI/res/drawable/ic_celebration.xml
new file mode 100644
index 0000000..10fe406
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_celebration.xml
@@ -0,0 +1,37 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M2,22l14,-5L7,8L2,22zM12.35,16.18L5.3,18.7l2.52,-7.05L12.35,16.18z"
+        android:fillColor="#FFFFFFFF"/>
+    <path
+        android:pathData="M14.53,12.53l5.59,-5.59c0.49,-0.49 1.28,-0.49 1.77,0l0.59,0.59l1.06,-1.06l-0.59,-0.59c-1.07,-1.07 -2.82,-1.07 -3.89,0l-5.59,5.59L14.53,12.53z"
+        android:fillColor="#FFFFFFFF"/>
+    <path
+        android:pathData="M10.06,6.88L9.47,7.47l1.06,1.06l0.59,-0.59c1.07,-1.07 1.07,-2.82 0,-3.89l-0.59,-0.59L9.47,4.53l0.59,0.59C10.54,5.6 10.54,6.4 10.06,6.88z"
+        android:fillColor="#FFFFFFFF"/>
+    <path
+        android:pathData="M17.06,11.88l-1.59,1.59l1.06,1.06l1.59,-1.59c0.49,-0.49 1.28,-0.49 1.77,0l1.61,1.61l1.06,-1.06l-1.61,-1.61C19.87,10.81 18.13,10.81 17.06,11.88z"
+        android:fillColor="#FFFFFFFF"/>
+    <path
+        android:pathData="M15.06,5.88l-3.59,3.59l1.06,1.06l3.59,-3.59c1.07,-1.07 1.07,-2.82 0,-3.89l-1.59,-1.59l-1.06,1.06l1.59,1.59C15.54,4.6 15.54,5.4 15.06,5.88z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable/ic_gift.xml b/packages/SystemUI/res/drawable/ic_gift.xml
new file mode 100644
index 0000000..fab36c3
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_gift.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M22,5h-5.18C16.93,4.69 17,4.35 17,4c0,-1.65 -1.35,-3 -3,-3c-0.77,0 -1.47,0.3 -2,0.78C11.47,1.3 10.77,1 10,1C8.35,1 7,2.35 7,4c0,0.35 0.07,0.69 0.18,1H2v6h2v11h16V11h2V5zM14,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1s-1,-0.45 -1,-1S13.45,3 14,3zM9,4c0,-0.55 0.45,-1 1,-1s1,0.45 1,1s-0.45,1 -1,1S9,4.55 9,4zM4,7h7v2H4V7zM6,11h5v9H6V11zM18,20h-5v-9h5V20zM20,9h-7V7h7V9z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_pages.xml b/packages/SystemUI/res/drawable/ic_pages.xml
new file mode 100644
index 0000000..9cd076d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_pages.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M19,5v14L5,19L5,5h14m0,-2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,17l1.57,-3.43L17,12l-3.43,-1.57L12,7l-1.57,3.43L7,12l3.43,1.57L12,17z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_play_games.xml b/packages/SystemUI/res/drawable/ic_play_games.xml
new file mode 100644
index 0000000..20096f4
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_play_games.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M20.47,8c-0.39,-2.3 -2.4,-4 -4.81,-4L8.34,4C5.93,4 3.93,5.7 3.53,8 3.53,8 2,16.8 2,16.93 2,18.07 2.93,19 4.07,19c0.57,0 1.09,-0.2 1.47,-0.58L9,15h6l3.46,3.42c0.38,0.38 0.89,0.58 1.47,0.58 1.15,0 2.07,-0.93 2.07,-2.07C22,16.8 20.47,8 20.47,8zM11,10L9,10v2L8,12v-2L6,10L6,9h2L8,7h1v2h2v1zM13.8,10.3c-0.44,0 -0.8,-0.36 -0.8,-0.8 0,-0.44 0.36,-0.8 0.8,-0.8 0.44,0 0.8,0.36 0.8,0.8 0,0.44 -0.36,0.8 -0.8,0.8zM15.49,12c-0.44,0 -0.8,-0.36 -0.8,-0.8 0,-0.44 0.36,-0.8 0.8,-0.8 0.44,0 0.8,0.36 0.8,0.8 0,0.44 -0.36,0.8 -0.8,0.8zM15.49,8.6c-0.44,0 -0.8,-0.36 -0.8,-0.8s0.36,-0.8 0.8,-0.8c0.44,0 0.8,0.36 0.8,0.8s-0.36,0.8 -0.8,0.8zM17.2,10.3c-0.44,0 -0.8,-0.36 -0.8,-0.8 0,-0.44 0.36,-0.8 0.8,-0.8s0.8,0.36 0.8,0.8c0,0.44 -0.36,0.8 -0.8,0.8z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_video.xml b/packages/SystemUI/res/drawable/ic_video.xml
new file mode 100644
index 0000000..3668338
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_video.xml
@@ -0,0 +1,24 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M9,7v8l7,-4zM21,3L3,3c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h5v2h8v-2h5c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,17L3,17L3,5h18v12z"
+        android:fillColor="#FFFFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/people_tile_large_with_content.xml b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
index 4994c69..e294dad 100644
--- a/packages/SystemUI/res/layout/people_tile_large_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_large_with_content.xml
@@ -34,8 +34,6 @@
 
             <ImageView
                 android:id="@+id/person_icon"
-                android:layout_marginStart="-2dp"
-                android:layout_marginTop="-2dp"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_weight="1" />
@@ -73,12 +71,12 @@
         <include layout="@layout/people_tile_emoji_background_large" />
 
         <TextView
-            android:layout_gravity="top"
             android:id="@+id/name"
-            android:layout_width="match_parent"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:paddingBottom="@dimen/below_name_text_padding"
-            android:gravity="start|top"
+            android:layout_gravity="start|center_vertical"
+            android:gravity="start|center_vertical"
             android:singleLine="true"
             android:ellipsize="end"
             android:text="@string/empty_user_name"
@@ -103,7 +101,7 @@
 
                 <ImageView
                     android:id="@+id/predefined_icon"
-                    android:tint="?android:attr/colorAccent"
+                    android:tint="?android:attr/textColorTertiary"
                     android:gravity="start|center_vertical"
                     android:layout_width="@dimen/regular_predefined_icon"
                     android:layout_height="@dimen/regular_predefined_icon" />
diff --git a/packages/SystemUI/res/layout/people_tile_medium_empty.xml b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
index bebc872..8b2fddc 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_empty.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_empty.xml
@@ -27,19 +27,23 @@
         android:orientation="horizontal"
         android:layout_width="match_parent"
         android:layout_height="match_parent">
-        <ImageView
-            android:id="@+id/person_icon"
-            android:layout_marginTop="-2dp"
-            android:layout_marginStart="-2dp"
-            android:layout_width="64dp"
-            android:layout_height="64dp" />
-        <ImageView
-            android:id="@+id/availability"
-            android:gravity="top"
-            android:layout_marginStart="-2dp"
-            android:layout_width="10dp"
-            android:layout_height="10dp"
-            android:background="@drawable/availability_dot_10dp" />
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+            <ImageView
+                android:id="@+id/person_icon"
+                android:layout_width="64dp"
+                android:layout_height="64dp" />
+            <ImageView
+                android:id="@+id/availability"
+                android:layout_width="10dp"
+                android:layout_height="10dp"
+                android:gravity="top"
+                android:layout_gravity="top"
+                android:layout_marginStart="-2dp"
+                android:background="@drawable/availability_dot_10dp" />
+        </LinearLayout>
         <LinearLayout
             android:orientation="vertical"
             android:paddingStart="4dp"
diff --git a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
index a7a6354..47cab42 100644
--- a/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
+++ b/packages/SystemUI/res/layout/people_tile_medium_with_content.xml
@@ -47,8 +47,6 @@
                 <ImageView
                     android:gravity="start"
                     android:id="@+id/person_icon"
-                    android:layout_marginStart="-2dp"
-                    android:layout_marginTop="-2dp"
                     android:layout_width="52dp"
                     android:layout_height="52dp" />
 
@@ -112,7 +110,8 @@
                 android:clipToOutline="true">
                 <TextView
                     android:id="@+id/name"
-                    android:gravity="center_vertical"
+                    android:layout_gravity="start|center_vertical"
+                    android:gravity="start|center_vertical"
                     android:layout_weight="1"
                     android:text="@string/empty_user_name"
                     android:textAppearance="@*android:style/TextAppearance.DeviceDefault.ListItem"
@@ -140,7 +139,7 @@
                     />
                 <ImageView
                     android:id="@+id/predefined_icon"
-                    android:tint="?android:attr/colorAccent"
+                    android:tint="?android:attr/textColorTertiary"
                     android:gravity="end|center_vertical"
                     android:layout_width="@dimen/regular_predefined_icon"
                     android:layout_height="@dimen/regular_predefined_icon" />
diff --git a/packages/SystemUI/res/layout/people_tile_small.xml b/packages/SystemUI/res/layout/people_tile_small.xml
index 4e5c04c..7a1371d 100644
--- a/packages/SystemUI/res/layout/people_tile_small.xml
+++ b/packages/SystemUI/res/layout/people_tile_small.xml
@@ -39,7 +39,7 @@
 
         <ImageView
             android:id="@+id/predefined_icon"
-            android:tint="?android:attr/colorAccent"
+            android:tint="?android:attr/textColorTertiary"
             android:layout_gravity="center"
             android:layout_width="18dp"
             android:layout_height="22dp" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 3543fd1..c16f13e 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -64,10 +64,6 @@
         android:clipToPadding="false"
         android:clipChildren="false">
 
-        <include
-            layout="@layout/keyguard_status_view"
-            android:visibility="gone"/>
-
         <com.android.systemui.scrim.ScrimView
             android:id="@+id/scrim_notifications"
             android:layout_width="0dp"
@@ -78,7 +74,11 @@
             systemui:layout_constraintEnd_toEndOf="parent"
             systemui:layout_constraintTop_toTopOf="parent"
             systemui:layout_constraintBottom_toBottomOf="parent"
-            />
+        />
+
+        <include
+            layout="@layout/keyguard_status_view"
+            android:visibility="gone"/>
 
         <include layout="@layout/dock_info_overlay" />
 
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index ee7eb4b..964b135 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.accessibility;
 
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
 
 import android.annotation.NonNull;
@@ -70,7 +71,7 @@
     private final ImageView mImageView;
     private final Runnable mWindowInsetChangeRunnable;
     private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
-    private int mMagnificationMode = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+    private int mMagnificationMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
     private final LayoutParams mParams;
     @VisibleForTesting
     final Rect mDraggableWindowBounds = new Rect();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 9871b4e..146f430 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -54,14 +54,16 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.SomeArgs;
 import com.android.systemui.SystemUI;
+import com.android.systemui.assist.ui.DisplayUtils;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.doze.DozeReceiver;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.inject.Inject;
 import javax.inject.Provider;
@@ -79,13 +81,14 @@
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
     private final CommandQueue mCommandQueue;
-    private final StatusBarStateController mStatusBarStateController;
     private final ActivityTaskManager mActivityTaskManager;
     @Nullable private final FingerprintManager mFingerprintManager;
     @Nullable private final FaceManager mFaceManager;
     private final Provider<UdfpsController> mUdfpsControllerFactory;
     private final Provider<SidefpsController> mSidefpsControllerFactory;
     @Nullable private final PointF mFaceAuthSensorLocation;
+    @Nullable private final PointF mFingerprintLocation;
+    private final Set<Callback> mCallbacks = new HashSet<>();
 
     // TODO: These should just be saved from onSaveState
     private SomeArgs mCurrentDialogArgs;
@@ -142,6 +145,10 @@
                     if (mSidefpsProps != null) {
                         mSidefpsController = mSidefpsControllerFactory.get();
                     }
+
+                    for (Callback cb : mCallbacks) {
+                        cb.onAllAuthenticatorsRegistered();
+                    }
                 }
             };
 
@@ -195,6 +202,20 @@
         }
     }
 
+    /**
+     * Adds a callback. See {@link Callback}.
+     */
+    public void addCallback(@NonNull Callback callback) {
+        mCallbacks.add(callback);
+    }
+
+    /**
+     * Removes a callback. See {@link Callback}.
+     */
+    public void removeCallback(@NonNull Callback callback) {
+        mCallbacks.remove(callback);
+    }
+
     @Override
     public void dozeTimeTick() {
         if (mUdfpsController != null) {
@@ -335,6 +356,17 @@
     }
 
     /**
+     * @return where the fingerprint sensor exists in pixels in portrait mode. devices without an
+     * overridden value will use the default value even if they don't have a fingerprint sensor
+     */
+    @Nullable public PointF getFingerprintSensorLocation() {
+        if (getUdfpsSensorLocation() != null) {
+            return getUdfpsSensorLocation();
+        }
+        return mFingerprintLocation;
+    }
+
+    /**
      * @return where the face authentication sensor exists relative to the screen in pixels in
      * portrait mode.
      */
@@ -387,7 +419,6 @@
 
     @Inject
     public AuthController(Context context, CommandQueue commandQueue,
-            StatusBarStateController statusBarStateController,
             ActivityTaskManager activityTaskManager,
             @Nullable FingerprintManager fingerprintManager,
             @Nullable FaceManager faceManager,
@@ -395,7 +426,6 @@
             Provider<SidefpsController> sidefpsControllerFactory) {
         super(context);
         mCommandQueue = commandQueue;
-        mStatusBarStateController = statusBarStateController;
         mActivityTaskManager = activityTaskManager;
         mFingerprintManager = fingerprintManager;
         mFaceManager = faceManager;
@@ -414,6 +444,10 @@
                     (float) faceAuthLocation[1]);
         }
 
+        mFingerprintLocation = new PointF(DisplayUtils.getWidth(mContext) / 2,
+                mContext.getResources().getDimensionPixelSize(
+                com.android.systemui.R.dimen.physical_fingerprint_sensor_center_screen_location_y));
+
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
 
@@ -481,14 +515,24 @@
      */
     @Override
     public void onBiometricAuthenticated() {
-        mCurrentDialog.onAuthenticationSucceeded();
+        if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: ");
+
+        if (mCurrentDialog != null) {
+            mCurrentDialog.onAuthenticationSucceeded();
+        } else {
+            Log.w(TAG, "onBiometricAuthenticated callback but dialog gone");
+        }
     }
 
     @Override
     public void onBiometricHelp(String message) {
         if (DEBUG) Log.d(TAG, "onBiometricHelp: " + message);
 
-        mCurrentDialog.onHelp(message);
+        if (mCurrentDialog != null) {
+            mCurrentDialog.onHelp(message);
+        } else {
+            Log.w(TAG, "onBiometricHelp callback but dialog gone");
+        }
     }
 
     @Nullable
@@ -527,19 +571,23 @@
         final boolean isSoftError = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED
                 || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT);
 
-        if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
-            if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
-            mCurrentDialog.animateToCredentialUI();
-        } else if (isSoftError) {
-            final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
-                    ? mContext.getString(R.string.biometric_not_recognized)
-                    : getErrorString(modality, error, vendorCode);
-            if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
-            mCurrentDialog.onAuthenticationFailed(errorMessage);
+        if (mCurrentDialog != null) {
+            if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
+                if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
+                mCurrentDialog.animateToCredentialUI();
+            } else if (isSoftError) {
+                final String errorMessage = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED)
+                        ? mContext.getString(R.string.biometric_not_recognized)
+                        : getErrorString(modality, error, vendorCode);
+                if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
+                mCurrentDialog.onAuthenticationFailed(errorMessage);
+            } else {
+                final String errorMessage = getErrorString(modality, error, vendorCode);
+                if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
+                mCurrentDialog.onError(errorMessage);
+            }
         } else {
-            final String errorMessage = getErrorString(modality, error, vendorCode);
-            if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
-            mCurrentDialog.onError(errorMessage);
+            Log.w(TAG, "onBiometricError callback but dialog is gone");
         }
 
         onCancelUdfps();
@@ -697,4 +745,12 @@
                 .setMultiSensorConfig(multiSensorConfig)
                 .build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
     }
+
+    interface Callback {
+        /**
+         * Called when authenticators are registered. If authenticators are already
+         * registered before this call, this callback will never be triggered.
+         */
+        void onAllAuthenticatorsRegistered();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index 257bd25..cf577a3 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -28,6 +28,7 @@
 import com.android.systemui.statusbar.commandline.Command
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.StatusBar
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.ViewController
@@ -40,6 +41,7 @@
  */
 @StatusBarScope
 class AuthRippleController @Inject constructor(
+    private val statusBar: StatusBar,
     private val sysuiContext: Context,
     private val authController: AuthController,
     private val configurationController: ConfigurationController,
@@ -49,13 +51,14 @@
     private val bypassController: KeyguardBypassController,
     rippleView: AuthRippleView?
 ) : ViewController<AuthRippleView>(rippleView) {
-    private var fingerprintSensorLocation: PointF? = null
+    var fingerprintSensorLocation: PointF? = null
     private var faceSensorLocation: PointF? = null
 
     @VisibleForTesting
     public override fun onViewAttached() {
         updateRippleColor()
         updateSensorLocation()
+        authController.addCallback(authControllerCallback)
         configurationController.addCallback(configurationChangedListener)
         keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback)
         commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
@@ -63,6 +66,7 @@
 
     @VisibleForTesting
     public override fun onViewDetached() {
+        authController.removeCallback(authControllerCallback)
         keyguardUpdateMonitor.removeCallback(keyguardUpdateMonitorCallback)
         configurationController.removeCallback(configurationChangedListener)
         commandRegistry.unregisterCommand("auth-ripple")
@@ -97,9 +101,10 @@
         })
     }
 
-    private fun updateSensorLocation() {
-        fingerprintSensorLocation = authController.udfpsSensorLocation
+    fun updateSensorLocation() {
+        fingerprintSensorLocation = authController.fingerprintSensorLocation
         faceSensorLocation = authController.faceAuthSensorLocation
+        statusBar.updateCircleReveal()
     }
 
     private fun updateRippleColor() {
@@ -134,6 +139,8 @@
             }
     }
 
+    private val authControllerCallback = AuthController.Callback { updateSensorLocation() }
+
     inner class AuthRippleCommand : Command {
         override fun execute(pw: PrintWriter, args: List<String>) {
             if (args.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 374ddae..01fbe39 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -23,7 +23,11 @@
 import android.graphics.Canvas
 import android.graphics.Paint
 import android.graphics.PointF
+import android.media.AudioAttributes
+import android.os.VibrationEffect
+import android.os.Vibrator
 import android.util.AttributeSet
+import android.util.MathUtils
 import android.view.View
 import android.view.animation.PathInterpolator
 import com.android.internal.graphics.ColorUtils
@@ -31,15 +35,26 @@
 
 private const val RIPPLE_ANIMATION_DURATION: Long = 1533
 private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
+private const val RIPPLE_VIBRATION_PRIMITIVE: Int = VibrationEffect.Composition.PRIMITIVE_LOW_TICK
+private const val RIPPLE_VIBRATION_SIZE: Int = 60
+private const val RIPPLE_VIBRATION_SCALE_START: Float = 0.6f
+private const val RIPPLE_VIBRATION_SCALE_DECAY: Float = -0.1f
 
 /**
  * Expanding ripple effect on the transition from biometric authentication success to showing
  * launcher.
  */
 class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
+    private val vibrator: Vibrator? = context?.getSystemService(Vibrator::class.java)
     private var rippleInProgress: Boolean = false
     private val rippleShader = RippleShader()
     private val ripplePaint = Paint()
+    private val rippleVibrationEffect = createVibrationEffect(vibrator)
+    private val rippleVibrationAttrs =
+            AudioAttributes.Builder()
+                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+                    .build()
 
     init {
         rippleShader.color = 0xffffffff.toInt() // default color
@@ -95,6 +110,7 @@
                 visibility = GONE
             }
         })
+        vibrate()
         animatorSet.start()
         visibility = VISIBLE
         rippleInProgress = true
@@ -108,4 +124,23 @@
         // draw over the entire screen
         canvas?.drawRect(0f, 0f, width.toFloat(), height.toFloat(), ripplePaint)
     }
+
+    private fun vibrate() {
+        if (rippleVibrationEffect != null) {
+            vibrator?.vibrate(rippleVibrationEffect, rippleVibrationAttrs)
+        }
+    }
+
+    private fun createVibrationEffect(vibrator: Vibrator?): VibrationEffect? {
+        if (vibrator?.areAllPrimitivesSupported(RIPPLE_VIBRATION_PRIMITIVE) == false) {
+            return null
+        }
+        val composition = VibrationEffect.startComposition()
+        for (i in 0 until RIPPLE_VIBRATION_SIZE) {
+            val scale =
+                    RIPPLE_VIBRATION_SCALE_START * MathUtils.exp(RIPPLE_VIBRATION_SCALE_DECAY * i)
+            composition.addPrimitive(RIPPLE_VIBRATION_PRIMITIVE, scale, 0 /* delay */)
+        }
+        return composition.compose()
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 3075617..5c360a6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -496,7 +496,6 @@
         mSensorProps = findFirstUdfps();
         // At least one UDFPS sensor exists
         checkArgument(mSensorProps != null);
-        mStatusBar.setSensorRect(getSensorLocation());
 
         mCoreLayoutParams = new WindowManager.LayoutParams(
                 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
index 98d8866..6a025a7 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceActivity.java
@@ -184,10 +184,4 @@
         // Refresh tile views to sync new conversations.
         buildActivity();
     }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        finish();
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java b/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
index f3cb359..96aeb60 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleStoryIconFactory.java
@@ -29,6 +29,8 @@
 import android.util.IconDrawableFactory;
 import android.util.Log;
 
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
@@ -58,7 +60,7 @@
         mIconDrawableFactory = iconDrawableFactory;
         mImportantConversationColor = context.getColor(R.color.important_conversation);
         mAccentColor = Utils.getColorAttr(context,
-                com.android.internal.R.attr.colorAccentPrimary).getDefaultColor();
+                com.android.internal.R.attr.colorAccentPrimaryVariant).getDefaultColor();
         mContext = context;
     }
 
@@ -83,7 +85,8 @@
      * Returns a {@link Drawable} for the entire conversation. The shortcut icon will be badged
      * with the launcher icon of the app specified by packageName.
      */
-    public Drawable getPeopleTileDrawable(Drawable headDrawable, String packageName, int userId,
+    public Drawable getPeopleTileDrawable(RoundedBitmapDrawable headDrawable, String packageName,
+            int userId,
             boolean important, boolean newStory) {
         return new PeopleStoryIconDrawable(headDrawable, getAppBadge(packageName, userId),
                 mIconBitmapSize, mImportantConversationColor, important, mIconSize, mDensity,
@@ -96,7 +99,7 @@
      */
     public static class PeopleStoryIconDrawable extends Drawable {
         private float mFullIconSize;
-        private Drawable mAvatar;
+        private RoundedBitmapDrawable mAvatar;
         private Drawable mBadgeIcon;
         private int mIconSize;
         private Paint mPriorityRingPaint;
@@ -105,12 +108,13 @@
         private Paint mStoryPaint;
         private float mDensity;
 
-        PeopleStoryIconDrawable(Drawable avatar,
+        PeopleStoryIconDrawable(RoundedBitmapDrawable avatar,
                 Drawable badgeIcon,
                 int iconSize,
                 @ColorInt int ringColor,
                 boolean showImportantRing, float fullIconSize, float density,
                 @ColorInt int accentColor, boolean showStoryRing) {
+            avatar.setCircular(true);
             mAvatar = avatar;
             mBadgeIcon = badgeIcon;
             mIconSize = iconSize;
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
index 59c7fd1..72d382a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleTileViewHelper.java
@@ -45,9 +45,6 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
-import android.icu.text.MeasureFormat;
-import android.icu.util.Measure;
-import android.icu.util.MeasureUnit;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.UserHandle;
@@ -61,6 +58,9 @@
 import android.widget.RemoteViews;
 import android.widget.TextView;
 
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.systemui.R;
@@ -72,6 +72,7 @@
 import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Objects;
@@ -94,6 +95,8 @@
     public static final int LAYOUT_LARGE = 2;
 
     private static final int MIN_CONTENT_MAX_LINES = 2;
+    private static final int NAME_MAX_LINES_WITHOUT_LAST_INTERACTION = 3;
+    private static final int NAME_MAX_LINES_WITH_LAST_INTERACTION = 1;
 
     private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_NOTIF_CONTENT = 16 + 22 + 8 + 16;
     private static final int FIXED_HEIGHT_DIMENS_FOR_LARGE_STATUS_CONTENT = 16 + 16 + 24 + 4 + 16;
@@ -225,7 +228,9 @@
                 Log.d(TAG,
                         "Create status view for: " + statusesForEntireView.get(0).getActivity());
             }
-            return createStatusRemoteViews(statusesForEntireView.get(0));
+            ConversationStatus mostRecentlyStartedStatus = statusesForEntireView.stream().max(
+                    Comparator.comparing(s -> s.getStartTimeMillis())).get();
+            return createStatusRemoteViews(mostRecentlyStartedStatus);
         }
 
         return createLastInteractionRemoteViews();
@@ -579,11 +584,33 @@
             setMaxLines(views, false);
         }
         setAvailabilityDotPadding(views, R.dimen.availability_dot_status_padding);
-        // TODO: Set status pre-defined icons
-        views.setImageViewResource(R.id.predefined_icon, R.drawable.ic_person);
+        views.setImageViewResource(R.id.predefined_icon, getDrawableForStatus(status));
         return views;
     }
 
+    private int getDrawableForStatus(ConversationStatus status) {
+        switch (status.getActivity()) {
+            case ACTIVITY_NEW_STORY:
+                return R.drawable.ic_pages;
+            case ACTIVITY_ANNIVERSARY:
+                return R.drawable.ic_celebration;
+            case ACTIVITY_UPCOMING_BIRTHDAY:
+                return R.drawable.ic_gift;
+            case ACTIVITY_BIRTHDAY:
+                return R.drawable.ic_cake;
+            case ACTIVITY_LOCATION:
+                return R.drawable.ic_location;
+            case ACTIVITY_GAME:
+                return R.drawable.ic_play_games;
+            case ACTIVITY_VIDEO:
+                return R.drawable.ic_video;
+            case ACTIVITY_AUDIO:
+                return R.drawable.ic_music_note;
+            default:
+                return R.drawable.ic_person;
+        }
+    }
+
     /**
      * Update the padding of the availability dot. The padding on the availability dot decreases
      * on the status layouts compared to all other layouts.
@@ -658,7 +685,6 @@
     }
 
     private RemoteViews decorateBackground(RemoteViews views, CharSequence content) {
-        int visibility = View.GONE;
         CharSequence emoji = getDoubleEmoji(content);
         if (!TextUtils.isEmpty(emoji)) {
             setEmojiBackground(views, emoji);
@@ -768,6 +794,7 @@
     }
 
     private RemoteViews setViewForContentLayout(RemoteViews views) {
+        views = decorateBackground(views, "");
         if (mLayoutSize == LAYOUT_SMALL) {
             views.setViewVisibility(R.id.predefined_icon, View.VISIBLE);
             views.setViewVisibility(R.id.name, View.GONE);
@@ -819,6 +846,7 @@
 
     private RemoteViews createLastInteractionRemoteViews() {
         RemoteViews views = new RemoteViews(mContext.getPackageName(), getEmptyLayout());
+        views.setInt(R.id.name, "setMaxLines", NAME_MAX_LINES_WITH_LAST_INTERACTION);
         if (mLayoutSize == LAYOUT_SMALL) {
             views.setViewVisibility(R.id.name, View.VISIBLE);
             views.setViewVisibility(R.id.predefined_icon, View.GONE);
@@ -836,6 +864,9 @@
         } else {
             if (DEBUG) Log.d(TAG, "Hide last interaction");
             views.setViewVisibility(R.id.last_interaction, View.GONE);
+            if (mLayoutSize == LAYOUT_MEDIUM) {
+                views.setInt(R.id.name, "setMaxLines", NAME_MAX_LINES_WITHOUT_LAST_INTERACTION);
+            }
         }
         return views;
     }
@@ -891,8 +922,9 @@
                 context.getPackageManager(),
                 IconDrawableFactory.newInstance(context, false),
                 maxAvatarSize);
-        Drawable drawable = icon.loadDrawable(context);
-        Drawable personDrawable = storyIcon.getPeopleTileDrawable(drawable,
+        RoundedBitmapDrawable roundedDrawable = RoundedBitmapDrawableFactory.create(
+                context.getResources(), icon.getBitmap());
+        Drawable personDrawable = storyIcon.getPeopleTileDrawable(roundedDrawable,
                 tile.getPackageName(), getUserId(tile), tile.isImportantConversation(),
                 hasNewStory);
         return convertDrawableToBitmap(personDrawable);
@@ -907,14 +939,11 @@
         }
         long now = System.currentTimeMillis();
         Duration durationSinceLastInteraction = Duration.ofMillis(now - lastInteraction);
-        MeasureFormat formatter = MeasureFormat.getInstance(Locale.getDefault(),
-                MeasureFormat.FormatWidth.WIDE);
         if (durationSinceLastInteraction.toDays() <= ONE_DAY) {
             return null;
         } else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK) {
-            return context.getString(R.string.days_timestamp, formatter.formatMeasures(
-                    new Measure(durationSinceLastInteraction.toDays(),
-                            MeasureUnit.DAY)));
+            return context.getString(R.string.days_timestamp,
+                    durationSinceLastInteraction.toDays());
         } else if (durationSinceLastInteraction.toDays() == DAYS_IN_A_WEEK) {
             return context.getString(R.string.one_week_timestamp);
         } else if (durationSinceLastInteraction.toDays() < DAYS_IN_A_WEEK * 2) {
diff --git a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
index 9e0dd72..2602d7a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
+++ b/packages/SystemUI/src/com/android/systemui/people/widget/PeopleSpaceWidgetManager.java
@@ -667,12 +667,16 @@
         if (icon != null) {
             updatedTile.setUserIcon(icon);
         }
+        if (DEBUG) Log.d(TAG, "Statuses: " + conversation.getStatuses().toString());
+        NotificationChannel channel = conversation.getParentNotificationChannel();
+        if (channel != null) {
+            if (DEBUG) Log.d(TAG, "Important:" + channel.isImportantConversation());
+            updatedTile.setIsImportantConversation(channel.isImportantConversation());
+        }
         updatedTile
                 .setContactUri(uri)
                 .setStatuses(conversation.getStatuses())
-                .setLastInteractionTimestamp(conversation.getLastEventTimestamp())
-                .setIsImportantConversation(conversation.getParentNotificationChannel() != null
-                        && conversation.getParentNotificationChannel().isImportantConversation());
+                .setLastInteractionTimestamp(conversation.getLastEventTimestamp());
         updateAppWidgetOptionsAndView(appWidgetId, updatedTile.build());
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index b93da4b..99c0f4e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -31,8 +31,8 @@
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.animation.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -180,7 +180,7 @@
 
             if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
                 viewState.alpha = Interpolators.getNotificationScrimAlpha(
-                        ambientState.getExpansionFraction());
+                        ambientState.getExpansionFraction(), true /* notification */);
             } else {
                 viewState.alpha = 1f - ambientState.getHideAmount();
             }
@@ -255,7 +255,6 @@
         int backgroundTop = 0;
         int clipTopAmount = 0;
         float firstElementRoundness = 0.0f;
-        ActivatableNotificationView previousAnv = null;
 
         for (int i = 0; i < mHostLayoutController.getChildCount(); i++) {
             ExpandableView child = mHostLayoutController.getChildAt(i);
@@ -327,52 +326,10 @@
                 notGoneIndex++;
             }
 
-            final float viewEnd = viewStart + child.getActualHeight();
-            final float cornerAnimationDistance = mCornerAnimationDistance
-                    * mAmbientState.getExpansionFraction();
-            final float cornerAnimationTop = shelfStart - cornerAnimationDistance;
-
             if (child instanceof ActivatableNotificationView) {
                 ActivatableNotificationView anv =
                         (ActivatableNotificationView) child;
-
-                final boolean isUnlockedHeadsUp = !mAmbientState.isOnKeyguard()
-                        && !mAmbientState.isShadeExpanded()
-                        && child instanceof ExpandableView
-                        && ((ExpandableNotificationRow) child).isHeadsUp();
-                if (viewStart < shelfStart
-                        && !mHostLayoutController.isViewAffectedBySwipe(anv)
-                        && !isUnlockedHeadsUp
-                        && !mAmbientState.isPulsing()
-                        && !mAmbientState.isDozing()) {
-
-                    if (viewEnd >= cornerAnimationTop) {
-                        // Round bottom corners within animation bounds
-                        final float changeFraction = MathUtils.saturate(
-                                (viewEnd - cornerAnimationTop) / cornerAnimationDistance);
-                        final float roundness = anv.isLastInSection() ? 1f : changeFraction * 1f;
-                        anv.setBottomRoundness(roundness, false);
-
-                    } else if (viewEnd < cornerAnimationTop) {
-                        // Fast scroll skips frames and leaves corners with unfinished rounding.
-                        // Reset top and bottom corners outside of animation bounds.
-                        anv.setBottomRoundness(anv.isLastInSection() ? 1f : 0f, false);
-                    }
-
-                    if (viewStart >= cornerAnimationTop) {
-                        // Round top corners within animation bounds
-                        final float changeFraction = MathUtils.saturate(
-                                (viewStart - cornerAnimationTop) / cornerAnimationDistance);
-                        final float roundness = anv.isFirstInSection() ? 1f : changeFraction * 1f;
-                        anv.setTopRoundness(roundness, false);
-
-                    } else if (viewStart < cornerAnimationTop) {
-                        // Fast scroll skips frames and leaves corners with unfinished rounding.
-                        // Reset top and bottom corners outside of animation bounds.
-                        anv.setTopRoundness(anv.isFirstInSection() ? 1f : 0f, false);
-                    }
-                }
-                previousAnv = anv;
+                updateCornerRoundnessOnScroll(anv, viewStart, shelfStart);
             }
         }
 
@@ -408,6 +365,58 @@
         }
     }
 
+    private void updateCornerRoundnessOnScroll(ActivatableNotificationView anv, float viewStart,
+            float shelfStart) {
+
+        final boolean isUnlockedHeadsUp = !mAmbientState.isOnKeyguard()
+                && !mAmbientState.isShadeExpanded()
+                && anv instanceof ExpandableNotificationRow
+                && ((ExpandableNotificationRow) anv).isHeadsUp();
+
+        final boolean shouldUpdateCornerRoundness = viewStart < shelfStart
+                && !mHostLayoutController.isViewAffectedBySwipe(anv)
+                && !isUnlockedHeadsUp
+                && !mAmbientState.isPulsing()
+                && !mAmbientState.isDozing();
+
+        if (!shouldUpdateCornerRoundness) {
+            return;
+        }
+
+        final float viewEnd = viewStart + anv.getActualHeight();
+        final float cornerAnimationDistance = mCornerAnimationDistance
+                * mAmbientState.getExpansionFraction();
+        final float cornerAnimationTop = shelfStart - cornerAnimationDistance;
+
+        if (viewEnd >= cornerAnimationTop) {
+            // Round bottom corners within animation bounds
+            final float changeFraction = MathUtils.saturate(
+                    (viewEnd - cornerAnimationTop) / cornerAnimationDistance);
+            anv.setBottomRoundness(anv.isLastInSection() ? 1f : changeFraction,
+                    false /* animate */);
+
+        } else if (viewEnd < cornerAnimationTop) {
+            // Fast scroll skips frames and leaves corners with unfinished rounding.
+            // Reset top and bottom corners outside of animation bounds.
+            anv.setBottomRoundness(anv.isLastInSection() ? 1f : 0f,
+                    false /* animate */);
+        }
+
+        if (viewStart >= cornerAnimationTop) {
+            // Round top corners within animation bounds
+            final float changeFraction = MathUtils.saturate(
+                    (viewStart - cornerAnimationTop) / cornerAnimationDistance);
+            anv.setTopRoundness(anv.isFirstInSection() ? 1f : changeFraction,
+                    false /* animate */);
+
+        } else if (viewStart < cornerAnimationTop) {
+            // Fast scroll skips frames and leaves corners with unfinished rounding.
+            // Reset top and bottom corners outside of animation bounds.
+            anv.setTopRoundness(anv.isFirstInSection() ? 1f : 0f,
+                    false /* animate */);
+        }
+    }
+
     /**
      * Clips transient views to the top of the shelf - Transient views are only used for
      * disappearing views/animations and need to be clipped correctly by the shelf to ensure they
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index e931ec4..0d34e90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -24,8 +24,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import com.android.systemui.animation.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.notification.dagger.SilentHeader;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -382,7 +382,7 @@
 
         if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) {
             viewState.alpha = Interpolators.getNotificationScrimAlpha(
-                    ambientState.getExpansionFraction());
+                    ambientState.getExpansionFraction(), true /* notification */);
         } else {
             viewState.alpha = 1f - ambientState.getHideAmount();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 7c63763..b92f7c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -548,8 +548,11 @@
      */
     public void setNotificationsBounds(float left, float top, float right, float bottom) {
         if (mClipsQsScrim) {
-            // "top - 1" to have 1 px of scrims overlap, see: b/186644628
-            mNotificationsScrim.setDrawableBounds(left, top - 1, right, bottom);
+            // notification scrim's rounded corners are anti-aliased, but clipping of the QS scrim
+            // can't be and it's causing jagged corners. That's why notification scrim needs
+            // to overlap QS scrim by one pixel - both vertically (top - 1) and
+            // horizontally (left - 1 and right + 1), see: b/186644628
+            mNotificationsScrim.setDrawableBounds(left - 1, top - 1, right + 1, bottom);
             mScrimBehind.setBottomEdgePosition((int) top);
         } else {
             mNotificationsScrim.setDrawableBounds(left, top, right, bottom);
@@ -883,7 +886,7 @@
     }
 
     private float getInterpolatedFraction() {
-        return Interpolators.getNotificationScrimAlpha(mPanelExpansion);
+        return Interpolators.getNotificationScrimAlpha(mPanelExpansion, false /* notification */);
     }
 
     private void setScrimAlpha(ScrimView scrim, float alpha) {
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 eec896a..1364d47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -73,9 +73,9 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
-import android.graphics.RectF;
 import android.media.AudioAttributes;
 import android.metrics.LogMaker;
 import android.net.Uri;
@@ -150,6 +150,7 @@
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.animation.DelegateLaunchAnimatorController;
 import com.android.systemui.assist.AssistManager;
+import com.android.systemui.biometrics.AuthRippleController;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.camera.CameraIntents;
 import com.android.systemui.charging.WirelessChargingAnimation;
@@ -326,9 +327,15 @@
     public static final int FADE_KEYGUARD_DURATION = 300;
     public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
 
+    public static final long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS =
+            new long[]{20, 20, 20, 20, 100, 20};
+    public static final int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES =
+            new int[]{39, 82, 139, 213, 0, 127};
 
-    /** If true, the system is in the half-boot-to-decryption-screen state.
-     * Prudently disable QS and notifications.  */
+    /**
+     * If true, the system is in the half-boot-to-decryption-screen state.
+     * Prudently disable QS and notifications.
+     */
     public static final boolean ONLY_CORE_APPS;
 
     /** If true, the lockscreen will show a distinct wallpaper */
@@ -380,6 +387,7 @@
     protected NotificationShadeWindowView mNotificationShadeWindowView;
     protected StatusBarWindowView mPhoneStatusBarWindow;
     protected PhoneStatusBarView mStatusBarView;
+    private AuthRippleController mAuthRippleController;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
     protected NotificationShadeWindowController mNotificationShadeWindowController;
     protected StatusBarWindowController mStatusBarWindowController;
@@ -600,7 +608,7 @@
     private int mLastCameraLaunchSource;
     protected PowerManager.WakeLock mGestureWakeLock;
     private Vibrator mVibrator;
-    private long[] mCameraLaunchGestureVibePattern;
+    private VibrationEffect mCameraLaunchGestureVibrationEffect;
 
     private final int[] mTmpInt2 = new int[2];
 
@@ -1311,12 +1319,8 @@
         mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
                 "GestureWakeLock");
         mVibrator = mContext.getSystemService(Vibrator.class);
-        int[] pattern = mContext.getResources().getIntArray(
-                R.array.config_cameraLaunchGestureVibePattern);
-        mCameraLaunchGestureVibePattern = new long[pattern.length];
-        for (int i = 0; i < pattern.length; i++) {
-            mCameraLaunchGestureVibePattern[i] = pattern[i];
-        }
+        mCameraLaunchGestureVibrationEffect = getCameraGestureVibrationEffect(
+                mVibrator, context.getResources());
 
         // receive broadcasts
         registerBroadcastReceiver();
@@ -1556,7 +1560,9 @@
         mPhoneStatusBarWindow = mSuperStatusBarViewFactory.getStatusBarWindowView();
         mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
         statusBarComponent.getLockIconViewController().init();
-        statusBarComponent.getAuthRippleController().init();
+
+        mAuthRippleController = statusBarComponent.getAuthRippleController();
+        mAuthRippleController.init();
     }
 
     protected void startKeyguard() {
@@ -2801,7 +2807,7 @@
             int[] result = new int[]{ActivityManager.START_CANCELED};
 
             mActivityLaunchAnimator.startIntentWithAnimation(animController,
-                    areLaunchAnimationsEnabled(), (adapter) -> {
+                    areLaunchAnimationsEnabled(), intent.getPackage(), (adapter) -> {
                         ActivityOptions options = new ActivityOptions(
                                 getActivityOptions(mDisplayId, adapter));
                         options.setDisallowEnterPictureInPictureWhileLaunching(
@@ -3791,7 +3797,8 @@
 
     @Override
     public void onDozeAmountChanged(float linear, float eased) {
-        if (mFeatureFlags.useNewLockscreenAnimations()) {
+        if (mFeatureFlags.useNewLockscreenAnimations()
+                && !mCircleRevealAnimator.isRunning()) {
             mLightRevealScrim.setRevealAmount(1f - linear);
         }
     }
@@ -3828,6 +3835,23 @@
         Trace.endSection();
     }
 
+    /**
+     * Update the parameters for the dozing circle reveal that animates when the user authenticates
+     * from AOD using the fingerprint sensor.
+     */
+    public void updateCircleReveal() {
+        final PointF fpLocation = mAuthRippleController.getFingerprintSensorLocation();
+        if (fpLocation != null) {
+            mCircleReveal =
+                    new CircleReveal(
+                            fpLocation.x,
+                            fpLocation.y,
+                            0,
+                            Math.max(Math.max(fpLocation.x, getDisplayWidth() - fpLocation.x),
+                                    Math.max(fpLocation.y, getDisplayHeight() - fpLocation.y)));
+        }
+    }
+
     private void startCircleReveal() {
         mLightRevealScrim.setRevealEffect(mCircleReveal);
         mCircleRevealAnimator.cancel();
@@ -3840,7 +3864,6 @@
 
     private boolean shouldShowCircleReveal() {
         return mCircleReveal != null && !mCircleRevealAnimator.isRunning()
-                && mKeyguardUpdateMonitor.isUdfpsEnrolled()
                 && mBiometricUnlockController.getBiometricType() == FINGERPRINT;
     }
 
@@ -4062,12 +4085,37 @@
 
     private void vibrateForCameraGesture() {
         // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
-        mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */);
+        mVibrator.vibrate(mCameraLaunchGestureVibrationEffect);
+    }
+
+    private static VibrationEffect getCameraGestureVibrationEffect(Vibrator vibrator,
+            Resources resources) {
+        if (vibrator.areAllPrimitivesSupported(
+                VibrationEffect.Composition.PRIMITIVE_QUICK_RISE,
+                VibrationEffect.Composition.PRIMITIVE_CLICK)) {
+            return VibrationEffect.startComposition()
+                    .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+                    .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 50)
+                    .compose();
+        }
+        if (vibrator.hasAmplitudeControl()) {
+            return VibrationEffect.createWaveform(
+                    CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS,
+                    CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES,
+                    /* repeat= */ -1);
+        }
+
+        int[] pattern = resources.getIntArray(R.array.config_cameraLaunchGestureVibePattern);
+        long[] timings = new long[pattern.length];
+        for (int i = 0; i < pattern.length; i++) {
+            timings[i] = pattern[i];
+        }
+        return VibrationEffect.createWaveform(timings, /* repeat= */ -1);
     }
 
     /**
      * @return true if the screen is currently fully off, i.e. has finished turning off and has
-     *         since not started turning on.
+     * since not started turning on.
      */
     public boolean isScreenFullyOff() {
         return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
@@ -4278,15 +4326,6 @@
         updateScrimController();
     }
 
-    /**
-     * Set the location of the sensor on UDFPS if existent.
-     */
-    public void setSensorRect(RectF rect) {
-        final float startRadius = (rect.right - rect.left) / 2f;
-        mCircleReveal = new CircleReveal(rect.centerX(), rect.centerY(),
-                startRadius, rect.centerY() - startRadius);
-    }
-
     @VisibleForTesting
     public void updateScrimController() {
         Trace.beginSection("StatusBar#updateScrimController");
@@ -4565,7 +4604,7 @@
                                 animationController, this, intent.isActivity()) : null;
 
                 mActivityLaunchAnimator.startPendingIntentWithAnimation(
-                        controller, areLaunchAnimationsEnabled(),
+                        controller, areLaunchAnimationsEnabled(), intent.getCreatorPackage(),
                         (animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
                                 null, getActivityOptions(mDisplayId, animationAdapter)));
             } catch (PendingIntent.CanceledException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index ab58aae6..5cd4e13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -437,7 +437,7 @@
 
             mActivityLaunchAnimator.startPendingIntentWithAnimation(animationController,
                     !wasOccluded && mStatusBar.areLaunchAnimationsEnabled(),
-                    (adapter) -> {
+                    intent.getCreatorPackage(), (adapter) -> {
                         long eventTime = row.getAndResetLastActionUpTime();
                         Bundle options = eventTime > 0
                                 ? getActivityOptions(
@@ -469,6 +469,7 @@
 
                 mActivityLaunchAnimator.startIntentWithAnimation(
                         animationController, mStatusBar.areLaunchAnimationsEnabled(),
+                        intent.getPackage(),
                         (adapter) -> TaskStackBuilder.create(mContext)
                                 .addNextIntentWithParentStack(intent)
                                 .startActivities(getActivityOptions(
@@ -499,7 +500,7 @@
                                 true /* isActivityIntent */);
 
                 mActivityLaunchAnimator.startIntentWithAnimation(animationController,
-                        mStatusBar.areLaunchAnimationsEnabled(),
+                        mStatusBar.areLaunchAnimationsEnabled(), intent.getPackage(),
                         (adapter) -> tsb.startActivities(
                                 getActivityOptions(mStatusBar.getDisplayId(), adapter),
                                 UserHandle.CURRENT));
diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt b/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
index 603d690..8187956 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
+++ b/packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
@@ -76,29 +76,41 @@
             }
             val linearInterp = LinearInterpolator()
             val scaleInterp = PathInterpolator(0.3f, 0f, 1f, 1f)
-            val sX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.9f).apply {
+            val viewScaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.9f).apply {
                 interpolator = scaleInterp
                 duration = 250
             }
-            val sY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.9f).apply {
+            val viewScaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.9f).apply {
                 interpolator = scaleInterp
                 duration = 250
             }
-            val vA = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
+            val viewElevation = ObjectAnimator.ofFloat(view, "elevation",
+                view.elevation, 0f).apply {
+                interpolator = linearInterp
+                duration = 40
+                startDelay = 150
+            }
+            val viewAlpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f).apply {
                 interpolator = linearInterp
                 duration = 100
                 startDelay = 150
             }
-            val tA = ObjectAnimator.ofFloat(text, "alpha", 1f, 0f).apply {
+            val textAlpha = ObjectAnimator.ofFloat(text, "alpha", 1f, 0f).apply {
                 interpolator = linearInterp
                 duration = 166
             }
-            val iA = ObjectAnimator.ofFloat(icon, "alpha", 1f, 0f).apply {
+            val iconAlpha = ObjectAnimator.ofFloat(icon, "alpha", 1f, 0f).apply {
                 interpolator = linearInterp
                 duration = 166
             }
             return AnimatorSet().apply {
-                playTogether(sX, sY, vA, tA, iA)
+                playTogether(
+                    viewScaleX,
+                    viewScaleY,
+                    viewElevation,
+                    viewAlpha,
+                    textAlpha,
+                    iconAlpha)
             }
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index d9a240f..936ec80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -100,8 +100,6 @@
     private AccessibilityManager mAccessibilityManager;
     @Mock
     private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
-    @Mock
-    private Handler mHandler;
     private TestableWindowManager mWindowManager;
     private ViewPropertyAnimator mViewPropertyAnimator;
     private MagnificationModeSwitch mMagnificationModeSwitch;
@@ -152,12 +150,12 @@
     }
 
     @Test
-    public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() {
-        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+    public void showFullscreenModeButton_addViewAndSetImageResource() {
+        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
 
         verify(mSpyImageView).setImageResource(
-                getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
-        verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class));
+                getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN));
+        assertEquals(mSpyImageView, mWindowManager.getAttachedView());
         assertShowFadingAnimation(FADE_IN_ALPHA);
         assertShowFadingAnimation(FADE_OUT_ALPHA);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 897d78b..f2ef5c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -51,7 +51,11 @@
         // We start in a new thread so that we can ensure that the callbacks are called in the main
         // thread.
         thread {
-            activityLaunchAnimator.startIntentWithAnimation(controller, animate, intentStarter)
+            activityLaunchAnimator.startIntentWithAnimation(
+                    controller = controller,
+                    animate = animate,
+                    intentStarter = intentStarter
+            )
         }.join()
     }
 
@@ -135,11 +139,14 @@
         verify(controller).onLaunchAnimationStart(anyBoolean())
     }
 
-    private fun fakeWindow() = RemoteAnimationTarget(
-            0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
-            Point(), Rect(), Rect(), WindowConfiguration(), false, SurfaceControl(), Rect(),
-            ActivityManager.RunningTaskInfo()
-    )
+    private fun fakeWindow(): RemoteAnimationTarget {
+        val bounds = Rect(10 /* left */, 20 /* top */, 30 /* right */, 40 /* bottom */)
+        return RemoteAnimationTarget(
+                0, RemoteAnimationTarget.MODE_OPENING, SurfaceControl(), false, Rect(), Rect(), 0,
+                Point(), Rect(), bounds, WindowConfiguration(), false, SurfaceControl(), Rect(),
+                ActivityManager.RunningTaskInfo()
+        )
+    }
 }
 
 /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
index 36a031a..06f9253 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricViewTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
+import android.hardware.biometrics.BiometricPrompt;
 import android.hardware.biometrics.PromptInfo;
 import android.os.Bundle;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -202,7 +203,7 @@
         waitForIdleSync();
 
         verify(mCallback).onAction(AuthBiometricView.Callback.ACTION_ERROR);
-        assertEquals(AuthBiometricView.STATE_ERROR, mBiometricView.mState);
+        assertEquals(AuthBiometricView.STATE_IDLE, mBiometricView.mState);
     }
 
     @Test
@@ -253,6 +254,12 @@
             public TextView getIndicatorView() {
                 return indicatorView;
             }
+
+            @Override
+            public int getDelayAfterError() {
+                // keep a real delay to test saving in the error state
+                return BiometricPrompt.HIDE_DIALOG_DELAY;
+            }
         });
 
         final String failureMessage = "testFailureMessage";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index bb2e55f..db5648a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -62,7 +62,6 @@
 
 import com.android.internal.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 
 import org.junit.Before;
@@ -96,8 +95,6 @@
     @Mock
     private CommandQueue mCommandQueue;
     @Mock
-    private StatusBarStateController mStatusBarStateController;
-    @Mock
     private ActivityTaskManager mActivityTaskManager;
     @Mock
     private FingerprintManager mFingerprintManager;
@@ -152,7 +149,7 @@
         when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
 
         mAuthController = new TestableAuthController(context, mCommandQueue,
-                mStatusBarStateController, mActivityTaskManager, mFingerprintManager, mFaceManager,
+                mActivityTaskManager, mFingerprintManager, mFaceManager,
                 () -> mUdfpsController, () -> mSidefpsController);
 
         mAuthController.start();
@@ -561,13 +558,12 @@
         private PromptInfo mLastBiometricPromptInfo;
 
         TestableAuthController(Context context, CommandQueue commandQueue,
-                StatusBarStateController statusBarStateController,
                 ActivityTaskManager activityTaskManager,
                 FingerprintManager fingerprintManager,
                 FaceManager faceManager,
                 Provider<UdfpsController> udfpsControllerFactory,
                 Provider<SidefpsController> sidefpsControllerFactory) {
-            super(context, commandQueue, statusBarStateController, activityTaskManager,
+            super(context, commandQueue, activityTaskManager,
                     fingerprintManager, faceManager, udfpsControllerFactory,
                     sidefpsControllerFactory);
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
index 247748a..240fdf3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.statusbar.NotificationShadeWindowController
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.phone.StatusBar
 import com.android.systemui.statusbar.policy.ConfigurationController
 import org.junit.Before
 import org.junit.Test
@@ -44,6 +45,7 @@
 @RunWith(AndroidTestingRunner::class)
 class AuthRippleControllerTest : SysuiTestCase() {
     private lateinit var controller: AuthRippleController
+    @Mock private lateinit var statusBar: StatusBar
     @Mock private lateinit var rippleView: AuthRippleView
     @Mock private lateinit var commandRegistry: CommandRegistry
     @Mock private lateinit var configurationController: ConfigurationController
@@ -56,6 +58,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         controller = AuthRippleController(
+            statusBar,
             context,
             authController,
             configurationController,
@@ -72,7 +75,7 @@
     fun testFingerprintTrigger_Ripple() {
         // GIVEN fp exists, keyguard is visible, user doesn't need strong auth
         val fpsLocation = PointF(5f, 5f)
-        `when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
+        `when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
         controller.onViewAttached()
         `when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
         `when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
@@ -193,7 +196,7 @@
 
     @Test
     fun testNullFingerprintSensorLocationDoesNothing() {
-        `when`(authController.udfpsSensorLocation).thenReturn(null)
+        `when`(authController.fingerprintSensorLocation).thenReturn(null)
         controller.onViewAttached()
 
         val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
index 3b56f22..67505c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/people/PeopleTileViewHelperTest.java
@@ -69,6 +69,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.time.Duration;
 import java.util.Arrays;
 
 @RunWith(AndroidTestingRunner.class)
@@ -185,6 +186,30 @@
     }
 
     @Test
+    public void testLastInteractionTime() {
+        long now = System.currentTimeMillis();
+        long fiveDaysAgo = now - Duration.ofDays(5).toMillis();
+        String lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+                fiveDaysAgo);
+        assertThat(lastInteractionString).isEqualTo("5 days ago");
+
+        long lessThanOneDayAgo = now - Duration.ofHours(20).toMillis();
+        lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+                lessThanOneDayAgo);
+        assertThat(lastInteractionString).isNull();
+
+        long overOneWeekAgo = now - Duration.ofDays(8).toMillis();
+        lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+                overOneWeekAgo);
+        assertThat(lastInteractionString).isEqualTo("Over 1 week ago");
+
+        long overTwoWeeksAgo = now - Duration.ofDays(15).toMillis();
+        lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
+                overTwoWeeksAgo);
+        assertThat(lastInteractionString).isEqualTo("Over 2 weeks ago");
+    }
+
+    @Test
     public void testCreateRemoteViewsWithLastInteractionTime() {
         PeopleSpaceTile tileWithLastInteraction =
                 PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setLastInteractionTimestamp(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index a431a78..8b0b579 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -1118,7 +1118,7 @@
     public void testNotificationTransparency_inKeyguardState() {
         mScrimController.transitionTo(ScrimState.KEYGUARD);
 
-        assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.8f);
+        assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.2f, /* expansion */ 0.4f);
         assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0.8f, /* expansion */ 0.2f);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index be86af5..407afbe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -269,7 +269,7 @@
         verify(mShadeController, atLeastOnce()).collapsePanel();
 
         verify(mActivityLaunchAnimator).startPendingIntentWithAnimation(any(),
-                eq(false) /* animate */, any());
+                eq(false) /* animate */, any(), any());
 
         verify(mAssistManager).hideAssist();
 
diff --git a/services/Android.bp b/services/Android.bp
index 1dd2192..f2e0b20 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -141,7 +141,6 @@
     libs: [
         "android.hidl.manager-V1.0-java",
         "framework-tethering.stubs.module_lib",
-        "service-art.stubs.system_server",
     ],
 
     // Uncomment to enable output of certain warnings (deprecated, unchecked)
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index ab85b5e..83dfe8e 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -20,6 +20,7 @@
 import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES;
 import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED;
 import static android.content.Context.BIND_IMPORTANT;
+import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
@@ -657,7 +658,14 @@
         }
 
         @Override
-        public void createAssociation(String packageName, String macAddress, int userId) {
+        public void createAssociation(String packageName, String macAddress, int userId,
+                byte[] certificate) {
+            if (!getContext().getPackageManager().hasSigningCertificate(
+                    packageName, certificate, CERT_INPUT_SHA256)) {
+                Slog.e(LOG_TAG, "Given certificate doesn't match the package certificate.");
+                return;
+            }
+
             getContext().enforceCallingOrSelfPermission(
                     android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES, "createAssociation");
 
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 6e7771d..e336b6b 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -39,11 +39,9 @@
 import libcore.io.IoUtils;
 
 import java.io.DataInputStream;
-import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
@@ -377,11 +375,16 @@
 
         try {
             FileChannel channel = getBlockOutputChannel();
-            ByteBuffer buf = ByteBuffer.allocate(DIGEST_SIZE_BYTES + HEADER_SIZE);
+            int header_size = DIGEST_SIZE_BYTES + HEADER_SIZE;
+            ByteBuffer buf = ByteBuffer.allocate(header_size);
             buf.put(new byte[DIGEST_SIZE_BYTES]);
             buf.putInt(PARTITION_TYPE_MARKER);
             buf.putInt(0);
             channel.write(buf);
+            // corrupt the payload explicitly
+            int payload_size = (int) getBlockDeviceSize() - header_size;
+            buf = ByteBuffer.allocate(payload_size);
+            channel.write(buf);
             channel.force(true);
         } catch (IOException e) {
             Slog.e(TAG, "failed to format block", e);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 0f3aa65..562f8f44 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -21,38 +21,40 @@
 import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
 import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
 import static android.app.ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;
+import static android.app.ActivityManager.PROCESS_STATE_PERSISTENT_UI;
 import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
 import static android.app.ActivityManager.PROCESS_STATE_TOP;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST;
+import static android.os.PowerExemptionManager.REASON_ACTIVITY_STARTER;
 import static android.os.PowerExemptionManager.REASON_ACTIVITY_VISIBILITY_GRACE_PERIOD;
+import static android.os.PowerExemptionManager.REASON_ALLOWLISTED_PACKAGE;
+import static android.os.PowerExemptionManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_BACKGROUND_FGS_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_COMPANION_DEVICE_MANAGER;
+import static android.os.PowerExemptionManager.REASON_DENIED;
+import static android.os.PowerExemptionManager.REASON_DEVICE_DEMO_MODE;
+import static android.os.PowerExemptionManager.REASON_DEVICE_OWNER;
+import static android.os.PowerExemptionManager.REASON_FGS_BINDING;
+import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
 import static android.os.PowerExemptionManager.REASON_OPT_OUT_REQUESTED;
 import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_PLATFORM_VPN;
 import static android.os.PowerExemptionManager.REASON_OP_ACTIVATE_VPN;
+import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT;
+import static android.os.PowerExemptionManager.REASON_PROC_STATE_PERSISTENT_UI;
+import static android.os.PowerExemptionManager.REASON_PROC_STATE_TOP;
+import static android.os.PowerExemptionManager.REASON_PROFILE_OWNER;
+import static android.os.PowerExemptionManager.REASON_SERVICE_LAUNCH;
+import static android.os.PowerExemptionManager.REASON_START_ACTIVITY_FLAG;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_ALLOW_LISTED;
+import static android.os.PowerExemptionManager.REASON_SYSTEM_UID;
 import static android.os.PowerExemptionManager.REASON_TEMP_ALLOWED_WHILE_IN_USE;
-import static android.os.PowerWhitelistManager.REASON_ACTIVITY_STARTER;
-import static android.os.PowerWhitelistManager.REASON_ALLOWLISTED_PACKAGE;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_COMPANION_DEVICE_MANAGER;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
-import static android.os.PowerWhitelistManager.REASON_DEVICE_DEMO_MODE;
-import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_FGS_BINDING;
-import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_ACTIVITY_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_INSTR_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT;
-import static android.os.PowerWhitelistManager.REASON_PROC_STATE_PERSISTENT_UI;
-import static android.os.PowerWhitelistManager.REASON_PROC_STATE_TOP;
-import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_START_ACTIVITY_FLAG;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID;
-import static android.os.PowerWhitelistManager.REASON_UID_VISIBLE;
-import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
-import static android.os.PowerWhitelistManager.getReasonCodeFromProcState;
-import static android.os.PowerWhitelistManager.reasonCodeToString;
+import static android.os.PowerExemptionManager.REASON_UID_VISIBLE;
+import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
+import static android.os.PowerExemptionManager.getReasonCodeFromProcState;
+import static android.os.PowerExemptionManager.reasonCodeToString;
 import static android.os.Process.INVALID_UID;
 import static android.os.Process.NFC_UID;
 import static android.os.Process.ROOT_UID;
@@ -118,8 +120,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.PowerWhitelistManager;
-import android.os.PowerWhitelistManager.ReasonCode;
+import android.os.PowerExemptionManager.ReasonCode;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -135,6 +136,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
+import android.util.Pair;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -3614,8 +3616,9 @@
                         + " for fg-service launch");
             }
             mAm.tempAllowlistUidLocked(r.appInfo.uid,
-                    SERVICE_START_FOREGROUND_TIMEOUT, PowerWhitelistManager.REASON_SERVICE_LAUNCH,
-                    "fg-service-launch", TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
+                    SERVICE_START_FOREGROUND_TIMEOUT, REASON_SERVICE_LAUNCH,
+                    "fg-service-launch",
+                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                     r.mRecentCallingUid);
         }
 
@@ -5740,6 +5743,66 @@
         int ret = shouldAllowFgsStartForegroundLocked(allowWhileInUse, callingPid, callingUid,
                 callingPackage, r);
 
+        String bindFromPackage = null;
+        if (ret == REASON_DENIED) {
+            // If the callingUid is not allowed to start FGS, check if the callingUid has any
+            // service that is bound by a clientUid, the clientUid can propagate its BG-FGS-start
+            // capability down to the callingUid.
+            final ArraySet<Integer> checkedClientUids = new ArraySet<>();
+            final Pair<Integer, String> isAllowed = mAm.mProcessList.searchEachLruProcessesLOSP(
+                    false, pr -> {
+                if (pr.uid == callingUid) {
+                    final ProcessServiceRecord psr = pr.mServices;
+                    final int serviceCount = psr.mServices.size();
+                    for (int svc = 0; svc < serviceCount; svc++) {
+                        final ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
+                                psr.mServices.valueAt(svc).getConnections();
+                        final int size = conns.size();
+                        for (int conni = 0; conni < size; conni++) {
+                            final ArrayList<ConnectionRecord> crs = conns.valueAt(conni);
+                            for (int con = 0; con < crs.size(); con++) {
+                                final ConnectionRecord cr = crs.get(con);
+                                final ProcessRecord clientPr = cr.binding.client;
+                                // Persistent process does not propagate BG-FGS-start capability
+                                // down to service over binding.
+                                if (clientPr.mState.getCurProcState()
+                                        <= PROCESS_STATE_PERSISTENT_UI) {
+                                    continue;
+                                }
+                                final int clientPid = clientPr.mPid;
+                                final int clientUid = clientPr.uid;
+                                // An UID can bind to itself, do not check on itself again.
+                                // Also skip already checked clientUid.
+                                if (clientUid == callingUid
+                                        || checkedClientUids.contains(clientUid)) {
+                                    continue;
+                                }
+                                final String clientPackageName = cr.clientPackageName;
+                                final @ReasonCode int allowWhileInUse2 =
+                                        shouldAllowFgsWhileInUsePermissionLocked(clientPackageName,
+                                                clientPid, clientUid, null /* serviceRecord */,
+                                                false /* allowBackgroundActivityStarts */);
+                                final @ReasonCode int allowStartFgs =
+                                        shouldAllowFgsStartForegroundLocked(allowWhileInUse2,
+                                                clientPid, clientUid, clientPackageName, null /* targetService */);
+                                if (allowStartFgs != REASON_DENIED) {
+                                    return new Pair<>(allowStartFgs, clientPackageName);
+                                } else {
+                                    checkedClientUids.add(clientUid);
+                                }
+
+                            }
+                        }
+                    }
+                }
+                return null;
+            });
+            if (isAllowed != null) {
+                ret = REASON_FGS_BINDING;
+                bindFromPackage = isAllowed.second;
+            }
+        }
+
         final int uidState = mAm.getUidStateLocked(callingUid);
         int callerTargetSdkVersion = INVALID_UID;
         try {
@@ -5765,6 +5828,7 @@
                         + "; targetSdkVersion:" + r.appInfo.targetSdkVersion
                         + "; callerTargetSdkVersion:" + callerTargetSdkVersion
                         + "; startForegroundCount:" + r.mStartForegroundCount
+                        + "; bindFromPackage:" + bindFromPackage
                         + "]";
         if (!debugInfo.equals(r.mInfoAllowStartForeground)) {
             r.mLoggedInfoAllowStartForeground = false;
@@ -5790,9 +5854,7 @@
             final Integer allowedType = mAm.mProcessList.searchEachLruProcessesLOSP(false, app -> {
                 if (app.uid == callingUid) {
                     final ProcessStateRecord state = app.mState;
-                    if (state.getAllowedStartFgs() != REASON_DENIED) {
-                        return state.getAllowedStartFgs();
-                    } else if (state.isAllowedStartFgsState()) {
+                    if (state.isAllowedStartFgsState()) {
                         return getReasonCodeFromProcState(state.getAllowStartFgsState());
                     } else if (state.areBackgroundFgsStartsAllowedByToken()) {
                         return REASON_FGS_BINDING;
@@ -5891,6 +5953,7 @@
         }
         if (ret == REASON_DENIED) {
             if (mAm.mConstants.mFgsAllowOptOut
+                    && targetService != null
                     && targetService.appInfo.hasRequestForegroundServiceExemption()) {
                 ret = REASON_OPT_OUT_REQUESTED;
             }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 85e8315..6cb374a 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -139,7 +139,7 @@
                     .onMalformedInput(CodingErrorAction.REPLACE)
                     .onUnmappableCharacter(CodingErrorAction.REPLACE)
                     .replaceWith("?");
-    private static final int MAX_LOW_POWER_STATS_SIZE = 8192;
+    private static final int MAX_LOW_POWER_STATS_SIZE = 16384;
     private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000;
     private static final String EMPTY = "Empty";
 
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index f32423f..b325ea3 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -159,6 +159,10 @@
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ASPECT_RATIO,
                 WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class,
                 WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<>(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ANALOG_CLOCK_SECONDS_HAND_FPS,
+                WidgetFlags.KEY_ANALOG_CLOCK_SECONDS_HAND_FPS, int.class,
+                WidgetFlags.ANALOG_CLOCK_SECONDS_HAND_FPS_DEFAULT));
         // add other device configs here...
     }
 
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 2e2a297..661e0b8 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -42,7 +42,6 @@
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
 import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
 import static android.os.Process.SCHED_OTHER;
 import static android.os.Process.THREAD_GROUP_BACKGROUND;
 import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -1574,8 +1573,7 @@
         state.setAdjTarget(null);
         state.setEmpty(false);
         state.setCached(false);
-        state.setAllowStartFgsState(PROCESS_STATE_NONEXISTENT);
-        state.resetAllowStartFgs();
+        state.resetAllowStartFgsState();
         app.mOptRecord.setShouldNotFreeze(false);
 
         final int appUid = app.info.uid;
@@ -1630,7 +1628,6 @@
             state.setCurAdj(state.getMaxAdj());
             state.setCompletedAdjSeq(state.getAdjSeq());
             state.bumpAllowStartFgsState(state.getCurProcState());
-            state.setAllowStartFgs();
             // if curAdj is less than prevAppAdj, then this process was promoted
             return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState;
         }
@@ -2028,12 +2025,6 @@
 
                     final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
 
-                    // pass client's mAllowStartFgs to the app if client is not persistent process.
-                    if (cstate.getAllowedStartFgs() != REASON_DENIED
-                            && cstate.getMaxAdj() >= ProcessList.FOREGROUND_APP_ADJ) {
-                        state.setAllowStartFgs(cstate.getAllowedStartFgs());
-                    }
-
                     if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
                         if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) {
                             continue;
@@ -2524,7 +2515,6 @@
         state.updateLastInvisibleTime(hasVisibleActivities);
         state.setHasForegroundActivities(foregroundActivities);
         state.setCompletedAdjSeq(mAdjSeq);
-        state.setAllowStartFgs();
 
         // if curAdj or curProcState improved, then this process was promoted
         return state.getCurAdj() < prevAppAdj || state.getCurProcState() < prevProcState
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 5c3bf60..8f77b87 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -89,7 +89,7 @@
     /**
      * All ServiceRecord running in this process.
      */
-    private final ArraySet<ServiceRecord> mServices = new ArraySet<>();
+    final ArraySet<ServiceRecord> mServices = new ArraySet<>();
 
     /**
      * Services that are currently executing code (need to remain foreground).
diff --git a/services/core/java/com/android/server/am/ProcessStateRecord.java b/services/core/java/com/android/server/am/ProcessStateRecord.java
index 801e382..d83e13c 100644
--- a/services/core/java/com/android/server/am/ProcessStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessStateRecord.java
@@ -16,28 +16,9 @@
 
 package com.android.server.am;
 
-import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
-import static android.Manifest.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND;
-import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
 import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_ACTIVITY_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_BACKGROUND_FGS_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_DENIED;
-import static android.os.PowerWhitelistManager.REASON_DEVICE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_PROFILE_OWNER;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_ALLOW_LISTED;
-import static android.os.PowerWhitelistManager.REASON_SYSTEM_UID;
-import static android.os.PowerWhitelistManager.ReasonCode;
-import static android.os.PowerWhitelistManager.getReasonCodeFromProcState;
-import static android.os.PowerWhitelistManager.reasonCodeToString;
-import static android.os.Process.NFC_UID;
-import static android.os.Process.ROOT_UID;
-import static android.os.Process.SHELL_UID;
-import static android.os.Process.SYSTEM_UID;
 
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
 import static com.android.server.am.ProcessRecord.TAG;
@@ -47,7 +28,6 @@
 import android.content.ComponentName;
 import android.os.Binder;
 import android.os.SystemClock;
-import android.os.UserHandle;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.TimeUtils;
@@ -56,7 +36,6 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.FrameworkStatsLog;
 
-
 import java.io.PrintWriter;
 
 /**
@@ -327,20 +306,6 @@
     private final ArraySet<Binder> mBackgroundFgsStartTokens = new ArraySet<>();
 
     /**
-     * Does the process has permission to start FGS from background.
-     */
-    @GuardedBy("mService")
-    private @ReasonCode int mAllowStartFgsByPermission = REASON_DENIED;
-
-    /**
-     * Can this process start FGS from background?
-     * If this process has the ability to start FGS from background, this ability can be passed to
-     * another process through service binding.
-     */
-    @GuardedBy("mService")
-    private @ReasonCode int mAllowStartFgs = REASON_DENIED;
-
-    /**
      * Whether or not this process has been in forced-app-standby state.
      */
     @GuardedBy("mService")
@@ -435,7 +400,6 @@
         mApp = app;
         mService = app.mService;
         mProcLock = mService.mProcLock;
-        setAllowStartFgsByPermission();
     }
 
     void init(long now) {
@@ -1152,9 +1116,8 @@
     }
 
     @GuardedBy("mService")
-    void resetAllowStartFgs() {
+    void resetAllowStartFgsState() {
         mAllowStartFgsState = PROCESS_STATE_NONEXISTENT;
-        mAllowStartFgs = mAllowStartFgsByPermission;
     }
 
     @GuardedBy("mService")
@@ -1165,11 +1128,6 @@
     }
 
     @GuardedBy("mService")
-    void setAllowStartFgsState(int allowStartFgsState) {
-        mAllowStartFgsState = allowStartFgsState;
-    }
-
-    @GuardedBy("mService")
     int getAllowStartFgsState() {
         return mAllowStartFgsState;
     }
@@ -1180,98 +1138,6 @@
     }
 
     @GuardedBy("mService")
-    void setAllowStartFgsByPermission() {
-        int ret = REASON_DENIED;
-        boolean isSystem = false;
-        final int uid = UserHandle.getAppId(mApp.info.uid);
-        switch (uid) {
-            case ROOT_UID:
-            case SYSTEM_UID:
-            case NFC_UID:
-            case SHELL_UID:
-                isSystem = true;
-                break;
-            default:
-                isSystem = false;
-                break;
-        }
-
-        if (isSystem) {
-            ret = REASON_SYSTEM_UID;
-        }
-
-        if (ret == REASON_DENIED) {
-            if (ActivityManager.checkComponentPermission(START_ACTIVITIES_FROM_BACKGROUND,
-                    mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
-                ret = REASON_BACKGROUND_ACTIVITY_PERMISSION;
-            } else if (ActivityManager.checkComponentPermission(
-                    START_FOREGROUND_SERVICES_FROM_BACKGROUND,
-                    mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
-                ret = REASON_BACKGROUND_FGS_PERMISSION;
-            } else if (ActivityManager.checkComponentPermission(SYSTEM_ALERT_WINDOW,
-                    mApp.info.uid, -1, true) == PERMISSION_GRANTED) {
-                ret = REASON_SYSTEM_ALERT_WINDOW_PERMISSION;
-            }
-        }
-        mAllowStartFgs = mAllowStartFgsByPermission = ret;
-    }
-
-    // TODO(b/188063200) Clean up this method. Why do we need to duplicate only some of the checks?
-    @GuardedBy("mService")
-    void setAllowStartFgs() {
-        if (mAllowStartFgs != REASON_DENIED) {
-            return;
-        }
-        if (mAllowStartFgs == REASON_DENIED) {
-            if (isAllowedStartFgsState()) {
-                mAllowStartFgs = getReasonCodeFromProcState(mAllowStartFgsState);
-            }
-        }
-
-        if (mAllowStartFgs == REASON_DENIED) {
-            // Is the calling UID a device owner app?
-            if (mService.mInternal != null) {
-                if (mService.mInternal.isDeviceOwner(mApp.info.uid)) {
-                    mAllowStartFgs = REASON_DEVICE_OWNER;
-                }
-            }
-        }
-
-        if (mAllowStartFgs == REASON_DENIED) {
-            // Is the calling UID a profile owner app?
-            if (mService.mInternal != null) {
-                if (mService.mInternal.isProfileOwner(mApp.info.uid)) {
-                    mAllowStartFgs = REASON_PROFILE_OWNER;
-                }
-            }
-        }
-
-        if (mAllowStartFgs == REASON_DENIED) {
-            // uid is on DeviceIdleController's user/system allowlist
-            // or AMS's FgsStartTempAllowList.
-            ActivityManagerService.FgsTempAllowListItem item =
-                    mService.isAllowlistedForFgsStartLOSP(mApp.info.uid);
-            if (item != null) {
-                if (item == ActivityManagerService.FAKE_TEMP_ALLOW_LIST_ITEM) {
-                    mAllowStartFgs = REASON_SYSTEM_ALLOW_LISTED;
-                } else {
-                    mAllowStartFgs = item.mReasonCode;
-                }
-            }
-        }
-    }
-
-    @GuardedBy("mService")
-    void setAllowStartFgs(@ReasonCode int allowStartFgs) {
-        mAllowStartFgs = allowStartFgs;
-    }
-
-    @GuardedBy("mService")
-    @ReasonCode int getAllowedStartFgs() {
-        return mAllowStartFgs;
-    }
-
-    @GuardedBy("mService")
     void setForcedAppStandby(boolean standby) {
         mForcedAppStandby = standby;
     }
@@ -1334,10 +1200,6 @@
         pw.println();
         pw.print(prefix); pw.print("allowStartFgsState=");
         pw.println(mAllowStartFgsState);
-        if (mAllowStartFgs != REASON_DENIED) {
-            pw.print(prefix); pw.print("allowStartFgs=");
-            pw.println(reasonCodeToString(mAllowStartFgs));
-        }
         if (mHasShownUi || mApp.mProfile.hasPendingUiClean()) {
             pw.print(prefix); pw.print("hasShownUi="); pw.print(mHasShownUi);
             pw.print(" pendingUiClean="); pw.println(mApp.mProfile.hasPendingUiClean());
diff --git a/services/core/java/com/android/server/biometrics/BiometricStrengthController.java b/services/core/java/com/android/server/biometrics/BiometricStrengthController.java
index 270621c..768dc36 100644
--- a/services/core/java/com/android/server/biometrics/BiometricStrengthController.java
+++ b/services/core/java/com/android/server/biometrics/BiometricStrengthController.java
@@ -48,16 +48,9 @@
      */
     private static final String KEY_BIOMETRIC_STRENGTHS = "biometric_strengths";
 
-    /**
-     * Default (no-op) value of the flag KEY_BIOMETRIC_STRENGTHS
-     */
-    public static final String DEFAULT_BIOMETRIC_STRENGTHS = null;
-
     private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener = properties -> {
-        for (String name : properties.getKeyset()) {
-            if (KEY_BIOMETRIC_STRENGTHS.equals(name)) {
-                updateStrengths();
-            }
+        if (properties.getKeyset().contains(KEY_BIOMETRIC_STRENGTHS)) {
+            updateStrengths();
         }
     };
 
@@ -75,7 +68,17 @@
      * has been changed.
      */
     public void updateStrengths() {
-        final Map<Integer, Integer> idToStrength = getIdToStrengthMap();
+        final String newValue = DeviceConfig.getString(DeviceConfig.NAMESPACE_BIOMETRICS,
+                KEY_BIOMETRIC_STRENGTHS, "null");
+        if ("null".equals(newValue) || newValue.isEmpty()) {
+            revertStrengths();
+        } else {
+            updateStrengths(newValue);
+        }
+    }
+
+    private void updateStrengths(String flags) {
+        final Map<Integer, Integer> idToStrength = getIdToStrengthMap(flags);
         if (idToStrength == null) {
             return;
         }
@@ -91,12 +94,18 @@
         }
     }
 
+    private void revertStrengths() {
+        for (BiometricSensor sensor : mService.mSensors) {
+            Slog.d(TAG, "updateStrengths: revert sensorId=" + sensor.id + " to oemStrength="
+                    + sensor.oemStrength);
+            sensor.updateStrength(sensor.oemStrength);
+        }
+    }
+
     /**
      * @return a map of <ID, Strength>
      */
-    private Map<Integer, Integer> getIdToStrengthMap() {
-        final String flags = DeviceConfig.getString(DeviceConfig.NAMESPACE_BIOMETRICS,
-                KEY_BIOMETRIC_STRENGTHS, DEFAULT_BIOMETRIC_STRENGTHS);
+    private static Map<Integer, Integer> getIdToStrengthMap(String flags) {
         if (flags == null || flags.isEmpty()) {
             Slog.d(TAG, "Flags are null or empty");
             return null;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 6482a2e..99f4e2c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -82,7 +82,20 @@
     private final int mCookie;
     boolean mAlreadyDone;
 
-    @NonNull protected Callback mCallback;
+    // Use an empty callback by default since delayed operations can receive events
+    // before they are started and cause NPE in subclasses that access this field directly.
+    @NonNull protected Callback mCallback = new Callback() {
+        @Override
+        public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) {
+            Slog.e(TAG, "mCallback onClientStarted: called before set (should not happen)");
+        }
+
+        @Override
+        public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
+                boolean success) {
+            Slog.e(TAG, "mCallback onClientFinished: called before set (should not happen)");
+        }
+    };
 
     /**
      * @return A ClientMonitorEnum constant defined in biometrics.proto
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index d29a0c7..0f97b90 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -26,9 +26,7 @@
 import android.compat.annotation.Disabled;
 import android.compat.annotation.EnabledSince;
 import android.compat.annotation.Overridable;
-import android.content.Context;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 
 import com.android.internal.compat.AndroidBuildClassifier;
 import com.android.internal.compat.CompatibilityChangeInfo;
@@ -161,15 +159,17 @@
      *
      * @param packageName Package name to tentatively enable the change for.
      * @param override The package override to be set
+     * @param allowedState Whether the override is allowed.
+     * @param versionCode The version code of the package.
      */
     void addPackageOverride(String packageName, PackageOverride override,
-            OverrideAllowedState allowedState, Context context) {
+            OverrideAllowedState allowedState, @Nullable Long versionCode) {
         if (getLoggingOnly()) {
             throw new IllegalArgumentException(
                     "Can't add overrides for a logging only change " + toString());
         }
         mRawOverrides.put(packageName, override);
-        recheckOverride(packageName, allowedState, context);
+        recheckOverride(packageName, allowedState, versionCode);
     }
 
     /**
@@ -179,32 +179,24 @@
      * overrides, check if they need to be demoted to deferred.</p>
      *
      * @param packageName Package name to apply deferred overrides for.
-     * @param allowed Whether the override is allowed.
+     * @param allowedState Whether the override is allowed.
+     * @param versionCode The version code of the package.
      *
      * @return {@code true} if the recheck yielded a result that requires invalidating caches
      *         (a deferred override was consolidated or a regular override was removed).
      */
     boolean recheckOverride(String packageName, OverrideAllowedState allowedState,
-            Context context) {
+            @Nullable Long versionCode) {
         boolean allowed = (allowedState.state == OverrideAllowedState.ALLOWED);
 
-        Long version = null;
-        try {
-            ApplicationInfo applicationInfo = context.getPackageManager().getApplicationInfo(
-                    packageName, 0);
-            version = applicationInfo.longVersionCode;
-        } catch (PackageManager.NameNotFoundException e) {
-            // Do nothing
-        }
-
         // If the app is not installed or no longer has raw overrides, evaluate to false
-        if (version == null || !hasRawOverride(packageName) || !allowed) {
+        if (versionCode == null || !hasRawOverride(packageName) || !allowed) {
             removePackageOverrideInternal(packageName);
             return false;
         }
 
         // Evaluate the override based on its version
-        int overrideValue = mRawOverrides.get(packageName).evaluate(version);
+        int overrideValue = mRawOverrides.get(packageName).evaluate(versionCode);
         switch (overrideValue) {
             case VALUE_UNDEFINED:
                 removePackageOverrideInternal(packageName);
@@ -229,11 +221,13 @@
      * <p>Note, this method is not thread safe so callers must ensure thread safety.
      *
      * @param pname Package name to reset to defaults for.
+     * @param allowedState Whether the override is allowed.
+     * @param versionCode The version code of the package.
      */
     boolean removePackageOverride(String pname, OverrideAllowedState allowedState,
-            Context context) {
+            @Nullable Long versionCode) {
         if (mRawOverrides.remove(pname) != null) {
-            recheckOverride(pname, allowedState, context);
+            recheckOverride(pname, allowedState, versionCode);
             return true;
         }
         return false;
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 9247568..909ed11 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -16,11 +16,13 @@
 
 package com.android.server.compat;
 
+import android.annotation.Nullable;
 import android.app.compat.ChangeIdStateCache;
 import android.app.compat.PackageOverride;
 import android.compat.Compatibility.ChangeConfig;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.os.Environment;
 import android.text.TextUtils;
 import android.util.LongArray;
@@ -51,7 +53,6 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -249,6 +250,7 @@
         OverrideAllowedState allowedState =
                 mOverrideValidator.getOverrideAllowedState(changeId, packageName);
         allowedState.enforce(changeId, packageName);
+        Long versionCode = getVersionCodeOrNull(packageName);
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c == null) {
@@ -256,7 +258,7 @@
                 c = new CompatChange(changeId);
                 addChange(c);
             }
-            c.addPackageOverride(packageName, overrides, allowedState, mContext);
+            c.addPackageOverride(packageName, overrides, allowedState, versionCode);
             invalidateCache();
         }
         return alreadyKnown;
@@ -336,6 +338,7 @@
      * It does not invalidate the cache nor save the overrides.
      */
     private boolean removeOverrideUnsafe(long changeId, String packageName) {
+        Long versionCode = getVersionCodeOrNull(packageName);
         synchronized (mChanges) {
             CompatChange c = mChanges.get(changeId);
             if (c != null) {
@@ -343,7 +346,7 @@
                         mOverrideValidator.getOverrideAllowedState(changeId, packageName);
                 if (c.hasPackageOverride(packageName)) {
                     allowedState.enforce(changeId, packageName);
-                    c.removePackageOverride(packageName, allowedState, mContext);
+                    c.removePackageOverride(packageName, allowedState, versionCode);
                     invalidateCache();
                     return true;
                 }
@@ -653,26 +656,33 @@
      * Rechecks all the existing overrides for a package.
      */
     void recheckOverrides(String packageName) {
-        // Local cache of compat changes. Holding a lock on mChanges for the whole duration of the
-        // method will cause a deadlock.
-        List<CompatChange> changes;
+        Long versionCode = getVersionCodeOrNull(packageName);
         synchronized (mChanges) {
-            changes = new ArrayList<>(mChanges.size());
+            boolean shouldInvalidateCache = false;
             for (int idx = 0; idx < mChanges.size(); ++idx) {
-                changes.add(mChanges.valueAt(idx));
+                CompatChange c = mChanges.valueAt(idx);
+                if (!c.hasPackageOverride(packageName)) {
+                    continue;
+                }
+                OverrideAllowedState allowedState =
+                        mOverrideValidator.getOverrideAllowedStateForRecheck(c.getId(),
+                                packageName);
+                shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, versionCode);
+            }
+            if (shouldInvalidateCache) {
+                invalidateCache();
             }
         }
-        boolean shouldInvalidateCache = false;
-        for (CompatChange c: changes) {
-            if (!c.hasPackageOverride(packageName)) {
-                continue;
-            }
-            OverrideAllowedState allowedState =
-                    mOverrideValidator.getOverrideAllowedStateForRecheck(c.getId(), packageName);
-            shouldInvalidateCache |= c.recheckOverride(packageName, allowedState, mContext);
-        }
-        if (shouldInvalidateCache) {
-            invalidateCache();
+    }
+
+    @Nullable
+    private Long getVersionCodeOrNull(String packageName) {
+        try {
+            ApplicationInfo applicationInfo = mContext.getPackageManager().getApplicationInfo(
+                    packageName, 0);
+            return applicationInfo.longVersionCode;
+        } catch (PackageManager.NameNotFoundException e) {
+            return null;
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c947463..14861c2d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -780,7 +780,6 @@
     private static final String COMPANION_PACKAGE_NAME = "com.android.companiondevicemanager";
 
     // Compilation reasons.
-    public static final int REASON_UNKNOWN = -1;
     public static final int REASON_FIRST_BOOT = 0;
     public static final int REASON_BOOT_AFTER_OTA = 1;
     public static final int REASON_POST_BOOT = 2;
@@ -793,7 +792,8 @@
     public static final int REASON_BACKGROUND_DEXOPT = 9;
     public static final int REASON_AB_OTA = 10;
     public static final int REASON_INACTIVE_PACKAGE_DOWNGRADE = 11;
-    public static final int REASON_SHARED = 12;
+    public static final int REASON_CMDLINE = 12;
+    public static final int REASON_SHARED = 13;
 
     public static final int REASON_LAST = REASON_SHARED;
 
@@ -8472,7 +8472,7 @@
                             libInfo.getPackageName(), libInfo.getAllCodePaths(),
                             libInfo.getName(), libInfo.getLongVersion(),
                             libInfo.getType(), libInfo.getDeclaringPackage(),
-                            getPackagesUsingSharedLibraryLPr(libInfo, flags, userId),
+                            getPackagesUsingSharedLibraryLPr(libInfo, flags, callingUid, userId),
                             (libInfo.getDependencies() == null
                                     ? null
                                     : new ArrayList<>(libInfo.getDependencies())),
@@ -8544,9 +8544,11 @@
                             libraryInfo.getPath(), libraryInfo.getPackageName(),
                             libraryInfo.getAllCodePaths(), libraryInfo.getName(),
                             libraryInfo.getLongVersion(), libraryInfo.getType(),
-                            libraryInfo.getDeclaringPackage(), getPackagesUsingSharedLibraryLPr(
-                            libraryInfo, flags, userId), libraryInfo.getDependencies() == null
-                            ? null : new ArrayList<>(libraryInfo.getDependencies()),
+                            libraryInfo.getDeclaringPackage(),
+                            getPackagesUsingSharedLibraryLPr(
+                                    libraryInfo, flags, callingUid, userId),
+                            libraryInfo.getDependencies() == null
+                                    ? null : new ArrayList<>(libraryInfo.getDependencies()),
                             libraryInfo.isNative());
 
                     if (result == null) {
@@ -8562,7 +8564,7 @@
 
     @GuardedBy("mLock")
     private List<VersionedPackage> getPackagesUsingSharedLibraryLPr(
-            SharedLibraryInfo libInfo, int flags, int userId) {
+            SharedLibraryInfo libInfo, int flags, int callingUid, int userId) {
         List<VersionedPackage> versionedPackages = null;
         final int packageCount = mSettings.getPackagesLocked().size();
         for (int i = 0; i < packageCount; i++) {
@@ -8585,6 +8587,9 @@
                 if (ps.usesStaticLibrariesVersions[libIdx] != libInfo.getLongVersion()) {
                     continue;
                 }
+                if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
+                    continue;
+                }
                 if (versionedPackages == null) {
                     versionedPackages = new ArrayList<>();
                 }
@@ -8597,6 +8602,9 @@
             } else if (ps.pkg != null) {
                 if (ArrayUtils.contains(ps.pkg.getUsesLibraries(), libName)
                         || ArrayUtils.contains(ps.pkg.getUsesOptionalLibraries(), libName)) {
+                    if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
+                        continue;
+                    }
                     if (versionedPackages == null) {
                         versionedPackages = new ArrayList<>();
                     }
@@ -11942,7 +11950,7 @@
         int flags = (checkProfiles ? DexoptOptions.DEXOPT_CHECK_FOR_PROFILES_UPDATES : 0) |
                 (force ? DexoptOptions.DEXOPT_FORCE : 0) |
                 (bootComplete ? DexoptOptions.DEXOPT_BOOT_COMPLETE : 0);
-        return performDexOpt(new DexoptOptions(packageName, REASON_UNKNOWN,
+        return performDexOpt(new DexoptOptions(packageName, REASON_CMDLINE,
                 targetCompilerFilter, splitName, flags));
     }
 
@@ -14321,7 +14329,7 @@
         // Remove the shared library overlays from its dependent packages.
         for (int currentUserId : UserManagerService.getInstance().getUserIds()) {
             final List<VersionedPackage> dependents = getPackagesUsingSharedLibraryLPr(
-                    libraryInfo, 0, currentUserId);
+                    libraryInfo, 0, Process.SYSTEM_UID, currentUserId);
             if (dependents == null) {
                 continue;
             }
@@ -20684,7 +20692,7 @@
                             continue;
                         }
                         List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
-                                libraryInfo, MATCH_KNOWN_PACKAGES, currUserId);
+                                libraryInfo, MATCH_KNOWN_PACKAGES, Process.SYSTEM_UID, currUserId);
                         if (!ArrayUtils.isEmpty(libClientPackages)) {
                             Slog.w(TAG, "Not removing package " + pkg.getManifestPackageName()
                                     + " hosting lib " + libraryInfo.getName() + " version "
@@ -26795,7 +26803,7 @@
                             continue;
                         }
                         final List<VersionedPackage> dependents = getPackagesUsingSharedLibraryLPr(
-                                info, 0, userId);
+                                info, 0, Process.SYSTEM_UID, userId);
                         if (dependents == null) {
                             continue;
                         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
index 636db11..7c1f054 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -40,6 +40,7 @@
         "bg-dexopt",
         "ab-ota",
         "inactive",
+        "cmdline",
         // "shared" must be the last entry
         "shared"
     };
@@ -141,9 +142,6 @@
     }
 
     public static String getReasonName(int reason) {
-        if (reason == PackageManagerService.REASON_UNKNOWN) {
-            return "unknown";
-        }
         if (reason < 0 || reason >= REASON_STRINGS.length) {
             throw new IllegalArgumentException("reason " + reason + " invalid");
         }
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 3576950..1859b4c 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -607,6 +607,7 @@
             TRON_COMPILATION_REASON_INSTALL_BULK_SECONDARY_DOWNGRADED_WITH_DM = 19;
     private static final int TRON_COMPILATION_REASON_BOOT_AFTER_OTA = 20;
     private static final int TRON_COMPILATION_REASON_POST_BOOT = 21;
+    private static final int TRON_COMPILATION_REASON_CMDLINE = 22;
 
     // The annotation to add as a suffix to the compilation reason when dexopt was
     // performed with dex metadata.
@@ -617,7 +618,7 @@
      */
     private static int getCompilationReasonTronValue(String compilationReason) {
         switch (compilationReason) {
-            case "unknown" : return TRON_COMPILATION_REASON_UNKNOWN;
+            case "cmdline" : return TRON_COMPILATION_REASON_CMDLINE;
             case "error" : return TRON_COMPILATION_REASON_ERROR;
             case "first-boot" : return TRON_COMPILATION_REASON_FIRST_BOOT;
             case "boot-after-ota": return TRON_COMPILATION_REASON_BOOT_AFTER_OTA;
diff --git a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
index 091d820..946f8d5 100644
--- a/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
+++ b/services/core/java/com/android/server/pm/dex/ArtStatsLogUtils.java
@@ -58,8 +58,6 @@
     private static final Map<Integer, Integer> COMPILATION_REASON_MAP = new HashMap();
 
     static {
-        COMPILATION_REASON_MAP.put(PackageManagerService.REASON_UNKNOWN, ArtStatsLog.
-                ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_UNKNOWN);
         COMPILATION_REASON_MAP.put(PackageManagerService.REASON_FIRST_BOOT, ArtStatsLog.
                 ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_FIRST_BOOT);
         COMPILATION_REASON_MAP.put(PackageManagerService.REASON_BOOT_AFTER_OTA, ArtStatsLog.
@@ -85,6 +83,8 @@
         COMPILATION_REASON_MAP.put(PackageManagerService.REASON_INACTIVE_PACKAGE_DOWNGRADE,
                 ArtStatsLog.
                         ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_INACTIVE);
+        COMPILATION_REASON_MAP.put(PackageManagerService.REASON_CMDLINE,
+                ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_CMDLINE);
         COMPILATION_REASON_MAP.put(PackageManagerService.REASON_SHARED,
                 ArtStatsLog.ART_DATUM_REPORTED__COMPILATION_REASON__ART_COMPILATION_REASON_SHARED);
     }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 065dc6e..38966b9 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
@@ -90,7 +89,6 @@
 import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE;
 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.content.res.Configuration.ASSETS_SEQ_UNDEFINED;
 import static android.content.res.Configuration.EMPTY;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
@@ -279,7 +277,6 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
-import android.permission.PermissionManager;
 import android.service.dreams.DreamActivity;
 import android.service.dreams.DreamManagerInternal;
 import android.service.voice.IVoiceInteractionSession;
@@ -7457,11 +7454,9 @@
 
     @Override
     public boolean providesMaxBounds() {
-        // System and SystemUI should always be able to access the physical display bounds,
-        // so do not provide it with the overridden maximum bounds.
-        // TODO(b/179179513) check WindowState#mOwnerCanAddInternalSystemWindow instead
-        if (getUid() == SYSTEM_UID || PermissionManager.checkPermission(INTERNAL_SYSTEM_WINDOW,
-                getPid(), info.applicationInfo.uid) == PERMISSION_GRANTED) {
+        // System should always be able to access the DisplayArea bounds, so do not provide it with
+        // compat max window bounds.
+        if (getUid() == SYSTEM_UID) {
             return false;
         }
         // Do not sandbox to activity window bounds if the feature is disabled.
diff --git a/services/core/java/com/android/server/wm/BlurController.java b/services/core/java/com/android/server/wm/BlurController.java
index ff10168..0363944 100644
--- a/services/core/java/com/android/server/wm/BlurController.java
+++ b/services/core/java/com/android/server/wm/BlurController.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.view.ICrossWindowBlurEnabledListener;
+import android.view.TunnelModeEnabledListener;
 
 /**
  * Keeps track of the different factors that determine whether cross-window blur is enabled
@@ -45,6 +46,16 @@
     private volatile boolean mBlurEnabled;
     private boolean mInPowerSaveMode;
     private boolean mBlurDisabledSetting;
+    private boolean mTunnelModeEnabled = false;
+
+    private TunnelModeEnabledListener mTunnelModeListener =
+            new TunnelModeEnabledListener(Runnable::run) {
+        @Override
+        public void onTunnelModeEnabledChanged(boolean tunnelModeEnabled) {
+            mTunnelModeEnabled = tunnelModeEnabled;
+            updateBlurEnabled();
+        }
+    };
 
     BlurController(Context context, PowerManager powerManager) {
         mContext = context;
@@ -78,6 +89,8 @@
                 });
         mBlurDisabledSetting = getBlurDisabledSetting();
 
+        TunnelModeEnabledListener.register(mTunnelModeListener);
+
         updateBlurEnabled();
     }
 
@@ -99,7 +112,7 @@
     private void updateBlurEnabled() {
         synchronized (mLock) {
             final boolean newEnabled = CROSS_WINDOW_BLUR_SUPPORTED && !mBlurDisabledSetting
-                    && !mInPowerSaveMode;
+                    && !mInPowerSaveMode && !mTunnelModeEnabled;
             if (mBlurEnabled == newEnabled) {
                 return;
             }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0251537..7df5744 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8105,11 +8105,10 @@
             // This could prevent if there is no container animation, we still have to apply the
             // pending transaction and exit waiting.
             mAnimator.mNotifyWhenNoAnimation = true;
-            WindowContainer animatingContainer = null;
-            while (mAnimator.isAnimationScheduled() || timeoutRemaining > 0) {
-                animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
-                        ANIMATION_TYPE_ALL);
-                if (animatingContainer == null) {
+            while (timeoutRemaining > 0) {
+                boolean isAnimating = mAnimator.isAnimationScheduled()
+                        || mRoot.isAnimating(TRANSITION | CHILDREN, ANIMATION_TYPE_ALL);
+                if (!isAnimating) {
                     break;
                 }
                 long startTime = System.currentTimeMillis();
@@ -8121,6 +8120,9 @@
             }
             mAnimator.mNotifyWhenNoAnimation = false;
 
+            WindowContainer animatingContainer;
+            animatingContainer = mRoot.getAnimatingContainer(TRANSITION | CHILDREN,
+                    ANIMATION_TYPE_ALL);
             if (mAnimator.isAnimationScheduled() || animatingContainer != null) {
                 Slog.w(TAG, "Timed out waiting for animations to complete,"
                         + " animatingContainer=" + animatingContainer
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 8d43bbb..ce8f6df 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -1190,7 +1190,7 @@
             pw.println(mEnrollmentSpecificId);
         }
 
-        pw.print("mAdminCanGrantSensorsPermissions");
+        pw.print("mAdminCanGrantSensorsPermissions=");
         pw.println(mAdminCanGrantSensorsPermissions);
 
         pw.print("mUsbDataSignaling=");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 891ed3d..bc130e2 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8579,6 +8579,7 @@
         final DevicePolicyData policyData = getUserData(userId);
         policyData.mCurrentInputMethodSet = false;
         saveSettingsLocked(userId);
+        mPolicyCache.onUserRemoved(userId);
         final DevicePolicyData systemPolicyData = getUserData(UserHandle.USER_SYSTEM);
         systemPolicyData.mLastSecurityLogRetrievalTime = -1;
         systemPolicyData.mLastBugReportRequestTime = -1;
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ad89e96..d487483 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -103,7 +103,6 @@
 import com.android.internal.widget.ILockSettings;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.appbinding.AppBindingService;
-import com.android.server.art.ArtManagerLocal;
 import com.android.server.attention.AttentionManagerService;
 import com.android.server.audio.AudioService;
 import com.android.server.biometrics.AuthService;
@@ -2632,10 +2631,6 @@
         mSystemServiceManager.startService(GAME_MANAGER_SERVICE_CLASS);
         t.traceEnd();
 
-        t.traceBegin("ArtManagerLocal");
-        LocalManagerRegistry.addManager(ArtManagerLocal.class, new ArtManagerLocal());
-        t.traceEnd();
-
         if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB)) {
             t.traceBegin("UwbService");
             mSystemServiceManager.startService(UWB_SERVICE_CLASS);
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 47505a3..e31be82 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -43,6 +43,7 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.util.EventLog;
 import android.util.Log;
 
 import com.android.internal.content.PackageMonitor;
@@ -736,13 +737,19 @@
 
     @Override
     public MidiDeviceInfo getServiceDeviceInfo(String packageName, String className) {
+        int uid = Binder.getCallingUid();
         synchronized (mDevicesByInfo) {
             for (Device device : mDevicesByInfo.values()) {
                  ServiceInfo serviceInfo = device.getServiceInfo();
                  if (serviceInfo != null &&
                         packageName.equals(serviceInfo.packageName) &&
                         className.equals(serviceInfo.name)) {
-                    return device.getDeviceInfo();
+                    if (device.isUidAllowed(uid)) {
+                        return device.getDeviceInfo();
+                    } else {
+                        EventLog.writeEvent(0x534e4554, "185796676", -1, "");
+                        return null;
+                    }
                 }
             }
             return null;
diff --git a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
index c631026..49d5e50 100644
--- a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
+++ b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
@@ -20,26 +20,18 @@
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
 import android.app.people.ConversationStatus;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
+import android.os.Binder;
 import android.os.CancellationSignal;
-import android.os.SystemClock;
 
 import com.android.server.LocalServices;
-import com.android.server.notification.NotificationRecord;
 import com.android.server.people.PeopleServiceInternal;
 
-import java.util.concurrent.TimeUnit;
-
 /**
  * If a {@link ConversationStatus} is added to the system with an expiration time, remove that
  * status at that time
@@ -53,18 +45,22 @@
 
     void scheduleExpiration(Context context, @UserIdInt int userId, String pkg,
             String conversationId, ConversationStatus status) {
-
-        final PendingIntent pi = PendingIntent.getBroadcast(context,
-                REQUEST_CODE,
-                new Intent(ACTION)
-                        .setData(new Uri.Builder().scheme(SCHEME)
-                                .appendPath(getKey(userId, pkg, conversationId, status))
-                                .build())
-                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
-                        .putExtra(EXTRA_USER_ID, userId),
-                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
-        context.getSystemService(AlarmManager.class).setExactAndAllowWhileIdle(
-                AlarmManager.RTC_WAKEUP, status.getEndTimeMillis(), pi);
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final PendingIntent pi = PendingIntent.getBroadcast(context,
+                    REQUEST_CODE,
+                    new Intent(ACTION)
+                            .setData(new Uri.Builder().scheme(SCHEME)
+                                    .appendPath(getKey(userId, pkg, conversationId, status))
+                                    .build())
+                            .addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+                            .putExtra(EXTRA_USER_ID, userId),
+                    PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
+            context.getSystemService(AlarmManager.class).setExactAndAllowWhileIdle(
+                    AlarmManager.RTC_WAKEUP, status.getEndTimeMillis(), pi);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
     }
 
     private static String getKey(@UserIdInt int userId, String pkg,
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index 9be1ac4..2206b0a 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -22,6 +22,7 @@
 import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
 
+import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -36,7 +37,6 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
@@ -414,11 +414,31 @@
             Slog.w(TAG, "Hotword detection service name not found");
             throw new IllegalStateException("Hotword detection service name not found");
         }
-        if (!isIsolatedProcessLocked(mHotwordDetectionComponentName)) {
+        ServiceInfo hotwordDetectionServiceInfo = getServiceInfoLocked(
+                mHotwordDetectionComponentName, mUser);
+        if (hotwordDetectionServiceInfo == null) {
+            Slog.w(TAG, "Hotword detection service info not found");
+            throw new IllegalStateException("Hotword detection service info not found");
+        }
+        if (!isIsolatedProcessLocked(hotwordDetectionServiceInfo)) {
             Slog.w(TAG, "Hotword detection service not in isolated process");
             throw new IllegalStateException("Hotword detection service not in isolated process");
         }
-        // TODO : Need to check related permissions for hotword detection service
+        if (!Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE.equals(
+                hotwordDetectionServiceInfo.permission)) {
+            Slog.w(TAG, "Hotword detection service does not require permission "
+                    + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+            throw new SecurityException("Hotword detection service does not require permission "
+                    + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+        }
+        if (mContext.getPackageManager().checkPermission(
+                Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE,
+                mInfo.getServiceInfo().packageName) == PackageManager.PERMISSION_GRANTED) {
+            Slog.w(TAG, "Voice interaction service should not hold permission "
+                    + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+            throw new SecurityException("Voice interaction service should not hold permission "
+                    + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE);
+        }
 
         if (sharedMemory != null && !sharedMemory.setProtect(OsConstants.PROT_READ)) {
             Slog.w(TAG, "Can't set sharedMemory to be read-only");
@@ -522,23 +542,24 @@
                 mHotwordDetectionConnection);
     }
 
-    boolean isIsolatedProcessLocked(ComponentName componentName) {
-        IPackageManager pm = AppGlobals.getPackageManager();
+    private static ServiceInfo getServiceInfoLocked(@NonNull ComponentName componentName,
+            int userHandle) {
         try {
-            ServiceInfo serviceInfo = pm.getServiceInfo(componentName,
+            return AppGlobals.getPackageManager().getServiceInfo(componentName,
                     PackageManager.GET_META_DATA
                             | PackageManager.MATCH_DIRECT_BOOT_AWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, mUser);
-            if (serviceInfo != null) {
-                return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
-                        && (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
-            }
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userHandle);
         } catch (RemoteException e) {
             if (DEBUG) {
-                Slog.w(TAG, "isIsolatedProcess RemoteException : " + e);
+                Slog.w(TAG, "getServiceInfoLocked RemoteException : " + e);
             }
         }
-        return false;
+        return null;
+    }
+
+    boolean isIsolatedProcessLocked(@NonNull ServiceInfo serviceInfo) {
+        return (serviceInfo.flags & ServiceInfo.FLAG_ISOLATED_PROCESS) != 0
+                && (serviceInfo.flags & ServiceInfo.FLAG_EXTERNAL_SERVICE) == 0;
     }
 
     public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/telecomm/java/android/telecom/CallDiagnosticService.java b/telecomm/java/android/telecom/CallDiagnosticService.java
index 011dc17..336a8ea 100644
--- a/telecomm/java/android/telecom/CallDiagnosticService.java
+++ b/telecomm/java/android/telecom/CallDiagnosticService.java
@@ -294,6 +294,10 @@
         CallDiagnostics callDiagnostics;
         synchronized (mLock) {
             callDiagnostics = mDiagnosticCallByTelecomCallId.get(telecomCallId);
+            if (callDiagnostics == null) {
+                // Possible to get a call update after a call is removed.
+                return;
+            }
             mCallByTelecomCallId.put(telecomCallId, newCallDetails);
         }
         getExecutor().execute(() -> callDiagnostics.handleCallUpdated(newCallDetails));
@@ -306,12 +310,12 @@
     private void handleCallRemoved(@NonNull String telecomCallId) {
         Log.i(this, "handleCallRemoved: callId=%s - removed", telecomCallId);
 
-        if (mCallByTelecomCallId.containsKey(telecomCallId)) {
-            mCallByTelecomCallId.remove(telecomCallId);
-        }
-
         CallDiagnostics callDiagnostics;
         synchronized (mLock) {
+            if (mCallByTelecomCallId.containsKey(telecomCallId)) {
+                mCallByTelecomCallId.remove(telecomCallId);
+            }
+
             if (mDiagnosticCallByTelecomCallId.containsKey(telecomCallId)) {
                 callDiagnostics = mDiagnosticCallByTelecomCallId.remove(telecomCallId);
             } else {
@@ -353,7 +357,10 @@
     private void handleCallDisconnected(@NonNull String callId,
             @NonNull DisconnectCause disconnectCause) {
         Log.i(this, "handleCallDisconnected: call=%s; cause=%s", callId, disconnectCause);
-        CallDiagnostics callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+        CallDiagnostics callDiagnostics;
+        synchronized (mLock) {
+            callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+        }
         CharSequence message;
         if (disconnectCause.getImsReasonInfo() != null) {
             message = callDiagnostics.onCallDisconnected(disconnectCause.getImsReasonInfo());
@@ -391,7 +398,9 @@
             @NonNull CallQuality callQuality) {
         Log.i(this, "handleCallQualityChanged; call=%s, cq=%s", callId, callQuality);
         CallDiagnostics callDiagnostics;
-        callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+        synchronized(mLock) {
+            callDiagnostics = mDiagnosticCallByTelecomCallId.get(callId);
+        }
         if (callDiagnostics != null) {
             callDiagnostics.onCallQualityReceived(callQuality);
         }