Merge "Temporarily disable some Bubbles checks"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index f66d12a..cdf5df6c 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -9,6 +9,7 @@
                cmds/uinput/
                core/jni/
                libs/input/
+               native/
                services/core/jni/
                services/incremental/
                tests/
diff --git a/api/current.txt b/api/current.txt
index d8d4adc..f4349d9 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11718,7 +11718,10 @@
     method public android.graphics.drawable.Drawable getIcon(int);
     method public CharSequence getLabel();
     method public String getName();
+    method public float getProgress();
     method public android.os.UserHandle getUser();
+    method public boolean isLoading();
+    method public boolean isStartable();
   }
 
   public class LauncherApps {
@@ -11758,6 +11761,7 @@
     ctor public LauncherApps.Callback();
     method public abstract void onPackageAdded(String, android.os.UserHandle);
     method public abstract void onPackageChanged(String, android.os.UserHandle);
+    method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
     method public abstract void onPackageRemoved(String, android.os.UserHandle);
     method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
     method public void onPackagesSuspended(String[], android.os.UserHandle);
@@ -15453,6 +15457,7 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
+    ctor public RadialGradient(float, float, @FloatRange(from=0.0f) float, float, float, @FloatRange(from=0.0f, fromInclusive=false) float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode);
   }
@@ -57413,6 +57418,7 @@
     method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
     method public android.os.Handler getHandler();
     method public CharSequence getSelectedText(int);
+    method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
     method public CharSequence getTextAfterCursor(int, int);
     method public CharSequence getTextBeforeCursor(int, int);
     method public boolean performContextMenuAction(int);
@@ -57621,6 +57627,17 @@
     method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeNameResId(int);
   }
 
+  public final class SurroundingText implements android.os.Parcelable {
+    ctor public SurroundingText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0xffffffff) int);
+    method public int describeContents();
+    method @IntRange(from=0xffffffff) public int getOffset();
+    method @IntRange(from=0) public int getSelectionEnd();
+    method @IntRange(from=0) public int getSelectionStart();
+    method @NonNull public CharSequence getText();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.SurroundingText> CREATOR;
+  }
+
 }
 
 package android.view.inspector {
diff --git a/api/system-current.txt b/api/system-current.txt
index 3207165..230ced8 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -310,6 +310,7 @@
     field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
     field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
     field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
+    field public static final int config_systemAutomotiveProjection = 17039402; // 0x104002a
     field public static final int config_systemGallery = 17039399; // 0x1040027
     field public static final int config_systemVideoCall = 17039401; // 0x1040029
   }
diff --git a/api/test-current.txt b/api/test-current.txt
index 8bf8c64..c92fb6c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -46,6 +46,7 @@
     field public static final int config_defaultAssistant = 17039393; // 0x1040021
     field public static final int config_defaultDialer = 17039395; // 0x1040023
     field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
+    field public static final int config_systemAutomotiveProjection = 17039402; // 0x104002a
     field public static final int config_systemGallery = 17039399; // 0x1040027
     field public static final int config_systemVideoCall = 17039401; // 0x1040029
   }
@@ -2372,7 +2373,7 @@
 
   public class TaskOrganizer extends android.window.WindowOrganizer {
     ctor public TaskOrganizer();
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.TaskAppearedInfo createRootTask(int, int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.app.ActivityManager.RunningTaskInfo createRootTask(int, int);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public boolean deleteRootTask(@NonNull android.window.WindowContainerToken);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public android.window.WindowContainerToken getImeTarget(int);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 3d67e65..c9356c5 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3361,6 +3361,7 @@
     optional int32 color_preference = 9;
     optional android.stats.style.LocationPreference location_preference = 10;
     optional android.stats.style.DatePreference date_preference = 11;
+    optional android.stats.style.LaunchedPreference launched_preference = 12;
 }
 
 /**
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index cfc6e3f..b6e5d88 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -546,7 +546,21 @@
             return false;
         }
     }
-
+    for (int i = 0; i < config.value_metric_size(); i++, metricIndex++) {
+        const ValueMetric& metric = config.value_metric(i);
+        set<int64_t> conditionDependencies;
+        if (metric.has_condition()) {
+            conditionDependencies.insert(metric.condition());
+        }
+        if (!determineMetricUpdateStatus(
+                    config, metric, metric.id(), METRIC_TYPE_VALUE, {metric.what()},
+                    conditionDependencies, metric.slice_by_state(), metric.links(),
+                    oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+                    replacedMatchers, replacedConditions, replacedStates,
+                    metricsToUpdate[metricIndex])) {
+            return false;
+        }
+    }
     for (int i = 0; i < config.gauge_metric_size(); i++, metricIndex++) {
         const GaugeMetric& metric = config.gauge_metric(i);
         set<int64_t> conditionDependencies;
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index dc951be..0066030 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -170,6 +170,23 @@
     }
     return metric;
 }
+
+ValueMetric createValueMetric(string name, const AtomMatcher& what, optional<int64_t> condition,
+                              vector<int64_t> states) {
+    ValueMetric metric;
+    metric.set_id(StringToId(name));
+    metric.set_what(what.id());
+    metric.set_bucket(TEN_MINUTES);
+    metric.mutable_value_field()->set_field(what.simple_atom_matcher().atom_id());
+    metric.mutable_value_field()->add_child()->set_field(2);
+    if (condition) {
+        metric.set_condition(condition.value());
+    }
+    for (const int64_t state : states) {
+        metric.add_slice_by_state(state);
+    }
+    return metric;
+}
 }  // anonymous namespace
 
 TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
@@ -1537,6 +1554,115 @@
     EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
 }
 
+TEST_F(ConfigUpdateTest, TestValueMetricPreserve) {
+    StatsdConfig config;
+    AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+    *config.add_atom_matcher() = startMatcher;
+    AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+    *config.add_atom_matcher() = stopMatcher;
+    AtomMatcher whatMatcher = CreateTemperatureAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    Predicate predicate = CreateScreenIsOnPredicate();
+    *config.add_predicate() = predicate;
+    State sliceState = CreateScreenState();
+    *config.add_state() = sliceState;
+
+    *config.add_value_metric() =
+            createValueMetric("VALUE1", whatMatcher, predicate.id(), {sliceState.id()});
+    EXPECT_TRUE(initConfig(config));
+
+    unordered_map<int64_t, int> metricToActivationMap;
+    vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+    EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+                                                 metricToActivationMap,
+                                                 /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+                                                 /*replacedStates=*/{}, metricsToUpdate));
+    EXPECT_EQ(metricsToUpdate[0], UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestValueMetricDefinitionChange) {
+    StatsdConfig config;
+    AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    *config.add_value_metric() = createValueMetric("VALUE1", whatMatcher, nullopt, {});
+    EXPECT_TRUE(initConfig(config));
+
+    // Change skip zero diff output, which should change the proto, causing replacement.
+    config.mutable_value_metric(0)->set_skip_zero_diff_output(true);
+
+    unordered_map<int64_t, int> metricToActivationMap;
+    vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+    EXPECT_TRUE(determineAllMetricUpdateStatuses(config, oldMetricProducerMap, oldMetricProducers,
+                                                 metricToActivationMap,
+                                                 /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+                                                 /*replacedStates=*/{}, metricsToUpdate));
+    EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestValueMetricWhatChanged) {
+    StatsdConfig config;
+    AtomMatcher whatMatcher = CreateTemperatureAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    *config.add_value_metric() = createValueMetric("VALUE1", whatMatcher, nullopt, {});
+    EXPECT_TRUE(initConfig(config));
+
+    unordered_map<int64_t, int> metricToActivationMap;
+    vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+    EXPECT_TRUE(determineAllMetricUpdateStatuses(
+            config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+            /*replacedMatchers*/ {whatMatcher.id()}, /*replacedConditions=*/{},
+            /*replacedStates=*/{}, metricsToUpdate));
+    EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestValueMetricConditionChanged) {
+    StatsdConfig config;
+    AtomMatcher startMatcher = CreateScreenTurnedOnAtomMatcher();
+    *config.add_atom_matcher() = startMatcher;
+    AtomMatcher stopMatcher = CreateScreenTurnedOffAtomMatcher();
+    *config.add_atom_matcher() = stopMatcher;
+    AtomMatcher whatMatcher = CreateTemperatureAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    Predicate predicate = CreateScreenIsOnPredicate();
+    *config.add_predicate() = predicate;
+
+    *config.add_value_metric() = createValueMetric("VALUE1", whatMatcher, predicate.id(), {});
+    EXPECT_TRUE(initConfig(config));
+
+    unordered_map<int64_t, int> metricToActivationMap;
+    vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+    EXPECT_TRUE(determineAllMetricUpdateStatuses(
+            config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+            /*replacedMatchers*/ {}, /*replacedConditions=*/{predicate.id()},
+            /*replacedStates=*/{}, metricsToUpdate));
+    EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestValueMetricStateChanged) {
+    StatsdConfig config;
+    AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+    *config.add_atom_matcher() = whatMatcher;
+
+    State sliceState = CreateScreenState();
+    *config.add_state() = sliceState;
+
+    *config.add_value_metric() =
+            createValueMetric("VALUE1", whatMatcher, nullopt, {sliceState.id()});
+    EXPECT_TRUE(initConfig(config));
+
+    unordered_map<int64_t, int> metricToActivationMap;
+    vector<UpdateStatus> metricsToUpdate(1, UPDATE_UNKNOWN);
+    EXPECT_TRUE(determineAllMetricUpdateStatuses(
+            config, oldMetricProducerMap, oldMetricProducers, metricToActivationMap,
+            /*replacedMatchers*/ {}, /*replacedConditions=*/{},
+            /*replacedStates=*/{sliceState.id()}, metricsToUpdate));
+    EXPECT_EQ(metricsToUpdate[0], UPDATE_REPLACE);
+}
+
 TEST_F(ConfigUpdateTest, TestUpdateEventMetrics) {
     StatsdConfig config;
 
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index a970322..66a7f4d 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -98,7 +98,7 @@
     void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
     NotificationChannel getNotificationChannel(String callingPkg, int userId, String pkg, String channelId);
     NotificationChannel getConversationNotificationChannel(String callingPkg, int userId, String pkg, String channelId, boolean returnParentIfNoConversationChannel, String conversationId);
-    void createConversationNotificationChannelForPackage(String pkg, int uid, String triggeringKey, in NotificationChannel parentChannel, String conversationId);
+    void createConversationNotificationChannelForPackage(String pkg, int uid, in NotificationChannel parentChannel, String conversationId);
     NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId, String conversationId, boolean includeDeleted);
     void deleteNotificationChannel(String pkg, String channelId);
     void deleteConversationNotificationChannels(String pkg, int uid, String conversationId);
diff --git a/core/java/android/app/people/ConversationChannel.java b/core/java/android/app/people/ConversationChannel.java
index 39c5c85..a648b3b 100644
--- a/core/java/android/app/people/ConversationChannel.java
+++ b/core/java/android/app/people/ConversationChannel.java
@@ -17,6 +17,7 @@
 package android.app.people;
 
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 import android.content.pm.ShortcutInfo;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -30,7 +31,9 @@
 public final class ConversationChannel implements Parcelable {
 
     private ShortcutInfo mShortcutInfo;
+    private int mUid;
     private NotificationChannel mParentNotificationChannel;
+    private NotificationChannelGroup mParentNotificationChannelGroup;
     private long mLastEventTimestamp;
     private boolean mHasActiveNotifications;
 
@@ -46,18 +49,24 @@
         }
     };
 
-    public ConversationChannel(ShortcutInfo shortcutInfo,
-            NotificationChannel parentNotificationChannel, long lastEventTimestamp,
+    public ConversationChannel(ShortcutInfo shortcutInfo, int uid,
+            NotificationChannel parentNotificationChannel,
+            NotificationChannelGroup parentNotificationChannelGroup, long lastEventTimestamp,
             boolean hasActiveNotifications) {
         mShortcutInfo = shortcutInfo;
+        mUid = uid;
         mParentNotificationChannel = parentNotificationChannel;
+        mParentNotificationChannelGroup = parentNotificationChannelGroup;
         mLastEventTimestamp = lastEventTimestamp;
         mHasActiveNotifications = hasActiveNotifications;
     }
 
     public ConversationChannel(Parcel in) {
         mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
+        mUid = in.readInt();
         mParentNotificationChannel = in.readParcelable(NotificationChannel.class.getClassLoader());
+        mParentNotificationChannelGroup =
+                in.readParcelable(NotificationChannelGroup.class.getClassLoader());
         mLastEventTimestamp = in.readLong();
         mHasActiveNotifications = in.readBoolean();
     }
@@ -70,7 +79,9 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeParcelable(mShortcutInfo, flags);
+        dest.writeInt(mUid);
         dest.writeParcelable(mParentNotificationChannel, flags);
+        dest.writeParcelable(mParentNotificationChannelGroup, flags);
         dest.writeLong(mLastEventTimestamp);
         dest.writeBoolean(mHasActiveNotifications);
     }
@@ -79,10 +90,18 @@
         return mShortcutInfo;
     }
 
+    public int getUid() {
+        return mUid;
+    }
+
     public NotificationChannel getParentNotificationChannel() {
         return mParentNotificationChannel;
     }
 
+    public NotificationChannelGroup getParentNotificationChannelGroup() {
+        return mParentNotificationChannelGroup;
+    }
+
     public long getLastEventTimestamp() {
         return mLastEventTimestamp;
     }
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 389458b..d9ecf46 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -21,9 +21,9 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.LocusId;
-import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.LauncherActivityInfoInternal;
 import android.content.pm.LauncherApps;
 import android.content.pm.ShortcutQueryWrapper;
 import android.content.pm.IPackageInstallerCallback;
@@ -47,7 +47,7 @@
     void removeOnAppsChangedListener(in IOnAppsChangedListener listener);
     ParceledListSlice getLauncherActivities(
             String callingPackage, String packageName, in UserHandle user);
-    ActivityInfo resolveActivity(
+    LauncherActivityInfoInternal resolveLauncherActivityInternal(
             String callingPackage, in ComponentName component, in UserHandle user);
     void startSessionDetailsActivityAsUser(in IApplicationThread caller, String callingPackage,
                 String callingFeatureId, in PackageInstaller.SessionInfo sessionInfo,
diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl
index fcb1de0..f24ed80 100644
--- a/core/java/android/content/pm/IOnAppsChangedListener.aidl
+++ b/core/java/android/content/pm/IOnAppsChangedListener.aidl
@@ -33,4 +33,5 @@
             in Bundle launcherExtras);
     void onPackagesUnsuspended(in UserHandle user, in String[] packageNames);
     void onShortcutChanged(in UserHandle user, String packageName, in ParceledListSlice shortcuts);
+    void onPackageProgressChanged(in UserHandle user, String packageName, float progress);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 30f3325..c32d344 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -31,7 +31,6 @@
 import android.content.pm.IPackageDeleteObserver;
 import android.content.pm.IPackageDeleteObserver2;
 import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageLoadingProgressCallback;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.IntentFilterVerificationInfo;
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 67deb82..ead80d0 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -16,7 +16,6 @@
 
 package android.content.pm;
 
-import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
@@ -35,28 +34,19 @@
     private static final String TAG = "LauncherActivityInfo";
 
     private final PackageManager mPm;
-
-    @UnsupportedAppUsage
-    private ActivityInfo mActivityInfo;
-    private ComponentName mComponentName;
     private UserHandle mUser;
+    private final LauncherActivityInfoInternal mInternal;
 
     /**
      * Create a launchable activity object for a given ResolveInfo and user.
      *
      * @param context The context for fetching resources.
-     * @param info ResolveInfo from which to create the LauncherActivityInfo.
-     * @param user The UserHandle of the profile to which this activity belongs.
-     */
-    LauncherActivityInfo(Context context, ActivityInfo info, UserHandle user) {
-        this(context);
-        mActivityInfo = info;
-        mComponentName =  new ComponentName(info.packageName, info.name);
-        mUser = user;
-    }
 
-    LauncherActivityInfo(Context context) {
+     */
+    LauncherActivityInfo(Context context, UserHandle user, LauncherActivityInfoInternal internal) {
         mPm = context.getPackageManager();
+        mUser = user;
+        mInternal = internal;
     }
 
     /**
@@ -65,7 +55,7 @@
      * @return ComponentName of the activity
      */
     public ComponentName getComponentName() {
-        return mComponentName;
+        return mInternal.getComponentName();
     }
 
     /**
@@ -90,7 +80,28 @@
      */
     public CharSequence getLabel() {
         // TODO: Go through LauncherAppsService
-        return mActivityInfo.loadLabel(mPm);
+        return mInternal.getActivityInfo().loadLabel(mPm);
+    }
+
+    /**
+     * @return whether the package is startable.
+     */
+    public boolean isStartable() {
+        return mInternal.getIncrementalStatesInfo().isStartable();
+    }
+
+    /**
+     * @return whether the package is still loading.
+     */
+    public boolean isLoading() {
+        return mInternal.getIncrementalStatesInfo().isLoading();
+    }
+
+    /**
+     * @return Package loading progress
+     */
+    public float getProgress() {
+        return mInternal.getIncrementalStatesInfo().getProgress();
     }
 
     /**
@@ -103,20 +114,20 @@
      */
     public Drawable getIcon(int density) {
         // TODO: Go through LauncherAppsService
-        final int iconRes = mActivityInfo.getIconResource();
+        final int iconRes = mInternal.getActivityInfo().getIconResource();
         Drawable icon = null;
         // Get the preferred density icon from the app's resources
         if (density != 0 && iconRes != 0) {
             try {
-                final Resources resources
-                        = mPm.getResourcesForApplication(mActivityInfo.applicationInfo);
+                final Resources resources = mPm.getResourcesForApplication(
+                        mInternal.getActivityInfo().applicationInfo);
                 icon = resources.getDrawableForDensity(iconRes, density);
             } catch (NameNotFoundException | Resources.NotFoundException exc) {
             }
         }
         // Get the default density icon
         if (icon == null) {
-            icon = mActivityInfo.loadIcon(mPm);
+            icon = mInternal.getActivityInfo().loadIcon(mPm);
         }
         return icon;
     }
@@ -128,7 +139,7 @@
      * @hide remove before shipping
      */
     public int getApplicationFlags() {
-        return mActivityInfo.applicationInfo.flags;
+        return mInternal.getActivityInfo().flags;
     }
 
     /**
@@ -136,7 +147,7 @@
      * @return
      */
     public ApplicationInfo getApplicationInfo() {
-        return mActivityInfo.applicationInfo;
+        return mInternal.getActivityInfo().applicationInfo;
     }
 
     /**
@@ -147,7 +158,7 @@
     public long getFirstInstallTime() {
         try {
             // TODO: Go through LauncherAppsService
-            return mPm.getPackageInfo(mActivityInfo.packageName,
+            return mPm.getPackageInfo(mInternal.getActivityInfo().packageName,
                     PackageManager.MATCH_UNINSTALLED_PACKAGES).firstInstallTime;
         } catch (NameNotFoundException nnfe) {
             // Sorry, can't find package
@@ -160,7 +171,7 @@
      * @return the name from android:name for the acitivity.
      */
     public String getName() {
-        return mActivityInfo.name;
+        return mInternal.getActivityInfo().name;
     }
 
     /**
diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.aidl b/core/java/android/content/pm/LauncherActivityInfoInternal.aidl
new file mode 100644
index 0000000..5d98d54
--- /dev/null
+++ b/core/java/android/content/pm/LauncherActivityInfoInternal.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2020, 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.content.pm;
+
+parcelable LauncherActivityInfoInternal;
\ No newline at end of file
diff --git a/core/java/android/content/pm/LauncherActivityInfoInternal.java b/core/java/android/content/pm/LauncherActivityInfoInternal.java
new file mode 100644
index 0000000..417f168
--- /dev/null
+++ b/core/java/android/content/pm/LauncherActivityInfoInternal.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2020 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.content.pm;
+
+import android.annotation.NonNull;
+import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class LauncherActivityInfoInternal implements Parcelable {
+    @UnsupportedAppUsage
+    @NonNull private ActivityInfo mActivityInfo;
+    @NonNull private ComponentName mComponentName;
+    @NonNull private IncrementalStatesInfo mIncrementalStatesInfo;
+
+    /**
+     * @param info ActivityInfo from which to create the LauncherActivityInfo.
+     * @param incrementalStatesInfo The package's states.
+     */
+    public LauncherActivityInfoInternal(@NonNull ActivityInfo info,
+            @NonNull IncrementalStatesInfo incrementalStatesInfo) {
+        mActivityInfo = info;
+        mComponentName = new ComponentName(info.packageName, info.name);
+        mIncrementalStatesInfo = incrementalStatesInfo;
+    }
+
+    public LauncherActivityInfoInternal(Parcel source) {
+        mActivityInfo = source.readParcelable(ActivityInfo.class.getClassLoader());
+        mComponentName = new ComponentName(mActivityInfo.packageName, mActivityInfo.name);
+        mIncrementalStatesInfo = source.readParcelable(
+                IncrementalStatesInfo.class.getClassLoader());
+    }
+
+    public ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    public ActivityInfo getActivityInfo() {
+        return mActivityInfo;
+    }
+
+    public IncrementalStatesInfo getIncrementalStatesInfo() {
+        return mIncrementalStatesInfo;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mActivityInfo, 0);
+        dest.writeParcelable(mIncrementalStatesInfo, 0);
+    }
+
+    public static final @android.annotation.NonNull Creator<LauncherActivityInfoInternal> CREATOR =
+            new Creator<LauncherActivityInfoInternal>() {
+        public LauncherActivityInfoInternal createFromParcel(Parcel source) {
+            return new LauncherActivityInfoInternal(source);
+        }
+        public LauncherActivityInfoInternal[] newArray(int size) {
+            return new LauncherActivityInfoInternal[size];
+        }
+    };
+}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 1a694b3..b7af397 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -218,6 +218,7 @@
          * Indicates that a package was modified in the specified profile.
          * This can happen, for example, when the package is updated or when
          * one or more components are enabled or disabled.
+         * It can also happen if package state has changed, i.e., package becomes unstartable.
          *
          * @param packageName The name of the package that has changed.
          * @param user The UserHandle of the profile that generated the change.
@@ -323,6 +324,16 @@
         public void onShortcutsChanged(@NonNull String packageName,
                 @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
         }
+
+        /**
+         * Indicates that the loading progress of an installed package has changed.
+         *
+         * @param packageName The name of the package that has changed.
+         * @param user The UserHandle of the profile that generated the change.
+         * @param progress The new progress value, between [0, 1].
+         */
+        public void onPackageProgressChanged(@NonNull String packageName,
+                @NonNull UserHandle user, float progress) {}
     }
 
     /**
@@ -715,16 +726,15 @@
     public LauncherActivityInfo resolveActivity(Intent intent, UserHandle user) {
         logErrorForInvalidProfileAccess(user);
         try {
-            ActivityInfo ai = mService.resolveActivity(mContext.getPackageName(),
-                    intent.getComponent(), user);
-            if (ai != null) {
-                LauncherActivityInfo info = new LauncherActivityInfo(mContext, ai, user);
-                return info;
+            LauncherActivityInfoInternal ai = mService.resolveLauncherActivityInternal(
+                    mContext.getPackageName(), intent.getComponent(), user);
+            if (ai == null) {
+                return null;
             }
+            return new LauncherActivityInfo(mContext, user, ai);
         } catch (RemoteException re) {
             throw re.rethrowFromSystemServer();
         }
-        return null;
     }
 
     /**
@@ -813,13 +823,13 @@
     }
 
     private List<LauncherActivityInfo> convertToActivityList(
-            @Nullable ParceledListSlice<ResolveInfo> activities, UserHandle user) {
-        if (activities == null) {
+            @Nullable ParceledListSlice<LauncherActivityInfoInternal> internals, UserHandle user) {
+        if (internals == null || internals.getList().isEmpty()) {
             return Collections.EMPTY_LIST;
         }
         ArrayList<LauncherActivityInfo> lais = new ArrayList<>();
-        for (ResolveInfo ri : activities.getList()) {
-            LauncherActivityInfo lai = new LauncherActivityInfo(mContext, ri.activityInfo, user);
+        for (LauncherActivityInfoInternal internal : internals.getList()) {
+            LauncherActivityInfo lai = new LauncherActivityInfo(mContext, user, internal);
             if (DEBUG) {
                 Log.v(TAG, "Returning activity for profile " + user + " : "
                         + lai.getComponentName());
@@ -1667,6 +1677,19 @@
                 }
             }
         }
+
+        public void onPackageProgressChanged(UserHandle user, String packageName,
+                float progress) {
+            if (DEBUG) {
+                Log.d(TAG, "onPackageProgressChanged " + user.getIdentifier() + ","
+                        + packageName + "," + progress);
+            }
+            synchronized (LauncherApps.this) {
+                for (CallbackMessageHandler callback : mCallbacks) {
+                    callback.postOnPackageProgressChanged(user, packageName, progress);
+                }
+            }
+        }
     };
 
     private static class CallbackMessageHandler extends Handler {
@@ -1678,6 +1701,7 @@
         private static final int MSG_SUSPENDED = 6;
         private static final int MSG_UNSUSPENDED = 7;
         private static final int MSG_SHORTCUT_CHANGED = 8;
+        private static final int MSG_LOADING_PROGRESS_CHANGED = 9;
 
         private LauncherApps.Callback mCallback;
 
@@ -1688,6 +1712,7 @@
             boolean replacing;
             UserHandle user;
             List<ShortcutInfo> shortcuts;
+            float mLoadingProgress;
         }
 
         public CallbackMessageHandler(Looper looper, LauncherApps.Callback callback) {
@@ -1727,6 +1752,10 @@
                 case MSG_SHORTCUT_CHANGED:
                     mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
                     break;
+                case MSG_LOADING_PROGRESS_CHANGED:
+                    mCallback.onPackageProgressChanged(info.packageName, info.user,
+                            info.mLoadingProgress);
+                    break;
             }
         }
 
@@ -1793,6 +1822,15 @@
             info.shortcuts = shortcuts;
             obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
         }
+
+        public void postOnPackageProgressChanged(UserHandle user, String packageName,
+                float progress) {
+            CallbackInfo info = new CallbackInfo();
+            info.packageName = packageName;
+            info.user = user;
+            info.mLoadingProgress = progress;
+            obtainMessage(MSG_LOADING_PROGRESS_CHANGED, info).sendToTarget();
+        }
     }
 
     /**
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e54a53e..3fb9a9e 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -6191,9 +6191,30 @@
     public abstract Resources getResourcesForApplication(@NonNull String packageName)
             throws NameNotFoundException;
 
-    /** @hide */
+    /**
+     * Please don't use this function because it is no longer supported.
+     *
+     * @deprecated Instead of using this function, please use
+     *             {@link Context#createContextAsUser(UserHandle, int)} to create the specified user
+     *             context, {@link Context#getPackageManager()} to get PackageManager instance for
+     *             the specified user, and then
+     *             {@link PackageManager#getResourcesForApplication(String)} to get the same
+     *             Resources instance.
+     * @see {@link Context#createContextAsUser(android.os.UserHandle, int)}
+     * @see {@link Context#getPackageManager()}
+     * @see {@link android.content.pm.PackageManager#getResourcesForApplication(java.lang.String)}
+     * TODO(b/170852794): mark maxTargetSdk as {@code Build.VERSION_CODES.S}
+     * @hide
+     */
     @NonNull
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170928809,
+            publicAlternatives = "Use {@code Context#createContextAsUser(UserHandle, int)}"
+                    + " to create the relevant user context,"
+                    + " {@link android.content.Context#getPackageManager()} and"
+                    + " {@link android.content.pm.PackageManager#getResourcesForApplication("
+                    + "java.lang.String)}"
+                    + " instead.")
+    @Deprecated
     public abstract Resources getResourcesForApplicationAsUser(@NonNull String packageName,
             @UserIdInt int userId) throws NameNotFoundException;
 
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index 9471e49..401bb9d 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -424,36 +424,37 @@
      *
      * @hide
      */
-    public static final String SETTING_NAME_HDMI_CEC_ENABLED = "hdmi_cec_enabled";
+    public static final String CEC_SETTING_NAME_HDMI_CEC_ENABLED = "hdmi_cec_enabled";
     /**
      * Name of a setting deciding on the Standby message behaviour on sleep.
      *
      * @hide
      */
-    public static final String SETTING_NAME_SEND_STANDBY_ON_SLEEP = "send_standby_on_sleep";
+    public static final String CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP = "send_standby_on_sleep";
     /**
      * Name of a setting deciding on power state action when losing Active Source.
      *
      * @hide
      */
-    public static final String SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
+    public static final String CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
             "power_state_change_on_active_source_lost";
     /**
      * Name of a setting deciding whether System Audio Muting is allowed.
      *
      * @hide
      */
-    public static final String SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING = "system_audio_mode_muting";
+    public static final String CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING =
+            "system_audio_mode_muting";
     /**
      * @hide
      */
     @StringDef({
-        SETTING_NAME_HDMI_CEC_ENABLED,
-        SETTING_NAME_SEND_STANDBY_ON_SLEEP,
-        SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
-        SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
+        CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+        CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP,
+        CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
+        CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING,
     })
-    public @interface SettingName {}
+    public @interface CecSettingName {}
 
     // True if we have a logical device of type playback hosted in the system.
     private final boolean mHasPlaybackDevice;
@@ -1301,14 +1302,15 @@
      * @hide
      */
     @NonNull
+    @CecSettingName
     @RequiresPermission(android.Manifest.permission.HDMI_CEC)
-    public List<String> getAvailableCecSettings() {
+    public List<String> getUserCecSettings() {
         if (mService == null) {
             Log.e(TAG, "HdmiControlService is not available");
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            return mService.getAvailableCecSettings();
+            return mService.getUserCecSettings();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1326,7 +1328,7 @@
      */
     @NonNull
     @RequiresPermission(android.Manifest.permission.HDMI_CEC)
-    public List<String> getAllowedCecSettingValues(@NonNull String name) {
+    public List<String> getAllowedCecSettingValues(@NonNull @CecSettingName String name) {
         if (mService == null) {
             Log.e(TAG, "HdmiControlService is not available");
             throw new RuntimeException("HdmiControlService is not available");
@@ -1354,7 +1356,7 @@
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            mService.setCecSettingValue(SETTING_NAME_HDMI_CEC_ENABLED, value);
+            mService.setCecSettingValue(CEC_SETTING_NAME_HDMI_CEC_ENABLED, value);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1377,7 +1379,7 @@
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            return mService.getCecSettingValue(SETTING_NAME_HDMI_CEC_ENABLED);
+            return mService.getCecSettingValue(CEC_SETTING_NAME_HDMI_CEC_ENABLED);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1399,7 +1401,7 @@
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            mService.setCecSettingValue(SETTING_NAME_SEND_STANDBY_ON_SLEEP, value);
+            mService.setCecSettingValue(CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP, value);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1422,7 +1424,7 @@
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            return mService.getCecSettingValue(SETTING_NAME_SEND_STANDBY_ON_SLEEP);
+            return mService.getCecSettingValue(CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1446,7 +1448,7 @@
         }
         try {
             mService.setCecSettingValue(
-                    SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, value);
+                    CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, value);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1470,7 +1472,7 @@
         }
         try {
             return mService.getCecSettingValue(
-                    SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST);
+                    CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1492,7 +1494,7 @@
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            mService.setCecSettingValue(SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, value);
+            mService.setCecSettingValue(CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING, value);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1515,7 +1517,7 @@
             throw new RuntimeException("HdmiControlService is not available");
         }
         try {
-            return mService.getCecSettingValue(SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING);
+            return mService.getCecSettingValue(CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
index 46a3c4f..22d4640 100644
--- a/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
+++ b/core/java/android/hardware/hdmi/HdmiControlServiceWrapper.java
@@ -296,8 +296,8 @@
         }
 
         @Override
-        public List<String> getAvailableCecSettings() {
-            return HdmiControlServiceWrapper.this.getAvailableCecSettings();
+        public List<String> getUserCecSettings() {
+            return HdmiControlServiceWrapper.this.getUserCecSettings();
         }
 
         @Override
@@ -489,7 +489,7 @@
             IHdmiCecVolumeControlFeatureListener listener) {}
 
     /** @hide */
-    public List<String> getAvailableCecSettings() {
+    public List<String> getUserCecSettings() {
         return new ArrayList<>();
     }
 
diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
index 3478b23..6df164b 100644
--- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl
@@ -87,7 +87,7 @@
     boolean isHdmiCecVolumeControlEnabled();
     void reportAudioStatus(int deviceType, int volume, int maxVolume, boolean isMute);
     void setSystemAudioModeOnForAudioOnlySource();
-    List<String> getAvailableCecSettings();
+    List<String> getUserCecSettings();
     List<String> getAllowedCecSettingValues(String name);
     String getCecSettingValue(String name);
     void setCecSettingValue(String name, String value);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 25fec32..e9b6857 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -194,7 +194,7 @@
      */
     @BlockUntrustedTouchesMode
     public static final int DEFAULT_BLOCK_UNTRUSTED_TOUCHES_MODE =
-            BlockUntrustedTouchesMode.DISABLED;
+            BlockUntrustedTouchesMode.PERMISSIVE;
 
     /**
      * Prevent touches from being consumed by apps if these touches passed through a non-trusted
diff --git a/core/java/android/net/vcn/OWNERS b/core/java/android/net/vcn/OWNERS
new file mode 100644
index 0000000..33b9f0f
--- /dev/null
+++ b/core/java/android/net/vcn/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+
+benedictwong@google.com
+ckesting@google.com
+evitayan@google.com
+nharold@google.com
+jchalard@google.com
\ No newline at end of file
diff --git a/core/java/android/os/CombinedVibrationEffect.aidl b/core/java/android/os/CombinedVibrationEffect.aidl
new file mode 100644
index 0000000..330733c
--- /dev/null
+++ b/core/java/android/os/CombinedVibrationEffect.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+parcelable CombinedVibrationEffect;
diff --git a/core/java/android/os/CombinedVibrationEffect.java b/core/java/android/os/CombinedVibrationEffect.java
new file mode 100644
index 0000000..77bfa57
--- /dev/null
+++ b/core/java/android/os/CombinedVibrationEffect.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+import android.annotation.NonNull;
+
+import java.util.Objects;
+
+/**
+ * A CombinedVibrationEffect describes a haptic effect to be performed by one or more {@link
+ * Vibrator Vibrators}.
+ *
+ * These effects may be any number of things, from single shot vibrations to complex waveforms.
+ *
+ * @hide
+ * @see VibrationEffect
+ */
+public abstract class CombinedVibrationEffect implements Parcelable {
+    private static final int PARCEL_TOKEN_MONO = 1;
+
+    /** @hide to prevent subclassing from outside of the framework */
+    public CombinedVibrationEffect() {
+    }
+
+    /**
+     * Create a synced vibration effect.
+     *
+     * A synced vibration effect should be performed by multiple vibrators at the same time.
+     *
+     * @param effect The {@link VibrationEffect} to perform
+     * @return The desired combined effect.
+     */
+    @NonNull
+    public static CombinedVibrationEffect createSynced(@NonNull VibrationEffect effect) {
+        CombinedVibrationEffect combined = new Mono(effect);
+        combined.validate();
+        return combined;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** @hide */
+    public abstract void validate();
+
+    /**
+     * Represents a single {@link VibrationEffect} that should be executed in all vibrators in sync.
+     *
+     * @hide
+     */
+    public static final class Mono extends CombinedVibrationEffect {
+        private final VibrationEffect mEffect;
+
+        public Mono(Parcel in) {
+            mEffect = VibrationEffect.CREATOR.createFromParcel(in);
+        }
+
+        public Mono(@NonNull VibrationEffect effect) {
+            mEffect = effect;
+        }
+
+        public VibrationEffect getEffect() {
+            return mEffect;
+        }
+
+        /** @hide */
+        @Override
+        public void validate() {
+            mEffect.validate();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof CombinedVibrationEffect.Mono)) {
+                return false;
+            }
+            CombinedVibrationEffect.Mono other = (CombinedVibrationEffect.Mono) o;
+            return other.mEffect.equals(other.mEffect);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mEffect);
+        }
+
+        @Override
+        public String toString() {
+            return "Mono{mEffect=" + mEffect + '}';
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeInt(PARCEL_TOKEN_MONO);
+            mEffect.writeToParcel(out, flags);
+        }
+
+        @NonNull
+        public static final Parcelable.Creator<Mono> CREATOR =
+                new Parcelable.Creator<Mono>() {
+                    @Override
+                    public Mono createFromParcel(@NonNull Parcel in) {
+                        // Skip the type token
+                        in.readInt();
+                        return new Mono(in);
+                    }
+
+                    @Override
+                    @NonNull
+                    public Mono[] newArray(int size) {
+                        return new Mono[size];
+                    }
+                };
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<CombinedVibrationEffect> CREATOR =
+            new Parcelable.Creator<CombinedVibrationEffect>() {
+                @Override
+                public CombinedVibrationEffect createFromParcel(Parcel in) {
+                    int token = in.readInt();
+                    if (token == PARCEL_TOKEN_MONO) {
+                        return new CombinedVibrationEffect.Mono(in);
+                    } else {
+                        throw new IllegalStateException(
+                                "Unexpected combined vibration event type token in parcel.");
+                    }
+                }
+
+                @Override
+                public CombinedVibrationEffect[] newArray(int size) {
+                    return new CombinedVibrationEffect[size];
+                }
+            };
+}
diff --git a/core/java/android/os/IVibratorManagerService.aidl b/core/java/android/os/IVibratorManagerService.aidl
index e821e31..08d2019 100644
--- a/core/java/android/os/IVibratorManagerService.aidl
+++ b/core/java/android/os/IVibratorManagerService.aidl
@@ -16,9 +16,13 @@
 
 package android.os;
 
+import android.os.CombinedVibrationEffect;
 import android.os.VibrationAttributes;
 
 /** {@hide} */
 interface IVibratorManagerService {
     int[] getVibratorIds();
+    void vibrate(int uid, String opPkg, in CombinedVibrationEffect effect,
+            in VibrationAttributes attributes, String reason, IBinder token);
+    void cancelVibrate(IBinder token);
 }
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 487e468..21ad38b 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -983,6 +983,8 @@
                 Composition.checkPrimitive(effect.id);
                 Preconditions.checkArgumentInRange(
                         effect.scale, 0.0f, 1.0f, "scale");
+                Preconditions.checkArgumentNonNegative(effect.delay,
+                        "Primitive delay must be zero or positive");
             }
         }
 
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 59934ac..a4c8114 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8936,12 +8936,6 @@
                 "packages_to_clear_data_before_full_restore";
 
         /**
-         * Setting to determine whether to use the new notification priority handling features.
-         * @hide
-         */
-        public static final String NOTIFICATION_NEW_INTERRUPTION_MODEL = "new_interruption_model";
-
-        /**
          * How often to check for location access.
          * @hide
          */
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 08d9905..579a8bf 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -16,7 +16,7 @@
 
 package android.service.notification;
 
-import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
+import static android.text.TextUtils.formatSimple;
 
 import android.annotation.NonNull;
 import android.app.Notification;
@@ -31,8 +31,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
-import android.provider.Settings;
-import android.text.TextUtils;
 
 import com.android.internal.logging.InstanceId;
 import com.android.internal.logging.nano.MetricsProto;
@@ -258,7 +256,7 @@
 
     @Override
     public String toString() {
-        return String.format(
+        return formatSimple(
                 "StatusBarNotification(pkg=%s user=%s id=%d tag=%s key=%s: %s)",
                 this.pkg, this.user, this.id, this.tag,
                 this.key, this.notification);
diff --git a/core/java/android/text/format/DateFormat.java b/core/java/android/text/format/DateFormat.java
index 4a0bec1..c2e3a80 100755
--- a/core/java/android/text/format/DateFormat.java
+++ b/core/java/android/text/format/DateFormat.java
@@ -29,6 +29,7 @@
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.SpannedString;
+import android.text.TextUtils;
 
 import java.text.SimpleDateFormat;
 import java.util.Calendar;
@@ -697,7 +698,7 @@
     }
 
     private static String zeroPad(int inValue, int inMinDigits) {
-        return String.format(Locale.getDefault(), "%0" + inMinDigits + "d", inValue);
+        return TextUtils.formatSimple("%0" + inMinDigits + "d", inValue);
     }
 
     /**
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index fda5e0d..bf9a838 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -60,10 +60,9 @@
         }
         final String logLine;
         if (mUseLocalTimestamps) {
-            logLine = String.format("%s - %s", LocalDateTime.now(), msg);
+            logLine = LocalDateTime.now() + " - " + msg;
         } else {
-            logLine = String.format(
-                    "%s / %s - %s", SystemClock.elapsedRealtime(), Instant.now(), msg);
+            logLine = SystemClock.elapsedRealtime() + " / " + Instant.now() + " - " + msg;
         }
         append(logLine);
     }
diff --git a/core/java/android/view/IRecentsAnimationController.aidl b/core/java/android/view/IRecentsAnimationController.aidl
index 983ab2e..f209d88 100644
--- a/core/java/android/view/IRecentsAnimationController.aidl
+++ b/core/java/android/view/IRecentsAnimationController.aidl
@@ -19,6 +19,7 @@
 import android.app.ActivityManager;
 import android.view.IRemoteAnimationFinishedCallback;
 import android.graphics.GraphicBuffer;
+import android.graphics.Rect;
 
 /**
  * Passed to the {@link IRecentsAnimationRunner} in order for the runner to control to let the
@@ -37,6 +38,15 @@
     ActivityManager.TaskSnapshot screenshotTask(int taskId);
 
     /**
+     * Sets the final bounds on a Task. This is used by Launcher to notify the system that
+     * animating Activity to PiP has completed and the associated task surface should be updated
+     * accordingly. This should be called before `finish`
+     * @param taskId for which the leash should be updated
+     * @param destinationBounds bounds of the final PiP window
+     */
+     void setFinishTaskBounds(int taskId, in Rect destinationBounds);
+
+    /**
      * Notifies to the system that the animation into Recents should end, and all leashes associated
      * with remote animation targets should be relinquished. If {@param moveHomeToTop} is true, then
      * the home activity should be moved to the top. Otherwise, the home activity is hidden and the
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index f572eb9..43a8992 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -140,7 +140,6 @@
      * @displayId The ID of the display where this token should be removed.
      */
     void removeWindowToken(IBinder token, int displayId);
-    void prepareAppTransition(int transit, boolean alwaysKeepCurrent);
 
     /**
      * Sets a singular remote controller of display rotations. There can only be one. The
@@ -180,8 +179,6 @@
     @UnsupportedAppUsage
     void overridePendingAppTransitionRemote(in RemoteAnimationAdapter remoteAnimationAdapter,
             int displayId);
-    @UnsupportedAppUsage
-    void executeAppTransition();
 
     /**
       * Used by system ui to report that recents has shown itself.
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 355b314..12ea936 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
@@ -54,7 +55,6 @@
     private CachingIconView mIcon;
     private View mProfileBadge;
     private View mFeedbackIcon;
-    private boolean mShowExpandButtonAtEnd;
     private boolean mShowWorkBadgeAtEnd;
     private int mHeaderTextMarginEnd;
     private Drawable mBackground;
@@ -86,14 +86,15 @@
         this(context, attrs, defStyleAttr, 0);
     }
 
-    public NotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+    public NotificationHeaderView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
         Resources res = getResources();
         mChildMinWidth = res.getDimensionPixelSize(R.dimen.notification_header_shrink_min_width);
         mContentEndMargin = res.getDimensionPixelSize(R.dimen.notification_content_margin_end);
         mEntireHeaderClickable = res.getBoolean(R.bool.config_notificationHeaderClickableForExpand);
 
-        int[] attrIds = { android.R.attr.gravity };
+        int[] attrIds = {android.R.attr.gravity};
         TypedArray ta = context.obtainStyledAttributes(attrs, attrIds, defStyleAttr, defStyleRes);
         mGravity = ta.getInt(0, 0);
         ta.recycle();
@@ -102,13 +103,14 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mAppName = findViewById(com.android.internal.R.id.app_name_text);
-        mHeaderText = findViewById(com.android.internal.R.id.header_text);
-        mSecondaryHeaderText = findViewById(com.android.internal.R.id.header_text_secondary);
-        mExpandButton = findViewById(com.android.internal.R.id.expand_button);
-        mIcon = findViewById(com.android.internal.R.id.icon);
-        mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
-        mFeedbackIcon = findViewById(com.android.internal.R.id.feedback);
+        mAppName = findViewById(R.id.app_name_text);
+        mHeaderText = findViewById(R.id.header_text);
+        mSecondaryHeaderText = findViewById(R.id.header_text_secondary);
+        mExpandButton = findViewById(R.id.expand_button);
+        mIcon = findViewById(R.id.icon);
+        mProfileBadge = findViewById(R.id.profile_badge);
+        mFeedbackIcon = findViewById(R.id.feedback);
+        setClipToPadding(false);
     }
 
     @Override
@@ -134,9 +136,7 @@
                     lp.topMargin + lp.bottomMargin, lp.height);
             child.measure(childWidthSpec, childHeightSpec);
             // Icons that should go at the end
-            if ((child == mExpandButton && mShowExpandButtonAtEnd)
-                    || child == mProfileBadge
-                    || child == mFeedbackIcon) {
+            if (child == mExpandButton || child == mProfileBadge || child == mFeedbackIcon) {
                 iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
             } else {
                 totalWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
@@ -198,9 +198,7 @@
             int top = (int) (getPaddingTop() + (ownHeight - childHeight) / 2.0f);
             int bottom = top + childHeight;
             // Icons that should go at the end
-            if ((child == mExpandButton && mShowExpandButtonAtEnd)
-                    || child == mProfileBadge
-                    || child == mFeedbackIcon) {
+            if (child == mExpandButton || child == mProfileBadge || child == mFeedbackIcon) {
                 if (end == getMeasuredWidth()) {
                     layoutRight = end - mContentEndMargin;
                 } else {
@@ -227,7 +225,7 @@
 
     @Override
     public LayoutParams generateLayoutParams(AttributeSet attrs) {
-        return new ViewGroup.MarginLayoutParams(getContext(), attrs);
+        return new MarginLayoutParams(getContext(), attrs);
     }
 
     /**
@@ -256,7 +254,7 @@
     }
 
     @Override
-    protected boolean verifyDrawable(Drawable who) {
+    protected boolean verifyDrawable(@NonNull Drawable who) {
         return super.verifyDrawable(who) || who == mBackground;
     }
 
@@ -292,26 +290,17 @@
         updateTouchListener();
     }
 
+    /**
+     * Sets whether or not the work badge appears at the end of the NotificationHeaderView.
+     * The expand button will always be closer to the end.
+     */
     public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) {
         if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) {
-            setClipToPadding(!showWorkBadgeAtEnd);
             mShowWorkBadgeAtEnd = showWorkBadgeAtEnd;
         }
     }
 
     /**
-     * Sets whether or not the expand button appears at the end of the NotificationHeaderView. If
-     * both this and {@link #setShowWorkBadgeAtEnd(boolean)} have been set to true, then the
-     * expand button will appear closer to the end than the work badge.
-     */
-    public void setShowExpandButtonAtEnd(boolean showExpandButtonAtEnd) {
-        if (showExpandButtonAtEnd != mShowExpandButtonAtEnd) {
-            setClipToPadding(!showExpandButtonAtEnd);
-            mShowExpandButtonAtEnd = showExpandButtonAtEnd;
-        }
-    }
-
-    /**
      * Sets the margin end for the text portion of the header, excluding right-aligned elements
      * @param headerTextMarginEnd margin size
      */
@@ -331,7 +320,10 @@
         return mHeaderTextMarginEnd;
     }
 
-    public class HeaderTouchListener implements View.OnTouchListener {
+    /**
+     * Handles clicks on the header based on the region tapped.
+     */
+    public class HeaderTouchListener implements OnTouchListener {
 
         private final ArrayList<Rect> mTouchRects = new ArrayList<>();
         private Rect mExpandButtonRect;
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index 5a8ac54..a5ff19e 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -19,7 +19,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 
 import android.annotation.Nullable;
-import android.app.WindowConfiguration;
 import android.app.WindowConfiguration.ActivityType;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.IBinder;
@@ -29,7 +28,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
-import android.view.WindowManager.TransitionType;
+import android.view.WindowManager.TransitionOldType;
 
 /**
  * Defines which animation types should be overridden by which remote animation.
@@ -48,13 +47,13 @@
     /**
      * Registers a remote animation for a specific transition.
      *
-     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param transition The old transition type. Must be one of WindowManager.TRANSIT_OLD_* values.
      * @param activityTypeFilter The remote animation only runs if an activity with type of this
      *                           parameter is involved in the transition.
      * @param adapter The adapter that described how to run the remote animation.
      */
     @UnsupportedAppUsage
-    public void addRemoteAnimation(@TransitionType int transition,
+    public void addRemoteAnimation(@TransitionOldType int transition,
             @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter) {
         mTransitionAnimationMap.put(transition,
                 new RemoteAnimationAdapterEntry(adapter, activityTypeFilter));
@@ -64,35 +63,37 @@
      * Registers a remote animation for a specific transition without defining an activity type
      * filter.
      *
-     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param transition The old transition type. Must be one of WindowManager.TRANSIT_OLD_* values.
      * @param adapter The adapter that described how to run the remote animation.
      */
     @UnsupportedAppUsage
-    public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
+    public void addRemoteAnimation(@TransitionOldType int transition,
+            RemoteAnimationAdapter adapter) {
         addRemoteAnimation(transition, ACTIVITY_TYPE_UNDEFINED, adapter);
     }
 
     /**
      * Checks whether a remote animation for specific transition is defined.
      *
-     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param transition The old transition type. Must be one of WindowManager.TRANSIT_OLD_* values.
      * @param activityTypes The set of activity types of activities that are involved in the
      *                      transition. Will be used for filtering.
      * @return Whether this definition has defined a remote animation for the specified transition.
      */
-    public boolean hasTransition(@TransitionType int transition, ArraySet<Integer> activityTypes) {
+    public boolean hasTransition(@TransitionOldType int transition,
+            ArraySet<Integer> activityTypes) {
         return getAdapter(transition, activityTypes) != null;
     }
 
     /**
      * Retrieves the remote animation for a specific transition.
      *
-     * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
+     * @param transition The old transition type. Must be one of WindowManager.TRANSIT_OLD_* values.
      * @param activityTypes The set of activity types of activities that are involved in the
      *                      transition. Will be used for filtering.
      * @return The remote animation adapter for the specified transition.
      */
-    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition,
+    public @Nullable RemoteAnimationAdapter getAdapter(@TransitionOldType int transition,
             ArraySet<Integer> activityTypes) {
         final RemoteAnimationAdapterEntry entry = mTransitionAnimationMap.get(transition);
         if (entry == null) {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 432d927..14748f0 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1207,7 +1207,7 @@
             // Therefore, we must explicitly recreate the {@link Surface} in these
             // cases.
             if (mUseBlastAdapter) {
-                mSurface.transferFrom(mBlastBufferQueue.createSurface());
+                mSurface.transferFrom(mBlastBufferQueue.createSurfaceWithHandle());
             } else {
                 mSurface.createFrom(mSurfaceControl);
             }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 9336872..565f6d8 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -135,168 +135,207 @@
      * Not set up for a transition.
      * @hide
      */
-    int TRANSIT_UNSET = -1;
+    int TRANSIT_OLD_UNSET = -1;
 
     /**
      * No animation for transition.
      * @hide
      */
-    int TRANSIT_NONE = 0;
+    int TRANSIT_OLD_NONE = 0;
 
     /**
      * A window in a new activity is being opened on top of an existing one in the same task.
      * @hide
      */
-    int TRANSIT_ACTIVITY_OPEN = 6;
+    int TRANSIT_OLD_ACTIVITY_OPEN = 6;
 
     /**
      * The window in the top-most activity is being closed to reveal the previous activity in the
      * same task.
      * @hide
      */
-    int TRANSIT_ACTIVITY_CLOSE = 7;
+    int TRANSIT_OLD_ACTIVITY_CLOSE = 7;
 
     /**
      * A window in a new task is being opened on top of an existing one in another activity's task.
      * @hide
      */
-    int TRANSIT_TASK_OPEN = 8;
+    int TRANSIT_OLD_TASK_OPEN = 8;
 
     /**
      * A window in the top-most activity is being closed to reveal the previous activity in a
      * different task.
      * @hide
      */
-    int TRANSIT_TASK_CLOSE = 9;
+    int TRANSIT_OLD_TASK_CLOSE = 9;
 
     /**
      * A window in an existing task is being displayed on top of an existing one in another
      * activity's task.
      * @hide
      */
-    int TRANSIT_TASK_TO_FRONT = 10;
+    int TRANSIT_OLD_TASK_TO_FRONT = 10;
 
     /**
      * A window in an existing task is being put below all other tasks.
      * @hide
      */
-    int TRANSIT_TASK_TO_BACK = 11;
+    int TRANSIT_OLD_TASK_TO_BACK = 11;
 
     /**
      * A window in a new activity that doesn't have a wallpaper is being opened on top of one that
      * does, effectively closing the wallpaper.
      * @hide
      */
-    int TRANSIT_WALLPAPER_CLOSE = 12;
+    int TRANSIT_OLD_WALLPAPER_CLOSE = 12;
 
     /**
      * A window in a new activity that does have a wallpaper is being opened on one that didn't,
      * effectively opening the wallpaper.
      * @hide
      */
-    int TRANSIT_WALLPAPER_OPEN = 13;
+    int TRANSIT_OLD_WALLPAPER_OPEN = 13;
 
     /**
      * A window in a new activity is being opened on top of an existing one, and both are on top
      * of the wallpaper.
      * @hide
      */
-    int TRANSIT_WALLPAPER_INTRA_OPEN = 14;
+    int TRANSIT_OLD_WALLPAPER_INTRA_OPEN = 14;
 
     /**
      * The window in the top-most activity is being closed to reveal the previous activity, and
      * both are on top of the wallpaper.
      * @hide
      */
-    int TRANSIT_WALLPAPER_INTRA_CLOSE = 15;
+    int TRANSIT_OLD_WALLPAPER_INTRA_CLOSE = 15;
 
     /**
      * A window in a new task is being opened behind an existing one in another activity's task.
      * The new window will show briefly and then be gone.
      * @hide
      */
-    int TRANSIT_TASK_OPEN_BEHIND = 16;
+    int TRANSIT_OLD_TASK_OPEN_BEHIND = 16;
 
     /**
      * An activity is being relaunched (e.g. due to configuration change).
      * @hide
      */
-    int TRANSIT_ACTIVITY_RELAUNCH = 18;
+    int TRANSIT_OLD_ACTIVITY_RELAUNCH = 18;
 
     /**
      * Keyguard is going away.
      * @hide
      */
-    int TRANSIT_KEYGUARD_GOING_AWAY = 20;
+    int TRANSIT_OLD_KEYGUARD_GOING_AWAY = 20;
 
     /**
      * Keyguard is going away with showing an activity behind that requests wallpaper.
      * @hide
      */
-    int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
+    int TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
 
     /**
      * Keyguard is being occluded.
      * @hide
      */
-    int TRANSIT_KEYGUARD_OCCLUDE = 22;
+    int TRANSIT_OLD_KEYGUARD_OCCLUDE = 22;
 
     /**
      * Keyguard is being unoccluded.
      * @hide
      */
-    int TRANSIT_KEYGUARD_UNOCCLUDE = 23;
+    int TRANSIT_OLD_KEYGUARD_UNOCCLUDE = 23;
 
     /**
      * A translucent activity is being opened.
      * @hide
      */
-    int TRANSIT_TRANSLUCENT_ACTIVITY_OPEN = 24;
+    int TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN = 24;
 
     /**
      * A translucent activity is being closed.
      * @hide
      */
-    int TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE = 25;
+    int TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE = 25;
 
     /**
      * A crashing activity is being closed.
      * @hide
      */
-    int TRANSIT_CRASHING_ACTIVITY_CLOSE = 26;
+    int TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE = 26;
 
     /**
      * A task is changing windowing modes
      * @hide
      */
-    int TRANSIT_TASK_CHANGE_WINDOWING_MODE = 27;
+    int TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE = 27;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "TRANSIT_OLD_" }, value = {
+            TRANSIT_OLD_UNSET,
+            TRANSIT_OLD_NONE,
+            TRANSIT_OLD_ACTIVITY_OPEN,
+            TRANSIT_OLD_ACTIVITY_CLOSE,
+            TRANSIT_OLD_TASK_OPEN,
+            TRANSIT_OLD_TASK_CLOSE,
+            TRANSIT_OLD_TASK_TO_FRONT,
+            TRANSIT_OLD_TASK_TO_BACK,
+            TRANSIT_OLD_WALLPAPER_CLOSE,
+            TRANSIT_OLD_WALLPAPER_OPEN,
+            TRANSIT_OLD_WALLPAPER_INTRA_OPEN,
+            TRANSIT_OLD_WALLPAPER_INTRA_CLOSE,
+            TRANSIT_OLD_TASK_OPEN_BEHIND,
+            TRANSIT_OLD_ACTIVITY_RELAUNCH,
+            TRANSIT_OLD_KEYGUARD_GOING_AWAY,
+            TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+            TRANSIT_OLD_KEYGUARD_OCCLUDE,
+            TRANSIT_OLD_KEYGUARD_UNOCCLUDE,
+            TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN,
+            TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE,
+            TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
+            TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface TransitionOldType {}
+
+    /** @hide */
+    int TRANSIT_NONE = 0;
+    /** @hide */
+    int TRANSIT_OPEN = 1;
+    /** @hide */
+    int TRANSIT_CLOSE = 2;
+    /** @hide */
+    int TRANSIT_TO_FRONT = 3;
+    /** @hide */
+    int TRANSIT_TO_BACK = 4;
+    /** @hide */
+    int TRANSIT_RELAUNCH = 5;
+    /** @hide */
+    int TRANSIT_CHANGE_WINDOWING_MODE = 6;
+    /** @hide */
+    int TRANSIT_KEYGUARD_GOING_AWAY = 7;
+    /** @hide */
+    int TRANSIT_KEYGUARD_OCCLUDE = 8;
+    /** @hide */
+    int TRANSIT_KEYGUARD_UNOCCLUDE = 9;
 
     /**
      * @hide
      */
     @IntDef(prefix = { "TRANSIT_" }, value = {
-            TRANSIT_UNSET,
             TRANSIT_NONE,
-            TRANSIT_ACTIVITY_OPEN,
-            TRANSIT_ACTIVITY_CLOSE,
-            TRANSIT_TASK_OPEN,
-            TRANSIT_TASK_CLOSE,
-            TRANSIT_TASK_TO_FRONT,
-            TRANSIT_TASK_TO_BACK,
-            TRANSIT_WALLPAPER_CLOSE,
-            TRANSIT_WALLPAPER_OPEN,
-            TRANSIT_WALLPAPER_INTRA_OPEN,
-            TRANSIT_WALLPAPER_INTRA_CLOSE,
-            TRANSIT_TASK_OPEN_BEHIND,
-            TRANSIT_ACTIVITY_RELAUNCH,
+            TRANSIT_OPEN,
+            TRANSIT_CLOSE,
+            TRANSIT_TO_FRONT,
+            TRANSIT_TO_BACK,
+            TRANSIT_RELAUNCH,
+            TRANSIT_CHANGE_WINDOWING_MODE,
             TRANSIT_KEYGUARD_GOING_AWAY,
-            TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
             TRANSIT_KEYGUARD_OCCLUDE,
             TRANSIT_KEYGUARD_UNOCCLUDE,
-            TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
-            TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE,
-            TRANSIT_CRASHING_ACTIVITY_CLOSE,
-            TRANSIT_TASK_CHANGE_WINDOWING_MODE
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface TransitionType {}
@@ -326,13 +365,20 @@
     int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION = 0x8;
 
     /**
+     * Transition flag: App is crashed.
+     * @hide
+     */
+    int TRANSIT_FLAG_APP_CRASHED = 0x10;
+
+    /**
      * @hide
      */
     @IntDef(flag = true, prefix = { "TRANSIT_FLAG_" }, value = {
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE,
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION,
             TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER,
-            TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION
+            TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION,
+            TRANSIT_FLAG_APP_CRASHED
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface TransitionFlags {}
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 73636f8..e071113 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -19,6 +19,8 @@
 import static android.view.OnReceiveContentCallback.Payload.SOURCE_INPUT_METHOD;
 
 import android.annotation.CallSuper;
+import android.annotation.IntRange;
+import android.annotation.Nullable;
 import android.content.ClipData;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -585,6 +587,48 @@
     }
 
     /**
+     * The default implementation returns the given amount of text around the current cursor
+     * position in the buffer.
+     */
+    @Nullable
+    public SurroundingText getSurroundingText(
+            @IntRange(from = 0) int beforeLength, @IntRange(from = 0)  int afterLength, int flags) {
+        final Editable content = getEditable();
+        if (content == null) return null;
+
+        int selStart = Selection.getSelectionStart(content);
+        int selEnd = Selection.getSelectionEnd(content);
+
+        // Guard against the case where the cursor has not been positioned yet.
+        if (selStart < 0 || selEnd < 0) {
+            return null;
+        }
+
+        if (selStart > selEnd) {
+            int tmp = selStart;
+            selStart = selEnd;
+            selEnd = tmp;
+        }
+
+        int contentLength = content.length();
+        int startPos = selStart - beforeLength;
+        int endPos = selEnd + afterLength;
+
+        // Guards the start and end pos within range [0, contentLength].
+        startPos = Math.max(0, startPos);
+        endPos = Math.min(contentLength, endPos);
+
+        CharSequence surroundingText;
+        if ((flags & GET_TEXT_WITH_STYLES) != 0) {
+            surroundingText = content.subSequence(startPos, endPos);
+        } else {
+            surroundingText = TextUtils.substring(content, startPos, endPos);
+        }
+        return new SurroundingText(
+                surroundingText, selStart - startPos, selEnd - startPos, startPos);
+    }
+
+    /**
      * The default implementation turns this into the enter key.
      */
     public boolean performEditorAction(int actionCode) {
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 4337ed5..c7acd29 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -16,14 +16,20 @@
 
 package android.view.inputmethod;
 
+import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.inputmethodservice.InputMethodService;
 import android.os.Bundle;
 import android.os.Handler;
+import android.text.TextUtils;
 import android.view.KeyCharacterMap;
 import android.view.KeyEvent;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * The InputConnection interface is the communication channel from an
  * {@link InputMethod} back to the application that is receiving its
@@ -122,14 +128,20 @@
  * of each other, and the IME may use them however they see fit.</p>
  */
 public interface InputConnection {
+    /** @hide */
+    @IntDef(flag = true, prefix = { "GET_TEXT_" }, value = {
+            GET_TEXT_WITH_STYLES,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface GetTextType {}
+
     /**
-     * Flag for use with {@link #getTextAfterCursor} and
-     * {@link #getTextBeforeCursor} to have style information returned
-     * along with the text. If not set, {@link #getTextAfterCursor}
-     * sends only the raw text, without style or other spans. If set,
-     * it may return a complex CharSequence of both text and style
-     * spans. <strong>Editor authors</strong>: you should strive to
-     * send text with styles if possible, but it is not required.
+     * Flag for use with {@link #getTextAfterCursor}, {@link #getTextBeforeCursor} and
+     * {@link #getSurroundingText} to have style information returned along with the text. If not
+     * set, {@link #getTextAfterCursor} sends only the raw text, without style or other spans. If
+     * set, it may return a complex CharSequence of both text and style spans.
+     * <strong>Editor authors</strong>: you should strive to send text with styles if possible, but
+     * it is not required.
      */
     int GET_TEXT_WITH_STYLES = 0x0001;
 
@@ -264,6 +276,61 @@
     CharSequence getSelectedText(int flags);
 
     /**
+     * Gets the surrounding text around the current cursor, with <var>beforeLength</var> characters
+     * of text before the cursor (start of the selection), <var>afterLength</var> characters of text
+     * after the cursor (end of the selection), and all of the selected text.
+     *
+     * <p>This method may fail either if the input connection has become invalid (such as its
+     * process crashing), or the client is taking too long to respond with the text (it is given a
+     * couple seconds to return), or the protocol is not supported. In any of these cases, null is
+     * returned.
+     *
+     * <p>This method does not affect the text in the editor in any way, nor does it affect the
+     * selection or composing spans.</p>
+     *
+     * <p>If {@link #GET_TEXT_WITH_STYLES} is supplied as flags, the editor should return a
+     * {@link android.text.Spanned} with all the spans set on the text.</p>
+     *
+     * <p><strong>IME authors:</strong> please consider this will trigger an IPC round-trip that
+     * will take some time. Assume this method consumes a lot of time. If you are using this to get
+     * the initial surrounding text around the cursor, you may consider using
+     * {@link EditorInfo#getInitialTextBeforeCursor(int, int)},
+     * {@link EditorInfo#getInitialSelectedText(int)}, and
+     * {@link EditorInfo#getInitialTextAfterCursor(int, int)} to prevent IPC costs.</p>
+     *
+     * @param beforeLength The expected length of the text before the cursor.
+     * @param afterLength The expected length of the text after the cursor.
+     * @param flags Supplies additional options controlling how the text is returned. Defined by the
+     *              constants.
+     * @return an {@link android.view.inputmethod.SurroundingText} object describing the surrounding
+     * text and state of selection, or null if the input connection is no longer valid, or the
+     * editor can't comply with the request for some reason, or the application does not implement
+     * this method. The length of the returned text might be less than the sum of
+     * <var>beforeLength</var> and <var>afterLength</var> .
+     */
+    @Nullable
+    default SurroundingText getSurroundingText(
+            @IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength,
+            @GetTextType int flags) {
+        CharSequence textBeforeCursor = getTextBeforeCursor(beforeLength, flags);
+        if (textBeforeCursor == null) {
+            textBeforeCursor = "";
+        }
+        CharSequence selectedText = getSelectedText(flags);
+        if (selectedText == null) {
+            selectedText = "";
+        }
+        CharSequence textAfterCursor = getTextAfterCursor(afterLength, flags);
+        if (textAfterCursor == null) {
+            textAfterCursor = "";
+        }
+        CharSequence surroundingText =
+                TextUtils.concat(textBeforeCursor, selectedText, textAfterCursor);
+        return new SurroundingText(surroundingText, textBeforeCursor.length(),
+                textBeforeCursor.length() + selectedText.length(), -1);
+    }
+
+    /**
      * Retrieve the current capitalization mode in effect at the
      * current cursor position in the text. See
      * {@link android.text.TextUtils#getCapsMode TextUtils.getCapsMode}
diff --git a/core/java/android/view/inputmethod/InputConnectionInspector.java b/core/java/android/view/inputmethod/InputConnectionInspector.java
index 5f25bf5..7621da7 100644
--- a/core/java/android/view/inputmethod/InputConnectionInspector.java
+++ b/core/java/android/view/inputmethod/InputConnectionInspector.java
@@ -44,6 +44,7 @@
             MissingMethodFlags.GET_HANDLER,
             MissingMethodFlags.CLOSE_CONNECTION,
             MissingMethodFlags.COMMIT_CONTENT,
+            MissingMethodFlags.GET_SURROUNDING_TEXT
     })
     public @interface MissingMethodFlags {
         /**
@@ -86,6 +87,11 @@
          * {@link android.os.Build.VERSION_CODES#N} MR-1 and later.
          */
         int COMMIT_CONTENT = 1 << 7;
+        /**
+         * {@link InputConnection#getSurroundingText(int, int, int)} is available in
+         * {@link android.os.Build.VERSION_CODES#S} and later.
+         */
+        int GET_SURROUNDING_TEXT = 1 << 8;
     }
 
     private static final Map<Class, Integer> sMissingMethodsMap = Collections.synchronizedMap(
@@ -138,6 +144,9 @@
         if (!hasCommitContent(clazz)) {
             flags |= MissingMethodFlags.COMMIT_CONTENT;
         }
+        if (!hasGetSurroundingText(clazz)) {
+            flags |= MissingMethodFlags.GET_SURROUNDING_TEXT;
+        }
         sMissingMethodsMap.put(clazz, flags);
         return flags;
     }
@@ -216,6 +225,16 @@
         }
     }
 
+    private static boolean hasGetSurroundingText(@NonNull final Class clazz) {
+        try {
+            final Method method = clazz.getMethod("getSurroundingText", int.class, int.class,
+                    int.class);
+            return !Modifier.isAbstract(method.getModifiers());
+        } catch (NoSuchMethodException e) {
+            return false;
+        }
+    }
+
     public static String getMissingMethodFlagsAsString(@MissingMethodFlags final int flags) {
         final StringBuilder sb = new StringBuilder();
         boolean isEmpty = true;
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index f671e22..ec7fa60 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -16,6 +16,7 @@
 
 package android.view.inputmethod;
 
+import android.annotation.Nullable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.view.KeyEvent;
@@ -101,6 +102,16 @@
      * {@inheritDoc}
      * @throws NullPointerException if the target is {@code null}.
      */
+    @Nullable
+    @Override
+    public SurroundingText getSurroundingText(int beforeLength, int afterLength, int flags) {
+        return mTarget.getSurroundingText(beforeLength, afterLength, flags);
+    }
+
+    /**
+     * {@inheritDoc}
+     * @throws NullPointerException if the target is {@code null}.
+     */
     @Override
     public int getCursorCapsMode(int reqModes) {
         return mTarget.getCursorCapsMode(reqModes);
diff --git a/core/java/android/view/inputmethod/SurroundingText.aidl b/core/java/android/view/inputmethod/SurroundingText.aidl
new file mode 100644
index 0000000..7a9898e
--- /dev/null
+++ b/core/java/android/view/inputmethod/SurroundingText.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2020 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.inputmethod;
+
+parcelable SurroundingText;
\ No newline at end of file
diff --git a/core/java/android/view/inputmethod/SurroundingText.java b/core/java/android/view/inputmethod/SurroundingText.java
new file mode 100644
index 0000000..506f95a
--- /dev/null
+++ b/core/java/android/view/inputmethod/SurroundingText.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2020 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.inputmethod;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Information about the surrounding text around the cursor for use by an input method.
+ *
+ * <p>This contains information about the text and the selection relative to the text. </p>
+ */
+public final class SurroundingText implements Parcelable {
+    /**
+     * The surrounding text around the cursor.
+     */
+    @NonNull
+    private final CharSequence mText;
+
+    /**
+     * The text offset of the start of the selection in the surrounding text.
+     *
+     * <p>This needs to be the position relative to the {@link #mText} instead of the real position
+     * in the editor.</p>
+     */
+    @IntRange(from = 0)
+    private final int mSelectionStart;
+
+    /**
+     * The text offset of the end of the selection in the surrounding text.
+     *
+     * <p>This needs to be the position relative to the {@link #mText} instead of the real position
+     * in the editor.</p>
+     */
+    @IntRange(from = 0)
+    private final int mSelectionEnd;
+
+    /**
+     * The text offset between the start of the editor's text and the start of the surrounding text.
+     *
+     * <p>-1 indicates the offset information is unknown.</p>
+     */
+    @IntRange(from = -1)
+    private final int mOffset;
+
+    /**
+     * Constructor.
+     *
+     * @param text The surrounding text.
+     * @param selectionStart The text offset of the start of the selection in the surrounding text.
+     *                       Reversed selection is allowed.
+     * @param selectionEnd The text offset of the end of the selection in the surrounding text.
+     *                     Reversed selection is allowed.
+     * @param offset The text offset between the start of the editor's text and the start of the
+     *               surrounding text. -1 indicates the offset is unknown.
+     */
+    public SurroundingText(@NonNull final CharSequence text,
+            @IntRange(from = 0) int selectionStart, @IntRange(from = 0) int selectionEnd,
+            @IntRange(from = -1) int offset) {
+        mText = text;
+        mSelectionStart = selectionStart;
+        mSelectionEnd = selectionEnd;
+        mOffset = offset;
+    }
+
+    /**
+     * Returns the surrounding text around the cursor.
+     */
+    @NonNull
+    public CharSequence getText() {
+        return mText;
+    }
+
+    /**
+     * Returns the text offset of the start of the selection in the surrounding text.
+     */
+    @IntRange(from = 0)
+    public int getSelectionStart() {
+        return mSelectionStart;
+    }
+
+    /**
+     * Returns the text offset of the end of the selection in the surrounding text.
+     */
+    @IntRange(from = 0)
+    public int getSelectionEnd() {
+        return mSelectionEnd;
+    }
+
+    /**
+     * Returns text offset between the start of the editor's text and the start of the surrounding
+     * text.
+     *
+     * <p>-1 indicates the offset information is unknown.</p>
+     */
+    @IntRange(from = -1)
+    public int getOffset() {
+        return mOffset;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel out, int flags) {
+        TextUtils.writeToParcel(mText, out, flags);
+        out.writeInt(mSelectionStart);
+        out.writeInt(mSelectionEnd);
+        out.writeInt(mOffset);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<SurroundingText> CREATOR =
+            new Parcelable.Creator<SurroundingText>() {
+                @NonNull
+                public SurroundingText createFromParcel(Parcel in) {
+                    final CharSequence text =
+                            TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+                    final int selectionHead = in.readInt();
+                    final int selectionEnd = in.readInt();
+                    final int offset = in.readInt();
+                    return new SurroundingText(
+                            text == null ? "" : text,  selectionHead, selectionEnd, offset);
+                }
+
+                @NonNull
+                public SurroundingText[] newArray(int size) {
+                    return new SurroundingText[size];
+                }
+            };
+}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 97e0689..45b21c5 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -82,6 +82,7 @@
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputContentInfo;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.SurroundingText;
 import android.view.inspector.InspectableProperty;
 import android.view.inspector.InspectableProperty.EnumEntry;
 import android.widget.RemoteViews.OnClickHandler;
@@ -5997,6 +5998,12 @@
         }
 
         @Override
+        public SurroundingText getSurroundingText(int beforeLength, int afterLength, int flags) {
+            if (mTarget == null) return null;
+            return mTarget.getSurroundingText(beforeLength, afterLength, flags);
+        }
+
+        @Override
         public int getCursorCapsMode(int reqModes) {
             if (mTarget == null) return InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
             return mTarget.getCursorCapsMode(reqModes);
diff --git a/core/java/android/widget/RadioButton.java b/core/java/android/widget/RadioButton.java
index 3e26f63..a04d7c3 100644
--- a/core/java/android/widget/RadioButton.java
+++ b/core/java/android/widget/RadioButton.java
@@ -16,10 +16,13 @@
 
 package android.widget;
 
+import android.annotation.NonNull;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.R;
+
 
 /**
  * <p>
@@ -98,4 +101,15 @@
             }
         }
     }
+
+    /** @hide **/
+    @Override
+    @NonNull
+    protected CharSequence getButtonStateDescription() {
+        if (isChecked()) {
+            return getResources().getString(R.string.selected);
+        } else {
+            return getResources().getString(R.string.not_selected);
+        }
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7bb2b7e..3fc0f4e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -11051,12 +11051,12 @@
                     MotionEvent.actionToString(event.getActionMasked()),
                     event.getX(), event.getY());
         }
-        if (!isFromPrimePointer(event, false)) {
-            return true;
-        }
-
         final int action = event.getActionMasked();
         if (mEditor != null) {
+            if (!isFromPrimePointer(event, false)) {
+                return true;
+            }
+
             mEditor.onTouchEvent(event);
 
             if (mEditor.mInsertionPointCursorController != null
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index b5a11b1..3a84c1f 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -39,12 +39,8 @@
      */
     void unregisterTaskOrganizer(ITaskOrganizer organizer);
 
-    /**
-     * Creates a persistent root task in WM for a particular windowing-mode.
-     * {@link TaskOrganizer#onTaskAppeared} won't be called since we are returning
-     * {@link TaskAppearedInfo} here.
-     */
-    TaskAppearedInfo createRootTask(int displayId, int windowingMode);
+    /** Creates a persistent root task in WM for a particular windowing-mode. */
+    ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode);
 
     /** Deletes a persistent root task in WM */
     boolean deleteRootTask(in WindowContainerToken task);
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 5c86e1c..6c739be 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -29,6 +29,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
@@ -37,15 +38,19 @@
 @TestApi
 public class TaskOrganizer extends WindowOrganizer {
 
-    private ITaskOrganizerController mTaskOrganizerController;
+    private final ITaskOrganizerController mTaskOrganizerController;
+    // Callbacks WM Core are posted on this executor if it isn't null, otherwise direct calls are
+    // made on the incoming binder call.
+    private final Executor mExecutor;
 
     public TaskOrganizer() {
-        this(null);
+        this(null /*taskOrganizerController*/, null /*executor*/);
     }
 
     /** @hide */
     @VisibleForTesting
-    public TaskOrganizer(ITaskOrganizerController taskOrganizerController) {
+    public TaskOrganizer(ITaskOrganizerController taskOrganizerController, Executor executor) {
+        mExecutor = executor != null ? executor : command -> command.run();
         mTaskOrganizerController = taskOrganizerController != null
                 ? taskOrganizerController : getController();
     }
@@ -99,7 +104,7 @@
     /** Creates a persistent root task in WM for a particular windowing-mode. */
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
     @Nullable
-    public TaskAppearedInfo createRootTask(int displayId, int windowingMode) {
+    public ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) {
         try {
             return mTaskOrganizerController.createRootTask(displayId, windowingMode);
         } catch (RemoteException e) {
@@ -183,22 +188,22 @@
 
         @Override
         public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
-            TaskOrganizer.this.onTaskAppeared(taskInfo, leash);
+            mExecutor.execute(() -> TaskOrganizer.this.onTaskAppeared(taskInfo, leash));
         }
 
         @Override
         public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
-            TaskOrganizer.this.onTaskVanished(taskInfo);
+            mExecutor.execute(() -> TaskOrganizer.this.onTaskVanished(taskInfo));
         }
 
         @Override
         public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
-            TaskOrganizer.this.onTaskInfoChanged(info);
+            mExecutor.execute(() -> TaskOrganizer.this.onTaskInfoChanged(info));
         }
 
         @Override
         public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
-            TaskOrganizer.this.onBackPressedOnTaskRoot(info);
+            mExecutor.execute(() -> TaskOrganizer.this.onBackPressedOnTaskRoot(info));
         }
     };
 
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 34d1d4e..50174df 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -63,11 +63,11 @@
     })
     public @interface TransitionMode {}
 
-    private final @WindowManager.TransitionType int mType;
+    private final @WindowManager.TransitionOldType int mType;
     private final ArrayList<Change> mChanges = new ArrayList<>();
 
     /** @hide */
-    public TransitionInfo(@WindowManager.TransitionType int type) {
+    public TransitionInfo(@WindowManager.TransitionOldType int type) {
         mType = type;
     }
 
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index d8eaeda..52dc7e6 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -191,8 +191,9 @@
         mOnUnsuspend = intent.getParcelableExtra(EXTRA_UNSUSPEND_INTENT);
         if (mSuppliedDialogInfo != null) {
             try {
-                mSuspendingAppResources = mPm.getResourcesForApplicationAsUser(mSuspendingPackage,
-                        mUserId);
+                mSuspendingAppResources = createContextAsUser(
+                        UserHandle.of(mUserId), /* flags */ 0).getPackageManager()
+                        .getResourcesForApplication(mSuspendedPackage);
             } catch (PackageManager.NameNotFoundException ne) {
                 Slog.e(TAG, "Could not find resources for " + mSuspendingPackage, ne);
             }
diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java
index 5e886a6..7a87be3 100644
--- a/core/java/com/android/internal/compat/ChangeReporter.java
+++ b/core/java/com/android/internal/compat/ChangeReporter.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.compat;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.IntDef;
 import android.util.Log;
 import android.util.Slog;
@@ -175,7 +177,7 @@
     }
 
     private void debugLog(int uid, long changeId, int state) {
-        String message = String.format("Compat change id reported: %d; UID %d; state: %s", changeId,
+        String message = formatSimple("Compat change id reported: %d; UID %d; state: %s", changeId,
                 uid, stateToString(state));
         if (mSource == SOURCE_SYSTEM_SERVER) {
             Slog.d(TAG, message);
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index 3682b7b..af666d8 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -37,6 +37,7 @@
  * updating, and disappearing and reappearing on the SD card.
  */
 public abstract class PackageMonitor extends android.content.BroadcastReceiver {
+    static final String TAG = "PackageMonitor";
     static final IntentFilter sPackageFilt = new IntentFilter();
     static final IntentFilter sNonDataFilt = new IntentFilter();
     static final IntentFilter sExternalFilt = new IntentFilter();
@@ -48,6 +49,9 @@
         sPackageFilt.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
         sPackageFilt.addAction(Intent.ACTION_PACKAGE_RESTARTED);
         sPackageFilt.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_STARTABLE);
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_UNSTARTABLE);
+        sPackageFilt.addAction(Intent.ACTION_PACKAGE_FULLY_LOADED);
         sPackageFilt.addDataScheme("package");
         sNonDataFilt.addAction(Intent.ACTION_UID_REMOVED);
         sNonDataFilt.addAction(Intent.ACTION_USER_STOPPED);
@@ -305,6 +309,13 @@
     public void onPackageDataCleared(String packageName, int uid) {
     }
 
+    /**
+     * Callback to indicate the package's state has changed.
+     * @param packageName Name of an installed package
+     * @param uid The UID the package runs under.
+     */
+    public void onPackageStateChanged(String packageName, int uid) {}
+
     public int getChangingUserId() {
         return mChangeUserId;
     }
@@ -452,12 +463,21 @@
             String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
             mSomePackagesChanged = true;
             onPackagesUnsuspended(pkgList);
+        } else if (Intent.ACTION_PACKAGE_STARTABLE.equals(action)
+                || Intent.ACTION_PACKAGE_UNSTARTABLE.equals(action)
+                || Intent.ACTION_PACKAGE_FULLY_LOADED.equals(action)) {
+            String pkg = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
+            int uid = intent.getIntExtra(Intent.EXTRA_UID, 0);
+            mSomePackagesChanged = false;
+            if (pkg != null) {
+                onPackageStateChanged(pkg, uid);
+            }
         }
 
         if (mSomePackagesChanged) {
             onSomePackagesChanged();
         }
-        
+
         onFinishPackageChanges();
         mChangeUserId = UserHandle.USER_NULL;
     }
diff --git a/core/java/com/android/internal/inputmethod/CancellationGroup.java b/core/java/com/android/internal/inputmethod/CancellationGroup.java
index 09c9d12..a4a2208 100644
--- a/core/java/com/android/internal/inputmethod/CancellationGroup.java
+++ b/core/java/com/android/internal/inputmethod/CancellationGroup.java
@@ -263,6 +263,16 @@
                 super(factory);
             }
         }
+
+        /**
+         * Completable object of {@link android.view.inputmethod.SurroundingText}.
+         */
+        public static final class SurroundingText
+                extends Values<android.view.inputmethod.SurroundingText> {
+            private SurroundingText(@NonNull CancellationGroup factory) {
+                super(factory);
+            }
+        }
     }
 
     /**
@@ -292,6 +302,16 @@
         return new Completable.ExtractedText(this);
     }
 
+    /**
+     * @return an instance of {@link Completable.SurroundingText} that is associated with this
+     *         {@link CancellationGroup}.
+     */
+    @AnyThread
+    public Completable.SurroundingText createCompletableSurroundingText() {
+        return new Completable.SurroundingText(this);
+    }
+
+
     @AnyThread
     private boolean registerLatch(@NonNull CountDownLatch latch) {
         synchronized (mLock) {
diff --git a/core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl b/core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl
new file mode 100644
index 0000000..6c4f3d5
--- /dev/null
+++ b/core/java/com/android/internal/inputmethod/ISurroundingTextResultCallback.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.inputmethod;
+
+import android.view.inputmethod.SurroundingText;
+
+oneway interface ISurroundingTextResultCallback {
+    void onResult(in SurroundingText result);
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/inputmethod/ResultCallbacks.java b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
index 44a8a83..5eba898 100644
--- a/core/java/com/android/internal/inputmethod/ResultCallbacks.java
+++ b/core/java/com/android/internal/inputmethod/ResultCallbacks.java
@@ -129,4 +129,32 @@
             }
         };
     }
+
+    /**
+     * Creates {@link ISurroundingTextResultCallback.Stub} that is to set
+     * {@link CancellationGroup.Completable.SurroundingText} when receiving the result.
+     *
+     * @param value {@link CancellationGroup.Completable.SurroundingText} to be set when receiving
+     *              the result.
+     * @return {@link ISurroundingTextResultCallback.Stub} that can be passed as a binder IPC
+     *         parameter.
+     */
+    @AnyThread
+    public static ISurroundingTextResultCallback.Stub of(
+            @NonNull CancellationGroup.Completable.SurroundingText value) {
+        final AtomicReference<WeakReference<CancellationGroup.Completable.SurroundingText>>
+                atomicRef = new AtomicReference<>(new WeakReference<>(value));
+
+        return new ISurroundingTextResultCallback.Stub() {
+            @BinderThread
+            @Override
+            public void onResult(android.view.inputmethod.SurroundingText result) {
+                final CancellationGroup.Completable.SurroundingText value = unwrap(atomicRef);
+                if (value == null) {
+                    return;
+                }
+                value.onComplete(result);
+            }
+        };
+    }
 }
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index 7dc3871..c0648ab 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -70,7 +70,8 @@
         intent.setClassName(DIALOGS_PACKAGE, DIALOGS_PACKAGE + ".ManageDialog");
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_NO_HISTORY |
                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        return PendingIntent.getActivityAsUser(context, 0, intent, 0, null, UserHandle.CURRENT);
+        return PendingIntent.getActivityAsUser(context, 0 /* requestCode */, intent,
+                PendingIntent.FLAG_IMMUTABLE, null /* options */, UserHandle.CURRENT);
     }
 
     public static CharSequence getVpnLabel(Context context, String packageName)
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 9257c6d..cd5502c 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -35,11 +35,13 @@
 import android.view.inputmethod.InputConnectionInspector;
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputContentInfo;
+import android.view.inputmethod.SurroundingText;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.ICharSequenceResultCallback;
 import com.android.internal.inputmethod.IExtractedTextResultCallback;
 import com.android.internal.inputmethod.IIntResultCallback;
+import com.android.internal.inputmethod.ISurroundingTextResultCallback;
 import com.android.internal.os.SomeArgs;
 
 public abstract class IInputConnectionWrapper extends IInputContext.Stub {
@@ -70,6 +72,8 @@
     private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
     private static final int DO_CLOSE_CONNECTION = 150;
     private static final int DO_COMMIT_CONTENT = 160;
+    private static final int DO_GET_SURROUNDING_TEXT = 41;
+
 
     @GuardedBy("mLock")
     @Nullable
@@ -127,6 +131,21 @@
         dispatchMessage(mH.obtainMessage(DO_GET_SELECTED_TEXT, flags, 0 /* unused */, callback));
     }
 
+    /**
+     * Dispatches the request for retrieving surrounding text.
+     *
+     * <p>See {@link InputConnection#getSurroundingText(int, int, int)}.
+     */
+    public void getSurroundingText(int beforeLength, int afterLength, int flags,
+            ISurroundingTextResultCallback callback) {
+        final SomeArgs args = SomeArgs.obtain();
+        args.arg1 = beforeLength;
+        args.arg2 = afterLength;
+        args.arg3 = flags;
+        args.arg4 = callback;
+        dispatchMessage(mH.obtainMessage(DO_GET_SURROUNDING_TEXT, flags, 0 /* unused */, args));
+    }
+
     public void getCursorCapsMode(int reqModes, IIntResultCallback callback) {
         dispatchMessage(
                 mH.obtainMessage(DO_GET_CURSOR_CAPS_MODE, reqModes, 0 /* unused */, callback));
@@ -293,6 +312,33 @@
                 }
                 return;
             }
+            case DO_GET_SURROUNDING_TEXT: {
+                final SomeArgs args = (SomeArgs) msg.obj;
+                try {
+                    int beforeLength = (int) args.arg1;
+                    int afterLength  = (int) args.arg2;
+                    int flags = (int) args.arg3;
+                    final ISurroundingTextResultCallback callback =
+                            (ISurroundingTextResultCallback) args.arg4;
+                    final InputConnection ic = getInputConnection();
+                    final SurroundingText result;
+                    if (ic == null || !isActive()) {
+                        Log.w(TAG, "getSurroundingText on inactive InputConnection");
+                        result = null;
+                    } else {
+                        result = ic.getSurroundingText(beforeLength, afterLength, flags);
+                    }
+                    try {
+                        callback.onResult(result);
+                    } catch (RemoteException e) {
+                        Log.w(TAG, "Failed to return the result to getSurroundingText()."
+                                + " result=" + result, e);
+                    }
+                } finally {
+                    args.recycle();
+                }
+                return;
+            }
             case DO_GET_CURSOR_CAPS_MODE: {
                 final IIntResultCallback callback = (IIntResultCallback) msg.obj;
                 final InputConnection ic = getInputConnection();
diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl
index 86f1293..074908a 100644
--- a/core/java/com/android/internal/view/IInputContext.aidl
+++ b/core/java/com/android/internal/view/IInputContext.aidl
@@ -26,6 +26,7 @@
 import com.android.internal.inputmethod.ICharSequenceResultCallback;
 import com.android.internal.inputmethod.IExtractedTextResultCallback;
 import com.android.internal.inputmethod.IIntResultCallback;
+import com.android.internal.inputmethod.ISurroundingTextResultCallback;
 
 /**
  * Interface from an input method to the application, allowing it to perform
@@ -79,4 +80,7 @@
 
     void commitContent(in InputContentInfo inputContentInfo, int flags, in Bundle opts,
             IIntResultCallback callback);
+
+    void getSurroundingText(int beforeLength, int afterLength, int flags,
+            ISurroundingTextResultCallback callback);
 }
diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index 0bf5234..f086dd7 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -33,6 +33,7 @@
 import android.view.inputmethod.InputConnectionInspector;
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputContentInfo;
+import android.view.inputmethod.SurroundingText;
 
 import com.android.internal.inputmethod.CancellationGroup;
 import com.android.internal.inputmethod.ResultCallbacks;
@@ -157,6 +158,38 @@
         return getResultOrNull(value, "getSelectedText()");
     }
 
+    /**
+     * Get {@link SurroundingText} around the current cursor, with <var>beforeLength</var>
+     * characters of text before the cursor, <var>afterLength</var> characters of text after the
+     * cursor, and all of the selected text.
+     * @param beforeLength The expected length of the text before the cursor
+     * @param afterLength The expected length of the text after the cursor
+     * @param flags Supplies additional options controlling how the text is returned. May be either
+     *              0 or {@link #GET_TEXT_WITH_STYLES}.
+     * @return the surrounding text around the cursor position; the length of the returned text
+     * might be less than requested.  It could also be {@code null} when the editor or system could
+     * not support this protocol.
+     */
+    @AnyThread
+    public SurroundingText getSurroundingText(int beforeLength, int afterLength, int flags) {
+        if (mCancellationGroup.isCanceled()) {
+            return null;
+        }
+        if (isMethodMissing(MissingMethodFlags.GET_SURROUNDING_TEXT)) {
+            // This method is not implemented.
+            return null;
+        }
+        final CancellationGroup.Completable.SurroundingText value =
+                mCancellationGroup.createCompletableSurroundingText();
+        try {
+            mIInputContext.getSurroundingText(beforeLength, afterLength, flags,
+                    ResultCallbacks.of(value));
+        } catch (RemoteException e) {
+            return null;
+        }
+        return getResultOrNull(value, "getSurroundingText()");
+    }
+
     @AnyThread
     public int getCursorCapsMode(int reqModes) {
         if (mCancellationGroup.isCanceled()) {
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index 0fc0451..3e87cb5 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -53,9 +53,11 @@
     queue->decStrong((void*)nativeCreate);
 }
 
-static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr) {
+static jobject nativeGetSurface(JNIEnv* env, jclass clazz, jlong ptr,
+                                jboolean includeSurfaceControlHandle) {
     sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
-    return android_view_Surface_createFromSurface(env, queue->getSurface());
+    return android_view_Surface_createFromSurface(env,
+                                                  queue->getSurface(includeSurfaceControlHandle));
 }
 
 static void nativeSetNextTransaction(JNIEnv* env, jclass clazz, jlong ptr, jlong transactionPtr) {
@@ -77,7 +79,7 @@
 static const JNINativeMethod gMethods[] = {
         /* name, signature, funcPtr */
         {"nativeCreate", "(Ljava/lang/String;JJJZ)J", (void*)nativeCreate},
-        {"nativeGetSurface", "(J)Landroid/view/Surface;", (void*)nativeGetSurface},
+        {"nativeGetSurface", "(JZ)Landroid/view/Surface;", (void*)nativeGetSurface},
         {"nativeDestroy", "(J)V", (void*)nativeDestroy},
         {"nativeSetNextTransaction", "(JJ)V", (void*)nativeSetNextTransaction},
         {"nativeUpdate", "(JJJJ)V", (void*)nativeUpdate},
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 5c87f19..3a1ccd9 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -313,7 +313,7 @@
         return nativeObject;
     }
 
-    sp<Surface> surface = queue->getSurface();
+    sp<Surface> surface = queue->getSurface(true /* includeSurfaceControlHandle */);
     if (surface != NULL) {
         surface->incStrong(&sRefBaseOwner);
     }
@@ -349,7 +349,8 @@
     sp<Surface> sur;
     if (surfaceShim.graphicBufferProducer != nullptr) {
         // we have a new IGraphicBufferProducer, create a new Surface for it
-        sur = new Surface(surfaceShim.graphicBufferProducer, true);
+        sur = new Surface(surfaceShim.graphicBufferProducer, true,
+                          surfaceShim.surfaceControlHandle);
         // and keep a reference before passing to java
         sur->incStrong(&sRefBaseOwner);
     }
@@ -373,6 +374,7 @@
     android::view::Surface surfaceShim;
     if (self != nullptr) {
         surfaceShim.graphicBufferProducer = self->getIGraphicBufferProducer();
+        surfaceShim.surfaceControlHandle = self->getSurfaceControlHandle();
     }
     // Calling code in Surface.java has already written the name of the Surface
     // to the Parcel
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a61903d..62f844e 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -318,8 +318,13 @@
         }
     }
 
-    status_t err = client->createSurfaceChecked(
-            String8(name.c_str()), w, h, format, &surface, flags, parent, std::move(metadata));
+    sp<IBinder> parentHandle;
+    if (parent != nullptr) {
+        parentHandle = parent->getHandle();
+    }
+
+    status_t err = client->createSurfaceChecked(String8(name.c_str()), w, h, format, &surface,
+                                                flags, parentHandle, std::move(metadata));
     if (err == NAME_NOT_FOUND) {
         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
         return 0;
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 99fe1af..45f64f9 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2761,4 +2761,9 @@
     // CATEGORY: SETTINGS
     // OS: S
     REDUCE_BRIGHT_COLORS_SETTINGS = 1853;
+
+    // OPEN: Settings > Location > Time Zone Detection
+    // CATEGORY: SETTINGS
+    // OS: S
+    LOCATION_TIME_ZONE_DETECTION = 1854;
 }
diff --git a/core/proto/android/os/incident.proto b/core/proto/android/os/incident.proto
index 9fed1b9..fe65bda3 100644
--- a/core/proto/android/os/incident.proto
+++ b/core/proto/android/os/incident.proto
@@ -511,9 +511,14 @@
         (section).args = "sensorservice --proto"
     ];
 
-    optional com.android.server.powerstats.PowerStatsServiceProto powerstats = 3054 [
+    optional com.android.server.powerstats.PowerStatsServiceMeterProto powerstats_meter = 3054 [
         (section).type = SECTION_DUMPSYS,
-        (section).args = "power_stats --proto"
+        (section).args = "power_stats --proto meter"
+    ];
+
+    optional com.android.server.powerstats.PowerStatsServiceModelProto powerstats_model = 3055 [
+        (section).type = SECTION_DUMPSYS,
+        (section).args = "power_stats --proto model"
     ];
 
     // Dumps in text format (on userdebug and eng builds only): 4000 ~ 4999
diff --git a/core/proto/android/server/powerstatsservice.proto b/core/proto/android/server/powerstatsservice.proto
index c805244..9a7ed7c 100644
--- a/core/proto/android/server/powerstatsservice.proto
+++ b/core/proto/android/server/powerstatsservice.proto
@@ -20,44 +20,99 @@
 
 option java_multiple_files = true;
 
-message IncidentReportProto {
+/**
+ * IncidentReportMeterProto is used only in the parsing tool located
+ * in frameworks/base/tools which is used to parse this data out of
+ * incident reports.
+ */
+message IncidentReportMeterProto {
     /** Section number matches that in incident.proto */
-    optional PowerStatsServiceProto incident_report = 3054;
-}
-
-message PowerStatsServiceProto {
-    repeated RailInfoProto rail_info = 1;
-    repeated EnergyDataProto energy_data = 2;
+    optional PowerStatsServiceMeterProto incident_report = 3054;
 }
 
 /**
- * Rail information:
- * Reports information related to the rails being monitored.
+ * IncidentReportModelProto is used only in the parsing tool located
+ * in frameworks/base/tools which is used to parse this data out of
+ * incident reports.
  */
-message RailInfoProto {
-    /** Index corresponding to the rail */
-    optional int32 index = 1;
-
-    /** Name of the rail (opaque to the framework) */
-    optional string rail_name = 2;
-
-    /** Name of the subsystem to which this rail belongs (opaque to the framework) */
-    optional string subsys_name = 3;
-
-    /** Hardware sampling rate */
-    optional int32 sampling_rate = 4;
+message IncidentReportModelProto {
+    /** Section number matches that in incident.proto */
+    optional PowerStatsServiceModelProto incident_report = 3055;
 }
 
 /**
- * Rail level energy measurements:
- * Reports accumulated energy since boot on each rail.
+ * EnergyConsumer (model) data is exposed by the PowerStats HAL.  This data
+ * represents modeled energy consumption estimates and is provided per
+ * subsystem.  The default subsystems are defined in EnergyConsumerId.aidl.
+ * Energy model estimates will be logged to incident reports in addition to
+ * the raw energy meter data.
  */
-message EnergyDataProto {
+message PowerStatsServiceModelProto {
+    repeated EnergyConsumerIdProto energy_consumer_id = 1;
+    repeated EnergyConsumerResultProto energy_consumer_result = 2;
+}
+
+/**
+ * EnergyMeasurement (meter) data is exposed by the PowerStats HAL.  This data
+ * represents measurements taken directly from on-device energy meters.
+ * This raw energy meter data will be logged to incident reports.
+ */
+message PowerStatsServiceMeterProto {
+    repeated ChannelInfoProto channel_info = 1;
+    repeated EnergyMeasurementProto energy_measurement = 2;
+}
+
+/**
+ * Energy consumer ID:
+ * A list of default subsystems for which energy consumption estimates
+ * may be provided (hardware dependent).
+ */
+message EnergyConsumerIdProto {
+    /** Unique index identifying the energy consumer. */
+    optional int32 energy_consumer_id = 1;
+}
+
+/**
+ * Energy consumer result:
+ * An estimate of energy consumption since boot for the subsystem identified
+ * by the unique energy_consumer_id.
+ */
+message EnergyConsumerResultProto {
+    /** Unique index identifying the energy consumer. */
+    optional int32 energy_consumer_id = 1;
+
+    /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
+    optional int64 timestamp_ms = 2;
+
+    /** Accumulated energy since device boot in microwatt-seconds (uWs) */
+    optional int64 energy_uws = 3;
+}
+
+/**
+ * Channel information:
+ * Reports information related to the energy meter channels being monitored.
+ */
+message ChannelInfoProto {
     /**
-     * Index corresponding to the rail. This index matches
-     * the index returned in RailInfo
+     * Index corresponding to the energy meter channel. This index matches
+     * the index returned in ChannelInfo.
      */
-    optional int32 index = 1;
+    optional int32 channel_id = 1;
+
+    /** Name of the energy meter channel */
+    optional string channel_name = 2;
+}
+
+/**
+ * Energy measurements:
+ * Reports accumulated energy since boot for each energy meter.
+ */
+message EnergyMeasurementProto {
+    /**
+     * Index corresponding to the energy meter channel. This index matches
+     * the index returned in ChannelInfo.
+     */
+    optional int32 channel_id = 1;
 
     /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
     optional int64 timestamp_ms = 2;
diff --git a/core/proto/android/stats/style/style_enums.proto b/core/proto/android/stats/style/style_enums.proto
index 828e412..2876882 100644
--- a/core/proto/android/stats/style/style_enums.proto
+++ b/core/proto/android/stats/style/style_enums.proto
@@ -41,6 +41,7 @@
     LIVE_WALLPAPER_QUESTIONNAIRE_SELECT = 19;
     LIVE_WALLPAPER_QUESTIONNAIRE_APPLIED = 20;
     LIVE_WALLPAPER_EFFECT_SHOW = 21;
+    APP_LAUNCHED = 22;
 }
 
 enum LocationPreference {
@@ -55,3 +56,14 @@
     DATE_UNAVAILABLE = 1;
     DATE_MANUAL = 2;
 }
+
+enum LaunchedPreference {
+    LAUNCHED_PREFERENCE_UNSPECIFIED = 0;
+    LAUNCHED_LAUNCHER = 1;
+    LAUNCHED_SETTINGS = 2;
+    LAUNCHED_SUW = 3;
+    LAUNCHED_TIPS = 4;
+    LAUNCHED_LAUNCH_ICON = 5;
+    LAUNCHED_CROP_AND_SET_ACTION = 6;
+    LAUNCHED_DEEP_LINK = 7;
+}
diff --git a/core/proto/android/telephony/enums.proto b/core/proto/android/telephony/enums.proto
index d2c0276..2546b51 100644
--- a/core/proto/android/telephony/enums.proto
+++ b/core/proto/android/telephony/enums.proto
@@ -232,13 +232,13 @@
 // Data profile of the data call. From
 // frameworks/base/telephony/java/com/android/internal/telephony/RILConstants.java
 enum DataProfileEnum {
-    DATA_PROFILE_INVALID = -1;
     DATA_PROFILE_DEFAULT = 0;
     DATA_PROFILE_TETHERED = 1;
     DATA_PROFILE_IMS = 2;
     DATA_PROFILE_FOTA = 3;
     DATA_PROFILE_CBS = 4;
     DATA_PROFILE_OEM_BASE = 1000;
+    DATA_PROFILE_INVALID = -1;
 }
 
 // Reason of data call deactivation. From
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b4b634a..8d51294 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1857,6 +1857,8 @@
     <string name="config_defaultCallScreening" translatable="false"></string>
     <!-- The name of the package that will hold the system gallery role. -->
     <string name="config_systemGallery" translatable="false">com.android.gallery3d</string>
+    <!-- The names of the packages that will hold the automotive projection role. -->
+    <string name="config_systemAutomotiveProjection" translatable="false"></string>
     <!-- The name of the package that will hold the system cluster service role. -->
     <string name="config_systemAutomotiveCluster" translatable="false"></string>
     <!-- The name of the package that will hold the system video call role. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 45bdff9..39989dd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3074,6 +3074,8 @@
     <public name="config_systemAutomotiveCluster" />
     <!-- @hide @SystemApi @TestApi -->
     <public name="config_systemVideoCall" />
+    <!-- @hide @SystemApi @TestApi -->
+    <public name="config_systemAutomotiveProjection" />
   </public-group>
 
   <public-group type="id" first-id="0x01020055">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c2120de..8eb0853 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3056,10 +3056,14 @@
     <!-- Default text for a button that can be toggled on and off. -->
     <string name="capital_off">OFF</string>
 
-    <!-- Default state for CompoundButton for on and off. [CHAR LIMIT=32] -->
+    <!-- Default checked text used by accessibility for a button that can be checked or unchecked. [CHAR LIMIT=NONE] -->
     <string name="checked">checked</string>
-    <!-- Default text for a button that can be toggled on and off. [CHAR LIMIT=32] -->
+    <!-- Default not checked text used by accessibility for a button that can be checked or unchecked. [CHAR LIMIT=NONE] -->
     <string name="not_checked">not checked</string>
+    <!-- Default selected text used by accessibility for an element that can be selected or unselected. [CHAR LIMIT=NONE] -->
+    <string name="selected">selected</string>
+    <!-- Default not selected text used by accessibility for an element that can be selected or unselected. [CHAR LIMIT=NONE] -->
+    <string name="not_selected">not selected</string>
 
     <!-- Title of intent resolver dialog when selecting an application to run. -->
     <string name="whichApplication">Complete action using</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index caa3dff..94397d6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -826,6 +826,7 @@
   <java-symbol type="string" name="no_file_chosen" />
   <java-symbol type="string" name="no_matches" />
   <java-symbol type="string" name="noon" />
+  <java-symbol type="string" name="not_selected" />
   <java-symbol type="string" name="number_picker_increment_scroll_action" />
   <java-symbol type="string" name="number_picker_increment_scroll_mode" />
   <java-symbol type="string" name="old_app_action" />
@@ -959,6 +960,7 @@
   <java-symbol type="string" name="save_password_never" />
   <java-symbol type="string" name="save_password_notnow" />
   <java-symbol type="string" name="save_password_remember" />
+  <java-symbol type="string" name="selected" />
   <java-symbol type="string" name="sendText" />
   <java-symbol type="string" name="sending" />
   <java-symbol type="string" name="serviceClassData" />
diff --git a/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java b/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java
new file mode 100644
index 0000000..faa67a8
--- /dev/null
+++ b/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 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.os;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.testng.Assert.assertThrows;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@Presubmit
+@RunWith(JUnit4.class)
+public class CombinedVibrationEffectTest {
+
+    @Test
+    public void testValidateMono() {
+        CombinedVibrationEffect.createSynced(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+
+        assertThrows(IllegalArgumentException.class,
+                () -> CombinedVibrationEffect.createSynced(new VibrationEffect.OneShot(-1, -1)));
+    }
+
+    @Test
+    public void testSerializationMono() {
+        CombinedVibrationEffect original = CombinedVibrationEffect.createSynced(
+                VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+
+        Parcel parcel = Parcel.obtain();
+        original.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+        CombinedVibrationEffect restored = CombinedVibrationEffect.CREATOR.createFromParcel(parcel);
+        assertEquals(original, restored);
+    }
+}
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index e685292..c357414 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
 
 import android.content.ContentInterface;
 import android.content.ContentResolver;
@@ -100,6 +101,73 @@
     }
 
     @Test
+    public void testValidateOneShot() {
+        VibrationEffect.createOneShot(1, 255).validate();
+        VibrationEffect.createOneShot(1, VibrationEffect.DEFAULT_AMPLITUDE).validate();
+
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createOneShot(-1, 255).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createOneShot(0, 255).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createOneShot(1, -2).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createOneShot(1, 256).validate());
+    }
+
+    @Test
+    public void testValidatePrebaked() {
+        VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK).validate();
+        VibrationEffect.createPredefined(VibrationEffect.RINGTONES[1]).validate();
+
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createPredefined(-1).validate());
+    }
+
+    @Test
+    public void testValidateWaveform() {
+        VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1).validate();
+        VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, 0).validate();
+
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createWaveform(new long[0], new int[0], -1).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createWaveform(TEST_TIMINGS, new int[0], -1).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createWaveform(
+                        new long[]{0, 0, 0}, TEST_AMPLITUDES, -1).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createWaveform(
+                        TEST_TIMINGS, new int[]{-1, -1, -2}, -1).validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.createWaveform(
+                        TEST_TIMINGS, TEST_AMPLITUDES, TEST_TIMINGS.length).validate());
+    }
+
+    @Test
+    public void testValidateComposed() {
+        VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10)
+                .compose()
+                .validate();
+
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.startComposition().addPrimitive(-1).compose().validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.startComposition()
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, -1, 10)
+                        .compose()
+                        .validate());
+        assertThrows(IllegalArgumentException.class,
+                () -> VibrationEffect.startComposition()
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1)
+                        .compose()
+                        .validate());
+    }
+
+    @Test
     public void testScalePrebaked_ignoresScaleAndReturnsSameEffect() {
         VibrationEffect initial = VibrationEffect.get(VibrationEffect.RINGTONES[1]);
         assertSame(initial, initial.scale(0.5f));
diff --git a/core/tests/coretests/src/android/text/TextUtilsTest.java b/core/tests/coretests/src/android/text/TextUtilsTest.java
index 5362be3..a0fc349 100644
--- a/core/tests/coretests/src/android/text/TextUtilsTest.java
+++ b/core/tests/coretests/src/android/text/TextUtilsTest.java
@@ -853,6 +853,8 @@
 
     @Test
     public void testFormatSimple_Advanced() {
+        assertEquals("000000000000002a.ext",
+                formatSimple("%016x.%s", 42, "ext"));
         assertEquals("crtcl=0x002a:intrsv=Y:grnk=0x0018:gsmry=A:example:rnk=0x0000",
                 formatSimple("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
                         42, 'Y', 24, 'A', "example", 0));
diff --git a/core/tests/coretests/src/android/view/inputmethod/SurroundingTextTest.java b/core/tests/coretests/src/android/view/inputmethod/SurroundingTextTest.java
new file mode 100644
index 0000000..dfbc39c
--- /dev/null
+++ b/core/tests/coretests/src/android/view/inputmethod/SurroundingTextTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 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.inputmethod;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class SurroundingTextTest {
+
+    @Test
+    public void testSurroundingTextBasicCreation() {
+        SurroundingText surroundingText1 = new SurroundingText("test", 0, 0, 0);
+        assertThat(surroundingText1.getText(), is("test"));
+        assertThat(surroundingText1.getSelectionStart(), is(0));
+        assertThat(surroundingText1.getSelectionEnd(), is(0));
+        assertThat(surroundingText1.getOffset(), is(0));
+
+        SurroundingText surroundingText2 = new SurroundingText("", -1, -1, -1);
+        assertThat(surroundingText2.getText(), is(""));
+        assertThat(surroundingText2.getSelectionStart(), is(-1));
+        assertThat(surroundingText2.getSelectionEnd(), is(-1));
+        assertThat(surroundingText2.getOffset(), is(-1));
+
+        SurroundingText surroundingText3 = new SurroundingText("hello", 0, 5, 0);
+        assertThat(surroundingText3.getText(), is("hello"));
+        assertThat(surroundingText3.getSelectionStart(), is(0));
+        assertThat(surroundingText3.getSelectionEnd(), is(5));
+        assertThat(surroundingText3.getOffset(), is(0));
+    }
+
+    @Test
+    public void testSurroundingTextWriteToParcel() {
+        SurroundingText surroundingText = new SurroundingText("text", 0, 1, 2);
+        Parcel parcel = Parcel.obtain();
+        surroundingText.writeToParcel(parcel, 0);
+
+        parcel.setDataPosition(0);
+        SurroundingText surroundingTextFromParcel =
+                SurroundingText.CREATOR.createFromParcel(parcel);
+        assertThat(surroundingText.getText(), is("text"));
+        assertThat(surroundingText.getSelectionStart(), is(0));
+        assertThat(surroundingText.getSelectionEnd(), is(1));
+        assertThat(surroundingText.getOffset(), is(2));
+        assertThat(surroundingTextFromParcel.getText(), is("text"));
+        assertThat(surroundingTextFromParcel.getSelectionStart(), is(0));
+        assertThat(surroundingTextFromParcel.getSelectionEnd(), is(1));
+        assertThat(surroundingTextFromParcel.getOffset(), is(2));
+    }
+}
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
index f9140bc..cc68bb6 100644
--- a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiAudioSystemClientTest.java
@@ -376,7 +376,7 @@
         }
 
         @Override
-        public List<String> getAvailableCecSettings() {
+        public List<String> getUserCecSettings() {
             return new ArrayList<>();
         }
 
diff --git a/data/etc/car/com.android.car.provision.xml b/data/etc/car/com.android.car.provision.xml
index 14de7fe..37f64b5 100644
--- a/data/etc/car/com.android.car.provision.xml
+++ b/data/etc/car/com.android.car.provision.xml
@@ -16,8 +16,10 @@
   -->
 <permissions>
     <privapp-permissions package="com.android.car.provision">
+        <permission name="android.car.permission.CAR_POWERTRAIN"/>
         <permission name="android.permission.INTERACT_ACROSS_USERS"/>
         <permission name="android.permission.QUERY_ALL_PACKAGES"/>
+        <permission name="android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
         <permission name="android.permission.WRITE_SETTINGS"/>
     </privapp-permissions>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 98c3370..a430dcd 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -319,6 +319,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
+    "-1729340764": {
+      "message": "setFinishTaskBounds(%d): bounds=%s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_RECENTS_ANIMATIONS",
+      "at": "com\/android\/server\/wm\/RecentsAnimationController.java"
+    },
     "-1715268616": {
       "message": "Last window, removing starting window %s",
       "level": "VERBOSE",
diff --git a/graphics/java/android/graphics/BLASTBufferQueue.java b/graphics/java/android/graphics/BLASTBufferQueue.java
index 8284042..94bfdc9 100644
--- a/graphics/java/android/graphics/BLASTBufferQueue.java
+++ b/graphics/java/android/graphics/BLASTBufferQueue.java
@@ -29,7 +29,7 @@
     private static native long nativeCreate(String name, long surfaceControl, long width,
                                             long height, boolean tripleBufferingEnabled);
     private static native void nativeDestroy(long ptr);
-    private static native Surface nativeGetSurface(long ptr);
+    private static native Surface nativeGetSurface(long ptr, boolean includeSurfaceControlHandle);
     private static native void nativeSetNextTransaction(long ptr, long transactionPtr);
     private static native void nativeUpdate(long ptr, long surfaceControl, long width, long height);
     private static native void nativeFlushShadowQueue(long ptr);
@@ -49,7 +49,15 @@
      * @return a new Surface instance from the IGraphicsBufferProducer of the adapter.
      */
     public Surface createSurface() {
-        return nativeGetSurface(mNativeObject);
+        return nativeGetSurface(mNativeObject, false /* includeSurfaceControlHandle */);
+    }
+
+    /**
+     * @return a new Surface instance from the IGraphicsBufferProducer of the adapter and
+     * the SurfaceControl handle.
+     */
+    public Surface createSurfaceWithHandle() {
+        return nativeGetSurface(mNativeObject, true /* includeSurfaceControlHandle */);
     }
 
     public void setNextTransaction(SurfaceControl.Transaction t) {
diff --git a/graphics/java/android/graphics/RadialGradient.java b/graphics/java/android/graphics/RadialGradient.java
index 089d6de..864331a 100644
--- a/graphics/java/android/graphics/RadialGradient.java
+++ b/graphics/java/android/graphics/RadialGradient.java
@@ -18,6 +18,7 @@
 
 import android.annotation.ColorInt;
 import android.annotation.ColorLong;
+import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -34,6 +35,10 @@
     @UnsupportedAppUsage
     private TileMode mTileMode;
 
+    private final float mFocalX;
+    private final float mFocalY;
+    private final float mFocalRadius;
+
     // @ColorInts are replaced by @ColorLongs, but these remain due to @UnsupportedAppUsage.
     @UnsupportedAppUsage
     @ColorInt
@@ -64,8 +69,8 @@
     public RadialGradient(float centerX, float centerY, float radius,
             @NonNull @ColorInt int[] colors, @Nullable float[] stops,
             @NonNull TileMode tileMode) {
-        this(centerX, centerY, radius, convertColors(colors), stops, tileMode,
-                ColorSpace.get(ColorSpace.Named.SRGB));
+        this(centerX, centerY, 0f, centerX, centerY, radius, convertColors(colors),
+                stops, tileMode, ColorSpace.get(ColorSpace.Named.SRGB));
     }
 
     /**
@@ -88,27 +93,79 @@
     public RadialGradient(float centerX, float centerY, float radius,
             @NonNull @ColorLong long[] colors, @Nullable float[] stops,
             @NonNull TileMode tileMode) {
-        this(centerX, centerY, radius, colors.clone(), stops, tileMode, detectColorSpace(colors));
+        this(centerX, centerY, 0f, centerX, centerY, radius, colors.clone(), stops,
+                tileMode, detectColorSpace(colors));
+    }
+
+    /**
+     * Create a shader that draws a radial gradient given the start and end points as well as
+     * starting and ending radii. The starting point is often referred to as the focal center and
+     * represents the starting circle of the radial gradient.
+     *
+     * @param startX   The x-coordinate of the center of the starting circle of the radial gradient,
+     *                often referred to as the focal point.
+     * @param startY   The y-coordinate of the center of the starting circle of the radial gradient,
+     *                 often referred to as the focal point.
+     * @param startRadius The radius of the starting circle of the radial gradient, often referred
+     *                    to as the focal radius. Must be greater than or equal to zero.
+     * @param endX  The x-coordinate of the center of the radius for the end circle of the
+     *                 radial gradient
+     * @param endY  The y-coordinate of the center of the radius for the end circle of the
+     *                 radial gradient
+     * @param endRadius   The radius of the ending circle for this gradient. This must be strictly
+     *                    greater than zero. A radius value equal to zero is not allowed.
+     * @param colors   The colors to be distributed between the center and edge of the circle
+     * @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
+     *                 <code>1.0f</code>. The relative position of each corresponding color in
+     *                 the colors array. If <code>null</code>, colors are distributed evenly
+     *                 between the center and edge of the circle.
+     * @param tileMode The Shader tiling mode
+     *
+     * @throws IllegalArgumentException If one of the following circumstances:
+     *      - There are less than two colors
+     *      - The colors do not share the same {@link ColorSpace}
+     *      - The colors do not use a valid {@link ColorSpace}
+     *      - The {@code stops} parameter is not {@code null} and has a different length
+     *        from {@code colors}.
+     *      - The {@param startRadius} is negative
+     *      - The {@param endRadius} is less than or equal to zero
+     */
+    public RadialGradient(float startX, float startY, @FloatRange(from = 0.0f) float startRadius,
+            float endX, float endY, @FloatRange(from = 0.0f, fromInclusive = false) float endRadius,
+            @NonNull @ColorLong long[] colors, @Nullable float[] stops,
+            @NonNull TileMode tileMode) {
+        this(startX, startY, startRadius, endX, endY, endRadius, colors.clone(), stops, tileMode,
+                detectColorSpace(colors));
     }
 
     /**
      * Base constructor. Assumes @param colors is a copy that this object can hold onto,
      * and all colors share @param colorSpace.
      */
-    private RadialGradient(float centerX, float centerY, float radius,
-            @NonNull @ColorLong long[] colors, @Nullable float[] stops,
-            @NonNull TileMode tileMode, ColorSpace colorSpace) {
+    private RadialGradient(float startX, float startY, float startRadius, float endX, float endY,
+            float endRadius, @NonNull @ColorLong long[] colors, @Nullable float[] stops,
+            @NonNull TileMode tileMode, ColorSpace colorSpace
+    ) {
         super(colorSpace);
-
-        if (radius <= 0) {
-            throw new IllegalArgumentException("radius must be > 0");
+        // A focal or starting radius of zero with a focal point that matches the center is
+        // identical to a regular radial gradient
+        if (startRadius < 0) {
+            throw new IllegalArgumentException("starting/focal radius must be >= 0");
         }
+
+        if (endRadius <= 0) {
+            throw new IllegalArgumentException("ending radius must be > 0");
+        }
+
         if (stops != null && colors.length != stops.length) {
             throw new IllegalArgumentException("color and position arrays must be of equal length");
         }
-        mX = centerX;
-        mY = centerY;
-        mRadius = radius;
+        mX = endX;
+        mY = endY;
+        mRadius = endRadius;
+        mFocalX = startX;
+        mFocalY = startY;
+        mFocalRadius = startRadius;
         mColorLongs = colors;
         mPositions = stops != null ? stops.clone() : null;
         mTileMode = tileMode;
@@ -150,12 +207,12 @@
     /** @hide */
     @Override
     protected long createNativeInstance(long nativeMatrix) {
-        return nativeCreate(nativeMatrix, mX, mY, mRadius,
-                mColorLongs, mPositions, mTileMode.nativeInt,
-                colorSpace().getNativeInstance());
+        return nativeCreate(nativeMatrix, mFocalX, mFocalY, mFocalRadius, mX, mY, mRadius,
+                mColorLongs, mPositions, mTileMode.nativeInt, colorSpace().getNativeInstance());
     }
 
-    private static native long nativeCreate(long matrix, float x, float y, float radius,
-            @ColorLong long[] colors, float[] positions, int tileMode, long colorSpaceHandle);
+    private static native long nativeCreate(long matrix, float startX, float startY,
+            float startRadius, float endX, float endY, float endRadius, @ColorLong long[] colors,
+            float[] positions, int tileMode, long colorSpaceHandle);
 }
 
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index 90412f4..abf0e8a 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -39,6 +39,7 @@
 import android.os.Message;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -441,10 +442,11 @@
                 resPackage = context.getPackageName();
             }
             if (getResources() == null && !(getResPackage().equals("android"))) {
-                final PackageManager pm = context.getPackageManager();
+                final PackageManager pm = context.createContextAsUser(
+                        UserHandle.of(userId), /* flags */ 0).getPackageManager();
                 try {
                     // assign getResources() as the correct user
-                    mObj1 = pm.getResourcesForApplicationAsUser(resPackage, userId);
+                    mObj1 = pm.getResourcesForApplication(resPackage);
                 } catch (PackageManager.NameNotFoundException e) {
                     Log.e(TAG, String.format("Unable to find pkg=%s user=%d",
                                     getResPackage(),
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 6df62c0..a77aec2 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -535,7 +535,8 @@
         }
         intent.putExtra(EXTRA_ISSUERS, (Serializable) issuersList);
         // the PendingIntent is used to get calling package name
-        intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(), 0));
+        intent.putExtra(EXTRA_SENDER, PendingIntent.getActivity(activity, 0, new Intent(),
+                PendingIntent.FLAG_IMMUTABLE));
         activity.startActivity(intent);
     }
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
index cc5286d..9707260 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java
@@ -177,7 +177,7 @@
                 && (keymasterSwEnforcedUserAuthenticators == 0);
         boolean userAuthenticationValidWhileOnBody =
                 keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
-        boolean trustedUserPresenceRequred =
+        boolean trustedUserPresenceRequired =
                 keyCharacteristics.hwEnforced.getBoolean(
                     KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
 
@@ -209,7 +209,7 @@
                 keymasterHwEnforcedUserAuthenticators,
                 userAuthenticationRequirementEnforcedBySecureHardware,
                 userAuthenticationValidWhileOnBody,
-                trustedUserPresenceRequred,
+                trustedUserPresenceRequired,
                 invalidatedByBiometricEnrollment,
                 userConfirmationRequired);
     }
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java
index 773729e..c82b6e6b 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationUtils.java
@@ -48,7 +48,7 @@
             return null;
         }
 
-        // An error occured. However, some errors should not lead to init throwing an exception.
+        // An error occurred. However, some errors should not lead to init throwing an exception.
         // See below.
         InvalidKeyException e =
                 keyStore.getInvalidKeyException(key.getAlias(), key.getUid(), beginOpResultCode);
diff --git a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
index 02bf385..3f6ca0f 100644
--- a/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
+++ b/libs/WindowManager/Shell/res/raw/wm_shell_protolog.json
@@ -31,12 +31,6 @@
       "group": "WM_SHELL_TASK_ORG",
       "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
     },
-    "-1312360667": {
-      "message": "createRootTask() displayId=%d winMode=%d listener=%s",
-      "level": "VERBOSE",
-      "group": "WM_SHELL_TASK_ORG",
-      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
-    },
     "-880817403": {
       "message": "Task vanished taskId=%d",
       "level": "VERBOSE",
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
index 4cb5fd1..5bd693a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/FullscreenTaskListener.java
@@ -20,7 +20,9 @@
 import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
 
 import android.app.ActivityManager;
-import android.util.ArraySet;
+import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.util.ArrayMap;
 import android.util.Slog;
 import android.view.SurfaceControl;
 
@@ -37,7 +39,7 @@
 
     private final SyncTransactionQueue mSyncQueue;
 
-    private final ArraySet<Integer> mTasks = new ArraySet<>();
+    private final ArrayMap<Integer, SurfaceControl> mTasks = new ArrayMap<>();
 
     FullscreenTaskListener(SyncTransactionQueue syncQueue) {
         mSyncQueue = syncQueue;
@@ -46,16 +48,16 @@
     @Override
     public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
         synchronized (mTasks) {
-            if (mTasks.contains(taskInfo.taskId)) {
+            if (mTasks.containsKey(taskInfo.taskId)) {
                 throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
             }
             ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
                     taskInfo.taskId);
-            mTasks.add(taskInfo.taskId);
+            mTasks.put(taskInfo.taskId, leash);
             mSyncQueue.runInSync(t -> {
                 // Reset several properties back to fullscreen (PiP, for example, leaves all these
                 // properties in a bad state).
-                t.setPosition(leash, 0, 0);
+                updateSurfacePosition(t, taskInfo, leash);
                 t.setWindowCrop(leash, null);
                 // TODO(shell-transitions): Eventually set everything in transition so there's no
                 //                          SF Transaction here.
@@ -71,7 +73,7 @@
     @Override
     public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
         synchronized (mTasks) {
-            if (!mTasks.remove(taskInfo.taskId)) {
+            if (mTasks.remove(taskInfo.taskId) == null) {
                 Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
                 return;
             }
@@ -81,6 +83,23 @@
     }
 
     @Override
+    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        synchronized (mTasks) {
+            if (!mTasks.containsKey(taskInfo.taskId)) {
+                Slog.e(TAG, "Changed Task wasn't appeared or already vanished: #"
+                        + taskInfo.taskId);
+                return;
+            }
+            final SurfaceControl leash = mTasks.get(taskInfo.taskId);
+            mSyncQueue.runInSync(t -> {
+                // Reposition the task in case the bounds has been changed (such as Task level
+                // letterboxing).
+                updateSurfacePosition(t, taskInfo, leash);
+            });
+        }
+    }
+
+    @Override
     public void dump(@NonNull PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
         final String childPrefix = innerPrefix + "  ";
@@ -92,4 +111,13 @@
     public String toString() {
         return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
     }
+
+    /** Places the Task surface to the latest position. */
+    private static void updateSurfacePosition(SurfaceControl.Transaction t,
+            ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
+        // TODO(170725334) drop this after ag/12876439
+        final Configuration config = taskInfo.getConfiguration();
+        final Rect bounds = config.windowConfiguration.getBounds();
+        t.setPosition(leash, bounds.left, bounds.top);
+    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 8bd7193..cbc1c8d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -105,6 +105,8 @@
     // TODO(shell-transitions): move to a more "global" Shell location as this isn't only for Tasks
     private final Transitions mTransitions;
 
+    private final Object mLock = new Object();
+
     public ShellTaskOrganizer(SyncTransactionQueue syncQueue, TransactionPool transactionPool,
             ShellExecutor mainExecutor, ShellExecutor animExecutor) {
         this(null, syncQueue, transactionPool, mainExecutor, animExecutor);
@@ -114,7 +116,7 @@
     ShellTaskOrganizer(ITaskOrganizerController taskOrganizerController,
             SyncTransactionQueue syncQueue, TransactionPool transactionPool,
             ShellExecutor mainExecutor, ShellExecutor animExecutor) {
-        super(taskOrganizerController);
+        super(taskOrganizerController, mainExecutor);
         addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
         mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
         if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
@@ -122,68 +124,62 @@
 
     @Override
     public List<TaskAppearedInfo> registerOrganizer() {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Registering organizer");
-        final List<TaskAppearedInfo> taskInfos = super.registerOrganizer();
-        for (int i = 0; i < taskInfos.size(); i++) {
-            final TaskAppearedInfo info = taskInfos.get(i);
-            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s",
-                    info.getTaskInfo().taskId, info.getTaskInfo().baseIntent);
-            onTaskAppeared(info);
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "Registering organizer");
+            final List<TaskAppearedInfo> taskInfos = super.registerOrganizer();
+            for (int i = 0; i < taskInfos.size(); i++) {
+                final TaskAppearedInfo info = taskInfos.get(i);
+                ProtoLog.v(WM_SHELL_TASK_ORG, "Existing task: id=%d component=%s",
+                        info.getTaskInfo().taskId, info.getTaskInfo().baseIntent);
+                onTaskAppeared(info);
+            }
+            return taskInfos;
         }
-        return taskInfos;
-    }
-
-    public TaskAppearedInfo createRootTask(
-            int displayId, int windowingMode, TaskListener listener) {
-        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG,
-                "createRootTask() displayId=%d winMode=%d listener=%s",
-                displayId, windowingMode, listener.toString());
-        final TaskAppearedInfo info = super.createRootTask(displayId, windowingMode);
-
-        // Add the listener and send the task appeared signal
-        mTaskListeners.put(info.getTaskInfo().taskId, listener);
-        onTaskAppeared(info);
-        return info;
     }
 
     /**
      * Adds a listener for a specific task id.
      */
     public void addListenerForTaskId(TaskListener listener, int taskId) {
-        ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId);
-        if (mTaskListeners.get(taskId) != null) {
-            throw new IllegalArgumentException("Listener for taskId=" + taskId + " already exists");
-        }
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForTaskId taskId=%s", taskId);
+            if (mTaskListeners.get(taskId) != null) {
+                throw new IllegalArgumentException(
+                        "Listener for taskId=" + taskId + " already exists");
+            }
 
-        final TaskAppearedInfo info = mTasks.get(taskId);
-        if (info == null) {
-            throw new IllegalArgumentException("addListenerForTaskId unknown taskId=" + taskId);
-        }
+            final TaskAppearedInfo info = mTasks.get(taskId);
+            if (info == null) {
+                throw new IllegalArgumentException("addListenerForTaskId unknown taskId=" + taskId);
+            }
 
-        final TaskListener oldListener = getTaskListener(info.getTaskInfo());
-        mTaskListeners.put(taskId, listener);
-        updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener);
+            final TaskListener oldListener = getTaskListener(info.getTaskInfo());
+            mTaskListeners.put(taskId, listener);
+            updateTaskListenerIfNeeded(info.getTaskInfo(), info.getLeash(), oldListener, listener);
+        }
     }
 
     /**
      * Adds a listener for tasks with given types.
      */
     public void addListenerForType(TaskListener listener, @TaskListenerType int... listenerTypes) {
-        ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s",
-                Arrays.toString(listenerTypes), listener);
-        for (int listenerType : listenerTypes) {
-            if (mTaskListeners.get(listenerType) != null) {
-                throw new IllegalArgumentException("Listener for listenerType=" + listenerType
-                        + " already exists");
-            }
-            mTaskListeners.put(listenerType, listener);
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "addListenerForType types=%s listener=%s",
+                    Arrays.toString(listenerTypes), listener);
+            for (int listenerType : listenerTypes) {
+                if (mTaskListeners.get(listenerType) != null) {
+                    throw new IllegalArgumentException("Listener for listenerType=" + listenerType
+                            + " already exists");
+                }
+                mTaskListeners.put(listenerType, listener);
 
-            // Notify the listener of all existing tasks with the given type.
-            for (int i = mTasks.size() - 1; i >= 0; --i) {
-                final TaskAppearedInfo data = mTasks.valueAt(i);
-                final TaskListener taskListener = getTaskListener(data.getTaskInfo());
-                if (taskListener != listener) continue;
-                listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
+                // Notify the listener of all existing tasks with the given type.
+                for (int i = mTasks.size() - 1; i >= 0; --i) {
+                    final TaskAppearedInfo data = mTasks.valueAt(i);
+                    final TaskListener taskListener = getTaskListener(data.getTaskInfo());
+                    if (taskListener != listener) continue;
+                    listener.onTaskAppeared(data.getTaskInfo(), data.getLeash());
+                }
             }
         }
     }
@@ -192,30 +188,32 @@
      * Removes a registered listener.
      */
     public void removeListener(TaskListener listener) {
-        ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
-        final int index = mTaskListeners.indexOfValue(listener);
-        if (index == -1) {
-            Log.w(TAG, "No registered listener found");
-            return;
-        }
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "Remove listener=%s", listener);
+            final int index = mTaskListeners.indexOfValue(listener);
+            if (index == -1) {
+                Log.w(TAG, "No registered listener found");
+                return;
+            }
 
-        // Collect tasks associated with the listener we are about to remove.
-        final ArrayList<TaskAppearedInfo> tasks = new ArrayList<>();
-        for (int i = mTasks.size() - 1; i >= 0; --i) {
-            final TaskAppearedInfo data = mTasks.valueAt(i);
-            final TaskListener taskListener = getTaskListener(data.getTaskInfo());
-            if (taskListener != listener) continue;
-            tasks.add(data);
-        }
+            // Collect tasks associated with the listener we are about to remove.
+            final ArrayList<TaskAppearedInfo> tasks = new ArrayList<>();
+            for (int i = mTasks.size() - 1; i >= 0; --i) {
+                final TaskAppearedInfo data = mTasks.valueAt(i);
+                final TaskListener taskListener = getTaskListener(data.getTaskInfo());
+                if (taskListener != listener) continue;
+                tasks.add(data);
+            }
 
-        // Remove listener
-        mTaskListeners.removeAt(index);
+            // Remove listener
+            mTaskListeners.removeAt(index);
 
-        // Associate tasks with new listeners if needed.
-        for (int i = tasks.size() - 1; i >= 0; --i) {
-            final TaskAppearedInfo data = tasks.get(i);
-            updateTaskListenerIfNeeded(data.getTaskInfo(), data.getLeash(),
-                    null /* oldListener already removed*/, getTaskListener(data.getTaskInfo()));
+            // Associate tasks with new listeners if needed.
+            for (int i = tasks.size() - 1; i >= 0; --i) {
+                final TaskAppearedInfo data = tasks.get(i);
+                updateTaskListenerIfNeeded(data.getTaskInfo(), data.getLeash(),
+                        null /* oldListener already removed*/, getTaskListener(data.getTaskInfo()));
+            }
         }
     }
 
@@ -224,12 +222,16 @@
      * appears.
      */
     public void setPendingLaunchCookieListener(IBinder cookie, TaskListener listener) {
-        mLaunchCookieToListener.put(cookie, listener);
+        synchronized (mLock) {
+            mLaunchCookieToListener.put(cookie, listener);
+        }
     }
 
     @Override
     public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
-        onTaskAppeared(new TaskAppearedInfo(taskInfo, leash));
+        synchronized (mLock) {
+            onTaskAppeared(new TaskAppearedInfo(taskInfo, leash));
+        }
     }
 
     private void onTaskAppeared(TaskAppearedInfo info) {
@@ -245,35 +247,41 @@
 
     @Override
     public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
-        ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
-        final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
-        final TaskListener oldListener = getTaskListener(data.getTaskInfo());
-        final TaskListener newListener = getTaskListener(taskInfo);
-        mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash()));
-        final boolean updated = updateTaskListenerIfNeeded(
-                taskInfo, data.getLeash(), oldListener, newListener);
-        if (!updated && newListener != null) {
-            newListener.onTaskInfoChanged(taskInfo);
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "Task info changed taskId=%d", taskInfo.taskId);
+            final TaskAppearedInfo data = mTasks.get(taskInfo.taskId);
+            final TaskListener oldListener = getTaskListener(data.getTaskInfo());
+            final TaskListener newListener = getTaskListener(taskInfo);
+            mTasks.put(taskInfo.taskId, new TaskAppearedInfo(taskInfo, data.getLeash()));
+            final boolean updated = updateTaskListenerIfNeeded(
+                    taskInfo, data.getLeash(), oldListener, newListener);
+            if (!updated && newListener != null) {
+                newListener.onTaskInfoChanged(taskInfo);
+            }
         }
     }
 
     @Override
     public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
-        ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId);
-        final TaskListener listener = getTaskListener(taskInfo);
-        if (listener != null) {
-            listener.onBackPressedOnTaskRoot(taskInfo);
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "Task root back pressed taskId=%d", taskInfo.taskId);
+            final TaskListener listener = getTaskListener(taskInfo);
+            if (listener != null) {
+                listener.onBackPressedOnTaskRoot(taskInfo);
+            }
         }
     }
 
     @Override
     public void onTaskVanished(RunningTaskInfo taskInfo) {
-        ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId);
-        final int taskId = taskInfo.taskId;
-        final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
-        mTasks.remove(taskId);
-        if (listener != null) {
-            listener.onTaskVanished(taskInfo);
+        synchronized (mLock) {
+            ProtoLog.v(WM_SHELL_TASK_ORG, "Task vanished taskId=%d", taskInfo.taskId);
+            final int taskId = taskInfo.taskId;
+            final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
+            mTasks.remove(taskId);
+            if (listener != null) {
+                listener.onTaskVanished(taskInfo);
+            }
         }
     }
 
@@ -368,32 +376,34 @@
     }
 
     public void dump(@NonNull PrintWriter pw, String prefix) {
-        final String innerPrefix = prefix + "  ";
-        final String childPrefix = innerPrefix + "  ";
-        pw.println(prefix + TAG);
-        pw.println(innerPrefix + mTaskListeners.size() + " Listeners");
-        for (int i = mTaskListeners.size() - 1; i >= 0; --i) {
-            final int key = mTaskListeners.keyAt(i);
-            final TaskListener listener = mTaskListeners.valueAt(i);
-            pw.println(innerPrefix + "#" + i + " " + taskListenerTypeToString(key));
-            listener.dump(pw, childPrefix);
-        }
+        synchronized (mLock) {
+            final String innerPrefix = prefix + "  ";
+            final String childPrefix = innerPrefix + "  ";
+            pw.println(prefix + TAG);
+            pw.println(innerPrefix + mTaskListeners.size() + " Listeners");
+            for (int i = mTaskListeners.size() - 1; i >= 0; --i) {
+                final int key = mTaskListeners.keyAt(i);
+                final TaskListener listener = mTaskListeners.valueAt(i);
+                pw.println(innerPrefix + "#" + i + " " + taskListenerTypeToString(key));
+                listener.dump(pw, childPrefix);
+            }
 
-        pw.println();
-        pw.println(innerPrefix + mTasks.size() + " Tasks");
-        for (int i = mTasks.size() - 1; i >= 0; --i) {
-            final int key = mTasks.keyAt(i);
-            final TaskAppearedInfo info = mTasks.valueAt(i);
-            final TaskListener listener = getTaskListener(info.getTaskInfo());
-            pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener);
-        }
+            pw.println();
+            pw.println(innerPrefix + mTasks.size() + " Tasks");
+            for (int i = mTasks.size() - 1; i >= 0; --i) {
+                final int key = mTasks.keyAt(i);
+                final TaskAppearedInfo info = mTasks.valueAt(i);
+                final TaskListener listener = getTaskListener(info.getTaskInfo());
+                pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener);
+            }
 
-        pw.println();
-        pw.println(innerPrefix + mLaunchCookieToListener.size() + " Launch Cookies");
-        for (int i = mLaunchCookieToListener.size() - 1; i >= 0; --i) {
-            final IBinder key = mLaunchCookieToListener.keyAt(i);
-            final TaskListener listener = mLaunchCookieToListener.valueAt(i);
-            pw.println(innerPrefix + "#" + i + " cookie=" + key + " listener=" + listener);
+            pw.println();
+            pw.println(innerPrefix + mLaunchCookieToListener.size() + " Launch Cookies");
+            for (int i = mLaunchCookieToListener.size() - 1; i >= 0; --i) {
+                final IBinder key = mLaunchCookieToListener.keyAt(i);
+                final TaskListener listener = mLaunchCookieToListener.valueAt(i);
+                pw.println(innerPrefix + "#" + i + " cookie=" + key + " listener=" + listener);
+            }
         }
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
index 36e49d9..04be3b7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/Transitions.java
@@ -109,13 +109,13 @@
         mAnimExecutor.execute(va::start);
     }
 
-    private static boolean isOpeningType(@WindowManager.TransitionType int legacyType) {
+    private static boolean isOpeningType(@WindowManager.TransitionOldType int legacyType) {
         // TODO(shell-transitions): consider providing and using z-order vs the global type for
         //                          this determination.
-        return legacyType == WindowManager.TRANSIT_TASK_OPEN
-                || legacyType == WindowManager.TRANSIT_TASK_TO_FRONT
-                || legacyType == WindowManager.TRANSIT_TASK_OPEN_BEHIND
-                || legacyType == WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+        return legacyType == WindowManager.TRANSIT_OLD_TASK_OPEN
+                || legacyType == WindowManager.TRANSIT_OLD_TASK_TO_FRONT
+                || legacyType == WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND
+                || legacyType == WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
index 6d6cc20..0831818 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsHandler.java
@@ -60,7 +60,6 @@
     private float mDefaultAspectRatio;
     private float mMinAspectRatio;
     private float mMaxAspectRatio;
-    private float mAspectRatio;
     private int mDefaultStackGravity;
     private int mDefaultMinSize;
     private Point mScreenEdgeInsets;
@@ -80,7 +79,7 @@
         // Initialize the aspect ratio to the default aspect ratio.  Don't do this in reload
         // resources as it would clobber mAspectRatio when entering PiP from fullscreen which
         // triggers a configuration change and the resources to be reloaded.
-        mAspectRatio = mDefaultAspectRatio;
+        mPipBoundsState.setAspectRatio(mDefaultAspectRatio);
     }
 
     /**
@@ -133,10 +132,6 @@
         mCurrentMinSize = minEdgeSize;
     }
 
-    protected float getAspectRatio() {
-        return mAspectRatio;
-    }
-
     /**
      * Sets both shelf visibility and its height if applicable.
      * @return {@code true} if the internal shelf state is changed, {@code false} otherwise.
@@ -172,8 +167,8 @@
         if (animatingBounds.isEmpty()) {
             animatingBounds.set(defaultBounds);
         }
-        if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
-            transformBoundsToAspectRatio(normalBounds, mAspectRatio,
+        if (isValidPictureInPictureAspectRatio(mPipBoundsState.getAspectRatio())) {
+            transformBoundsToAspectRatio(normalBounds, mPipBoundsState.getAspectRatio(),
                     false /* useCurrentMinEdgeSize */, false /* useCurrentSize */);
         }
         displayInfo.copyFrom(mDisplayInfo);
@@ -212,27 +207,16 @@
     }
 
     /**
-     * Responds to IPinnedStackListener on resetting aspect ratio for the pinned window.
-     * It will normally follow up with a
-     * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} callback.
+     * See {@link #getDestinationBounds(Rect, Size, boolean)}
      */
-    public void onAspectRatioChanged(float aspectRatio) {
-        mAspectRatio = aspectRatio;
-    }
-
-    /**
-     * See {@link #getDestinationBounds(float, Rect, Size, boolean)}
-     */
-    public Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
-        return getDestinationBounds(aspectRatio, bounds, minimalSize,
-                false /* useCurrentMinEdgeSize */);
+    public Rect getDestinationBounds(Rect bounds, Size minimalSize) {
+        return getDestinationBounds(bounds, minimalSize, false /* useCurrentMinEdgeSize */);
     }
 
     /**
      * @return {@link Rect} of the destination PiP window bounds.
      */
-    public Rect getDestinationBounds(float aspectRatio, Rect bounds,
-            Size minimalSize, boolean useCurrentMinEdgeSize) {
+    public Rect getDestinationBounds(Rect bounds, Size minimalSize, boolean useCurrentMinEdgeSize) {
         boolean isReentryBounds = false;
         final Rect destinationBounds;
         if (bounds == null) {
@@ -255,11 +239,10 @@
             // Just adjusting bounds (e.g. on aspect ratio changed).
             destinationBounds = new Rect(bounds);
         }
-        if (isValidPictureInPictureAspectRatio(aspectRatio)) {
-            transformBoundsToAspectRatio(destinationBounds, aspectRatio, useCurrentMinEdgeSize,
-                    isReentryBounds);
+        if (isValidPictureInPictureAspectRatio(mPipBoundsState.getAspectRatio())) {
+            transformBoundsToAspectRatio(destinationBounds, mPipBoundsState.getAspectRatio(),
+                    useCurrentMinEdgeSize, isReentryBounds);
         }
-        mAspectRatio = aspectRatio;
         return destinationBounds;
     }
 
@@ -368,8 +351,8 @@
      * @param stackBounds
      */
     public void transformBoundsToAspectRatio(Rect stackBounds) {
-        transformBoundsToAspectRatio(stackBounds, mAspectRatio, true /* useCurrentMinEdgeSize */,
-                true /* useCurrentSize */);
+        transformBoundsToAspectRatio(stackBounds, mPipBoundsState.getAspectRatio(),
+                true /* useCurrentMinEdgeSize */, true /* useCurrentSize */);
     }
 
     /**
@@ -514,7 +497,6 @@
         pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
         pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
         pw.println(innerPrefix + "mMaxAspectRatio=" + mMaxAspectRatio);
-        pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
         pw.println(innerPrefix + "mDefaultStackGravity=" + mDefaultStackGravity);
         pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
         pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index 2625f16..aba2a3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -34,6 +34,7 @@
     private static final String TAG = PipBoundsState.class.getSimpleName();
 
     private final @NonNull Rect mBounds = new Rect();
+    private float mAspectRatio;
     private PipReentryState mPipReentryState;
     private ComponentName mLastPipComponentName;
 
@@ -46,6 +47,14 @@
         return new Rect(mBounds);
     }
 
+    public void setAspectRatio(float aspectRatio) {
+        mAspectRatio = aspectRatio;
+    }
+
+    public float getAspectRatio() {
+        return mAspectRatio;
+    }
+
     /**
      * Save the reentry state to restore to when re-entering PIP mode.
      *
@@ -120,6 +129,7 @@
         pw.println(prefix + TAG);
         pw.println(innerPrefix + "mBounds=" + mBounds);
         pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
+        pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
         if (mPipReentryState == null) {
             pw.println(innerPrefix + "mPipReentryState=null");
         } else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index cd5d35b..a284775 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -68,7 +68,6 @@
 import com.android.wm.shell.pip.phone.PipMenuActivityController;
 import com.android.wm.shell.pip.phone.PipMotionHelper;
 import com.android.wm.shell.pip.phone.PipUpdateThread;
-import com.android.wm.shell.pip.phone.PipUtils;
 import com.android.wm.shell.splitscreen.SplitScreen;
 
 import java.io.PrintWriter;
@@ -339,11 +338,11 @@
     public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
             PictureInPictureParams pictureInPictureParams) {
         mShouldIgnoreEnteringPipTransition = true;
-        mState = State.ENTERING_PIP;
+        sendOnPipTransitionStarted(componentName, TRANSITION_DIRECTION_TO_PIP);
         mPipBoundsState.setLastPipComponentName(componentName);
-        return mPipBoundsHandler.getDestinationBounds(
-                getAspectRatioOrDefault(pictureInPictureParams),
-                null /* bounds */, getMinimalSize(activityInfo));
+        mPipBoundsState.setAspectRatio(getAspectRatioOrDefault(pictureInPictureParams));
+        return mPipBoundsHandler.getDestinationBounds(null /* bounds */,
+                getMinimalSize(activityInfo));
     }
 
     /**
@@ -351,7 +350,10 @@
      * Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards.
      */
     public void stopSwipePipToHome(ComponentName componentName, Rect destinationBounds) {
-        mPipBoundsState.setBounds(destinationBounds);
+        // do nothing if there is no startSwipePipToHome being called before
+        if (mShouldIgnoreEnteringPipTransition) {
+            mPipBoundsState.setBounds(destinationBounds);
+        }
     }
 
     /**
@@ -494,11 +496,9 @@
         }
 
         if (mShouldIgnoreEnteringPipTransition) {
-            // Animation has been finished together with Recents, directly apply the sync
-            // transaction to PiP here.
-            applyEnterPipSyncTransaction(mPipBoundsState.getBounds(), () -> {
-                mState = State.ENTERED_PIP;
-            });
+            // animation is finished in the Launcher and here we directly apply the final touch.
+            applyEnterPipSyncTransaction(mPipBoundsState.getBounds(),
+                    () -> sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP));
             mShouldIgnoreEnteringPipTransition = false;
             return;
         }
@@ -514,9 +514,9 @@
             return;
         }
 
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                getAspectRatioOrDefault(mPictureInPictureParams),
-                null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
+        mPipBoundsState.setAspectRatio(getAspectRatioOrDefault(mPictureInPictureParams));
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(null /* bounds */,
+                getMinimalSize(mTaskInfo.topActivityInfo));
         Objects.requireNonNull(destinationBounds, "Missing destination bounds");
         final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
 
@@ -589,11 +589,19 @@
 
     private void sendOnPipTransitionStarted(
             @PipAnimationController.TransitionDirection int direction) {
+        sendOnPipTransitionStarted(mTaskInfo.baseActivity, direction);
+    }
+
+    private void sendOnPipTransitionStarted(ComponentName componentName,
+            @PipAnimationController.TransitionDirection int direction) {
+        if (direction == TRANSITION_DIRECTION_TO_PIP) {
+            mState = State.ENTERING_PIP;
+        }
         final Rect pipBounds = mPipBoundsState.getBounds();
         runOnMainHandler(() -> {
             for (int i = mPipTransitionCallbacks.size() - 1; i >= 0; i--) {
                 final PipTransitionCallback callback = mPipTransitionCallbacks.get(i);
-                callback.onPipTransitionStarted(mTaskInfo.baseActivity, direction, pipBounds);
+                callback.onPipTransitionStarted(componentName, direction, pipBounds);
             }
         });
     }
@@ -703,6 +711,7 @@
             return;
         }
         mShouldDeferEnteringPip = false;
+        mShouldIgnoreEnteringPipTransition = false;
         mPictureInPictureParams = null;
         mState = State.UNDEFINED;
         mPipUiEventLoggerLogger.setTaskInfo(null);
@@ -717,8 +726,8 @@
             Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
             return;
         }
+        // Aspect ratio changed, re-calculate destination bounds.
         final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                getAspectRatioOrDefault(newParams),
                 mPipBoundsState.getBounds(), getMinimalSize(info.topActivityInfo),
                 true /* userCurrentMinEdgeSize */);
         Objects.requireNonNull(destinationBounds, "Missing destination bounds");
@@ -735,7 +744,6 @@
     public void onFixedRotationFinished(int displayId) {
         if (mShouldDeferEnteringPip && mState.isInPip()) {
             final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
-                    getAspectRatioOrDefault(mPictureInPictureParams),
                     null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
             // schedule a regular animation to ensure all the callbacks are still being sent
             enterPipWithAlphaAnimation(destinationBounds, 0 /* durationMs */);
@@ -808,9 +816,8 @@
             return;
         }
 
-        final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
-                getAspectRatioOrDefault(mPictureInPictureParams),
-                null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
+        final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(null /* bounds */,
+                getMinimalSize(mTaskInfo.topActivityInfo));
         if (newDestinationBounds.equals(currentDestinationBounds)) return;
         if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
             animator.updateEndValue(newDestinationBounds);
@@ -831,7 +838,7 @@
                 params.getAspectRatioRational());
         mPictureInPictureParams = params;
         if (aspectRatioChanged) {
-            mPipBoundsHandler.onAspectRatioChanged(params.getAspectRatio());
+            mPipBoundsState.setAspectRatio(params.getAspectRatio());
         }
         return aspectRatioChanged;
     }
@@ -1083,7 +1090,6 @@
         return WINDOWING_MODE_UNDEFINED;
     }
 
-
     private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
             @PipAnimationController.TransitionDirection int direction, int durationMs) {
         if (Looper.myLooper() != mUpdateHandler.getLooper()) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index a089837..edc68e5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -197,8 +197,10 @@
 
         @Override
         public void onAspectRatioChanged(float aspectRatio) {
+            // TODO(b/169373982): Remove this callback as it is redundant with PipTaskOrg params
+            // change.
             mHandler.post(() -> {
-                mPipBoundsHandler.onAspectRatioChanged(aspectRatio);
+                mPipBoundsState.setAspectRatio(aspectRatio);
                 mTouchHandler.onAspectRatioChanged();
             });
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java
index 22c05fb..64e3758 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMediaController.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.pip.phone;
 
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
 
 import android.app.IActivityManager;
@@ -180,25 +181,25 @@
         mPauseAction = new RemoteAction(Icon.createWithResource(mContext,
                 R.drawable.pip_ic_pause_white), pauseDescription, pauseDescription,
                 PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PAUSE),
-                        FLAG_UPDATE_CURRENT));
+                        FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
 
         String playDescription = mContext.getString(R.string.pip_play);
         mPlayAction = new RemoteAction(Icon.createWithResource(mContext,
                 R.drawable.pip_ic_play_arrow_white), playDescription, playDescription,
                 PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PLAY),
-                        FLAG_UPDATE_CURRENT));
+                        FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
 
         String nextDescription = mContext.getString(R.string.pip_skip_to_next);
         mNextAction = new RemoteAction(Icon.createWithResource(mContext,
                 R.drawable.pip_ic_skip_next_white), nextDescription, nextDescription,
                 PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NEXT),
-                        FLAG_UPDATE_CURRENT));
+                        FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
 
         String prevDescription = mContext.getString(R.string.pip_skip_to_prev);
         mPrevAction = new RemoteAction(Icon.createWithResource(mContext,
                 R.drawable.pip_ic_skip_previous_white), prevDescription, prevDescription,
                 PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_PREV),
-                        FLAG_UPDATE_CURRENT));
+                        FLAG_UPDATE_CURRENT | FLAG_IMMUTABLE));
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
index 0a1aadc..f763d6d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskOrganizer.java
@@ -33,7 +33,6 @@
 import android.view.Display;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
-import android.window.TaskAppearedInfo;
 
 import androidx.annotation.NonNull;
 
@@ -69,15 +68,10 @@
     void init() throws RemoteException {
         synchronized (this) {
             try {
-                final TaskAppearedInfo primary = mTaskOrganizer.createRootTask(
-                        Display.DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, this);
-                final TaskAppearedInfo secondary = mTaskOrganizer.createRootTask(
-                        Display.DEFAULT_DISPLAY, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, this);
-                mPrimary = primary.getTaskInfo();
-                mPrimarySurface = primary.getLeash();
-                mSecondary = secondary.getTaskInfo();
-                mSecondarySurface = secondary.getLeash();
-                enableSplitScreenSupportIfNeeded();
+                mPrimary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
+                        WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+                mSecondary = mTaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
+                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
             } catch (Exception e) {
                 // teardown to prevent callbacks
                 mTaskOrganizer.removeListener(this);
@@ -98,29 +92,43 @@
         mSplitScreenController.mTransactionPool.release(t);
     }
 
-    private void enableSplitScreenSupportIfNeeded() {
-        if (mSplitScreenSupported || mPrimarySurface == null || mSecondarySurface == null) return;
+    @Override
+    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+        synchronized (this) {
+            if (mPrimary == null || mSecondary == null) {
+                Log.w(TAG, "Received onTaskAppeared before creating root tasks " + taskInfo);
+                return;
+            }
 
-        mSplitScreenSupported = true;
+            if (taskInfo.token.equals(mPrimary.token)) {
+                mPrimarySurface = leash;
+            } else if (taskInfo.token.equals(mSecondary.token)) {
+                mSecondarySurface = leash;
+            }
 
-        // Initialize dim surfaces:
-        mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
-                .setParent(mPrimarySurface).setColorLayer()
-                .setName("Primary Divider Dim")
-                .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
-                .build();
-        mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
-                .setParent(mSecondarySurface).setColorLayer()
-                .setName("Secondary Divider Dim")
-                .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
-                .build();
-        SurfaceControl.Transaction t = getTransaction();
-        t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
-        t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
-        t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
-        t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
-        t.apply();
-        releaseTransaction(t);
+            if (!mSplitScreenSupported && mPrimarySurface != null && mSecondarySurface != null) {
+                mSplitScreenSupported = true;
+
+                // Initialize dim surfaces:
+                mPrimaryDim = new SurfaceControl.Builder(mSurfaceSession)
+                        .setParent(mPrimarySurface).setColorLayer()
+                        .setName("Primary Divider Dim")
+                        .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
+                        .build();
+                mSecondaryDim = new SurfaceControl.Builder(mSurfaceSession)
+                        .setParent(mSecondarySurface).setColorLayer()
+                        .setName("Secondary Divider Dim")
+                        .setCallsite("SplitScreenTaskOrganizer.onTaskAppeared")
+                        .build();
+                SurfaceControl.Transaction t = getTransaction();
+                t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
+                t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
+                t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
+                t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
+                t.apply();
+                releaseTransaction(t);
+            }
+        }
     }
 
     @Override
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 4ff2bfc..8c4f546 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -26,7 +26,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("statusBarWindowIsAlwaysVisible", enabled, bugId) {
+    all("statusBarWindowIsAlwaysVisible", bugId, enabled) {
         this.showsAboveAppWindow(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
     }
 }
@@ -36,7 +36,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("navBarWindowIsAlwaysVisible", enabled, bugId) {
+    all("navBarWindowIsAlwaysVisible", bugId, enabled) {
         this.showsAboveAppWindow(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
     }
 }
@@ -52,7 +52,7 @@
     val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
     val endingBounds = WindowUtils.getDisplayBounds(endRotation)
     if (allStates) {
-        all("noUncoveredRegions", enabled, bugId) {
+        all("noUncoveredRegions", bugId, enabled) {
             if (startingBounds == endingBounds) {
                 this.coversAtLeastRegion(startingBounds)
             } else {
@@ -76,7 +76,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("navBarLayerIsAlwaysVisible", enabled, bugId) {
+    all("navBarLayerIsAlwaysVisible", bugId, enabled) {
         this.showsLayer(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE)
     }
 }
@@ -86,7 +86,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("statusBarLayerIsAlwaysVisible", enabled, bugId) {
+    all("statusBarLayerIsAlwaysVisible", bugId, enabled) {
         this.showsLayer(FlickerTestBase.STATUS_BAR_WINDOW_TITLE)
     }
 }
@@ -101,15 +101,15 @@
     val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
     val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
 
-    start("navBarLayerRotatesAndScales_StartingPos", enabled, bugId) {
+    start("navBarLayerRotatesAndScales_StartingPos", bugId, enabled) {
         this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
     }
-    end("navBarLayerRotatesAndScales_EndingPost", enabled, bugId) {
+    end("navBarLayerRotatesAndScales_EndingPost", bugId, enabled) {
         this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, endingPos)
     }
 
     if (startingPos == endingPos) {
-        all("navBarLayerRotatesAndScales", enabled, bugId) {
+        all("navBarLayerRotatesAndScales", bugId, enabled) {
             this.hasVisibleRegion(FlickerTestBase.NAVIGATION_BAR_WINDOW_TITLE, startingPos)
         }
     }
@@ -125,10 +125,10 @@
     val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
     val endingPos = WindowUtils.getStatusBarPosition(endRotation)
 
-    start("statusBarLayerRotatesScales_StartingPos", enabled, bugId) {
+    start("statusBarLayerRotatesScales_StartingPos", bugId, enabled) {
         this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, startingPos)
     }
-    end("statusBarLayerRotatesScales_EndingPos", enabled, bugId) {
+    end("statusBarLayerRotatesScales_EndingPos", bugId, enabled) {
         this.hasVisibleRegion(FlickerTestBase.STATUS_BAR_WINDOW_TITLE, endingPos)
     }
 }
diff --git a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
index 3b66c58..7f8321f 100644
--- a/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/test-apps/flickerapp/AndroidManifest.xml
@@ -32,6 +32,10 @@
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+            </intent-filter>
         </activity>
         <activity android:name=".ImeActivity"
              android:taskAffinity="com.android.wm.shell.flicker.testapp.ImeActivity"
@@ -41,6 +45,10 @@
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
             </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
+            </intent-filter>
         </activity>
     </application>
 </manifest>
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
index e0ac8e2..39117bb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipBoundsHandlerTest.java
@@ -123,7 +123,8 @@
                 (MAX_ASPECT_RATIO + DEFAULT_ASPECT_RATIO) / 2
         };
         for (float aspectRatio : aspectRatios) {
-            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+            mPipBoundsState.setAspectRatio(aspectRatio);
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                     EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
             final float actualAspectRatio =
                     destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -139,7 +140,8 @@
                 MAX_ASPECT_RATIO * 2
         };
         for (float aspectRatio : invalidAspectRatios) {
-            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+            mPipBoundsState.setAspectRatio(aspectRatio);
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                     EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
             final float actualAspectRatio =
                     destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -155,8 +157,9 @@
         final Rect currentBounds = new Rect(0, 0, 0, 100);
         currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
 
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
-                currentBounds, EMPTY_MINIMAL_SIZE);
+        mPipBoundsState.setAspectRatio(aspectRatio);
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(currentBounds,
+                EMPTY_MINIMAL_SIZE);
 
         final float actualAspectRatio =
                 destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -179,7 +182,8 @@
         for (int i = 0; i < aspectRatios.length; i++) {
             final float aspectRatio = aspectRatios[i];
             final Size minimalSize = minimalSizes[i];
-            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+            mPipBoundsState.setAspectRatio(aspectRatio);
+            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                     EMPTY_CURRENT_BOUNDS, minimalSize);
             assertTrue("Destination bounds is no smaller than minimal requirement",
                     (destinationBounds.width() == minimalSize.getWidth()
@@ -200,7 +204,8 @@
         currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
         final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);
 
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(aspectRatio,
+        mPipBoundsState.setAspectRatio(aspectRatio);
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                 currentBounds, minSize);
 
         assertTrue("Destination bounds ignores minimal size",
@@ -210,13 +215,14 @@
 
     @Test
     public void getDestinationBounds_reentryStateExists_restoreLastSize() {
-        final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
+        final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
         reentryBounds.scale(1.25f);
         final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
 
         mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         assertEquals(reentryBounds.width(), destinationBounds.width());
@@ -225,14 +231,15 @@
 
     @Test
     public void getDestinationBounds_reentryStateExists_restoreLastPosition() {
-        final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
+        final Rect reentryBounds = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
         reentryBounds.offset(0, -100);
         final float reentrySnapFraction = mPipBoundsHandler.getSnapFraction(reentryBounds);
 
         mPipBoundsState.saveReentryState(reentryBounds, reentrySnapFraction);
 
-        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         assertBoundsInclusionWithMargin("restoreLastPosition", reentryBounds, destinationBounds);
@@ -241,11 +248,12 @@
     @Test
     public void setShelfHeight_offsetBounds() {
         final int shelfHeight = 100;
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsHandler.setShelfHeight(true, shelfHeight);
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -shelfHeight);
@@ -255,11 +263,12 @@
     @Test
     public void onImeVisibilityChanged_offsetBounds() {
         final int imeHeight = 100;
-        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
+        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
-        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         oldPosition.offset(0, -imeHeight);
@@ -268,12 +277,13 @@
 
     @Test
     public void getDestinationBounds_noReentryState_useDefaultBounds() {
-        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        mPipBoundsState.setAspectRatio(DEFAULT_ASPECT_RATIO);
+        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         mPipBoundsState.clearReentryState();
 
-        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(DEFAULT_ASPECT_RATIO,
+        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(
                 EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
 
         assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp
index e36e355..45795ff 100644
--- a/libs/hwui/jni/Shader.cpp
+++ b/libs/hwui/jni/Shader.cpp
@@ -133,11 +133,25 @@
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
-static jlong RadialGradient_create(JNIEnv* env, jobject, jlong matrixPtr, jfloat x, jfloat y,
-        jfloat radius, jlongArray colorArray, jfloatArray posArray, jint tileMode,
+static jlong RadialGradient_create(JNIEnv* env,
+        jobject,
+        jlong matrixPtr,
+        jfloat startX,
+        jfloat startY,
+        jfloat startRadius,
+        jfloat endX,
+        jfloat endY,
+        jfloat endRadius,
+        jlongArray colorArray,
+        jfloatArray posArray,
+        jint tileMode,
         jlong colorSpaceHandle) {
-    SkPoint center;
-    center.set(x, y);
+
+    SkPoint start;
+    start.set(startX, startY);
+
+    SkPoint end;
+    end.set(endX, endY);
 
     std::vector<SkColor4f> colors = convertColorLongs(env, colorArray);
 
@@ -148,11 +162,17 @@
     #error Need to convert float array to SkScalar array before calling the following function.
 #endif
 
-    sk_sp<SkShader> shader = SkGradientShader::MakeRadial(center, radius, &colors[0],
-            GraphicsJNI::getNativeColorSpace(colorSpaceHandle), pos, colors.size(),
-            static_cast<SkTileMode>(tileMode), sGradientShaderFlags, nullptr);
+    auto colorSpace = GraphicsJNI::getNativeColorSpace(colorSpaceHandle);
+    auto skTileMode = static_cast<SkTileMode>(tileMode);
+    sk_sp<SkShader> shader = SkGradientShader::MakeTwoPointConical(start, startRadius, end,
+                    endRadius, &colors[0], std::move(colorSpace), pos, colors.size(), skTileMode,
+                    sGradientShaderFlags, nullptr);
     ThrowIAE_IfNull(env, shader);
 
+    // Explicitly create a new shader with the specified matrix to match existing behavior.
+    // Passing in the matrix in the instantiation above can throw exceptions for non-invertible
+    // matrices. However, makeWithLocalMatrix will still allow for the shader to be created
+    // and skia handles null-shaders internally (i.e. is ignored)
     const SkMatrix* matrix = reinterpret_cast<const SkMatrix*>(matrixPtr);
     if (matrix) {
         shader = shader->makeWithLocalMatrix(*matrix);
@@ -279,7 +299,7 @@
 };
 
 static const JNINativeMethod gRadialGradientMethods[] = {
-    { "nativeCreate",     "(JFFF[J[FIJ)J",  (void*)RadialGradient_create     },
+    { "nativeCreate",     "(JFFFFFF[J[FIJ)J",  (void*)RadialGradient_create     },
 };
 
 static const JNINativeMethod gSweepGradientMethods[] = {
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 195122d..8b28cc4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4049,7 +4049,8 @@
         //     the associated intent will be handled by the component being registered
         mediaButtonIntent.setComponent(eventReceiver);
         PendingIntent pi = PendingIntent.getBroadcast(getContext(),
-                0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
+                0/*requestCode, ignored*/, mediaButtonIntent,
+                PendingIntent.FLAG_IMMUTABLE);
         registerMediaButtonIntent(pi, eventReceiver);
     }
 
@@ -4102,7 +4103,8 @@
         //     the associated intent will be handled by the component being registered
         mediaButtonIntent.setComponent(eventReceiver);
         PendingIntent pi = PendingIntent.getBroadcast(getContext(),
-                0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
+                0/*requestCode, ignored*/, mediaButtonIntent,
+                PendingIntent.FLAG_IMMUTABLE);
         unregisterMediaButtonIntent(pi);
     }
 
diff --git a/native/android/Android.bp b/native/android/Android.bp
index 797d3fd..02e1ebe 100644
--- a/native/android/Android.bp
+++ b/native/android/Android.bp
@@ -105,6 +105,7 @@
 cc_library_shared {
     name: "libandroid_net",
     defaults: ["libandroid_defaults"],
+    llndk_stubs: "libandroid_net.llndk",
     srcs: ["net.c"],
 
     shared_libs: ["libnetd_client"],
@@ -113,7 +114,7 @@
 }
 
 llndk_library {
-    name: "libandroid_net",
+    name: "libandroid_net.llndk",
     export_include_dirs: ["include"],
     symbol_file: "libandroid_net.map.txt",
     unversioned: true,
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 0a466f4..c503721 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -137,12 +137,24 @@
         return nullptr;
     }
 
+    Surface* surface = static_cast<Surface*>(window);
+    sp<IBinder> parentHandle = surface->getSurfaceControlHandle();
+
     uint32_t flags = ISurfaceComposerClient::eFXSurfaceBufferState;
-    sp<SurfaceControl> surfaceControl =
-            client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */,
-                                            // Format is only relevant for buffer queue layers.
-                                            PIXEL_FORMAT_UNKNOWN /* format */, flags,
-                                            static_cast<Surface*>(window));
+    sp<SurfaceControl> surfaceControl;
+    if (parentHandle) {
+        surfaceControl =
+                client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */,
+                                      // Format is only relevant for buffer queue layers.
+                                      PIXEL_FORMAT_UNKNOWN /* format */, flags, parentHandle);
+    } else {
+        surfaceControl =
+                client->createWithSurfaceParent(String8(debug_name), 0 /* width */, 0 /* height */,
+                                                // Format is only relevant for buffer queue layers.
+                                                PIXEL_FORMAT_UNKNOWN /* format */, flags,
+                                                static_cast<Surface*>(window));
+    }
+
     if (!surfaceControl) {
         return nullptr;
     }
@@ -164,7 +176,7 @@
             client->createSurface(String8(debug_name), 0 /* width */, 0 /* height */,
                                   // Format is only relevant for buffer queue layers.
                                   PIXEL_FORMAT_UNKNOWN /* format */, flags,
-                                  surfaceControlParent);
+                                  surfaceControlParent->getHandle());
     if (!surfaceControl) {
         return nullptr;
     }
diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt
index 4029202..3a4eda0 100644
--- a/non-updatable-api/current.txt
+++ b/non-updatable-api/current.txt
@@ -11718,7 +11718,10 @@
     method public android.graphics.drawable.Drawable getIcon(int);
     method public CharSequence getLabel();
     method public String getName();
+    method public float getProgress();
     method public android.os.UserHandle getUser();
+    method public boolean isLoading();
+    method public boolean isStartable();
   }
 
   public class LauncherApps {
@@ -11758,6 +11761,7 @@
     ctor public LauncherApps.Callback();
     method public abstract void onPackageAdded(String, android.os.UserHandle);
     method public abstract void onPackageChanged(String, android.os.UserHandle);
+    method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
     method public abstract void onPackageRemoved(String, android.os.UserHandle);
     method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
     method public void onPackagesSuspended(String[], android.os.UserHandle);
@@ -15435,6 +15439,7 @@
   public class RadialGradient extends android.graphics.Shader {
     ctor public RadialGradient(float, float, float, @ColorInt @NonNull int[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
+    ctor public RadialGradient(float, float, @FloatRange(from=0.0f) float, float, float, @FloatRange(from=0.0f, fromInclusive=false) float, @ColorLong @NonNull long[], @Nullable float[], @NonNull android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, @ColorInt int, @ColorInt int, @NonNull android.graphics.Shader.TileMode);
     ctor public RadialGradient(float, float, float, @ColorLong long, @ColorLong long, @NonNull android.graphics.Shader.TileMode);
   }
@@ -55536,6 +55541,7 @@
     method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
     method public android.os.Handler getHandler();
     method public CharSequence getSelectedText(int);
+    method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
     method public CharSequence getTextAfterCursor(int, int);
     method public CharSequence getTextBeforeCursor(int, int);
     method public boolean performContextMenuAction(int);
@@ -55744,6 +55750,17 @@
     method public android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder setSubtypeNameResId(int);
   }
 
+  public final class SurroundingText implements android.os.Parcelable {
+    ctor public SurroundingText(@NonNull CharSequence, @IntRange(from=0) int, @IntRange(from=0) int, @IntRange(from=0xffffffff) int);
+    method public int describeContents();
+    method @IntRange(from=0xffffffff) public int getOffset();
+    method @IntRange(from=0) public int getSelectionEnd();
+    method @IntRange(from=0) public int getSelectionStart();
+    method @NonNull public CharSequence getText();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.SurroundingText> CREATOR;
+  }
+
 }
 
 package android.view.inspector {
diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt
index e871814..5c8c4d5 100644
--- a/non-updatable-api/system-current.txt
+++ b/non-updatable-api/system-current.txt
@@ -310,6 +310,7 @@
     field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
     field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
     field public static final int config_systemAutomotiveCluster = 17039400; // 0x1040028
+    field public static final int config_systemAutomotiveProjection = 17039402; // 0x104002a
     field public static final int config_systemGallery = 17039399; // 0x1040027
     field public static final int config_systemVideoCall = 17039401; // 0x1040029
   }
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 8667ba1..b6179ed 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -154,4 +154,13 @@
 
     <!-- The Activity name for the Rear View Camera, if empty, the feature will be disabled. -->
     <string name="config_rearViewCameraActivity" translatable="false"></string>
+
+    <!-- Whether the Notification Panel should be inset by the top system bar. -->
+    <bool name="config_notif_panel_inset_by_top_systembar" translatable="false">false</bool>
+    <!-- Whether the Notification Panel should be inset by the bottom system bar. -->
+    <bool name="config_notif_panel_inset_by_bottom_systembar" translatable="false">true</bool>
+    <!-- Whether the Notification Panel should be inset by the left system bar. -->
+    <bool name="config_notif_panel_inset_by_left_systembar" translatable="false">false</bool>
+    <!-- Whether the Notification Panel should be inset by the right system bar. -->
+    <bool name="config_notif_panel_inset_by_right_systembar" translatable="false">false</bool>
 </resources>
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index 4b66069..599e69c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -49,6 +49,7 @@
 import com.android.systemui.car.CarDeviceProvisionedController;
 import com.android.systemui.car.CarServiceProvider;
 import com.android.systemui.car.window.OverlayPanelViewController;
+import com.android.systemui.car.window.OverlayViewController;
 import com.android.systemui.car.window.OverlayViewGlobalStateController;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -84,6 +85,11 @@
     private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
     private final NotificationVisibilityLogger mNotificationVisibilityLogger;
 
+    private final boolean mFitTopSystemBarInset;
+    private final boolean mFitBottomSystemBarInset;
+    private final boolean mFitLeftSystemBarInset;
+    private final boolean mFitRightSystemBarInset;
+
     private float mInitialBackgroundAlpha;
     private float mBackgroundAlphaDiff;
 
@@ -164,6 +170,15 @@
         mEnableHeadsUpNotificationWhenNotificationShadeOpen = mResources.getBoolean(
                 com.android.car.notification.R.bool
                         .config_enableHeadsUpNotificationWhenNotificationShadeOpen);
+
+        mFitTopSystemBarInset = mResources.getBoolean(
+                R.bool.config_notif_panel_inset_by_top_systembar);
+        mFitBottomSystemBarInset = mResources.getBoolean(
+                R.bool.config_notif_panel_inset_by_bottom_systembar);
+        mFitLeftSystemBarInset = mResources.getBoolean(
+                R.bool.config_notif_panel_inset_by_left_systembar);
+        mFitRightSystemBarInset = mResources.getBoolean(
+                R.bool.config_notif_panel_inset_by_right_systembar);
     }
 
     // CommandQueue.Callbacks
@@ -215,8 +230,26 @@
     }
 
     @Override
-    protected int getInsetTypesToFit() {
-        return WindowInsets.Type.navigationBars();
+    protected int getInsetSidesToFit() {
+        int insetSidesToFit = OverlayViewController.NO_INSET_SIDE;
+
+        if (mFitTopSystemBarInset) {
+            insetSidesToFit = insetSidesToFit | WindowInsets.Side.TOP;
+        }
+
+        if (mFitBottomSystemBarInset) {
+            insetSidesToFit = insetSidesToFit | WindowInsets.Side.BOTTOM;
+        }
+
+        if (mFitLeftSystemBarInset) {
+            insetSidesToFit = insetSidesToFit | WindowInsets.Side.LEFT;
+        }
+
+        if (mFitRightSystemBarInset) {
+            insetSidesToFit = insetSidesToFit | WindowInsets.Side.RIGHT;
+        }
+
+        return insetSidesToFit;
     }
 
     @Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
index 6c3a632..b989c42 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
@@ -27,6 +27,9 @@
  * Owns a {@link View} that is present in SystemUIOverlayWindow.
  */
 public class OverlayViewController {
+    protected static final int INVALID_INSET_SIDE = -1;
+    protected static final int NO_INSET_SIDE = 0;
+
     private final int mStubId;
     private final OverlayViewGlobalStateController mOverlayViewGlobalStateController;
 
@@ -188,4 +191,28 @@
     protected int getInsetTypesToFit() {
         return statusBars();
     }
+
+    /**
+     * Optionally returns the sides of enabled system bar insets to fit to the sysui overlay window
+     * when this {@link OverlayViewController} is in the foreground.
+     *
+     * For example, if the bottom and left system bars are enabled and this method returns
+     * WindowInsets.Side.LEFT, then the inset from the bottom system bar will be ignored.
+     *
+     * NOTE: By default, this method returns {@link #INVALID_INSET_SIDE}, so insets to fit are
+     * defined by {@link #getInsetTypesToFit()}, and not by this method, unless it is overridden
+     * by subclasses.
+     *
+     * NOTE: {@link #NO_INSET_SIDE} signifies no insets from any system bars will be honored. Each
+     * {@link OverlayViewController} can first take this value and add sides of the system bar
+     * insets to honor to it.
+     *
+     * NOTE: If getInsetSidesToFit is overridden to return {@link WindowInsets.Side}, it always
+     * takes precedence over {@link #getInsetTypesToFit()}. That is, the return value of {@link
+     * #getInsetTypesToFit()} will be ignored.
+     */
+    @WindowInsets.Side.InsetsSide
+    protected int getInsetSidesToFit() {
+        return INVALID_INSET_SIDE;
+    }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
index 0da2360..10f436b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
@@ -21,6 +21,8 @@
 
 import android.annotation.Nullable;
 import android.util.Log;
+import android.view.WindowInsets;
+import android.view.WindowInsets.Side.InsetsSide;
 import android.view.WindowInsets.Type.InsetsType;
 import android.view.WindowInsetsController;
 
@@ -119,7 +121,7 @@
 
         updateInternalsWhenShowingView(viewController);
         refreshUseStableInsets();
-        refreshInsetTypesToFit();
+        refreshInsetsToFit();
         refreshWindowFocus();
         refreshNavigationBarVisibility();
         refreshStatusBarVisibility();
@@ -193,7 +195,7 @@
         mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
         refreshHighestZOrderWhenHidingView(viewController);
         refreshUseStableInsets();
-        refreshInsetTypesToFit();
+        refreshInsetsToFit();
         refreshWindowFocus();
         refreshNavigationBarVisibility();
         refreshStatusBarVisibility();
@@ -255,11 +257,25 @@
                 mHighestZOrder == null ? false : mHighestZOrder.shouldUseStableInsets());
     }
 
-    private void refreshInsetTypesToFit() {
+    /**
+     * Refreshes the insets to fit (or honor) either by {@link InsetsType} or {@link InsetsSide}.
+     *
+     * By default, the insets to fit are defined by the {@link InsetsType}. But if an
+     * {@link OverlayViewController} overrides {@link OverlayViewController#getInsetSidesToFit()} to
+     * return an {@link InsetsSide}, then that takes precedence over {@link InsetsType}.
+     */
+    private void refreshInsetsToFit() {
         if (mZOrderVisibleSortedMap.isEmpty()) {
             setFitInsetsTypes(statusBars());
         } else {
-            setFitInsetsTypes(mHighestZOrder.getInsetTypesToFit());
+            if (mHighestZOrder.getInsetSidesToFit() != OverlayViewController.INVALID_INSET_SIDE) {
+                // First fit all system bar insets as setFitInsetsSide defines which sides of system
+                // bar insets to actually honor.
+                setFitInsetsTypes(WindowInsets.Type.systemBars());
+                setFitInsetsSides(mHighestZOrder.getInsetSidesToFit());
+            } else {
+                setFitInsetsTypes(mHighestZOrder.getInsetTypesToFit());
+            }
         }
     }
 
@@ -272,10 +288,16 @@
         mSystemUIOverlayWindowController.setWindowVisible(visible);
     }
 
+    /** Sets the insets to fit based on the {@link InsetsType} */
     private void setFitInsetsTypes(@InsetsType int types) {
         mSystemUIOverlayWindowController.setFitInsetsTypes(types);
     }
 
+    /** Sets the insets to fit based on the {@link InsetsSide} */
+    private void setFitInsetsSides(@InsetsSide int sides) {
+        mSystemUIOverlayWindowController.setFitInsetsSides(sides);
+    }
+
     /**
      * Sets the {@link android.view.WindowManager.LayoutParams#FLAG_ALT_FOCUSABLE_IM} flag of the
      * sysui overlay window.
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
index b22de84..0e73f25 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
@@ -120,6 +120,13 @@
         updateWindow();
     }
 
+    /** Sets the sides of system bar insets to fit. Note: This should be rarely used. */
+    public void setFitInsetsSides(@WindowInsets.Side.InsetsSide int sides) {
+        mLpChanged.setFitInsetsSides(sides);
+        mLpChanged.setFitInsetsIgnoringVisibility(mUsingStableInsets);
+        updateWindow();
+    }
+
     /** Sets the window to the visible state. */
     public void setWindowVisible(boolean visible) {
         mVisible = visible;
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java
index 294aa0d..9c2931a 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java
@@ -33,6 +33,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
+import android.view.WindowInsets;
 import android.view.WindowInsetsController;
 
 import androidx.test.filters.SmallTest;
@@ -887,6 +888,65 @@
         verify(mOverlayViewController2, never()).inflate(mBaseLayout);
     }
 
+    @Test
+    public void showView_setInsetsToFitByType_setsFitInsetsType() {
+        int insetTypeToFit = WindowInsets.Type.navigationBars();
+        setupOverlayViewController1();
+        when(mOverlayViewController1.getInsetTypesToFit()).thenReturn(insetTypeToFit);
+
+        mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+        verify(mSystemUIOverlayWindowController).setFitInsetsTypes(insetTypeToFit);
+    }
+
+    @Test
+    public void refreshInsetsToFit_setInsetsToFitBySide_setsFitInsetsSides() {
+        int insetSidesToFit = WindowInsets.Side.LEFT;
+        setupOverlayViewController1();
+        when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit);
+
+        mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+        verify(mSystemUIOverlayWindowController).setFitInsetsSides(insetSidesToFit);
+    }
+
+    @Test
+    public void refreshInsetsToFit_setInsetsToFitBySideUsed_firstFitsAllSystemBars() {
+        int insetSidesToFit = WindowInsets.Side.LEFT;
+        setupOverlayViewController1();
+        when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit);
+
+        mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+        verify(mSystemUIOverlayWindowController).setFitInsetsTypes(WindowInsets.Type.systemBars());
+    }
+
+    @Test
+    public void refreshInsetsToFit_bothInsetTypeAndSideDefined_insetSideTakesPrecedence() {
+        int insetTypesToFit = WindowInsets.Type.navigationBars();
+        int insetSidesToFit = WindowInsets.Side.LEFT;
+        setupOverlayViewController1();
+        when(mOverlayViewController1.getInsetTypesToFit()).thenReturn(insetTypesToFit);
+        when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit);
+
+        mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+        verify(mSystemUIOverlayWindowController).setFitInsetsSides(insetSidesToFit);
+    }
+
+    @Test
+    public void refreshInsetsToFit_bothInsetTypeAndSideDefined_insetTypeIgnored() {
+        int insetTypesToFit = WindowInsets.Type.navigationBars();
+        int insetSidesToFit = WindowInsets.Side.LEFT;
+        setupOverlayViewController1();
+        when(mOverlayViewController1.getInsetTypesToFit()).thenReturn(insetTypesToFit);
+        when(mOverlayViewController1.getInsetSidesToFit()).thenReturn(insetSidesToFit);
+
+        mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+        verify(mSystemUIOverlayWindowController, never()).setFitInsetsTypes(insetTypesToFit);
+    }
+
     private void setupOverlayViewController1() {
         setupOverlayViewController(mOverlayViewController1, R.id.overlay_view_controller_stub_1,
                 R.id.overlay_view_controller_1);
@@ -913,6 +973,8 @@
         }
         when(overlayViewController.getLayout()).thenReturn(layout);
         when(overlayViewController.isInflated()).thenReturn(true);
+        when(overlayViewController.getInsetSidesToFit()).thenReturn(
+                OverlayViewController.INVALID_INSET_SIDE);
     }
 
     private void setOverlayViewControllerAsShowing(OverlayViewController overlayViewController) {
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 7c8dc24..8c55328 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -97,7 +97,7 @@
     <string name="bluetooth_hearing_aid_profile_summary_connected" msgid="8191273236809964030">"श्रवण यंत्रांशी कनेक्ट केले आहे"</string>
     <string name="bluetooth_a2dp_profile_summary_connected" msgid="7422607970115444153">"मीडिया ऑडिओवर कनेक्ट केले"</string>
     <string name="bluetooth_headset_profile_summary_connected" msgid="2420981566026949688">"फोन ऑडिओ वर कनेक्ट केले"</string>
-    <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"फाईल स्थानांतर सर्व्हरवर कनेक्ट केले"</string>
+    <string name="bluetooth_opp_profile_summary_connected" msgid="2393521801478157362">"फाइल स्थानांतर सर्व्हरवर कनेक्ट केले"</string>
     <string name="bluetooth_map_profile_summary_connected" msgid="4141725591784669181">"नकाशाशी कनेक्ट केले"</string>
     <string name="bluetooth_sap_profile_summary_connected" msgid="1280297388033001037">"SAP शी कनेक्‍ट केले"</string>
     <string name="bluetooth_opp_profile_summary_not_connected" msgid="3959741824627764954">"फाइल स्थानांतर सर्व्हरशी कनेक्ट केले नाही"</string>
@@ -109,7 +109,7 @@
     <string name="bluetooth_sap_profile_summary_use_for" msgid="6204902866176714046">"SIM प्रवेशासाठी वापरा"</string>
     <string name="bluetooth_a2dp_profile_summary_use_for" msgid="7324694226276491807">"मीडिया ऑडिओसाठी वापरा"</string>
     <string name="bluetooth_headset_profile_summary_use_for" msgid="808970643123744170">"फोन ऑडिओसाठी वापरा"</string>
-    <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"फाईल स्थानांतरणासाठी वापरा"</string>
+    <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"फाइल स्थानांतरणासाठी वापरा"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"इनपुट साठी वापरा"</string>
     <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"श्रवण यंत्रांसाठी वापरा"</string>
     <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"पेअर करा"</string>
@@ -268,8 +268,8 @@
     <string name="bluetooth_select_a2dp_codec_type_help_info" msgid="8647200416514412338">"फोन किंवा हेडसेटला सपोर्ट करत नाही म्हणजे ती निकामी झाली आहे"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample" msgid="6253965294594390806">"प्रति पॅटर्न ब्लूटूध ऑडिओ बिट"</string>
     <string name="bluetooth_select_a2dp_codec_bits_per_sample_dialog_title" msgid="4898693684282596143">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: बिट प्रति नमुना"</string>
-    <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडिओ चॅनेल मोड"</string>
-    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: चॅनेल मोड"</string>
+    <string name="bluetooth_select_a2dp_codec_channel_mode" msgid="364277285688014427">"ब्लूटूथ ऑडिओ चॅनल मोड"</string>
+    <string name="bluetooth_select_a2dp_codec_channel_mode_dialog_title" msgid="2076949781460359589">"ब्लूटूथ ऑडिओ Codec ट्रिगर करा\nनिवड: चॅनल मोड"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality" msgid="3233402355917446304">"ब्लूटूथ ऑडिओ LDAC कोडेक: प्लेबॅक गुणवत्ता"</string>
     <string name="bluetooth_select_a2dp_codec_ldac_playback_quality_dialog_title" msgid="7274396574659784285">"ब्लूटूथ ऑडिओ LDAC\nकोडेक निवड ट्रिगर करा: प्लेबॅक गुणवत्ता"</string>
     <string name="bluetooth_select_a2dp_codec_streaming_label" msgid="2040810756832027227">"स्ट्रीमिंग: <xliff:g id="STREAMING_PARAMETER">%1$s</xliff:g>"</string>
@@ -370,7 +370,7 @@
     <string name="app_process_limit_title" msgid="8361367869453043007">"पार्श्वभूमी प्रक्रिया मर्यादा"</string>
     <string name="show_all_anrs" msgid="9160563836616468726">"बॅकग्राउंड ANR दाखवा"</string>
     <string name="show_all_anrs_summary" msgid="8562788834431971392">"बॅकग्राउंड अ‍ॅप्ससाठी अ‍ॅप प्रतिसाद देत नाही दाखवते"</string>
-    <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना चॅनेल चेतावण्या दाखवा"</string>
+    <string name="show_notification_channel_warnings" msgid="3448282400127597331">"सूचना चॅनल चेतावण्या दाखवा"</string>
     <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"एखादे अ‍ॅप वैध चॅनेलशिवाय सूचना पोस्ट करते तेव्हा स्क्रीनवर चेतावणी देते"</string>
     <string name="force_allow_on_external" msgid="9187902444231637880">"बाह्यवर ॲप्सना अनुमती देण्याची सक्ती करा"</string>
     <string name="force_allow_on_external_summary" msgid="8525425782530728238">"manifest मूल्यांकडे दुर्लक्ष करून, कोणत्याही ॲपला बाह्य स्टोरेजवर लेखन केले जाण्यासाठी पात्र बनविते"</string>
@@ -404,11 +404,11 @@
     <string name="select_webview_provider_title" msgid="3917815648099445503">"वेबदृश्य अंमलबजावणी"</string>
     <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"वेबदृश्य अंमलबजावणी सेट करा"</string>
     <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"ही निवड यापुढे वैध असणार नाही. पुन्हा प्रयत्न करा."</string>
-    <string name="convert_to_file_encryption" msgid="2828976934129751818">"फाईल कूटबद्धीकरणावर रूपांतरित करा"</string>
+    <string name="convert_to_file_encryption" msgid="2828976934129751818">"फाइल कूटबद्धीकरणावर रूपांतरित करा"</string>
     <string name="convert_to_file_encryption_enabled" msgid="840757431284311754">"रूपांतरित करा..."</string>
-    <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"फाईल आधीपासून एंक्रिप्ट होती"</string>
-    <string name="title_convert_fbe" msgid="5780013350366495149">"फाईल आधारित कूटबद्धीकरणावर रूपांतरित करणे"</string>
-    <string name="convert_to_fbe_warning" msgid="34294381569282109">"फाईल आधारित कूटबद्धीकरणावर डेटा विभाजक रूपांतरित करा.\n !!चेतावणी!! हे आपल्‍या सर्व डेटास मिटवेल.\n हे वैशिष्ट्य अल्‍फा आहे आणि कदाचित योग्यरित्या कार्य करू शकत नाही.\n सुरू ठेवण्‍यासाठी \'पुसा आणि रूपांतरित करा...\' दाबा."</string>
+    <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"फाइल आधीपासून एंक्रिप्ट होती"</string>
+    <string name="title_convert_fbe" msgid="5780013350366495149">"फाइल आधारित कूटबद्धीकरणावर रूपांतरित करणे"</string>
+    <string name="convert_to_fbe_warning" msgid="34294381569282109">"फाइल आधारित कूटबद्धीकरणावर डेटा विभाजक रूपांतरित करा.\n !!चेतावणी!! हे आपल्‍या सर्व डेटास मिटवेल.\n हे वैशिष्ट्य अल्‍फा आहे आणि कदाचित योग्यरित्या कार्य करू शकत नाही.\n सुरू ठेवण्‍यासाठी \'पुसा आणि रूपांतरित करा...\' दाबा."</string>
     <string name="button_convert_fbe" msgid="1159861795137727671">"पुसा आणि रुपांतरित करा..."</string>
     <string name="picture_color_mode" msgid="1013807330552931903">"चित्र रंग मोड"</string>
     <string name="picture_color_mode_desc" msgid="151780973768136200">"sRGB वापरा"</string>
@@ -525,7 +525,7 @@
     <string name="accessor_expires_text" msgid="4625619273236786252">"भाडेपट्टी <xliff:g id="DATE">%s</xliff:g> रोजी एक्स्पायर होईल"</string>
     <string name="delete_blob_text" msgid="2819192607255625697">"शेअर केलेला डेटा हटवा"</string>
     <string name="delete_blob_confirmation_text" msgid="7807446938920827280">"तुम्हाला नक्की हा शेअर केलेला डेटा हटवायचा आहे का?"</string>
-    <string name="user_add_user_item_summary" msgid="5748424612724703400">"वापरकर्त्यांकडे त्यांचे स्वत:चे अ‍ॅप्स आणि सामग्री आहे"</string>
+    <string name="user_add_user_item_summary" msgid="5748424612724703400">"वापरकर्त्यांकडे त्यांचे स्वत:चे अ‍ॅप्स आणि आशय आहे"</string>
     <string name="user_add_profile_item_summary" msgid="5418602404308968028">"तुम्ही आपल्या खात्यावरुन अ‍ॅप्स आणि सामग्रीमध्ये प्रवेश करण्यास प्रतिबंध करु शकता"</string>
     <string name="user_add_user_item_title" msgid="2394272381086965029">"वापरकर्ता"</string>
     <string name="user_add_profile_item_title" msgid="3111051717414643029">"प्रतिबंधित प्रोफाईल"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e7b1482..197655e 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -451,7 +451,7 @@
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
     <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Laddas långsamt"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Laddar inte"</string>
-    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Inkopplad, kan inte laddas just nu"</string>
+    <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Ansluten, kan inte laddas just nu"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Fullt"</string>
     <string name="disabled_by_admin_summary_text" msgid="5343911767402923057">"Strys av administratören"</string>
     <string name="disabled" msgid="8017887509554714950">"Inaktiverad"</string>
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index c1bdb56..c4b36fb 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -142,7 +142,6 @@
         Settings.Secure.CHARGING_VIBRATION_ENABLED,
         Settings.Secure.ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS,
         Settings.Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS,
-        Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL,
         Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK,
         Settings.Secure.UI_NIGHT_MODE,
         Settings.Secure.DARK_THEME_CUSTOM_START_TIME,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 388bf28..7f694ad 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -206,7 +206,6 @@
                 Secure.ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(Secure.USER_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.ASSIST_GESTURE_SETUP_COMPLETE, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.TRUST_AGENTS_EXTEND_UNLOCK, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, JSON_OBJECT_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_WHEN_TRUST_LOST, BOOLEAN_VALIDATOR);
diff --git a/packages/SystemUI/docs/broadcasts.md b/packages/SystemUI/docs/broadcasts.md
index 8ec20f5..e709278 100644
--- a/packages/SystemUI/docs/broadcasts.md
+++ b/packages/SystemUI/docs/broadcasts.md
@@ -62,17 +62,17 @@
  * @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an
  *                 executor in the main thread (default).
  * @param user A user handle to determine which broadcast should be dispatched to this receiver.
- *             By default, it is the user of the context (system user in SystemUI).
+ *             Pass `null` to use the user of the context (system user in SystemUI).
  * @throws IllegalArgumentException if the filter has other constraints that are not actions or
  *                                  categories or the filter has no actions.
  */
 @JvmOverloads
-fun registerReceiver(
-        BroadcastReceiver, 
-        IntentFilter, 
-        Executor? = context.mainExecutor,
-        UserHandle = context.user
-) {
+open fun registerReceiver(
+    receiver: BroadcastReceiver,
+    filter: IntentFilter,
+    executor: Executor? = null,
+    user: UserHandle? = null
+)
 ```
 
 All subscriptions are done with the same overloaded method. As specified in the doc, in order to pass a `UserHandle` with the default `Executor`, pass `null` for the `Executor`.
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index f22c729..3714db3 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -67,6 +67,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentEnd="true"
         android:layout_alignParentTop="true"
+        android:layout_marginBottom="24dp"
         android:visibility="gone">
         <com.android.keyguard.GradientTextClock
             android:id="@+id/gradient_clock_view"
@@ -88,4 +89,15 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@id/clock_view" />
+
+    <com.android.systemui.statusbar.phone.NotificationIconContainer
+        android:id="@+id/left_aligned_notification_icon_container"
+        android:paddingStart="16dp"
+        android:paddingEnd="16dp"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/notification_shelf_height"
+        android:layout_marginTop="@dimen/widget_vertical_padding"
+        android:layout_below="@id/keyguard_status_area"
+        android:visibility="gone"
+    />
 </com.android.keyguard.KeyguardClockSwitch>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index d63724d..57ce0b5 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -387,9 +387,6 @@
          off-screen. -->
     <bool name="config_fadeDependingOnAmountSwiped">false</bool>
 
-    <!-- Whether or not to show the expand button at the end of the notification header. -->
-    <bool name="config_showNotificationExpandButtonAtEnd">false</bool>
-
     <!-- Whether or the notifications should be clipped to be reduced in height if it has been
          scrolled to the top of the screen. -->
     <bool name="config_clipNotificationScrollToTop">true</bool>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
index 76513c6..611c4b7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationControllerCompat.java
@@ -17,6 +17,7 @@
 package com.android.systemui.shared.system;
 
 import android.app.ActivityManager.TaskSnapshot;
+import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.IRecentsAnimationController;
@@ -70,6 +71,21 @@
     }
 
     /**
+     * Sets the final bounds on a Task. This is used by Launcher to notify the system that
+     * animating Activity to PiP has completed and the associated task surface should be updated
+     * accordingly. This should be called before `finish`
+     * @param taskId Task id of the Activity in PiP mode.
+     * @param destinationBounds Bounds of the PiP window on home.
+     */
+    public void setFinishTaskBounds(int taskId, Rect destinationBounds) {
+        try {
+            mAnimationController.setFinishTaskBounds(taskId, destinationBounds);
+        } catch (RemoteException e) {
+            Log.d(TAG, "Failed to set finish task bounds", e);
+        }
+    }
+
+    /**
      * Finish the current recents animation.
      * @param toHome Going to home or back to the previous app.
      * @param sendUserLeaveHint determines whether userLeaveHint will be set true to the previous
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
index 5b41d5f..d3066b4 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java
@@ -39,27 +39,29 @@
 
     private static final String TAG = "WindowManagerWrapper";
 
-    public static final int TRANSIT_UNSET = WindowManager.TRANSIT_UNSET;
-    public static final int TRANSIT_NONE = WindowManager.TRANSIT_NONE;
-    public static final int TRANSIT_ACTIVITY_OPEN = WindowManager.TRANSIT_ACTIVITY_OPEN;
-    public static final int TRANSIT_ACTIVITY_CLOSE = WindowManager.TRANSIT_ACTIVITY_CLOSE;
-    public static final int TRANSIT_TASK_OPEN = WindowManager.TRANSIT_TASK_OPEN;
-    public static final int TRANSIT_TASK_CLOSE = WindowManager.TRANSIT_TASK_CLOSE;
-    public static final int TRANSIT_TASK_TO_FRONT = WindowManager.TRANSIT_TASK_TO_FRONT;
-    public static final int TRANSIT_TASK_TO_BACK = WindowManager.TRANSIT_TASK_TO_BACK;
-    public static final int TRANSIT_WALLPAPER_CLOSE = WindowManager.TRANSIT_WALLPAPER_CLOSE;
-    public static final int TRANSIT_WALLPAPER_OPEN = WindowManager.TRANSIT_WALLPAPER_OPEN;
+    public static final int TRANSIT_UNSET = WindowManager.TRANSIT_OLD_UNSET;
+    public static final int TRANSIT_NONE = WindowManager.TRANSIT_OLD_NONE;
+    public static final int TRANSIT_ACTIVITY_OPEN = WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+    public static final int TRANSIT_ACTIVITY_CLOSE = WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+    public static final int TRANSIT_TASK_OPEN = WindowManager.TRANSIT_OLD_TASK_OPEN;
+    public static final int TRANSIT_TASK_CLOSE = WindowManager.TRANSIT_OLD_TASK_CLOSE;
+    public static final int TRANSIT_TASK_TO_FRONT = WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
+    public static final int TRANSIT_TASK_TO_BACK = WindowManager.TRANSIT_OLD_TASK_TO_BACK;
+    public static final int TRANSIT_WALLPAPER_CLOSE = WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE;
+    public static final int TRANSIT_WALLPAPER_OPEN = WindowManager.TRANSIT_OLD_WALLPAPER_OPEN;
     public static final int TRANSIT_WALLPAPER_INTRA_OPEN =
-            WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
+            WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
     public static final int TRANSIT_WALLPAPER_INTRA_CLOSE =
-            WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
-    public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-    public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
-    public static final int TRANSIT_KEYGUARD_GOING_AWAY = WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+            WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
+    public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
+    public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH;
+    public static final int TRANSIT_KEYGUARD_GOING_AWAY =
+            WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
     public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER =
-            WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
-    public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
-    public static final int TRANSIT_KEYGUARD_UNOCCLUDE = WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+            WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+    public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
+    public static final int TRANSIT_KEYGUARD_UNOCCLUDE =
+            WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
 
     public static final int NAV_BAR_POS_INVALID = NAV_BAR_INVALID;
     public static final int NAV_BAR_POS_LEFT = NAV_BAR_LEFT;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
index 53f8474..217cf70 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java
@@ -81,8 +81,7 @@
     abstract void resetState();
 
     @Override
-    public void init() {
-        super.init();
+    public void onInit() {
         mMessageAreaController.init();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 1562444..628193d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -20,6 +20,7 @@
 import android.content.res.Resources;
 import android.text.format.DateFormat;
 import android.util.TypedValue;
+import android.view.View;
 import android.view.ViewGroup;
 
 import com.android.internal.colorextraction.ColorExtractor;
@@ -29,6 +30,8 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.util.ViewController;
 
 import java.util.Locale;
@@ -47,6 +50,9 @@
     private final SysuiColorExtractor mColorExtractor;
     private final ClockManager mClockManager;
     private final KeyguardSliceViewController mKeyguardSliceViewController;
+    private final NotificationIconAreaController mNotificationIconAreaController;
+
+    private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
 
     private final StatusBarStateController.StateListener mStateListener =
             new StatusBarStateController.StateListener() {
@@ -79,21 +85,22 @@
             @Main Resources resources,
             StatusBarStateController statusBarStateController,
             SysuiColorExtractor colorExtractor, ClockManager clockManager,
-            KeyguardSliceViewController keyguardSliceViewController) {
+            KeyguardSliceViewController keyguardSliceViewController,
+            NotificationIconAreaController notificationIconAreaController) {
         super(keyguardClockSwitch);
         mResources = resources;
         mStatusBarStateController = statusBarStateController;
         mColorExtractor = colorExtractor;
         mClockManager = clockManager;
         mKeyguardSliceViewController = keyguardSliceViewController;
+        mNotificationIconAreaController = notificationIconAreaController;
     }
 
     /**
      * Attach the controller to the view it relates to.
      */
     @Override
-    public void init() {
-        super.init();
+    public void onInit() {
         mKeyguardSliceViewController.init();
     }
 
@@ -106,6 +113,7 @@
         mStatusBarStateController.addCallback(mStateListener);
         mColorExtractor.addOnColorsChangedListener(mColorsListener);
         mView.updateColors(getGradientColors());
+        updateAodIcons();
     }
 
     @Override
@@ -175,7 +183,9 @@
      * Update lockscreen mode that may change clock display.
      */
     void updateLockScreenMode(int mode) {
-        mView.updateLockScreenMode(mode);
+        mLockScreenMode = mode;
+        mView.updateLockScreenMode(mLockScreenMode);
+        updateAodIcons();
     }
 
     void updateTimeZone(TimeZone timeZone) {
@@ -188,6 +198,19 @@
         mView.setFormat24Hour(Patterns.sClockView24);
     }
 
+    private void updateAodIcons() {
+        NotificationIconContainer nic = (NotificationIconContainer)
+                mView.findViewById(
+                        com.android.systemui.R.id.left_aligned_notification_icon_container);
+
+        if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
+            // alt icon area is set in KeyguardClockSwitchController
+            mNotificationIconAreaController.setupAodIcons(nic, mLockScreenMode);
+        } else {
+            nic.setVisibility(View.GONE);
+        }
+    }
+
     private void setClockPlugin(ClockPlugin plugin) {
         mView.setClockPlugin(plugin, mStatusBarStateController.getState());
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index 351369c..3fafa5c 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -178,8 +178,7 @@
     }
 
     /** Initialize the Controller. */
-    public void init() {
-        super.init();
+    public void onInit() {
         mKeyguardSecurityContainerController.init();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index 3db9db7..730c177 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -190,8 +190,8 @@
     }
 
     @Override
-    public void init() {
-        super.init();
+    public void onInit() {
+        super.onInit();
         mMessageAreaController.init();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 1c23605..9a51150 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -169,8 +169,7 @@
     }
 
     @Override
-    public void init() {
-        super.init();
+    public void onInit() {
         mSecurityViewFlipperController.init();
     }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 7705db4..cc0d1b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -27,6 +27,8 @@
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.stack.AnimationProperties;
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.ViewController;
@@ -50,8 +52,10 @@
     private final KeyguardStateController mKeyguardStateController;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final ConfigurationController mConfigurationController;
+    private final NotificationIconAreaController mNotificationIconAreaController;
 
     private boolean mKeyguardStatusViewAnimating;
+    private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
 
     @Inject
     public KeyguardStatusViewController(
@@ -60,18 +64,19 @@
             KeyguardClockSwitchController keyguardClockSwitchController,
             KeyguardStateController keyguardStateController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
-            ConfigurationController configurationController) {
+            ConfigurationController configurationController,
+            NotificationIconAreaController notificationIconAreaController) {
         super(keyguardStatusView);
         mKeyguardSliceViewController = keyguardSliceViewController;
         mKeyguardClockSwitchController = keyguardClockSwitchController;
         mKeyguardStateController = keyguardStateController;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mConfigurationController = configurationController;
+        mNotificationIconAreaController = notificationIconAreaController;
     }
 
     @Override
-    public void init() {
-        super.init();
+    public void onInit() {
         mKeyguardClockSwitchController.init();
     }
 
@@ -79,6 +84,7 @@
     protected void onViewAttached() {
         mKeyguardUpdateMonitor.registerCallback(mInfoCallback);
         mConfigurationController.addCallback(mConfigurationListener);
+        updateAodIcons();
     }
 
     @Override
@@ -249,6 +255,17 @@
         mKeyguardClockSwitchController.refresh();
     }
 
+    private void updateAodIcons() {
+        NotificationIconContainer nic = (NotificationIconContainer)
+                mView.findViewById(com.android.systemui.R.id.clock_notification_icon_container);
+        if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
+            // alternate icon area is set in KeyguardClockSwitchController
+            mNotificationIconAreaController.setupAodIcons(nic, mLockScreenMode);
+        } else {
+            nic.setVisibility(View.GONE);
+        }
+    }
+
     private final ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
         @Override
@@ -266,8 +283,10 @@
     private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
         @Override
         public void onLockScreenModeChanged(int mode) {
+            mLockScreenMode = mode;
             mKeyguardClockSwitchController.updateLockScreenMode(mode);
             mKeyguardSliceViewController.updateLockScreenMode(mode);
+            updateAodIcons();
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 3348bd1..e709830 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -113,7 +113,7 @@
                     // TODO(b/170396074): Remove this when we don't need an icon anymore.
                     try {
                         int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
-                                Settings.Global.SHOW_PEOPLE_SPACE);
+                                Settings.Global.SHOW_PEOPLE_SPACE, 0);
                         context.getPackageManager().setComponentEnabledSetting(
                                 new ComponentName(context, PeopleSpaceActivity.class),
                                 showPeopleSpace == 1
@@ -128,7 +128,7 @@
                     // TODO(b/170396074): Remove this when we don't need a widget anymore.
                     try {
                         int showPeopleSpace = Settings.Global.getInt(context.getContentResolver(),
-                                Settings.Global.SHOW_PEOPLE_SPACE);
+                                Settings.Global.SHOW_PEOPLE_SPACE, 0);
                         context.getPackageManager().setComponentEnabledSetting(
                                 new ComponentName(context, PeopleSpaceWidgetProvider.class),
                                 showPeopleSpace == 1
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index b1ae56a..a4aeb8a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -456,6 +456,15 @@
         }
     }
 
+   /**
+     * Whether the current user has a UDFP enrolled.
+     */
+    public boolean hasUdfpsEnrolled() {
+        // TODO: (b/171392825) right now only checks whether the UDFPS sensor exists on this device
+        //  but not whether user has enrolled or not
+        return mUdfpsController != null;
+    }
+
     private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
         mCurrentDialogArgs = args;
         final @BiometricAuthenticator.Modality int type = args.argi1;
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index 83de324..eea168a 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -112,7 +112,7 @@
      * @param executor An executor to dispatch [BroadcastReceiver.onReceive]. Pass null to use an
      *                 executor in the main thread (default).
      * @param user A user handle to determine which broadcast should be dispatched to this receiver.
-     *             By default, it is the user of the context (system user in SystemUI).
+     *             Pass `null` to use the user of the context (system user in SystemUI).
      * @throws IllegalArgumentException if the filter has other constraints that are not actions or
      *                                  categories or the filter has no actions.
      */
@@ -120,13 +120,17 @@
     open fun registerReceiver(
         receiver: BroadcastReceiver,
         filter: IntentFilter,
-        executor: Executor? = context.mainExecutor,
-        user: UserHandle = context.user
+        executor: Executor? = null,
+        user: UserHandle? = null
     ) {
         checkFilter(filter)
         this.handler
-                .obtainMessage(MSG_ADD_RECEIVER,
-                        ReceiverData(receiver, filter, executor ?: context.mainExecutor, user))
+                .obtainMessage(MSG_ADD_RECEIVER, ReceiverData(
+                        receiver,
+                        filter,
+                        executor ?: context.mainExecutor,
+                        user ?: context.user
+                ))
                 .sendToTarget()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 028870f..8220835 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -44,6 +44,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.UiEventLoggerImpl;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.util.sensors.AsyncSensorManager;
@@ -98,7 +99,8 @@
     DozeSensors(Context context, AsyncSensorManager sensorManager,
             DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
             Callback callback, Consumer<Boolean> proxCallback, DozeLog dozeLog,
-            ProximitySensor proximitySensor, SecureSettings secureSettings) {
+            ProximitySensor proximitySensor, SecureSettings secureSettings,
+            AuthController authController) {
         mContext = context;
         mSensorManager = sensorManager;
         mConfig = config;
@@ -152,9 +154,9 @@
                         dozeLog),
                 new TriggerSensor(
                         findSensorWithType(config.udfpsLongPressSensorType()),
-                        Settings.Secure.DOZE_PULSE_ON_LONG_PRESS,
-                        false /* settingDef */,
-                        true /* configured */,
+                        "doze_pulse_on_auth",
+                        true /* settingDef */,
+                        authController.hasUdfpsEnrolled() /* configured */,
                         DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS,
                         true /* reports touch coordinates */,
                         true /* touchscreen */,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index 45e5c61..c581e85 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -177,7 +177,7 @@
         mAllowPulseTriggers = true;
         mDozeSensors = new DozeSensors(context, mSensorManager, dozeParameters,
                 config, wakeLock, this::onSensor, this::onProximityFar, dozeLog, proximitySensor,
-                secureSettings);
+                secureSettings, authController);
         mUiModeManager = mContext.getSystemService(UiModeManager.class);
         mDockManager = dockManager;
         mProxCheck = proxCheck;
@@ -286,7 +286,7 @@
                 } else if (isPickup) {
                     gentleWakeUp(pulseReason);
                 } else if (isUdfpsLongPress) {
-                    gentleWakeUp(pulseReason);
+                    requestPulse(DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, true, null);
                     // Since the gesture won't be received by the UDFPS view, manually inject an
                     // event.
                     mAuthController.onAodInterrupt((int) screenX, (int) screenY);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index b9fa872..80928d6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -18,10 +18,7 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.media.MediaMetadata;
 import android.media.MediaRoute2Info;
@@ -49,6 +46,8 @@
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.ShadeController;
 
 import java.util.ArrayList;
@@ -61,7 +60,7 @@
 /**
  * Controller for media output dialog
  */
-public class MediaOutputController implements LocalMediaManager.DeviceCallback{
+public class MediaOutputController implements LocalMediaManager.DeviceCallback {
 
     private static final String TAG = "MediaOutputController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -73,6 +72,7 @@
     private final ActivityStarter mActivityStarter;
     private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
     private final boolean mAboveStatusbar;
+    private final NotificationEntryManager mNotificationEntryManager;
     @VisibleForTesting
     final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
 
@@ -85,13 +85,15 @@
     @Inject
     public MediaOutputController(@NonNull Context context, String packageName,
             boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
-            lbm, ShadeController shadeController, ActivityStarter starter) {
+            lbm, ShadeController shadeController, ActivityStarter starter,
+            NotificationEntryManager notificationEntryManager) {
         mContext = context;
         mPackageName = packageName;
         mMediaSessionManager = mediaSessionManager;
         mShadeController = shadeController;
         mActivityStarter = starter;
         mAboveStatusbar = aboveStatusbar;
+        mNotificationEntryManager = notificationEntryManager;
         InfoMediaManager imm = new InfoMediaManager(mContext, packageName, null, lbm);
         mLocalMediaManager = new LocalMediaManager(mContext, lbm, imm, packageName);
     }
@@ -197,7 +199,7 @@
         if (DEBUG) {
             Log.d(TAG, "Media meta data does not contain icon information");
         }
-        return getPackageIcon();
+        return getNotificationIcon();
     }
 
     IconCompat getDeviceIconCompat(MediaDevice device) {
@@ -213,24 +215,15 @@
         return BluetoothUtils.createIconWithDrawable(drawable);
     }
 
-    private IconCompat getPackageIcon() {
+    IconCompat getNotificationIcon() {
         if (TextUtils.isEmpty(mPackageName)) {
             return null;
         }
-        try {
-            final Drawable drawable = mContext.getPackageManager().getApplicationIcon(mPackageName);
-            if (drawable instanceof BitmapDrawable) {
-                return IconCompat.createWithBitmap(((BitmapDrawable) drawable).getBitmap());
-            }
-            final Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
-                    drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
-            final Canvas canvas = new Canvas(bitmap);
-            drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
-            drawable.draw(canvas);
-            return IconCompat.createWithBitmap(bitmap);
-        } catch (PackageManager.NameNotFoundException e) {
-            if (DEBUG) {
-                Log.e(TAG, "Package is not found. Unable to get package icon.");
+        for (NotificationEntry entry
+                : mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
+            if (entry.getSbn().getNotification().hasMediaSession()
+                    && TextUtils.equals(entry.getSbn().getPackageName(), mPackageName)) {
+                return IconCompat.createFromIcon(entry.getSbn().getNotification().getLargeIcon());
             }
         }
         return null;
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index e912b7d..7d1a7ce 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -20,6 +20,7 @@
 import android.media.session.MediaSessionManager
 import com.android.settingslib.bluetooth.LocalBluetoothManager
 import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.statusbar.notification.NotificationEntryManager
 import com.android.systemui.statusbar.phone.ShadeController
 import javax.inject.Inject
 
@@ -31,7 +32,8 @@
     private val mediaSessionManager: MediaSessionManager,
     private val lbm: LocalBluetoothManager?,
     private val shadeController: ShadeController,
-    private val starter: ActivityStarter
+    private val starter: ActivityStarter,
+    private val notificationEntryManager: NotificationEntryManager
 ) {
     companion object {
         var mediaOutputDialog: MediaOutputDialog? = null
@@ -41,7 +43,7 @@
     fun create(packageName: String, aboveStatusBar: Boolean) {
         mediaOutputDialog?.dismiss()
         mediaOutputDialog = MediaOutputController(context, packageName, aboveStatusBar,
-                mediaSessionManager, lbm, shadeController, starter).run {
+                mediaSessionManager, lbm, shadeController, starter, notificationEntryManager).run {
             MediaOutputDialog(context, aboveStatusBar, this) }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
index 9d46b32..2ddcc5a 100644
--- a/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/people/PeopleSpaceUtils.java
@@ -50,7 +50,7 @@
             IPeopleManager peopleManager
     ) throws Exception {
         boolean showAllConversations = Settings.Global.getInt(context.getContentResolver(),
-                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE) == 0;
+                Settings.Global.PEOPLE_SPACE_CONVERSATION_TYPE, 0) == 0;
         List<ConversationChannelWrapper> conversations =
                 notificationManager.getConversations(
                         !showAllConversations /* priority only */).getList();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index acead98..4b9f431 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -34,8 +34,7 @@
     }
 
     @Override
-    public void init() {
-        super.init();
+    public void onInit() {
         mQuickStatusBarHeaderController.init();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index febb71c..44f847c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -257,15 +257,15 @@
         mRingerContainer.setOnClickListener(mOnClickListener);
         mPrivacyChip.setOnClickListener(mOnClickListener);
 
-        // Ignore privacy icons because they show in the space above QQS
-        mIconContainer.addIgnoredSlots(getIgnoredIconSlots());
-        mIconContainer.setShouldRestrictIcons(false);
-        mStatusBarIconController.addIconGroup(mIconManager);
-
         mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
         mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
         mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
 
+        // Ignore privacy icons because they show in the space above QQS
+        mIconContainer.setIgnoredSlots(getIgnoredIconSlots());
+        mIconContainer.setShouldRestrictIcons(false);
+        mStatusBarIconController.addIconGroup(mIconManager);
+
         setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
 
         mView.onAttach(mIconManager);
@@ -337,16 +337,17 @@
     private List<String> getIgnoredIconSlots() {
         ArrayList<String> ignored = new ArrayList<>();
         if (getChipEnabled()) {
-            ignored.add(mView.getResources().getString(
-                    com.android.internal.R.string.status_bar_camera));
-            ignored.add(mView.getResources().getString(
-                    com.android.internal.R.string.status_bar_microphone));
+            if (mAllIndicatorsEnabled || mMicCameraIndicatorsEnabled) {
+                ignored.add(mView.getResources().getString(
+                        com.android.internal.R.string.status_bar_camera));
+                ignored.add(mView.getResources().getString(
+                        com.android.internal.R.string.status_bar_microphone));
+            }
             if (mAllIndicatorsEnabled || mLocationIndicatorsEnabled) {
                 ignored.add(mView.getResources().getString(
                         com.android.internal.R.string.status_bar_location));
             }
         }
-
         return ignored;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
index a946513..db5a494 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotNotificationsController.java
@@ -25,13 +25,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Picture;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.view.WindowManager;
@@ -52,179 +45,16 @@
     private final Context mContext;
     private final Resources mResources;
     private final NotificationManager mNotificationManager;
-    private final Notification.BigPictureStyle mNotificationStyle;
-
-    private int mIconSize;
-    private int mPreviewWidth, mPreviewHeight;
-    private Notification.Builder mNotificationBuilder, mPublicNotificationBuilder;
 
     @Inject
     ScreenshotNotificationsController(Context context, WindowManager windowManager) {
         mContext = context;
         mResources = context.getResources();
-
         mNotificationManager =
                 (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
 
-        mIconSize = mResources.getDimensionPixelSize(
-                android.R.dimen.notification_large_icon_height);
-
         DisplayMetrics displayMetrics = new DisplayMetrics();
         windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
-
-
-        // determine the optimal preview size
-        int panelWidth = 0;
-        try {
-            panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
-        } catch (Resources.NotFoundException e) {
-        }
-        if (panelWidth <= 0) {
-            // includes notification_panel_width==match_parent (-1)
-            panelWidth = displayMetrics.widthPixels;
-        }
-        mPreviewWidth = panelWidth;
-        mPreviewHeight = mResources.getDimensionPixelSize(R.dimen.notification_max_height);
-
-        // Setup the notification
-        mNotificationStyle = new Notification.BigPictureStyle();
-    }
-
-    /**
-     * Resets the notification builders.
-     */
-    public void reset() {
-        // The public notification will show similar info but with the actual screenshot omitted
-        mPublicNotificationBuilder =
-                new Notification.Builder(mContext, NotificationChannels.SCREENSHOTS_HEADSUP);
-        mNotificationBuilder =
-                new Notification.Builder(mContext, NotificationChannels.SCREENSHOTS_HEADSUP);
-    }
-
-    /**
-     * Sets the current screenshot bitmap.
-     *
-     * @param image the bitmap of the current screenshot (used for preview)
-     */
-    public void setImage(Bitmap image) {
-        // Create the large notification icon
-        int imageWidth = image.getWidth();
-        int imageHeight = image.getHeight();
-
-        Paint paint = new Paint();
-        ColorMatrix desat = new ColorMatrix();
-        desat.setSaturation(0.25f);
-        paint.setColorFilter(new ColorMatrixColorFilter(desat));
-        Matrix matrix = new Matrix();
-        int overlayColor = 0x40FFFFFF;
-
-        matrix.setTranslate((mPreviewWidth - imageWidth) / 2f, (mPreviewHeight - imageHeight) / 2f);
-
-        Bitmap picture = generateAdjustedHwBitmap(
-                image, mPreviewWidth, mPreviewHeight, matrix, paint, overlayColor);
-
-        mNotificationStyle.bigPicture(picture.asShared());
-
-        // Note, we can't use the preview for the small icon, since it is non-square
-        float scale = (float) mIconSize / Math.min(imageWidth, imageHeight);
-        matrix.setScale(scale, scale);
-        matrix.postTranslate(
-                (mIconSize - (scale * imageWidth)) / 2,
-                (mIconSize - (scale * imageHeight)) / 2);
-        Bitmap icon =
-                generateAdjustedHwBitmap(image, mIconSize, mIconSize, matrix, paint, overlayColor);
-
-        /**
-         * NOTE: The following code prepares the notification builder for updating the
-         * notification after the screenshot has been written to disk.
-         */
-
-        // On the tablet, the large icon makes the notification appear as if it is clickable
-        // (and on small devices, the large icon is not shown) so defer showing the large icon
-        // until we compose the final post-save notification below.
-        mNotificationBuilder.setLargeIcon(icon.asShared());
-        // But we still don't set it for the expanded view, allowing the smallIcon to show here.
-        mNotificationStyle.bigLargeIcon((Bitmap) null);
-    }
-
-    /**
-     * Shows a notification to inform the user that a screenshot is currently being saved.
-     */
-    public void showSavingScreenshotNotification() {
-        final long now = System.currentTimeMillis();
-
-        mPublicNotificationBuilder
-                .setContentTitle(mResources.getString(R.string.screenshot_saving_title))
-                .setSmallIcon(R.drawable.stat_notify_image)
-                .setCategory(Notification.CATEGORY_PROGRESS)
-                .setWhen(now)
-                .setShowWhen(true)
-                .setColor(mResources.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-        SystemUI.overrideNotificationAppName(mContext, mPublicNotificationBuilder, true);
-
-        mNotificationBuilder
-                .setContentTitle(mResources.getString(R.string.screenshot_saving_title))
-                .setSmallIcon(R.drawable.stat_notify_image)
-                .setWhen(now)
-                .setShowWhen(true)
-                .setColor(mResources.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
-                .setStyle(mNotificationStyle)
-                .setPublicVersion(mPublicNotificationBuilder.build());
-        mNotificationBuilder.setFlag(Notification.FLAG_NO_CLEAR, true);
-        SystemUI.overrideNotificationAppName(mContext, mNotificationBuilder, true);
-
-        mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT,
-                mNotificationBuilder.build());
-    }
-
-    /**
-     * Shows a notification with the saved screenshot and actions that can be taken with it.
-     *
-     * @param actionData SavedImageData struct with image URI and actions
-     */
-    public void showScreenshotActionsNotification(
-            ScreenshotController.SavedImageData actionData) {
-        mNotificationBuilder.addAction(actionData.shareAction);
-        mNotificationBuilder.addAction(actionData.editAction);
-        mNotificationBuilder.addAction(actionData.deleteAction);
-        for (Notification.Action smartAction : actionData.smartActions) {
-            mNotificationBuilder.addAction(smartAction);
-        }
-
-        // Create the intent to show the screenshot in gallery
-        Intent launchIntent = new Intent(Intent.ACTION_VIEW);
-        launchIntent.setDataAndType(actionData.uri, "image/png");
-        launchIntent.setFlags(
-                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
-        final long now = System.currentTimeMillis();
-
-        // Update the text and the icon for the existing notification
-        mPublicNotificationBuilder
-                .setContentTitle(mResources.getString(R.string.screenshot_saved_title))
-                .setContentText(mResources.getString(R.string.screenshot_saved_text))
-                .setContentIntent(PendingIntent
-                        .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE))
-                .setWhen(now)
-                .setAutoCancel(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
-        mNotificationBuilder
-                .setContentTitle(mResources.getString(R.string.screenshot_saved_title))
-                .setContentText(mResources.getString(R.string.screenshot_saved_text))
-                .setContentIntent(PendingIntent
-                        .getActivity(mContext, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE))
-                .setWhen(now)
-                .setAutoCancel(true)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color))
-                .setPublicVersion(mPublicNotificationBuilder.build())
-                .setFlag(Notification.FLAG_NO_CLEAR, false);
-
-        mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT,
-                mNotificationBuilder.build());
     }
 
     /**
@@ -263,31 +93,4 @@
                 .build();
         mNotificationManager.notify(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT, n);
     }
-
-    /**
-     * Cancels the current screenshot notification.
-     */
-    public void cancelNotification() {
-        mNotificationManager.cancel(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
-    }
-
-    /**
-     * Generates a new hardware bitmap with specified values, copying the content from the
-     * passed in bitmap.
-     */
-    private Bitmap generateAdjustedHwBitmap(Bitmap bitmap, int width, int height, Matrix matrix,
-            Paint paint, int color) {
-        Picture picture = new Picture();
-        Canvas canvas = picture.beginRecording(width, height);
-        canvas.drawColor(color);
-        canvas.drawBitmap(bitmap, matrix, paint);
-        picture.endRecording();
-        return Bitmap.createBitmap(picture);
-    }
-
-    static void cancelScreenshotNotification(Context context) {
-        final NotificationManager nm =
-                (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
-        nm.cancel(SystemMessageProto.SystemMessage.NOTE_GLOBAL_SCREENSHOT);
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 8d82270..3c48302 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -54,7 +54,6 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -345,8 +344,7 @@
             return false;
         }
         boolean exceedsPriorityThreshold;
-        if (NotificationUtils.useNewInterruptionModel(mContext)
-                && hideSilentNotificationsOnLockscreen()) {
+        if (hideSilentNotificationsOnLockscreen()) {
             exceedsPriorityThreshold =
                     entry.getBucket() == BUCKET_MEDIA_CONTROLS
                             || (entry.getBucket() != BUCKET_SILENT
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java
index 5794f73..c301002 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationChannelHelper.java
@@ -56,7 +56,7 @@
         try {
             channel.setName(getName(entry));
             notificationManager.createConversationNotificationChannelForPackage(
-                    pkg, appUid, entry.getSbn().getKey(), channel,
+                    pkg, appUid, channel,
                     conversationId);
             channel = notificationManager.getConversationNotificationChannel(
                     context.getOpPackageName(), UserHandle.getUserId(appUid), pkg,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
index ce6013f..cd8897e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -61,10 +61,8 @@
             isFilteringEnabled() && !isMediaControlsEnabled() ->
                 intArrayOf(BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_PEOPLE,
                         BUCKET_ALERTING, BUCKET_SILENT)
-            NotificationUtils.useNewInterruptionModel(context) ->
-                intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
             else ->
-                intArrayOf(BUCKET_ALERTING)
+                intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 1af47dd..cbc113b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -16,12 +16,9 @@
 
 package com.android.systemui.statusbar.notification;
 
-import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
-
 import android.annotation.Nullable;
 import android.content.Context;
 import android.graphics.Color;
-import android.provider.Settings;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -76,15 +73,4 @@
         return (int) (dimensionPixelSize * factor);
     }
 
-    /**
-     * Returns the value of the new interruption model setting. This result is cached and cannot
-     * change except through reboots/process restarts.
-     */
-    public static boolean useNewInterruptionModel(Context context) {
-        if (sUseNewInterruptionModel == null) {
-            sUseNewInterruptionModel = Settings.Secure.getInt(context.getContentResolver(),
-                    NOTIFICATION_NEW_INTERRUPTION_MODEL, 1) != 0;
-        }
-        return sUseNewInterruptionModel;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
index 318cdb1..b1c6f53 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -37,7 +37,6 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.GroupEntry;
 import com.android.systemui.statusbar.notification.collection.ListEntry;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -150,8 +149,7 @@
         if (entry == null) {
             return false;
         }
-        if (NotificationUtils.useNewInterruptionModel(mContext)
-                && mHideSilentNotificationsOnLockscreen) {
+        if (mHideSilentNotificationsOnLockscreen) {
             return mHighPriorityProvider.isHighPriority(entry);
         } else {
             return entry.getRepresentativeEntry() != null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index f788dfe..5ee66fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1643,19 +1643,15 @@
 
     /** Sets the last time the notification being displayed audibly alerted the user. */
     public void setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) {
-        if (NotificationUtils.useNewInterruptionModel(mContext)) {
-            long timeSinceAlertedAudibly = System.currentTimeMillis() - lastAudiblyAlertedMs;
-            boolean alertedRecently =
-                    timeSinceAlertedAudibly < RECENTLY_ALERTED_THRESHOLD_MS;
+        long timeSinceAlertedAudibly = System.currentTimeMillis() - lastAudiblyAlertedMs;
+        boolean alertedRecently = timeSinceAlertedAudibly < RECENTLY_ALERTED_THRESHOLD_MS;
 
-            applyAudiblyAlertedRecently(alertedRecently);
+        applyAudiblyAlertedRecently(alertedRecently);
 
-            removeCallbacks(mExpireRecentlyAlertedFlag);
-            if (alertedRecently) {
-                long timeUntilNoLongerRecent =
-                        RECENTLY_ALERTED_THRESHOLD_MS - timeSinceAlertedAudibly;
-                postDelayed(mExpireRecentlyAlertedFlag, timeUntilNoLongerRecent);
-            }
+        removeCallbacks(mExpireRecentlyAlertedFlag);
+        if (alertedRecently) {
+            long timeUntilNoLongerRecent = RECENTLY_ALERTED_THRESHOLD_MS - timeSinceAlertedAudibly;
+            postDelayed(mExpireRecentlyAlertedFlag, timeUntilNoLongerRecent);
         }
     }
 
@@ -2856,7 +2852,8 @@
         }
         float x = event.getX();
         float y = event.getY();
-        NotificationHeaderView header = getVisibleNotificationViewWrapper().getNotificationHeader();
+        NotificationViewWrapper wrapper = getVisibleNotificationViewWrapper();
+        NotificationHeaderView header = wrapper == null ? null : wrapper.getNotificationHeader();
         if (header != null && header.isInTouchRect(x - getTranslation(), y)) {
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 8c82756..0fc4c42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -34,12 +34,10 @@
 import com.android.internal.widget.NotificationExpandButton;
 import com.android.settingslib.Utils;
 import com.android.systemui.Interpolators;
-import com.android.systemui.R;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
 import com.android.systemui.statusbar.notification.CustomInterpolatorTransformation;
 import com.android.systemui.statusbar.notification.ImageTransformState;
-import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
@@ -67,13 +65,9 @@
 
     private boolean mIsLowPriority;
     private boolean mTransformLowPriorityTitle;
-    private boolean mShowExpandButtonAtEnd;
 
     protected NotificationHeaderViewWrapper(Context ctx, View view, ExpandableNotificationRow row) {
         super(ctx, view, row);
-        mShowExpandButtonAtEnd = ctx.getResources().getBoolean(
-                R.bool.config_showNotificationExpandButtonAtEnd)
-                || NotificationUtils.useNewInterruptionModel(ctx);
         mTransformationHelper = new ViewTransformationHelper();
 
         // we want to avoid that the header clashes with the other text when transforming
@@ -115,9 +109,6 @@
         mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
         mAudiblyAlertedIcon = mView.findViewById(com.android.internal.R.id.alerted_icon);
         mFeedbackIcon = mView.findViewById(com.android.internal.R.id.feedback);
-        if (mNotificationHeader != null) {
-            mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd);
-        }
     }
 
     private void addFeedbackOnClickListener(ExpandableNotificationRow row) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 9320499..5cee5bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1340,8 +1340,11 @@
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getAppearStartPosition() {
         if (isHeadsUpTransition()) {
-            return mHeadsUpInset
-                    + getFirstVisibleSection().getFirstVisibleChild().getPinnedHeadsUpHeight();
+            final NotificationSection firstVisibleSection = getFirstVisibleSection();
+            final int pinnedHeight = firstVisibleSection != null
+                    ? firstVisibleSection.getFirstVisibleChild().getPinnedHeadsUpHeight()
+                    : 0;
+            return mHeadsUpInset + pinnedHeight;
         }
         return getMinExpansionHeight();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index d1c8355..e065b47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -91,9 +91,7 @@
 
     private boolean mAnimationsEnabled;
     private int mAodIconTint;
-    private boolean mFullyHidden;
     private boolean mAodIconsVisible;
-    private boolean mIsPulsing;
     private boolean mShowLowPriority = true;
 
     @VisibleForTesting
@@ -158,22 +156,23 @@
     }
 
     /**
-     * Called by the StatusBar. The StatusBar passes the NotificationIconContainer which holds
-     * the aod icons.
+     * Called by the Keyguard*ViewController whose view contains the aod icons.
      */
-    void setupAodIcons(@NonNull NotificationIconContainer aodIcons) {
+    public void setupAodIcons(@NonNull NotificationIconContainer aodIcons,
+            int lockScreenMode) {
         boolean changed = mAodIcons != null;
         if (changed) {
             mAodIcons.setAnimationsEnabled(false);
             mAodIcons.removeAllViews();
         }
         mAodIcons = aodIcons;
-        mAodIcons.setOnLockScreen(true);
+        mAodIcons.setOnLockScreen(true, lockScreenMode);
         updateAodIconsVisibility(false /* animate */);
         updateAnimations();
         if (changed) {
             updateAodNotificationIcons();
         }
+        updateIconLayoutParams(mContext);
     }
 
     public void setupShelf(NotificationShelfController notificationShelfController) {
@@ -182,23 +181,31 @@
     }
 
     public void onDensityOrFontScaleChanged(Context context) {
+        updateIconLayoutParams(context);
+    }
+
+    private void updateIconLayoutParams(Context context) {
         reloadDimens(context);
         final FrameLayout.LayoutParams params = generateIconLayoutParams();
         for (int i = 0; i < mNotificationIcons.getChildCount(); i++) {
             View child = mNotificationIcons.getChildAt(i);
             child.setLayoutParams(params);
         }
-        for (int i = 0; i < mShelfIcons.getChildCount(); i++) {
-            View child = mShelfIcons.getChildAt(i);
-            child.setLayoutParams(params);
-        }
         for (int i = 0; i < mCenteredIcon.getChildCount(); i++) {
             View child = mCenteredIcon.getChildAt(i);
             child.setLayoutParams(params);
         }
-        for (int i = 0; i < mAodIcons.getChildCount(); i++) {
-            View child = mAodIcons.getChildAt(i);
-            child.setLayoutParams(params);
+        if (mShelfIcons != null) {
+            for (int i = 0; i < mShelfIcons.getChildCount(); i++) {
+                View child = mShelfIcons.getChildAt(i);
+                child.setLayoutParams(params);
+            }
+        }
+        if (mAodIcons != null) {
+            for (int i = 0; i < mAodIcons.getChildCount(); i++) {
+                View child = mAodIcons.getChildAt(i);
+                child.setLayoutParams(params);
+            }
         }
     }
 
@@ -358,6 +365,9 @@
     }
 
     public void updateAodNotificationIcons() {
+        if (mAodIcons == null) {
+            return;
+        }
         updateIconsForLayout(entry -> entry.getIcons().getAodIcon(), mAodIcons,
                 false /* showAmbient */,
                 true /* showLowPriority */,
@@ -546,6 +556,9 @@
 
     @Override
     public void onDozingChanged(boolean isDozing) {
+        if (mAodIcons == null) {
+            return;
+        }
         boolean animate = mDozeParameters.getAlwaysOn()
                 && !mDozeParameters.getDisplayNeedsBlanking();
         mAodIcons.setDozing(isDozing, animate, 0);
@@ -564,7 +577,9 @@
 
     private void updateAnimations() {
         boolean inShade = mStatusBarStateController.getState() == StatusBarState.SHADE;
-        mAodIcons.setAnimationsEnabled(mAnimationsEnabled && !inShade);
+        if (mAodIcons != null) {
+            mAodIcons.setAnimationsEnabled(mAnimationsEnabled && !inShade);
+        }
         mCenteredIcon.setAnimationsEnabled(mAnimationsEnabled && inShade);
         mNotificationIcons.setAnimationsEnabled(mAnimationsEnabled && inShade);
     }
@@ -575,6 +590,9 @@
     }
 
     public void appearAodIcons() {
+        if (mAodIcons == null) {
+            return;
+        }
         if (mDozeParameters.shouldControlScreenOff()) {
             mAodIcons.setTranslationY(-mAodIconAppearTranslation);
             mAodIcons.setAlpha(0);
@@ -637,6 +655,9 @@
     }
 
     private void updateAodIconsVisibility(boolean animate) {
+        if (mAodIcons == null) {
+            return;
+        }
         boolean visible = mBypassController.getBypassEnabled()
                 || mWakeUpCoordinator.getNotificationsFullyHidden();
         if (mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index bf85852..9561851 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -34,6 +34,7 @@
 import androidx.collection.ArrayMap;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
@@ -148,6 +149,7 @@
     private float mActualPaddingStart = NO_VALUE;
     private boolean mDozing;
     private boolean mOnLockScreen;
+    private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
     private boolean mChangingViewPositions;
     private int mAddAnimationStartIndex = -1;
     private int mCannedAnimationStartIndex = -1;
@@ -453,7 +455,8 @@
             mFirstVisibleIconState = mIconStates.get(getChildAt(0));
         }
 
-        boolean center = mOnLockScreen;
+        boolean center = mOnLockScreen
+                && mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
         if (center && translationX < getLayoutEnd()) {
             float initialTranslation =
                     mFirstVisibleIconState == null ? 0 : mFirstVisibleIconState.xTranslation;
@@ -686,8 +689,13 @@
         }
     }
 
-    public void setOnLockScreen(boolean onLockScreen) {
+    /**
+     * Set whether the device is on the lockscreen and which lockscreen mode the device is
+     * configured to. Depending on these values, the layout of the AOD icons change.
+     */
+    public void setOnLockScreen(boolean onLockScreen, int lockScreenMode) {
         mOnLockScreen = onLockScreen;
+        mLockScreenMode = lockScreenMode;
     }
 
     public class IconState extends ViewState {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 47b16c8..b185f48 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -441,7 +441,6 @@
     private KeyguardIndicationController mKeyguardIndicationController;
     private Consumer<Boolean> mAffordanceLaunchListener;
     private int mShelfHeight;
-    private Runnable mOnReinflationListener;
     private int mDarkIconSize;
     private int mHeadsUpInset;
     private boolean mHeadsUpPinnedMode;
@@ -767,9 +766,6 @@
                 false,
                 mBarState);
         setKeyguardBottomAreaVisibility(mBarState, false);
-        if (mOnReinflationListener != null) {
-            mOnReinflationListener.run();
-        }
     }
 
     private void initBottomArea() {
@@ -3102,10 +3098,6 @@
         mKeyguardIndicationController.showTransientIndication(id);
     }
 
-    public void setOnReinflationListener(Runnable onReinflationListener) {
-        mOnReinflationListener = onReinflationListener;
-    }
-
     public void setAlpha(float alpha) {
         mView.setAlpha(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 c7932bb..9bd98f2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1035,10 +1035,8 @@
                 mStackScrollerController.getNotificationListContainer();
         mNotificationLogger.setUpWithContainer(notifListContainer);
 
-        updateAodIconArea();
         inflateShelf();
         mNotificationIconAreaController.setupShelf(mNotificationShelfController);
-        mNotificationPanelViewController.setOnReinflationListener(this::updateAodIconArea);
         mNotificationPanelViewController.addExpansionListener(mWakeUpCoordinator);
 
         // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
@@ -1270,12 +1268,6 @@
         ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
     }
 
-    private void updateAodIconArea() {
-        mNotificationIconAreaController.setupAodIcons(
-                getNotificationShadeWindowView()
-                        .findViewById(R.id.clock_notification_icon_container));
-    }
-
     @NonNull
     @Override
     public Lifecycle getLifecycle() {
diff --git a/packages/SystemUI/src/com/android/systemui/util/ViewController.java b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
index 3dbc6f1..880d09a 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/ViewController.java
@@ -26,8 +26,8 @@
  *
  * Implementations should handle setup and teardown related activities inside of
  * {@link #onViewAttached()} and {@link  #onViewDetached()}. Be sure to call {@link #init()} on
- * any child controllers that this uses. This can be done in {@link init()} if the controllers
- * are injected, or right after creation time of the child controller.
+ * any child controllers that this uses. This can be done in {@link #onInit()} if the
+ * controllers are injected, or right after creation time of the child controller.
  *
  * Tip: View "attachment" happens top down - parents are notified that they are attached before
  * any children. That means that if you call a method on a child controller in
@@ -62,11 +62,18 @@
         mView = view;
     }
 
-    /** Call immediately after constructing Controller in order to handle view lifecycle events. */
+    /**
+     * Call immediately after constructing Controller in order to handle view lifecycle events.
+     *
+     * Generally speaking, you don't want to override this method. Instead, override
+     * {@link #onInit()} as a way to have an run-once idempotent method that you can use for
+     * setup of your ViewController.
+     */
     public void init() {
         if (mInited) {
             return;
         }
+        onInit();
         mInited = true;
 
         if (mView != null) {
@@ -77,6 +84,14 @@
         }
     }
 
+    /**
+     * Run once when {@link #init()} is called.
+     *
+     * Override this to perform idempotent, one-time setup that your controller needs. It will
+     * be called before {@link #onViewAttached()}.
+     */
+    protected void onInit() {}
+
     protected Context getContext() {
         return mView.getContext();
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 094230d..4559113 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -16,7 +16,6 @@
 
 package com.android.keyguard;
 
-
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.never;
@@ -38,6 +37,8 @@
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationIconContainer;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -60,6 +61,8 @@
     @Mock
     private KeyguardClockSwitch mView;
     @Mock
+    private NotificationIconContainer mNotificationIcons;
+    @Mock
     private ClockPlugin mClockPlugin;
     @Mock
     ColorExtractor.GradientColors mGradientColors;
@@ -67,6 +70,8 @@
     KeyguardSliceViewController mKeyguardSliceViewController;
     @Mock
     Resources mResources;
+    @Mock
+    NotificationIconAreaController mNotificationIconAreaController;
 
     private KeyguardClockSwitchController mController;
 
@@ -74,6 +79,8 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
+        when(mView.findViewById(com.android.systemui.R.id.left_aligned_notification_icon_container))
+                .thenReturn(mNotificationIcons);
         when(mView.isAttachedToWindow()).thenReturn(true);
         when(mResources.getString(anyInt())).thenReturn("h:mm");
         mController = new KeyguardClockSwitchController(
@@ -82,7 +89,8 @@
                 mStatusBarStateController,
                 mColorExtractor,
                 mClockManager,
-                mKeyguardSliceViewController);
+                mKeyguardSliceViewController,
+                mNotificationIconAreaController);
 
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
         when(mColorExtractor.getColors(anyInt())).thenReturn(mGradientColors);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index 752a744..4cfbe69 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -22,6 +22,7 @@
 import android.testing.AndroidTestingRunner;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
@@ -47,6 +48,8 @@
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock
     ConfigurationController mConfigurationController;
+    @Mock
+    NotificationIconAreaController mNotificationIconAreaController;
 
     private KeyguardStatusViewController mController;
 
@@ -60,7 +63,8 @@
                 mKeyguardClockSwitchController,
                 mKeyguardStateController,
                 mKeyguardUpdateMonitor,
-                mConfigurationController);
+                mConfigurationController,
+                mNotificationIconAreaController);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
index da00e7e..1a78ca4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
@@ -53,7 +53,7 @@
         receiver: BroadcastReceiver,
         filter: IntentFilter,
         executor: Executor?,
-        user: UserHandle
+        user: UserHandle?
     ) {
         registeredReceivers.add(receiver)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 4f0ff42..0059881 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -42,6 +42,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.doze.DozeSensors.TriggerSensor;
 import com.android.systemui.plugins.SensorManagerPlugin;
 import com.android.systemui.statusbar.phone.DozeParameters;
@@ -84,6 +85,8 @@
     @Mock
     private DozeLog mDozeLog;
     @Mock
+    private AuthController mAuthController;
+    @Mock
     private ProximitySensor mProximitySensor;
     private FakeSettings mFakeSettings = new FakeSettings();
     private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
@@ -156,7 +159,7 @@
         TestableDozeSensors() {
             super(getContext(), mSensorManager, mDozeParameters,
                     mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
-                    mProximitySensor, mFakeSettings);
+                    mProximitySensor, mFakeSettings, mAuthController);
             for (TriggerSensor sensor : mSensors) {
                 if (sensor instanceof PluginSensor
                         && ((PluginSensor) sensor).mPluginSensor.getType()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 3ae02a4..6d87cc3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -196,6 +196,7 @@
         final int screenY = 100;
         final int reason = DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
         mTriggers.onSensor(reason, screenX, screenY, null);
+        verify(mHost).extendPulse(reason);
         verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 4639dcb..c897d8a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -39,6 +39,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.ShadeController;
 
 import org.junit.Before;
@@ -58,6 +59,8 @@
     private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
     private ShadeController mShadeController = mock(ShadeController.class);
     private ActivityStarter mStarter = mock(ActivityStarter.class);
+    private NotificationEntryManager mNotificationEntryManager =
+            mock(NotificationEntryManager.class);
 
     private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
     private MediaOutputController mMediaOutputController;
@@ -69,7 +72,8 @@
     @Before
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
-                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
         mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
                 mMediaOutputController);
         mMediaOutputBaseDialogImpl.onCreate(new Bundle());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 0576667..6ceac13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -27,15 +27,19 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Notification;
 import android.content.Context;
+import android.graphics.drawable.Icon;
 import android.media.MediaDescription;
 import android.media.MediaMetadata;
 import android.media.RoutingSessionInfo;
 import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
+import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
 import android.text.TextUtils;
 
+import androidx.core.graphics.drawable.IconCompat;
 import androidx.test.filters.SmallTest;
 
 import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -45,6 +49,8 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.ShadeController;
 
 import org.junit.Before;
@@ -81,6 +87,8 @@
     private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class);
     private ShadeController mShadeController = mock(ShadeController.class);
     private ActivityStarter mStarter = mock(ActivityStarter.class);
+    private NotificationEntryManager mNotificationEntryManager =
+            mock(NotificationEntryManager.class);
 
     private Context mSpyContext;
     private MediaOutputController mMediaOutputController;
@@ -100,8 +108,10 @@
                 MediaSessionManager.class);
         when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(
                 mCachedBluetoothDeviceManager);
+
         mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
-                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
         mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -144,7 +154,8 @@
     @Test
     public void start_withoutPackageName_verifyMediaControllerInit() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
-                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
 
         mMediaOutputController.start(mCb);
 
@@ -164,7 +175,9 @@
     @Test
     public void stop_withoutPackageName_verifyMediaControllerDeinit() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
-                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
+
         mMediaOutputController.start(mCb);
 
         mMediaOutputController.stop();
@@ -423,4 +436,53 @@
         }
         assertThat(newDevices.get(4).getId()).isEqualTo(TEST_DEVICE_5_ID);
     }
+
+    @Test
+    public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
+        mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
+
+        assertThat(mMediaOutputController.getNotificationIcon()).isNull();
+    }
+
+    @Test
+    public void getNotificationLargeIcon_withPackageNameAndMediaSession_returnsIconCompat() {
+        final List<NotificationEntry> entryList = new ArrayList<>();
+        final NotificationEntry entry = mock(NotificationEntry.class);
+        final StatusBarNotification sbn = mock(StatusBarNotification.class);
+        final Notification notification = mock(Notification.class);
+        final Icon icon = mock(Icon.class);
+        entryList.add(entry);
+
+        when(mNotificationEntryManager.getActiveNotificationsForCurrentUser())
+                .thenReturn(entryList);
+        when(entry.getSbn()).thenReturn(sbn);
+        when(sbn.getNotification()).thenReturn(notification);
+        when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(notification.hasMediaSession()).thenReturn(true);
+        when(notification.getLargeIcon()).thenReturn(icon);
+
+        assertThat(mMediaOutputController.getNotificationIcon() instanceof IconCompat).isTrue();
+    }
+
+    @Test
+    public void getNotificationLargeIcon_withPackageNameAndNoMediaSession_returnsNull() {
+        final List<NotificationEntry> entryList = new ArrayList<>();
+        final NotificationEntry entry = mock(NotificationEntry.class);
+        final StatusBarNotification sbn = mock(StatusBarNotification.class);
+        final Notification notification = mock(Notification.class);
+        final Icon icon = mock(Icon.class);
+        entryList.add(entry);
+
+        when(mNotificationEntryManager.getActiveNotificationsForCurrentUser())
+                .thenReturn(entryList);
+        when(entry.getSbn()).thenReturn(sbn);
+        when(sbn.getNotification()).thenReturn(notification);
+        when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+        when(notification.hasMediaSession()).thenReturn(false);
+        when(notification.getLargeIcon()).thenReturn(icon);
+
+        assertThat(mMediaOutputController.getNotificationIcon()).isNull();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 8648d91..c1e7db1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -34,6 +34,7 @@
 import com.android.settingslib.media.MediaDevice;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.ShadeController;
 
 import org.junit.After;
@@ -58,6 +59,8 @@
     private ActivityStarter mStarter = mock(ActivityStarter.class);
     private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
     private MediaDevice mMediaDevice = mock(MediaDevice.class);
+    private NotificationEntryManager mNotificationEntryManager =
+            mock(NotificationEntryManager.class);
 
     private MediaOutputDialog mMediaOutputDialog;
     private MediaOutputController mMediaOutputController;
@@ -66,7 +69,8 @@
     @Before
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
-                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputDialog = new MediaOutputDialog(mContext, false, mMediaOutputController);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
index 10f2bd5..5813350 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -34,6 +34,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.ShadeController;
 
 import org.junit.After;
@@ -59,6 +60,8 @@
     private LocalMediaManager mLocalMediaManager = mock(LocalMediaManager.class);
     private MediaDevice mMediaDevice = mock(MediaDevice.class);
     private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
+    private NotificationEntryManager mNotificationEntryManager =
+            mock(NotificationEntryManager.class);
 
     private MediaOutputGroupDialog mMediaOutputGroupDialog;
     private MediaOutputController mMediaOutputController;
@@ -67,7 +70,8 @@
     @Before
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
-                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter);
+                mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
+                mNotificationEntryManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
                 mMediaOutputController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
new file mode 100644
index 0000000..2269951
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs
+
+import android.content.Context
+import android.testing.AndroidTestingRunner
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.demomode.DemoModeController
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.privacy.PrivacyItemController
+import com.android.systemui.qs.carrier.QSCarrierGroup
+import com.android.systemui.qs.carrier.QSCarrierGroupController
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.statusbar.phone.StatusBarIconController
+import com.android.systemui.statusbar.phone.StatusIconContainer
+import com.android.systemui.statusbar.policy.Clock
+import com.android.systemui.statusbar.policy.NextAlarmController
+import com.android.systemui.util.RingerModeTracker
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.utils.leaks.FakeZenModeController
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Answers
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var view: QuickStatusBarHeader
+    @Mock
+    private lateinit var zenModeController: FakeZenModeController
+    @Mock
+    private lateinit var nextAlarmController: NextAlarmController
+    @Mock
+    private lateinit var privacyItemController: PrivacyItemController
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private lateinit var ringerModeTracker: RingerModeTracker
+    @Mock
+    private lateinit var activityStarter: ActivityStarter
+    @Mock
+    private lateinit var uiEventLogger: UiEventLogger
+    @Mock
+    private lateinit var qsTileHost: QSTileHost
+    @Mock
+    private lateinit var statusBarIconController: StatusBarIconController
+    @Mock
+    private lateinit var commandQueue: CommandQueue
+    @Mock
+    private lateinit var demoModeController: DemoModeController
+    @Mock
+    private lateinit var userTracker: UserTracker
+    @Mock
+    private lateinit var quickQSPanelController: QuickQSPanelController
+    @Mock(answer = Answers.RETURNS_SELF)
+    private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
+    @Mock
+    private lateinit var qsCarrierGroupController: QSCarrierGroupController
+    @Mock
+    private lateinit var iconContainer: StatusIconContainer
+    @Mock
+    private lateinit var qsCarrierGroup: QSCarrierGroup
+    @Mock
+    private lateinit var privacyChip: OngoingPrivacyChip
+    @Mock
+    private lateinit var clock: Clock
+    @Mock
+    private lateinit var mockView: View
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private lateinit var context: Context
+
+    private lateinit var controller: QuickStatusBarHeaderController
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        stubViews()
+        `when`(iconContainer.context).thenReturn(context)
+        `when`(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
+        `when`(view.resources).thenReturn(mContext.resources)
+        `when`(view.isAttachedToWindow).thenReturn(true)
+
+        controller = QuickStatusBarHeaderController(
+                view,
+                zenModeController,
+                nextAlarmController,
+                privacyItemController,
+                ringerModeTracker,
+                activityStarter,
+                uiEventLogger,
+                qsTileHost,
+                statusBarIconController,
+                commandQueue,
+                demoModeController,
+                userTracker,
+                quickQSPanelController,
+                qsCarrierGroupControllerBuilder
+        )
+    }
+
+    @After
+    fun tearDown() {
+        controller.onViewDetached()
+    }
+
+    @Test
+    fun testIgnoredSlotsOnAttached_noIndicators() {
+        setPrivacyController(false, false, false)
+
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(iconContainer).setIgnoredSlots(capture(captor))
+
+        assertThat(captor.value).isEmpty()
+    }
+
+    @Test
+    fun testIgnoredSlotsOnAttached_onlyMicCamera() {
+        setPrivacyController(false, true, false)
+
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(iconContainer).setIgnoredSlots(capture(captor))
+
+        val cameraString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_camera)
+        val micString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_microphone)
+
+        assertThat(captor.value).containsExactly(cameraString, micString)
+    }
+
+    @Test
+    fun testIgnoredSlotsOnAttached_onlyLocation() {
+        setPrivacyController(false, false, true)
+
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(iconContainer).setIgnoredSlots(capture(captor))
+
+        val locationString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_location)
+
+        assertThat(captor.value).containsExactly(locationString)
+    }
+
+    @Test
+    fun testIgnoredSlotsOnAttached_locationMicCamera() {
+        setPrivacyController(false, true, true)
+
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(iconContainer).setIgnoredSlots(capture(captor))
+
+        val cameraString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_camera)
+        val micString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_microphone)
+        val locationString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_location)
+
+        assertThat(captor.value).containsExactly(cameraString, micString, locationString)
+    }
+
+    @Test
+    fun testIgnoredSlotsOnAttached_all() {
+        setPrivacyController(true, false, false)
+
+        controller.init()
+
+        val captor = argumentCaptor<List<String>>()
+        verify(iconContainer).setIgnoredSlots(capture(captor))
+
+        val cameraString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_camera)
+        val micString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_microphone)
+        val locationString = mContext.resources.getString(
+                com.android.internal.R.string.status_bar_location)
+
+        assertThat(captor.value).containsExactly(cameraString, micString, locationString)
+    }
+
+    private fun stubViews() {
+        `when`(view.findViewById<View>(anyInt())).thenReturn(mockView)
+        `when`(view.findViewById<QSCarrierGroup>(R.id.carrier_group)).thenReturn(qsCarrierGroup)
+        `when`(view.findViewById<StatusIconContainer>(R.id.statusIcons)).thenReturn(iconContainer)
+        `when`(view.findViewById<OngoingPrivacyChip>(R.id.privacy_chip)).thenReturn(privacyChip)
+        `when`(view.findViewById<Clock>(R.id.clock)).thenReturn(clock)
+    }
+
+    private fun setPrivacyController(all: Boolean, micCamera: Boolean, location: Boolean) {
+        `when`(privacyItemController.allIndicatorsAvailable).thenReturn(all)
+        `when`(privacyItemController.micCameraAvailable).thenReturn(micCamera)
+        `when`(privacyItemController.locationAvailable).thenReturn(location)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index 808f17b..2a50273 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -18,7 +18,6 @@
 
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.content.Intent.ACTION_USER_SWITCHED;
-import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
@@ -322,8 +321,6 @@
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
-        Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1);
 
         NotificationEntry entry = new NotificationEntryBuilder()
@@ -339,8 +336,6 @@
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
-        Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
 
         final Notification notification = mock(Notification.class);
@@ -358,8 +353,6 @@
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
-        Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
 
         final Notification notification = mock(Notification.class);
@@ -377,8 +370,6 @@
         Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1);
         Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
-        Settings.Secure.putInt(mContext.getContentResolver(),
                 Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0);
 
         final Notification notification = mock(Notification.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
index 9971e0c..71f146b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
@@ -74,8 +74,6 @@
         mMockResources = mock(Resources.class);
         mPackageManagerSpy = spy(getContext().getPackageManager());
         doReturn(mMockResources).when(mPackageManagerSpy)
-                .getResourcesForApplicationAsUser(eq("mockPackage"), anyInt());
-        doReturn(mMockResources).when(mPackageManagerSpy)
                 .getResourcesForApplication(eq("mockPackage"));
         doReturn(mMockResources).when(mPackageManagerSpy).getResourcesForApplication(argThat(
                 (ArgumentMatcher<ApplicationInfo>) o -> "mockPackage".equals(o.packageName)));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
index 8948fd0..3a948f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
@@ -18,7 +18,6 @@
 
 import android.provider.DeviceConfig
 import android.provider.Settings
-import android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL
 import android.testing.AndroidTestingRunner
 
 import androidx.test.filters.SmallTest
@@ -43,8 +42,6 @@
 
     @Before
     public fun setup() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-        NOTIFICATION_NEW_INTERRUPTION_MODEL, 1)
         manager = NotificationSectionsFeatureManager(proxyFake, mContext)
         manager!!.clearCache()
         originalQsMediaPlayer = Settings.System.getInt(context.getContentResolver(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 9465a3d..61edcf9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -995,7 +995,7 @@
                 mTestHandler, null, Optional.of(mBubbles));
 
         verify(mMockINotificationManager, times(1)).createConversationNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
+                anyString(), anyInt(), any(), eq(CONVERSATION_ID));
     }
 
     @Test
@@ -1020,7 +1020,7 @@
                 mTestHandler, null, Optional.of(mBubbles));
 
         verify(mMockINotificationManager, never()).createConversationNotificationChannelForPackage(
-                anyString(), anyInt(), anyString(), any(), eq(CONVERSATION_ID));
+                anyString(), anyInt(), any(), eq(CONVERSATION_ID));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index 02a3e11..b482968 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -22,7 +22,6 @@
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
-import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
@@ -50,7 +49,6 @@
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -69,7 +67,6 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -163,15 +160,6 @@
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
         mEntry = new NotificationEntryBuilder().setSbn(mSbn).build();
-
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
-    }
-
-    @After
-    public void tearDown() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index 99e8c7e..37e8218 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -14,7 +14,6 @@
 
 package com.android.systemui.statusbar.notification.row;
 
-import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
 
 import static junit.framework.Assert.assertEquals;
@@ -43,7 +42,6 @@
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -66,12 +64,6 @@
         when(mRow.getEntry()).thenReturn(entry);
     }
 
-    @After
-    public void tearDown() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
-    }
-
     @Test
     public void testAttachDetach() {
         NotificationMenuRowPlugin row =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index bb85cec..ceb4d84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification.stack;
 
 import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED;
-import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
 import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
@@ -64,7 +63,6 @@
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
 
-import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
@@ -102,17 +100,12 @@
     @Mock private SysuiStatusBarStateController mStatusBarStateController;
     @Mock private NotificationSwipeHelper mNotificationSwipeHelper;
     @Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
-    private int mOriginalInterruptionModelSetting;
 
     @Before
     @UiThreadTest
     public void setUp() throws Exception {
         allowTestableLooperAsMainThread();
 
-        mOriginalInterruptionModelSetting = Settings.Secure.getInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
         Settings.Secure.putIntForUser(mContext.getContentResolver(), NOTIFICATION_HISTORY_ENABLED,
                 1, UserHandle.USER_CURRENT);
 
@@ -166,12 +159,6 @@
         doNothing().when(notificationShelf).setAnimationsEnabled(anyBoolean());
     }
 
-    @After
-    public void tearDown() {
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                NOTIFICATION_NEW_INTERRUPTION_MODEL, mOriginalInterruptionModelSetting);
-    }
-
     @Test
     public void testNotDimmedOnKeyguard() {
         when(mBarState.getState()).thenReturn(StatusBarState.SHADE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
index ede5fce..a1d419c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconAreaControllerTest.java
@@ -25,6 +25,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.bubbles.Bubbles;
 import com.android.systemui.demomode.DemoModeController;
@@ -76,7 +77,6 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-
         mController = new NotificationIconAreaController(
                 mContext,
                 mStatusBarStateController,
@@ -89,7 +89,6 @@
                 mDemoModeController,
                 mDarkIconDispatcher,
                 mStatusBarWindowController);
-        mController.setupAodIcons(mAodIcons);
     }
 
     @Test
@@ -108,6 +107,9 @@
 
     @Test
     public void testAppearResetsTranslation() {
+        mController.setupAodIcons(
+                mAodIcons,
+                KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL);
         when(mDozeParameters.shouldControlScreenOff()).thenReturn(false);
         mController.appearAodIcons();
         verify(mAodIcons).setTranslationY(0);
diff --git a/packages/Tethering/apex/manifest.json b/packages/Tethering/apex/manifest.json
index 538ffb3..11e205d 100644
--- a/packages/Tethering/apex/manifest.json
+++ b/packages/Tethering/apex/manifest.json
@@ -1,4 +1,4 @@
 {
   "name": "com.android.tethering",
-  "version": 300000000
+  "version": 309999900
 }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 60aa7cb..f76dd3f 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -117,6 +117,7 @@
         "android.hardware.contexthub-V1.0-java",
         "android.hardware.rebootescrow-java",
         "android.hardware.soundtrigger-V2.3-java",
+        "android.hardware.power.stats-java",
         "android.hidl.manager-V1.2-java",
         "capture_state_listener-aidl-java",
         "dnsresolver_aidl_interface-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 031ad42..4c8925b 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1109,4 +1109,17 @@
         }
     }
 
+    /**
+     * Retrieve all of the information we know about a particular activity class including its
+     * package states.
+     *
+     * @param packageName a specific package
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     *                         of the calling UID.
+     * @param userId The user for whom the package is installed
+     * @return IncrementalStatesInfo that contains information about package states.
+     */
+    public abstract IncrementalStatesInfo getIncrementalStatesInfo(String packageName,
+            int filterCallingUid, int userId);
+
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0cd6e0810..afea976 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -929,13 +929,6 @@
         }
 
         /**
-         * @see ServiceManager#checkService(String)
-         */
-        public boolean hasService(@NonNull String name) {
-            return ServiceManager.checkService(name) != null;
-        }
-
-        /**
          * @see IpConnectivityMetrics.Logger
          */
         public IpConnectivityMetrics.Logger getMetricsLogger() {
@@ -1078,7 +1071,8 @@
 
         // Do the same for Ethernet, since it's often not specified in the configs, although many
         // devices can use it via USB host adapters.
-        if (mNetConfigs[TYPE_ETHERNET] == null && mDeps.hasService(Context.ETHERNET_SERVICE)) {
+        if (mNetConfigs[TYPE_ETHERNET] == null
+                && mContext.getSystemService(Context.ETHERNET_SERVICE) != null) {
             mLegacyTypeTracker.addSupportedType(TYPE_ETHERNET);
             mNetworksDefined++;
         }
diff --git a/services/core/java/com/android/server/VibratorManagerService.java b/services/core/java/com/android/server/VibratorManagerService.java
index 2f35da7..356cd0c 100644
--- a/services/core/java/com/android/server/VibratorManagerService.java
+++ b/services/core/java/com/android/server/VibratorManagerService.java
@@ -16,12 +16,15 @@
 
 package com.android.server;
 
+import android.annotation.Nullable;
 import android.content.Context;
+import android.os.CombinedVibrationEffect;
 import android.os.IBinder;
 import android.os.IVibratorManagerService;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
+import android.os.VibrationAttributes;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -66,6 +69,17 @@
         return Arrays.copyOf(mVibratorIds, mVibratorIds.length);
     }
 
+    @Override // Binder call
+    public void vibrate(int uid, String opPkg, CombinedVibrationEffect effect,
+            @Nullable VibrationAttributes attrs, String reason, IBinder token) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
+    @Override // Binder call
+    public void cancelVibrate(IBinder token) {
+        throw new UnsupportedOperationException("Not implemented");
+    }
+
     @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
             String[] args, ShellCallback cb, ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 57f8112..f1c5915 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -18,6 +18,7 @@
 
 import static android.os.Process.ZYGOTE_POLICY_FLAG_EMPTY;
 import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE;
+import static android.text.TextUtils.formatSimple;
 
 import static com.android.server.am.ActivityManagerDebugConfig.*;
 
@@ -1892,7 +1893,7 @@
     }
 
     private String createBroadcastTraceTitle(BroadcastRecord record, int state) {
-        return String.format("Broadcast %s from %s (%s) %s",
+        return formatSimple("Broadcast %s from %s (%s) %s",
                 state == BroadcastRecord.DELIVERY_PENDING ? "in queue" : "dispatched",
                 record.callerPackage == null ? "" : record.callerPackage,
                 record.callerApp == null ? "process unknown" : record.callerApp.toShortString(),
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index df8bff2..be49ce4 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -265,4 +265,13 @@
             return mUnstableCount;
         }
     }
+
+    /**
+     * Returns the total number of stable and unstable references.
+     */
+    int totalRefCount() {
+        synchronized (mLock) {
+            return mStableCount + mUnstableCount;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 950f0a0..34256a0 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -62,6 +62,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.RescueParty;
 
@@ -261,7 +262,8 @@
                     // doesn't kill our process.
                     Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString()
                             + " is crashing; detaching " + r);
-                    boolean lastRef = decProviderCountLocked(conn, cpr, token, stable);
+                    boolean lastRef = decProviderCountLocked(conn, cpr, token, stable,
+                            false, false);
                     if (!lastRef) {
                         // This wasn't the last ref our process had on
                         // the provider...  we will be killed during cleaning up, bail.
@@ -697,10 +699,7 @@
                 if (conn == null) {
                     throw new NullPointerException("connection is null");
                 }
-                if (decProviderCountLocked(conn, null, null, stable)) {
-                    mService.updateOomAdjLocked(conn.provider.proc,
-                            OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
-                }
+                decProviderCountLocked(conn, null, null, stable, true, true);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -1275,30 +1274,56 @@
 
     @GuardedBy("mService")
     private boolean decProviderCountLocked(ContentProviderConnection conn,
-            ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) {
+            ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable,
+            boolean enforceDelay, boolean updateOomAdj) {
         if (conn == null) {
             cpr.removeExternalProcessHandleLocked(externalProcessToken);
             return false;
         }
-        if (conn.decrementCount(stable) != 0) {
+
+        if (conn.totalRefCount() > 1) {
+            conn.decrementCount(stable);
             return false;
         }
+        if (enforceDelay) {
+            // delay the removal of the provider for 5 seconds - this optimizes for those cases
+            // where providers are released and then quickly re-acquired, causing lots of churn.
+            BackgroundThread.getHandler().postDelayed(() -> {
+                handleProviderRemoval(conn, stable, updateOomAdj);
+            }, 5 * 1000);
+        } else {
+            handleProviderRemoval(conn, stable, updateOomAdj);
+        }
+        return true;
+    }
 
-        cpr = conn.provider;
-        conn.stopAssociation();
-        cpr.connections.remove(conn);
-        conn.client.conProviders.remove(conn);
-        if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
-            // The client is more important than last activity -- note the time this
-            // is happening, so we keep the old provider process around a bit as last
-            // activity to avoid thrashing it.
-            if (cpr.proc != null) {
-                cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
+    private void handleProviderRemoval(ContentProviderConnection conn, boolean stable,
+            boolean updateOomAdj) {
+        synchronized (mService) {
+            // if the proc was already killed or this is not the last reference, simply exit.
+            if (conn == null || conn.provider == null || conn.decrementCount(stable) != 0) {
+                return;
+            }
+
+            final ContentProviderRecord cpr = conn.provider;
+            conn.stopAssociation();
+            cpr.connections.remove(conn);
+            conn.client.conProviders.remove(conn);
+            if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {
+                // The client is more important than last activity -- note the time this
+                // is happening, so we keep the old provider process around a bit as last
+                // activity to avoid thrashing it.
+                if (cpr.proc != null) {
+                    cpr.proc.lastProviderTime = SystemClock.uptimeMillis();
+                }
+            }
+            mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
+                    cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
+            if (updateOomAdj) {
+                mService.updateOomAdjLocked(conn.provider.proc,
+                        OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER);
             }
         }
-        mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid,
-                cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName);
-        return true;
     }
 
     /**
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 662d8d5..cfc58a5 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1078,7 +1078,7 @@
 
         // Restore call state
         synchronized (mDeviceBroker.mSetModeLock) {
-            if (AudioSystem.setPhoneState(mMode, getModeOwnerUid())
+            if (mAudioSystem.setPhoneState(mMode, getModeOwnerUid())
                     ==  AudioSystem.AUDIO_STATUS_OK) {
                 mModeLogger.log(new AudioEventLogger.StringEvent(
                         "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode)
@@ -1165,7 +1165,7 @@
             HashMap<Integer, Integer> allowedCapturePolicies =
                     mPlaybackMonitor.getAllAllowedCapturePolicies();
             for (HashMap.Entry<Integer, Integer> entry : allowedCapturePolicies.entrySet()) {
-                int result = AudioSystem.setAllowedCapturePolicy(
+                int result = mAudioSystem.setAllowedCapturePolicy(
                         entry.getKey(),
                         AudioAttributes.capturePolicyToFlags(entry.getValue(), 0x0));
                 if (result != AudioSystem.AUDIO_STATUS_OK) {
@@ -2112,7 +2112,7 @@
     protected @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributesInt(
             @NonNull AudioAttributes attributes) {
         Objects.requireNonNull(attributes);
-        return AudioSystem.getDevicesForAttributes(attributes);
+        return mAudioSystem.getDevicesForAttributes(attributes);
     }
 
     /** Indicates no special treatment in the handling of the volume adjustement */
@@ -2219,7 +2219,7 @@
                         || maybeActiveStreamType == AudioSystem.STREAM_NOTIFICATION) {
                     activeForReal = wasStreamActiveRecently(maybeActiveStreamType, 0);
                 } else {
-                    activeForReal = AudioSystem.isStreamActive(maybeActiveStreamType, 0);
+                    activeForReal = mAudioSystem.isStreamActive(maybeActiveStreamType, 0);
                 }
                 if (activeForReal || mVolumeControlStream == -1) {
                     streamType = maybeActiveStreamType;
@@ -2916,7 +2916,7 @@
         int streamType = getHearingAidStreamType(newMode);
 
         final Set<Integer> deviceTypes = AudioSystem.generateAudioDeviceTypesSet(
-                AudioSystem.getDevicesForStream(streamType));
+                mAudioSystem.getDevicesForStream(streamType));
         final Set<Integer> absVolumeMultiModeCaseDevices = AudioSystem.intersectionAudioDeviceTypes(
                 mAbsVolumeMultiModeCaseDevices, deviceTypes);
         if (absVolumeMultiModeCaseDevices.isEmpty()) {
@@ -4123,7 +4123,7 @@
 
             if (actualMode != mMode) {
                 final long identity = Binder.clearCallingIdentity();
-                status = AudioSystem.setPhoneState(actualMode, getModeOwnerUid());
+                status = mAudioSystem.setPhoneState(actualMode, getModeOwnerUid());
                 Binder.restoreCallingIdentity(identity);
                 if (status == AudioSystem.AUDIO_STATUS_OK) {
                     if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); }
@@ -4597,7 +4597,7 @@
                             caller,
                             MUSIC_ACTIVE_POLL_PERIOD_MS);
                     int index = mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(device);
-                    if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
+                    if (mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
                             && (index > safeMediaVolumeIndex(device))) {
                         // Approximate cumulative active music time
                         mMusicActiveMs += MUSIC_ACTIVE_POLL_PERIOD_MS;
@@ -4981,8 +4981,8 @@
      *     in the last "delay_ms" ms.
      */
     private boolean wasStreamActiveRecently(int stream, int delay_ms) {
-        return AudioSystem.isStreamActive(stream, delay_ms)
-                || AudioSystem.isStreamActiveRemotely(stream, delay_ms);
+        return mAudioSystem.isStreamActive(stream, delay_ms)
+                || mAudioSystem.isStreamActiveRemotely(stream, delay_ms);
     }
 
     private int getActiveStreamType(int suggestedStreamType) {
@@ -4994,7 +4994,7 @@
         switch (mPlatformType) {
         case AudioSystem.PLATFORM_VOICE:
             if (isInCommunication()) {
-                if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
+                if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
                         == AudioSystem.FORCE_BT_SCO) {
                     // Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO...");
                     return AudioSystem.STREAM_BLUETOOTH_SCO;
@@ -5031,7 +5031,7 @@
             }
         default:
             if (isInCommunication()) {
-                if (AudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
+                if (mAudioSystem.getForceUse(AudioSystem.FOR_COMMUNICATION)
                         == AudioSystem.FORCE_BT_SCO) {
                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_BLUETOOTH_SCO");
                     return AudioSystem.STREAM_BLUETOOTH_SCO;
@@ -5039,30 +5039,30 @@
                     if (DEBUG_VOL)  Log.v(TAG, "getActiveStreamType: Forcing STREAM_VOICE_CALL");
                     return AudioSystem.STREAM_VOICE_CALL;
                 }
-            } else if (AudioSystem.isStreamActive(
+            } else if (mAudioSystem.isStreamActive(
                     AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
                 return AudioSystem.STREAM_NOTIFICATION;
-            } else if (AudioSystem.isStreamActive(
+            } else if (mAudioSystem.isStreamActive(
                     AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
                 return AudioSystem.STREAM_RING;
             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-                if (AudioSystem.isStreamActive(
+                if (mAudioSystem.isStreamActive(
                         AudioSystem.STREAM_NOTIFICATION, sStreamOverrideDelayMs)) {
                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
                     return AudioSystem.STREAM_NOTIFICATION;
-                } else if (AudioSystem.isStreamActive(
+                }
+                if (mAudioSystem.isStreamActive(
                         AudioSystem.STREAM_RING, sStreamOverrideDelayMs)) {
                     if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING");
                     return AudioSystem.STREAM_RING;
-                } else {
-                    if (DEBUG_VOL) {
-                        Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
-                                + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
-                    }
-                    return DEFAULT_VOL_STREAM_NO_PLAYBACK;
                 }
+                if (DEBUG_VOL) {
+                    Log.v(TAG, "getActiveStreamType: Forcing DEFAULT_VOL_STREAM_NO_PLAYBACK("
+                            + DEFAULT_VOL_STREAM_NO_PLAYBACK + ") b/c default");
+                }
+                return DEFAULT_VOL_STREAM_NO_PLAYBACK;
             }
             break;
         }
@@ -5477,7 +5477,7 @@
                 && DEVICE_MEDIA_UNMUTED_ON_PLUG_SET.contains(newDevice)
                 && mStreamStates[AudioSystem.STREAM_MUSIC].mIsMuted
                 && mStreamStates[AudioSystem.STREAM_MUSIC].getIndex(newDevice) != 0
-                && (newDevice & AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
+                && (newDevice & mAudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC)) != 0) {
             if (DEBUG_VOL) {
                 Log.i(TAG, String.format("onAccessoryPlugMediaUnmute unmuting device=%d [%s]",
                         newDevice, AudioSystem.getOutputDeviceName(newDevice)));
@@ -5945,7 +5945,7 @@
             if (!mSystemServer.isPrivileged()) {
                 return AudioSystem.DEVICE_NONE;
             }
-            final int devices = AudioSystem.getDevicesForStream(mStreamType);
+            final int devices = mAudioSystem.getDevicesForStream(mStreamType);
             if (devices == mObservedDevices) {
                 return devices;
             }
@@ -6670,7 +6670,7 @@
                             .record();
                     sForceUseLogger.log(
                             new AudioServiceEvents.ForceUseEvent(useCase, config, eventSource));
-                    AudioSystem.setForceUse(useCase, config);
+                    mAudioSystem.setForceUse(useCase, config);
                 }
                     break;
 
@@ -7993,7 +7993,7 @@
         }
     }
 
-    public static class VolumeController {
+    public class VolumeController {
         private static final String TAG = "VolumeController";
 
         private IVolumeController mController;
@@ -8033,7 +8033,7 @@
             if (resolvedStream == DEFAULT_VOL_STREAM_NO_PLAYBACK && mController != null) {
                 // never suppress media vol adjustement during media playback
                 if (resolvedStream == AudioSystem.STREAM_MUSIC
-                        && AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, mLongPressTimeout))
+                        && mAudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, mLongPressTimeout))
                 {
                     // media is playing, adjust the volume right away
                     return false;
@@ -8071,7 +8071,7 @@
             return binder(mController);
         }
 
-        private static IBinder binder(IVolumeController controller) {
+        private IBinder binder(IVolumeController controller) {
             return controller == null ? null : controller.asBinder();
         }
 
@@ -8800,7 +8800,7 @@
         int flags = AudioAttributes.capturePolicyToFlags(capturePolicy, 0x0);
         final long identity = Binder.clearCallingIdentity();
         synchronized (mPlaybackMonitor) {
-            int result = AudioSystem.setAllowedCapturePolicy(callingUid, flags);
+            int result = mAudioSystem.setAllowedCapturePolicy(callingUid, flags);
             if (result == AudioSystem.AUDIO_STATUS_OK) {
                 mPlaybackMonitor.setAllowedCapturePolicy(callingUid, capturePolicy);
             }
@@ -8943,7 +8943,7 @@
                 }
             }
             final long identity = Binder.clearCallingIdentity();
-            AudioSystem.registerPolicyMixes(mMixes, false);
+            mAudioSystem.registerPolicyMixes(mMixes, false);
             Binder.restoreCallingIdentity(identity);
             synchronized (mAudioPolicies) {
                 mAudioPolicies.remove(mPolicyCallback.asBinder());
@@ -8986,24 +8986,24 @@
         int addMixes(@NonNull ArrayList<AudioMix> mixes) {
             // TODO optimize to not have to unregister the mixes already in place
             synchronized (mMixes) {
-                AudioSystem.registerPolicyMixes(mMixes, false);
+                mAudioSystem.registerPolicyMixes(mMixes, false);
                 this.add(mixes);
-                return AudioSystem.registerPolicyMixes(mMixes, true);
+                return mAudioSystem.registerPolicyMixes(mMixes, true);
             }
         }
 
         int removeMixes(@NonNull ArrayList<AudioMix> mixes) {
             // TODO optimize to not have to unregister the mixes already in place
             synchronized (mMixes) {
-                AudioSystem.registerPolicyMixes(mMixes, false);
+                mAudioSystem.registerPolicyMixes(mMixes, false);
                 this.remove(mixes);
-                return AudioSystem.registerPolicyMixes(mMixes, true);
+                return mAudioSystem.registerPolicyMixes(mMixes, true);
             }
         }
 
         @AudioSystem.AudioSystemError int connectMixes() {
             final long identity = Binder.clearCallingIdentity();
-            int status = AudioSystem.registerPolicyMixes(mMixes, true);
+            int status = mAudioSystem.registerPolicyMixes(mMixes, true);
             Binder.restoreCallingIdentity(identity);
             return status;
         }
@@ -9039,7 +9039,7 @@
         @AudioSystem.AudioSystemError private int removeUidDeviceAffinitiesFromSystem(int uid) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                return AudioSystem.removeUidDeviceAffinities(uid);
+                return mAudioSystem.removeUidDeviceAffinities(uid);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -9049,7 +9049,7 @@
                 AudioDeviceArray deviceArray) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                return AudioSystem.setUidDeviceAffinities(uid, deviceArray.mDeviceTypes,
+                return mAudioSystem.setUidDeviceAffinities(uid, deviceArray.mDeviceTypes,
                         deviceArray.mDeviceAddresses);
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -9091,7 +9091,7 @@
                 @UserIdInt int userId) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                return AudioSystem.removeUserIdDeviceAffinities(userId);
+                return mAudioSystem.removeUserIdDeviceAffinities(userId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -9101,7 +9101,7 @@
                 @UserIdInt int userId, AudioDeviceArray deviceArray) {
             final long identity = Binder.clearCallingIdentity();
             try {
-                return AudioSystem.setUserIdDeviceAffinities(userId, deviceArray.mDeviceTypes,
+                return mAudioSystem.setUserIdDeviceAffinities(userId, deviceArray.mDeviceTypes,
                         deviceArray.mDeviceAddresses);
             } finally {
                 Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index ae64990..891c713 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -17,9 +17,12 @@
 package com.android.server.audio;
 
 import android.annotation.NonNull;
+import android.media.AudioAttributes;
 import android.media.AudioDeviceAttributes;
 import android.media.AudioSystem;
+import android.media.audiopolicy.AudioMix;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -40,6 +43,25 @@
     }
 
     /**
+     * Same as {@link AudioSystem#getDevicesForStream(int)}
+     * @param stream a valid stream type
+     * @return a mask of device types
+     */
+    public int getDevicesForStream(int stream) {
+        return AudioSystem.getDevicesForStream(stream);
+    }
+
+    /**
+     * Same as {@link AudioSystem#getDevicesForAttributes(AudioAttributes)}
+     * @param attributes the attributes for which the routing is queried
+     * @return the devices that the stream with the given attributes would be routed to
+     */
+    public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
+            @NonNull AudioAttributes attributes) {
+        return AudioSystem.getDevicesForAttributes(attributes);
+    }
+
+    /**
      * Same as {@link AudioSystem#setDeviceConnectionState(int, int, String, String, int)}
      * @param device
      * @param state
@@ -178,4 +200,104 @@
     public boolean isStreamActive(int stream, int inPastMs) {
         return AudioSystem.isStreamActive(stream, inPastMs);
     }
+
+    /**
+     * Same as {@link AudioSystem#isStreamActiveRemotely(int, int)}
+     * @param stream
+     * @param inPastMs
+     * @return
+     */
+    public boolean isStreamActiveRemotely(int stream, int inPastMs) {
+        return AudioSystem.isStreamActiveRemotely(stream, inPastMs);
+    }
+
+    /**
+     * Same as {@link AudioSystem#setPhoneState(int, int)}
+     * @param state
+     * @param uid
+     * @return
+     */
+    public int setPhoneState(int state, int uid) {
+        return AudioSystem.setPhoneState(state, uid);
+    }
+
+    /**
+     * Same as {@link AudioSystem#setAllowedCapturePolicy(int, int)}
+     * @param uid
+     * @param flags
+     * @return
+     */
+    public int setAllowedCapturePolicy(int uid, int flags) {
+        return AudioSystem.setAllowedCapturePolicy(uid, flags);
+    }
+
+    /**
+     * Same as {@link AudioSystem#setForceUse(int, int)}
+     * @param usage
+     * @param config
+     * @return
+     */
+    public int setForceUse(int usage, int config) {
+        return AudioSystem.setForceUse(usage, config);
+    }
+
+    /**
+     * Same as {@link AudioSystem#getForceUse(int)}
+     * @param usage
+     * @return
+     */
+    public int getForceUse(int usage) {
+        return AudioSystem.getForceUse(usage);
+    }
+
+    /**
+     * Same as {@link AudioSystem#registerPolicyMixes(ArrayList, boolean)}
+     * @param mixes
+     * @param register
+     * @return
+     */
+    public int registerPolicyMixes(ArrayList<AudioMix> mixes, boolean register) {
+        return AudioSystem.registerPolicyMixes(mixes, register);
+    }
+
+    /**
+     * Same as {@link AudioSystem#setUidDeviceAffinities(int, int[], String[])}
+     * @param uid
+     * @param types
+     * @param addresses
+     * @return
+     */
+    public int setUidDeviceAffinities(int uid, @NonNull int[] types,  @NonNull String[] addresses) {
+        return AudioSystem.setUidDeviceAffinities(uid, types, addresses);
+    }
+
+    /**
+     * Same as {@link AudioSystem#removeUidDeviceAffinities(int)}
+     * @param uid
+     * @return
+     */
+    public int removeUidDeviceAffinities(int uid) {
+        return AudioSystem.removeUidDeviceAffinities(uid);
+    }
+
+    /**
+     * Same as {@link AudioSystem#setUserIdDeviceAffinities(int, int[], String[])}
+     * @param userId
+     * @param types
+     * @param addresses
+     * @return
+     */
+    public int setUserIdDeviceAffinities(int userId, @NonNull int[] types,
+            @NonNull String[] addresses) {
+        return AudioSystem.setUserIdDeviceAffinities(userId, types, addresses);
+    }
+
+    /**
+     * Same as {@link AudioSystem#removeUserIdDeviceAffinities(int)}
+     * @param userId
+     * @return
+     */
+    public int removeUserIdDeviceAffinities(int userId) {
+        return AudioSystem.removeUserIdDeviceAffinities(userId);
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/LingerMonitor.java b/services/core/java/com/android/server/connectivity/LingerMonitor.java
index 04c000f..7fdc7a0 100644
--- a/services/core/java/com/android/server/connectivity/LingerMonitor.java
+++ b/services/core/java/com/android/server/connectivity/LingerMonitor.java
@@ -159,8 +159,9 @@
 
     @VisibleForTesting
     protected PendingIntent createNotificationIntent() {
-        return PendingIntent.getActivityAsUser(mContext, 0, CELLULAR_SETTINGS,
-                PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT);
+        return PendingIntent.getActivityAsUser(mContext, 0 /* requestCode */, CELLULAR_SETTINGS,
+                PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE,
+                null /* options */, UserHandle.CURRENT);
     }
 
     // Removes any notification that was put up as a result of switching to nai.
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 34b0aa2..26356b4 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -325,7 +325,8 @@
     public void setProvNotificationVisible(boolean visible, int id, String action) {
         if (visible) {
             Intent intent = new Intent(action);
-            PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
+            PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                    mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_IMMUTABLE);
             showNotification(id, NotificationType.SIGN_IN, null, null, pendingIntent, false);
         } else {
             clearNotification(id);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
index 393a66e..3224d31 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecConfig.java
@@ -16,6 +16,8 @@
 
 package com.android.server.hdmi;
 
+import static android.hardware.hdmi.HdmiControlManager.CecSettingName;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -56,10 +58,6 @@
     private static final String ETC_DIR = "etc";
     private static final String CONFIG_FILE = "cec_config.xml";
 
-    @Nullable private CecSettings mProductConfig = null;
-    @Nullable private CecSettings mVendorOverride = null;
-    @Nullable private StorageAdapter mStorageAdapter = null;
-
     @IntDef({
         STORAGE_SYSPROPS,
         STORAGE_GLOBAL_SETTINGS,
@@ -81,6 +79,11 @@
     public static final String SYSPROP_SYSTEM_AUDIO_MODE_MUTING =
             "ro.hdmi.cec.audio.system_audio_mode_muting.enabled";
 
+    @NonNull private final Context mContext;
+    @NonNull private final StorageAdapter mStorageAdapter;
+    @Nullable private final CecSettings mProductConfig;
+    @Nullable private final CecSettings mVendorOverride;
+
     /**
      * Setting storage input/output helper class.
      */
@@ -124,20 +127,22 @@
     }
 
     @VisibleForTesting
-    HdmiCecConfig(@Nullable CecSettings productConfig,
-                  @Nullable CecSettings vendorOverride,
-                  @Nullable StorageAdapter storageAdapter) {
+    HdmiCecConfig(@NonNull Context context,
+                  @NonNull StorageAdapter storageAdapter,
+                  @Nullable CecSettings productConfig,
+                  @Nullable CecSettings vendorOverride) {
+        mContext = context;
+        mStorageAdapter = storageAdapter;
         mProductConfig = productConfig;
         mVendorOverride = vendorOverride;
-        mStorageAdapter = storageAdapter;
     }
 
-    HdmiCecConfig() {
-        this(readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(),
+    HdmiCecConfig(@NonNull Context context) {
+        this(context, new StorageAdapter(),
+             readSettingsFromFile(Environment.buildPath(Environment.getProductDirectory(),
                                                         ETC_DIR, CONFIG_FILE)),
              readSettingsFromFile(Environment.buildPath(Environment.getVendorDirectory(),
-                                                        ETC_DIR, CONFIG_FILE)),
-             new StorageAdapter());
+                                                        ETC_DIR, CONFIG_FILE)));
     }
 
     @Nullable
@@ -179,13 +184,13 @@
     @Storage
     private int getStorage(@NonNull Setting setting) {
         switch (setting.getName()) {
-            case HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED:
+            case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED:
                 return STORAGE_GLOBAL_SETTINGS;
-            case HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP:
+            case HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP:
                 return STORAGE_GLOBAL_SETTINGS;
-            case HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
+            case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
                 return STORAGE_SYSPROPS;
-            case HdmiControlManager.SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
+            case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
                 return STORAGE_SYSPROPS;
             default:
                 throw new RuntimeException("Invalid CEC setting '" + setting.getName()
@@ -195,13 +200,13 @@
 
     private String getStorageKey(@NonNull Setting setting) {
         switch (setting.getName()) {
-            case HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED:
+            case HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED:
                 return Global.HDMI_CONTROL_ENABLED;
-            case HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP:
+            case HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP:
                 return Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP;
-            case HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
+            case HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST:
                 return SYSPROP_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST;
-            case HdmiControlManager.SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
+            case HdmiControlManager.CEC_SETTING_NAME_SYSTEM_AUDIO_MODE_MUTING:
                 return SYSPROP_SYSTEM_AUDIO_MODE_MUTING;
             default:
                 throw new RuntimeException("Invalid CEC setting '" + setting.getName()
@@ -209,7 +214,7 @@
         }
     }
 
-    private String retrieveValue(@NonNull Context context, @NonNull Setting setting) {
+    private String retrieveValue(@NonNull Setting setting) {
         @Storage int storage = getStorage(setting);
         String storageKey = getStorageKey(setting);
         if (storage == STORAGE_SYSPROPS) {
@@ -218,14 +223,13 @@
                     setting.getDefaultValue().getStringValue());
         } else if (storage == STORAGE_GLOBAL_SETTINGS) {
             Slog.d(TAG, "Reading '" + storageKey + "' global setting.");
-            return mStorageAdapter.retrieveGlobalSetting(context, storageKey,
+            return mStorageAdapter.retrieveGlobalSetting(mContext, storageKey,
                     setting.getDefaultValue().getStringValue());
         }
         return null;
     }
 
-    private void storeValue(@NonNull Context context, @NonNull Setting setting,
-                            @NonNull String value) {
+    private void storeValue(@NonNull Setting setting, @NonNull String value) {
         @Storage int storage = getStorage(setting);
         String storageKey = getStorageKey(setting);
         if (storage == STORAGE_SYSPROPS) {
@@ -233,38 +237,49 @@
             mStorageAdapter.storeSystemProperty(storageKey, value);
         } else if (storage == STORAGE_GLOBAL_SETTINGS) {
             Slog.d(TAG, "Setting '" + storageKey + "' global setting.");
-            mStorageAdapter.storeGlobalSetting(context, storageKey, value);
+            mStorageAdapter.storeGlobalSetting(mContext, storageKey, value);
         }
     }
 
     /**
-     * Returns a list of currently available settings based on the XML metadata.
+     * Returns a list of all settings based on the XML metadata.
      */
-    public List<String> getAvailableSettings() {
-        Set<String> availableSettings = new HashSet<String>();
+    public @CecSettingName List<String> getAllSettings() {
+        List<String> allSettings = new ArrayList<String>();
+        for (Setting setting : mProductConfig.getSetting()) {
+            allSettings.add(setting.getName());
+        }
+        return allSettings;
+    }
+
+    /**
+     * Returns a list of user-modifiable settings based on the XML metadata.
+     */
+    public @CecSettingName List<String> getUserSettings() {
+        Set<String> userSettings = new HashSet<String>();
         // First read from the product config.
         for (Setting setting : mProductConfig.getSetting()) {
             if (setting.getUserConfigurable()) {
-                availableSettings.add(setting.getName());
+                userSettings.add(setting.getName());
             }
         }
         if (mVendorOverride != null) {
             // Next either add or remove based on the vendor override.
             for (Setting setting : mVendorOverride.getSetting()) {
                 if (setting.getUserConfigurable()) {
-                    availableSettings.add(setting.getName());
+                    userSettings.add(setting.getName());
                 } else {
-                    availableSettings.remove(setting.getName());
+                    userSettings.remove(setting.getName());
                 }
             }
         }
-        return new ArrayList(availableSettings);
+        return new ArrayList(userSettings);
     }
 
     /**
      * For a given setting name returns values that are allowed for that setting.
      */
-    public List<String> getAllowedValues(@NonNull String name) {
+    public List<String> getAllowedValues(@NonNull @CecSettingName String name) {
         Setting setting = getSetting(name);
         if (setting == null) {
             throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
@@ -279,7 +294,7 @@
     /**
      * For a given setting name returns the default value for that setting.
      */
-    public String getDefaultValue(@NonNull String name) {
+    public String getDefaultValue(@NonNull @CecSettingName String name) {
         Setting setting = getSetting(name);
         if (setting == null) {
             throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
@@ -290,19 +305,19 @@
     /**
      * For a given setting name returns the current value of that setting.
      */
-    public String getValue(@NonNull Context context, @NonNull String name) {
+    public String getValue(@NonNull @CecSettingName String name) {
         Setting setting = getSetting(name);
         if (setting == null) {
             throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
         }
         Slog.d(TAG, "Getting CEC setting value '" + name + "'.");
-        return retrieveValue(context, setting);
+        return retrieveValue(setting);
     }
 
     /**
      * For a given setting name and value sets the current value of that setting.
      */
-    public void setValue(@NonNull Context context, @NonNull String name, @NonNull String value) {
+    public void setValue(@NonNull @CecSettingName String name, @NonNull String value) {
         Setting setting = getSetting(name);
         if (setting == null) {
             throw new IllegalArgumentException("Setting '" + name + "' does not exist.");
@@ -315,6 +330,6 @@
                                                + "' value: '" + value + "'.");
         }
         Slog.d(TAG, "Updating CEC setting '" + name + "' to '" + value + "'.");
-        storeValue(context, setting, value);
+        storeValue(setting, value);
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 98830cd..8bb89da 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -95,10 +95,12 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -188,7 +190,7 @@
     private boolean mHdmiCecVolumeControlEnabled;
 
     // Make sure HdmiCecConfig is instantiated and the XMLs are read.
-    private final HdmiCecConfig mHdmiCecConfig = new HdmiCecConfig();
+    private final HdmiCecConfig mHdmiCecConfig;
 
     /**
      * Interface to report send result.
@@ -486,6 +488,7 @@
         }
         mLocalDevices = deviceTypes;
         mSettingsObserver = new SettingsObserver(mHandler);
+        mHdmiCecConfig = new HdmiCecConfig(context);
     }
 
     protected static List<Integer> getIntList(String string) {
@@ -2319,6 +2322,19 @@
             pw.println("mHdmiCecVolumeControlEnabled: " + mHdmiCecVolumeControlEnabled);
             pw.decreaseIndent();
 
+            // CEC settings
+            pw.println("CEC settings:");
+            pw.increaseIndent();
+            HdmiCecConfig hdmiCecConfig = HdmiControlService.this.getHdmiCecConfig();
+            List<String> allSettings = hdmiCecConfig.getAllSettings();
+            Set<String> userSettings = new HashSet<>(hdmiCecConfig.getUserSettings());
+            for (String setting : allSettings) {
+                pw.println(setting + ": " + hdmiCecConfig.getValue(setting)
+                        + " (default: " + hdmiCecConfig.getDefaultValue(setting) + ")"
+                        + (userSettings.contains(setting) ? " [modifiable]" : ""));
+            }
+            pw.decreaseIndent();
+
             pw.println("mMhlController: ");
             pw.increaseIndent();
             mMhlController.dump(pw);
@@ -2334,11 +2350,11 @@
         }
 
         @Override
-        public List<String> getAvailableCecSettings() {
+        public List<String> getUserCecSettings() {
             enforceAccessPermission();
             long token = Binder.clearCallingIdentity();
             try {
-                return HdmiControlService.this.getHdmiCecConfig().getAvailableSettings();
+                return HdmiControlService.this.getHdmiCecConfig().getUserSettings();
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -2360,7 +2376,7 @@
             enforceAccessPermission();
             long token = Binder.clearCallingIdentity();
             try {
-                return HdmiControlService.this.getHdmiCecConfig().getValue(getContext(), name);
+                return HdmiControlService.this.getHdmiCecConfig().getValue(name);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -2371,7 +2387,7 @@
             enforceAccessPermission();
             long token = Binder.clearCallingIdentity();
             try {
-                HdmiControlService.this.getHdmiCecConfig().setValue(getContext(), name, value);
+                HdmiControlService.this.getHdmiCecConfig().setValue(name, value);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index fb23e01..7a2e4ed 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -242,6 +242,19 @@
                         }
                     }, UserHandle.USER_ALL);
         }
+
+        if (mContextHubWrapper.supportsAirplaneModeSettingNotifications()) {
+            sendAirplaneModeSettingUpdate();
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
+                    true /* notifyForDescendants */,
+                    new ContentObserver(null /* handler */) {
+                        @Override
+                        public void onChange(boolean selfChange) {
+                            sendAirplaneModeSettingUpdate();
+                        }
+                    }, UserHandle.USER_ALL);
+        }
     }
 
     /**
@@ -614,6 +627,7 @@
         if (eventType == AsyncEventType.RESTARTED) {
             sendLocationSettingUpdate();
             sendWifiSettingUpdate(true /* forceUpdate */);
+            sendAirplaneModeSettingUpdate();
 
             mTransactionManager.onHubReset();
             queryNanoAppsInternal(contextHubId);
@@ -958,6 +972,7 @@
 
     /**
      * Obtains the latest WiFi availability setting value and notifies the Context Hub.
+     *
      * @param forceUpdate True to force send update to the Context Hub, otherwise only send the
      *                    update when the WiFi availability changes.
      */
@@ -972,6 +987,17 @@
         }
     }
 
+    /**
+     * Obtains the latest airplane mode setting value and notifies the Context Hub.
+     */
+    private void sendAirplaneModeSettingUpdate() {
+        boolean enabled =
+                (Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.AIRPLANE_MODE_ON, 0)
+                        == 1);
+        mContextHubWrapper.onAirplaneModeSettingChanged(enabled);
+    }
+
     private String getCallingPackageName() {
         return mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
     }
diff --git a/services/core/java/com/android/server/location/IContextHubWrapper.java b/services/core/java/com/android/server/location/IContextHubWrapper.java
index 613964a..9ac7c6b 100644
--- a/services/core/java/com/android/server/location/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/IContextHubWrapper.java
@@ -116,6 +116,19 @@
      */
     public abstract void onWifiSettingChanged(boolean enabled);
 
+    /**
+     * @return True if this version of the Contexthub HAL supports airplane mode setting
+     * notifications.
+     */
+    public abstract boolean supportsAirplaneModeSettingNotifications();
+
+    /**
+     * Notifies the Contexthub implementation of an airplane mode setting change.
+     *
+     * @param enabled true if the airplane mode setting has been enabled.
+     */
+    public abstract void onAirplaneModeSettingChanged(boolean enabled);
+
     private static class ContextHubWrapperV1_0 extends IContextHubWrapper {
         private android.hardware.contexthub.V1_0.IContexthub mHub;
 
@@ -135,11 +148,18 @@
             return false;
         }
 
+        public boolean supportsAirplaneModeSettingNotifications() {
+            return false;
+        }
+
         public void onLocationSettingChanged(boolean enabled) {
         }
 
         public void onWifiSettingChanged(boolean enabled) {
         }
+
+        public void onAirplaneModeSettingChanged(boolean enabled) {
+        }
     }
 
     private static class ContextHubWrapperV1_1 extends IContextHubWrapper {
@@ -161,6 +181,10 @@
             return false;
         }
 
+        public boolean supportsAirplaneModeSettingNotifications() {
+            return false;
+        }
+
         public void onLocationSettingChanged(boolean enabled) {
             try {
                 mHub.onSettingChanged(Setting.LOCATION,
@@ -172,6 +196,9 @@
 
         public void onWifiSettingChanged(boolean enabled) {
         }
+
+        public void onAirplaneModeSettingChanged(boolean enabled) {
+        }
     }
 
     private static class ContextHubWrapperV1_2 extends IContextHubWrapper {
@@ -193,6 +220,10 @@
             return true;
         }
 
+        public boolean supportsAirplaneModeSettingNotifications() {
+            return true;
+        }
+
         public void onLocationSettingChanged(boolean enabled) {
             sendSettingChanged(Setting.LOCATION,
                     enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
@@ -203,6 +234,11 @@
                     enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
         }
 
+        public void onAirplaneModeSettingChanged(boolean enabled) {
+            sendSettingChanged(android.hardware.contexthub.V1_2.Setting.AIRPLANE_MODE,
+                    enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
+        }
+
         private void sendSettingChanged(byte setting, byte newValue) {
             try {
                 mHub.onSettingChanged_1_2(setting, newValue);
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 715e41c..5d0544b 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -17,6 +17,7 @@
 package com.android.server.locksettings;
 
 import static android.content.Context.USER_SERVICE;
+import static android.text.TextUtils.formatSimple;
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 import static com.android.internal.widget.LockPatternUtils.USER_FRP;
@@ -527,7 +528,7 @@
     protected String getSynthenticPasswordStateFilePathForUser(int userId, long handle,
             String name) {
         final File baseDir = getSyntheticPasswordDirectoryForUser(userId);
-        final String baseName = String.format("%016x.%s", handle, name);
+        final String baseName = formatSimple("%016x.%s", handle, name);
         return new File(baseDir, baseName).getAbsolutePath();
     }
 
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 05f2808..3a262d6 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -95,11 +95,13 @@
         mProfile = Objects.requireNonNull(profile);
 
         final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
-        mConfigIntent = PendingIntent.getActivity(mContext, 0, configIntent, 0);
+        mConfigIntent = PendingIntent.getActivity(mContext, 0 /* requestCode */, configIntent,
+                PendingIntent.FLAG_IMMUTABLE);
 
         final Intent resetIntent = new Intent(ACTION_LOCKDOWN_RESET);
         resetIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
-        mResetIntent = PendingIntent.getBroadcast(mContext, 0, resetIntent, 0);
+        mResetIntent = PendingIntent.getBroadcast(mContext, 0 /* requestCode */, resetIntent,
+                PendingIntent.FLAG_IMMUTABLE);
     }
 
     /**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index affdcea..dc9839c 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -18,11 +18,13 @@
 
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 
 import java.util.Set;
 
 public interface NotificationManagerInternal {
     NotificationChannel getNotificationChannel(String pkg, int uid, String channelId);
+    NotificationChannelGroup getNotificationChannelGroup(String pkg, int uid, String channelId);
     void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
             String tag, int id, Notification notification, int userId);
     void cancelNotification(String pkg, String basePkg, int callingUid, int callingPid,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0a11fbc..8ea4326 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3381,7 +3381,7 @@
 
         @Override
         public void createConversationNotificationChannelForPackage(String pkg, int uid,
-                String triggeringKey, NotificationChannel parentChannel, String conversationId) {
+                NotificationChannel parentChannel, String conversationId) {
             enforceSystemOrSystemUI("only system can call this");
             Preconditions.checkNotNull(parentChannel);
             Preconditions.checkNotNull(conversationId);
@@ -5590,6 +5590,12 @@
         }
 
         @Override
+        public NotificationChannelGroup getNotificationChannelGroup(String pkg, int uid, String
+                channelId) {
+            return mPreferencesHelper.getGroupForChannel(pkg, uid, channelId);
+        }
+
+        @Override
         public void enqueueNotification(String pkg, String opPkg, int callingUid, int callingPid,
                 String tag, int id, Notification notification, int userId) {
             enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
@@ -10078,24 +10084,27 @@
 
         @Override
         public boolean isActivityStartAllowed(int uid, String packageName) {
-            boolean block = CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid);
-            if (block || mPackagesShown.add(packageName)) {
-                mUiHandler.post(() ->
-                        Toast.makeText(getUiContext(),
-                                "Indirect activity start from "
-                                        + packageName + ". "
-                                        + "This will be blocked in S.\n"
-                                        + "See go/s-trampolines.",
-                                Toast.LENGTH_LONG).show());
-            }
-            String message =
+            String toastMessage = "Indirect activity start from " + packageName;
+            String logcatMessage =
                     "Indirect notification activity start (trampoline) from " + packageName;
-            if (block) {
-                Slog.e(TAG, message + " blocked");
+
+            if (CompatChanges.isChangeEnabled(NOTIFICATION_TRAMPOLINE_BLOCK, uid)) {
+                toast(toastMessage + " blocked.");
+                Slog.e(TAG, logcatMessage + " blocked");
                 return false;
+            } else {
+                if (mPackagesShown.add(packageName)) {
+                    toast(toastMessage + ". This will be blocked in S.");
+                }
+                Slog.w(TAG, logcatMessage + ", this should be avoided for performance reasons");
+                return true;
             }
-            Slog.w(TAG, message + ", this should be avoided for performance reasons");
-            return true;
+        }
+
+        private void toast(String message) {
+            mUiHandler.post(() ->
+                    Toast.makeText(getUiContext(), message + "\nSee go/s-trampolines.",
+                            Toast.LENGTH_LONG).show());
         }
     }
 }
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index bdf98f4..77713a6 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -1349,6 +1349,24 @@
         return groups;
     }
 
+    public NotificationChannelGroup getGroupForChannel(String pkg, int uid, String channelId) {
+        synchronized (mPackagePreferences) {
+            PackagePreferences p = getPackagePreferencesLocked(pkg, uid);
+            if (p != null) {
+                NotificationChannel nc = p.channels.get(channelId);
+                if (nc != null && !nc.isDeleted()) {
+                    if (nc.getGroup() != null) {
+                        NotificationChannelGroup group = p.groups.get(nc.getGroup());
+                        if (group != null) {
+                            return group;
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
     public ArrayList<ConversationChannelWrapper> getConversations(boolean onlyImportant) {
         synchronized (mPackagePreferences) {
             ArrayList<ConversationChannelWrapper> conversations = new ArrayList<>();
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index b145e1e..b4347e1 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,6 +15,8 @@
  */
 package com.android.server.notification;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.NonNull;
 import android.app.NotificationManager;
 import android.content.Context;
@@ -138,7 +140,7 @@
 
                 boolean isGroupSummary = record.getNotification().isGroupSummary();
                 record.setGlobalSortKey(
-                        String.format("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
+                        formatSimple("crtcl=0x%04x:intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
                         record.getCriticality(),
                         record.isRecentlyIntrusive()
                                 && record.getImportance() > NotificationManager.IMPORTANCE_MIN
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
index 43f4a34..26ace47 100644
--- a/services/core/java/com/android/server/pm/IncrementalStates.java
+++ b/services/core/java/com/android/server/pm/IncrementalStates.java
@@ -105,8 +105,8 @@
             if (!mStartableState.isStartable()) {
                 mStartableState.adoptNewStartableStateLocked(true);
             }
-            if (mLoadingState.isLoading() != isIncremental) {
-                mLoadingState.adoptNewLoadingStateLocked(isIncremental);
+            if (!isIncremental) {
+                updateProgressLocked(1);
             }
         }
         mHandler.post(PooledLambda.obtainRunnable(
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 9bb6f78..8eebf2a 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -44,6 +44,8 @@
 import android.content.pm.IPackageInstallerCallback;
 import android.content.pm.IPackageManager;
 import android.content.pm.IShortcutChangeCallback;
+import android.content.pm.IncrementalStatesInfo;
+import android.content.pm.LauncherActivityInfoInternal;
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageInfo;
@@ -369,18 +371,13 @@
             }
         }
 
-        private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid,
-                UserHandle user) {
+        private LauncherActivityInfoInternal getHiddenAppActivityInfo(String packageName,
+                int callingUid, UserHandle user) {
             Intent intent = new Intent();
             intent.setComponent(new ComponentName(packageName,
                     PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME));
-            final PackageManagerInternal pmInt =
-                    LocalServices.getService(PackageManagerInternal.class);
-            List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
-                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                    PackageManager.MATCH_DIRECT_BOOT_AWARE
-                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                    callingUid, user.getIdentifier());
+            final List<LauncherActivityInfoInternal> apps = queryIntentLauncherActivities(intent,
+                    callingUid, user);
             if (apps.size() > 0) {
                 return apps.get(0);
             }
@@ -399,14 +396,14 @@
         }
 
         @Override
-        public ParceledListSlice<ResolveInfo> getLauncherActivities(String callingPackage,
-                String packageName, UserHandle user) throws RemoteException {
-            ParceledListSlice<ResolveInfo> launcherActivities = queryActivitiesForUser(
-                    callingPackage,
-                    new Intent(Intent.ACTION_MAIN)
-                            .addCategory(Intent.CATEGORY_LAUNCHER)
-                            .setPackage(packageName),
-                    user);
+        public ParceledListSlice<LauncherActivityInfoInternal> getLauncherActivities(
+                String callingPackage, String packageName, UserHandle user) throws RemoteException {
+            ParceledListSlice<LauncherActivityInfoInternal> launcherActivities =
+                    queryActivitiesForUser(callingPackage,
+                            new Intent(Intent.ACTION_MAIN)
+                                    .addCategory(Intent.CATEGORY_LAUNCHER)
+                                    .setPackage(packageName),
+                            user);
             if (Settings.Global.getInt(mContext.getContentResolver(),
                     Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 1) == 0) {
                 return launcherActivities;
@@ -428,7 +425,8 @@
                     return launcherActivities;
                 }
 
-                final ArrayList<ResolveInfo> result = new ArrayList<>(launcherActivities.getList());
+                final ArrayList<LauncherActivityInfoInternal> result = new ArrayList<>(
+                        launcherActivities.getList());
                 final PackageManagerInternal pmInt =
                         LocalServices.getService(PackageManagerInternal.class);
                 if (packageName != null) {
@@ -440,7 +438,8 @@
                     ApplicationInfo appInfo = pmInt.getApplicationInfo(packageName, /*flags*/ 0,
                             callingUid, user.getIdentifier());
                     if (shouldShowSyntheticActivity(user, appInfo)) {
-                        ResolveInfo info = getHiddenAppActivityInfo(packageName, callingUid, user);
+                        LauncherActivityInfoInternal info = getHiddenAppActivityInfo(packageName,
+                                callingUid, user);
                         if (info != null) {
                             result.add(info);
                         }
@@ -448,8 +447,8 @@
                     return new ParceledListSlice<>(result);
                 }
                 final HashSet<String> visiblePackages = new HashSet<>();
-                for (ResolveInfo info : result) {
-                    visiblePackages.add(info.activityInfo.packageName);
+                for (LauncherActivityInfoInternal info : result) {
+                    visiblePackages.add(info.getActivityInfo().packageName);
                 }
                 List<ApplicationInfo> installedPackages = pmInt.getInstalledApplications(0,
                         user.getIdentifier(), callingUid);
@@ -458,8 +457,8 @@
                         if (!shouldShowSyntheticActivity(user, applicationInfo)) {
                             continue;
                         }
-                        ResolveInfo info = getHiddenAppActivityInfo(applicationInfo.packageName,
-                                callingUid, user);
+                        LauncherActivityInfoInternal info = getHiddenAppActivityInfo(
+                                applicationInfo.packageName, callingUid, user);
                         if (info != null) {
                             result.add(info);
                         }
@@ -533,7 +532,7 @@
         }
 
         @Override
-        public ActivityInfo resolveActivity(
+        public LauncherActivityInfoInternal resolveLauncherActivityInternal(
                 String callingPackage, ComponentName component, UserHandle user)
                 throws RemoteException {
             if (!canAccessProfile(user.getIdentifier(), "Cannot resolve activity")) {
@@ -545,10 +544,24 @@
             try {
                 final PackageManagerInternal pmInt =
                         LocalServices.getService(PackageManagerInternal.class);
-                return pmInt.getActivityInfo(component,
+                final ActivityInfo activityInfo = pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
                         callingUid, user.getIdentifier());
+                if (activityInfo == null) {
+                    return null;
+                }
+                if (component == null || component.getPackageName() == null) {
+                    // should not happen
+                    return null;
+                }
+                final IncrementalStatesInfo incrementalStatesInfo = pmInt.getIncrementalStatesInfo(
+                            component.getPackageName(), callingUid, user.getIdentifier());
+                if (incrementalStatesInfo == null) {
+                    // package does not exist; should not happen
+                    return null;
+                }
+                return new LauncherActivityInfoInternal(activityInfo, incrementalStatesInfo);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -562,28 +575,51 @@
                     new Intent(Intent.ACTION_CREATE_SHORTCUT).setPackage(packageName), user);
         }
 
-        private ParceledListSlice<ResolveInfo> queryActivitiesForUser(String callingPackage,
-                Intent intent, UserHandle user) {
+        private ParceledListSlice<LauncherActivityInfoInternal> queryActivitiesForUser(
+                String callingPackage, Intent intent, UserHandle user) {
             if (!canAccessProfile(user.getIdentifier(), "Cannot retrieve activities")) {
                 return null;
             }
-
             final int callingUid = injectBinderCallingUid();
             long ident = injectClearCallingIdentity();
             try {
-                final PackageManagerInternal pmInt =
-                        LocalServices.getService(PackageManagerInternal.class);
-                List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
-                        intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                        PackageManager.MATCH_DIRECT_BOOT_AWARE
-                                | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        callingUid, user.getIdentifier());
-                return new ParceledListSlice<>(apps);
+                return new ParceledListSlice<>(queryIntentLauncherActivities(intent, callingUid,
+                        user));
             } finally {
                 injectRestoreCallingIdentity(ident);
             }
         }
 
+        private List<LauncherActivityInfoInternal> queryIntentLauncherActivities(
+                Intent intent, int callingUid, UserHandle user) {
+            final PackageManagerInternal pmInt =
+                    LocalServices.getService(PackageManagerInternal.class);
+            List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
+                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                    PackageManager.MATCH_DIRECT_BOOT_AWARE
+                            | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
+                    callingUid, user.getIdentifier());
+            final int numResolveInfos = apps.size();
+            List<LauncherActivityInfoInternal> results = new ArrayList<>();
+            for (int i = 0; i < numResolveInfos; i++) {
+                final ResolveInfo ri = apps.get(i);
+                final String packageName = ri.activityInfo.packageName;
+                if (packageName == null) {
+                    // should not happen
+                    continue;
+                }
+                final IncrementalStatesInfo incrementalStatesInfo = pmInt.getIncrementalStatesInfo(
+                        packageName, callingUid, user.getIdentifier());
+                if (incrementalStatesInfo == null) {
+                    // package doesn't exist any more; should not happen
+                    continue;
+                }
+                results.add(new LauncherActivityInfoInternal(ri.activityInfo,
+                        incrementalStatesInfo));
+            }
+            return results;
+        }
+
         @Override
         public IntentSender getShortcutConfigActivityIntent(String callingPackage,
                 ComponentName component, UserHandle user) throws RemoteException {
@@ -1238,7 +1274,10 @@
                 } finally {
                     mListeners.finishBroadcast();
                 }
-
+                PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+                pmi.registerInstalledLoadingProgressCallback(packageName,
+                        new PackageLoadingProgressCallback(packageName, user),
+                        user.getIdentifier());
                 super.onPackageAdded(packageName, uid);
             }
 
@@ -1266,6 +1305,11 @@
 
             @Override
             public void onPackageModified(String packageName) {
+                onPackageChanged(packageName);
+                super.onPackageModified(packageName);
+            }
+
+            private void onPackageChanged(String packageName) {
                 UserHandle user = new UserHandle(getChangingUserId());
                 final int n = mListeners.beginBroadcast();
                 try {
@@ -1282,8 +1326,6 @@
                 } finally {
                     mListeners.finishBroadcast();
                 }
-
-                super.onPackageModified(packageName);
             }
 
             @Override
@@ -1435,6 +1477,7 @@
                         } catch (RemoteException re) {
                             Slog.d(TAG, "Callback failed ", re);
                         }
+
                     }
                 } catch (RuntimeException e) {
                     // When the user is locked we get IllegalState, so just catch all.
@@ -1443,6 +1486,12 @@
                     mListeners.finishBroadcast();
                 }
             }
+
+            @Override
+            public void onPackageStateChanged(String packageName, int uid) {
+                onPackageChanged(packageName);
+                super.onPackageStateChanged(packageName, uid);
+            }
         }
 
         class PackageCallbackList<T extends IInterface> extends RemoteCallbackList<T> {
@@ -1451,5 +1500,38 @@
                 checkCallbackCount();
             }
         }
+
+        class PackageLoadingProgressCallback extends
+                PackageManagerInternal.InstalledLoadingProgressCallback {
+            private String mPackageName;
+            private UserHandle mUser;
+
+            PackageLoadingProgressCallback(String packageName, UserHandle user) {
+                super(mCallbackHandler);
+                mPackageName = packageName;
+                mUser = user;
+            }
+
+            @Override
+            public void onLoadingProgressChanged(float progress) {
+                final int n = mListeners.beginBroadcast();
+                try {
+                    for (int i = 0; i < n; i++) {
+                        IOnAppsChangedListener listener = mListeners.getBroadcastItem(i);
+                        BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
+                        if (!isEnabledProfileOf(cookie.user, mUser, "onLoadingProgressChanged")) {
+                            continue;
+                        }
+                        try {
+                            listener.onPackageProgressChanged(mUser, mPackageName, progress);
+                        } catch (RemoteException re) {
+                            Slog.d(TAG, "Callback failed ", re);
+                        }
+                    }
+                } finally {
+                    mListeners.finishBroadcast();
+                }
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2e1543b..c282b99 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -592,10 +592,9 @@
             params.installFlags &= ~PackageManager.INSTALL_REQUEST_DOWNGRADE;
         }
 
-        if (callingUid != Process.SYSTEM_UID
-                && (params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {
-            // Only system_server or tools under specific conditions (test app installed
-            // through ADB, and verification disabled flag specified) can disable verification.
+        if ((params.installFlags & ADB_DEV_MODE) != ADB_DEV_MODE) {
+            // Only tools under specific conditions (test app installed through ADB, and
+            // verification disabled flag specified) can disable verification.
             params.installFlags &= ~PackageManager.INSTALL_DISABLE_VERIFICATION;
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c39152b..410fbe5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -181,6 +181,7 @@
 import android.content.pm.IPackageManagerNative;
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
+import android.content.pm.IncrementalStatesInfo;
 import android.content.pm.InstallSourceInfo;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.InstantAppRequest;
@@ -14322,10 +14323,6 @@
                     Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
         }
 
-        if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {
-            return false;
-        }
-
         // only when not installed from ADB, skip verification for instant apps when
         // the installer and verifier are the same.
         if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
@@ -25835,8 +25832,20 @@
             return mIncrementalManager.unregisterLoadingProgressCallback(ps.getPathString(),
                     (IPackageLoadingProgressCallback) callback.getBinder());
         }
+
+        @Override
+        public IncrementalStatesInfo getIncrementalStatesInfo(
+                @NonNull String packageName, int filterCallingUid, int userId) {
+            final PackageSetting ps = getPackageSettingForUser(packageName, filterCallingUid,
+                    userId);
+            if (ps == null) {
+                return null;
+            }
+            return ps.getIncrementalStates();
+        }
     }
 
+
     @GuardedBy("mLock")
     private SparseArray<String> getAppsWithSharedUserIdsLocked() {
         final SparseArray<String> sharedUserIds = new SparseArray<>();
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 667414e..6ffc598 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -16,16 +16,6 @@
 
 package com.android.server.pm.permission;
 
-import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
-import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
-import static android.content.pm.PermissionInfo.PROTECTION_NORMAL;
-import static android.content.pm.PermissionInfo.PROTECTION_SIGNATURE;
-import static android.content.pm.PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM;
-
-import static com.android.server.pm.Settings.ATTR_NAME;
-import static com.android.server.pm.Settings.ATTR_PACKAGE;
-import static com.android.server.pm.Settings.TAG_ITEM;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -58,42 +48,38 @@
 import java.util.Set;
 
 public final class BasePermission {
-    static final String TAG = "PackageManager";
+    private static final String TAG = "PackageManager";
 
-    public static final int TYPE_NORMAL = 0;
-    public static final int TYPE_BUILTIN = 1;
+    public static final int TYPE_MANIFEST = 0;
+    public static final int TYPE_CONFIG = 1;
     public static final int TYPE_DYNAMIC = 2;
-    @IntDef(value = {
-        TYPE_NORMAL,
-        TYPE_BUILTIN,
-        TYPE_DYNAMIC,
+    @IntDef({
+            TYPE_MANIFEST,
+            TYPE_CONFIG,
+            TYPE_DYNAMIC,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface PermissionType {}
 
-    @IntDef(value = {
-        PROTECTION_DANGEROUS,
-        PROTECTION_NORMAL,
-        PROTECTION_SIGNATURE,
-        PROTECTION_SIGNATURE_OR_SYSTEM,
+    @IntDef({
+            PermissionInfo.PROTECTION_DANGEROUS,
+            PermissionInfo.PROTECTION_NORMAL,
+            PermissionInfo.PROTECTION_SIGNATURE,
+            PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ProtectionLevel {}
 
+    private static final String ATTR_NAME = "name";
+    private static final String ATTR_PACKAGE = "package";
+    private static final String TAG_ITEM = "item";
+
     @NonNull
-    private final String mName;
-
-    private final @PermissionType int mType;
-
-    private String mPackageName;
-
-    private int mProtectionLevel;
-
-    @Nullable
     private PermissionInfo mPermissionInfo;
 
-    @Nullable
-    private PermissionInfo mPendingPermissionInfo;
+    private boolean mReconciled;
+
+    private final @PermissionType int mType;
 
     /** UID that owns the definition of this permission */
     private int mUid;
@@ -109,30 +95,31 @@
     private boolean mGidsPerUser;
 
     public BasePermission(@NonNull String name, String packageName, @PermissionType int type) {
-        mName = name;
-        mPackageName = packageName;
-        mType = type;
+        mPermissionInfo = new PermissionInfo();
+        mPermissionInfo.name = name;
+        mPermissionInfo.packageName = packageName;
         // Default to most conservative protection level.
-        mProtectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
+        mPermissionInfo.protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
+        mType = type;
     }
 
     @Override
     public String toString() {
-        return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " " + mName
-                + "}";
+        return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " "
+                + mPermissionInfo.name + "}";
     }
 
     @NonNull
     public String getName() {
-        return mName;
+        return mPermissionInfo.name;
     }
 
     public int getProtectionLevel() {
-        return mProtectionLevel;
+        return mPermissionInfo.protectionLevel;
     }
 
     public String getPackageName() {
-        return mPackageName;
+        return mPermissionInfo.packageName;
     }
 
     public int getType() {
@@ -149,7 +136,16 @@
     }
 
     public void setPermissionInfo(@Nullable PermissionInfo permissionInfo) {
-        mPermissionInfo = permissionInfo;
+        if (permissionInfo != null) {
+            mPermissionInfo = permissionInfo;
+        } else {
+            final PermissionInfo newPermissionInfo = new PermissionInfo();
+            newPermissionInfo.name = mPermissionInfo.name;
+            newPermissionInfo.packageName = mPermissionInfo.packageName;
+            newPermissionInfo.protectionLevel = mPermissionInfo.protectionLevel;
+            mPermissionInfo = newPermissionInfo;
+        }
+        mReconciled = permissionInfo != null;
     }
 
     public boolean hasGids() {
@@ -172,7 +168,7 @@
 
     public int calculateFootprint(BasePermission perm) {
         if (mUid == perm.mUid) {
-            return perm.mName.length() + perm.mPermissionInfo.calculateFootprint();
+            return perm.mPermissionInfo.name.length() + perm.mPermissionInfo.calculateFootprint();
         }
         return 0;
     }
@@ -190,128 +186,143 @@
     }
 
     public boolean isNormal() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                 == PermissionInfo.PROTECTION_NORMAL;
     }
     public boolean isRuntime() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                 == PermissionInfo.PROTECTION_DANGEROUS;
     }
 
     public boolean isInstalled() {
-        return mPermissionInfo != null
-                && (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) != 0;
+        return (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) != 0;
     }
 
     public boolean isRemoved() {
-        return mPermissionInfo != null
-                && (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0;
+        return (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0;
     }
 
     public boolean isSoftRestricted() {
-        return mPermissionInfo != null
-                && (mPermissionInfo.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0;
+        return (mPermissionInfo.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0;
     }
 
     public boolean isHardRestricted() {
-        return mPermissionInfo != null
-                && (mPermissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0;
+        return (mPermissionInfo.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0;
     }
 
     public boolean isHardOrSoftRestricted() {
-        return mPermissionInfo != null && (mPermissionInfo.flags
-                & (PermissionInfo.FLAG_HARD_RESTRICTED | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0;
+        return (mPermissionInfo.flags & (PermissionInfo.FLAG_HARD_RESTRICTED
+                | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0;
     }
 
     public boolean isImmutablyRestricted() {
-        return mPermissionInfo != null
-                && (mPermissionInfo.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
+        return (mPermissionInfo.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
     }
 
     public boolean isInstallerExemptIgnored() {
-        return mPermissionInfo != null
-                && (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLER_EXEMPT_IGNORED) != 0;
+        return (mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLER_EXEMPT_IGNORED) != 0;
     }
 
     public boolean isSignature() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                 == PermissionInfo.PROTECTION_SIGNATURE;
     }
 
     public boolean isAppOp() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
     }
+
     public boolean isDevelopment() {
-        return isSignature()
-                && (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;
+        return isSignature() && (mPermissionInfo.protectionLevel
+                & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;
     }
+
     public boolean isInstaller() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTALLER) != 0;
     }
+
     public boolean isInstant() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0;
     }
-    public boolean isOEM() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_OEM) != 0;
+
+    public boolean isOem() {
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_OEM) != 0;
     }
+
     public boolean isPre23() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_PRE23) != 0;
     }
+
     public boolean isPreInstalled() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_PREINSTALLED) != 0;
     }
+
     public boolean isPrivileged() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0;
     }
+
     public boolean isRuntimeOnly() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) != 0;
     }
+
     public boolean isSetup() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_SETUP) != 0;
     }
+
     public boolean isVerifier() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0;
     }
+
     public boolean isVendorPrivileged() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0;
-    }
-    public boolean isSystemTextClassifier() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER)
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED)
                 != 0;
     }
+
+    public boolean isSystemTextClassifier() {
+        return (mPermissionInfo.protectionLevel
+                & PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) != 0;
+    }
+
     public boolean isWellbeing() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_WELLBEING) != 0;
     }
+
     public boolean isDocumenter() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_DOCUMENTER) != 0;
     }
+
     public boolean isConfigurator() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR)
-            != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) != 0;
     }
+
     public boolean isIncidentReportApprover() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0;
+        return (mPermissionInfo.protectionLevel
+                & PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) != 0;
     }
+
     public boolean isAppPredictor() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR)
+                != 0;
     }
+
     public boolean isCompanion() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_COMPANION) != 0;
     }
 
     public boolean isRetailDemo() {
-        return (mProtectionLevel & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0;
+        return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0;
     }
 
     public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
-        if (!origPackageName.equals(mPackageName)) {
+        if (!origPackageName.equals(mPermissionInfo.packageName)) {
             return;
         }
-        mPackageName = newPackageName;
-        mPermissionInfo = null;
-        if (mPendingPermissionInfo != null) {
-            mPendingPermissionInfo.packageName = newPackageName;
-        }
+        final PermissionInfo newPermissionInfo = new PermissionInfo();
+        newPermissionInfo.name = mPermissionInfo.name;
+        newPermissionInfo.packageName = newPackageName;
+        newPermissionInfo.protectionLevel = mPermissionInfo.protectionLevel;
+        mPermissionInfo = newPermissionInfo;
+        mReconciled = false;
         mUid = 0;
         mGids = EmptyArray.INT;
         mGidsPerUser = false;
@@ -320,16 +331,16 @@
     public boolean addToTree(@ProtectionLevel int protectionLevel,
             @NonNull PermissionInfo permissionInfo, @NonNull BasePermission tree) {
         final boolean changed =
-                (mProtectionLevel != protectionLevel
-                    || mPermissionInfo == null
+                (mPermissionInfo.protectionLevel != protectionLevel
+                    || !mReconciled
                     || mUid != tree.mUid
                     || !Objects.equals(mPermissionInfo.packageName,
                             tree.mPermissionInfo.packageName)
                     || !comparePermissionInfos(mPermissionInfo, permissionInfo));
-        mProtectionLevel = protectionLevel;
         mPermissionInfo = new PermissionInfo(permissionInfo);
-        mPermissionInfo.protectionLevel = protectionLevel;
         mPermissionInfo.packageName = tree.mPermissionInfo.packageName;
+        mPermissionInfo.protectionLevel = protectionLevel;
+        mReconciled = true;
         mUid = tree.mUid;
         return changed;
     }
@@ -337,13 +348,12 @@
     public void updateDynamicPermission(Collection<BasePermission> permissionTrees) {
         if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
                 + getName() + " pkg=" + getPackageName()
-                + " info=" + mPendingPermissionInfo);
-        if (mPendingPermissionInfo != null) {
-            final BasePermission tree = findPermissionTree(permissionTrees, mName);
-            if (tree != null && tree.mPermissionInfo != null) {
-                mPermissionInfo = new PermissionInfo(mPendingPermissionInfo);
+                + " info=" + mPermissionInfo);
+        if (mType == TYPE_DYNAMIC) {
+            final BasePermission tree = findPermissionTree(permissionTrees, mPermissionInfo.name);
+            if (tree != null) {
                 mPermissionInfo.packageName = tree.mPermissionInfo.packageName;
-                mPermissionInfo.name = mName;
+                mReconciled = true;
                 mUid = tree.mUid;
             }
         }
@@ -354,9 +364,9 @@
             @NonNull AndroidPackage pkg, Collection<BasePermission> permissionTrees,
             boolean chatty) {
         // Allow system apps to redefine non-system permissions
-        if (bp != null && !Objects.equals(bp.mPackageName, p.packageName)) {
+        if (bp != null && !Objects.equals(bp.mPermissionInfo.packageName, p.packageName)) {
             final boolean currentOwnerIsSystem;
-            if (bp.mPermissionInfo == null) {
+            if (!bp.mReconciled) {
                 currentOwnerIsSystem = false;
             } else {
                 AndroidPackage currentPackage = packageManagerInternal.getPackage(
@@ -369,34 +379,34 @@
             }
 
             if (pkg.isSystem()) {
-                if (bp.mType == BasePermission.TYPE_BUILTIN && bp.mPermissionInfo == null) {
+                if (bp.mType == BasePermission.TYPE_CONFIG && !bp.mReconciled) {
                     // It's a built-in permission and no owner, take ownership now
                     p.flags |= PermissionInfo.FLAG_INSTALLED;
                     bp.mPermissionInfo = p;
+                    bp.mReconciled = true;
                     bp.mUid = pkg.getUid();
-                    bp.mPackageName = p.packageName;
                 } else if (!currentOwnerIsSystem) {
                     String msg = "New decl " + pkg + " of permission  "
-                            + p.name + " is system; overriding " + bp.mPackageName;
+                            + p.name + " is system; overriding " + bp.mPermissionInfo.packageName;
                     PackageManagerService.reportSettingsProblem(Log.WARN, msg);
                     bp = null;
                 }
             }
         }
         if (bp == null) {
-            bp = new BasePermission(p.name, p.packageName, TYPE_NORMAL);
+            bp = new BasePermission(p.name, p.packageName, TYPE_MANIFEST);
         }
         StringBuilder r = null;
-        if (bp.mPermissionInfo == null) {
-            if (bp.mPackageName == null
-                    || bp.mPackageName.equals(p.packageName)) {
+        if (!bp.mReconciled) {
+            if (bp.mPermissionInfo.packageName == null
+                    || bp.mPermissionInfo.packageName.equals(p.packageName)) {
                 final BasePermission tree = findPermissionTree(permissionTrees, p.name);
                 if (tree == null
-                        || tree.mPackageName.equals(p.packageName)) {
+                        || tree.mPermissionInfo.packageName.equals(p.packageName)) {
                     p.flags |= PermissionInfo.FLAG_INSTALLED;
                     bp.mPermissionInfo = p;
+                    bp.mReconciled = true;
                     bp.mUid = pkg.getUid();
-                    bp.mPackageName = p.packageName;
                     if (chatty) {
                         if (r == null) {
                             r = new StringBuilder(256);
@@ -408,13 +418,13 @@
                 } else {
                     Slog.w(TAG, "Permission " + p.name + " from package "
                             + p.packageName + " ignored: base tree "
-                            + tree.mName + " is from package "
-                            + tree.mPackageName);
+                            + tree.mPermissionInfo.name + " is from package "
+                            + tree.mPermissionInfo.packageName);
                 }
             } else {
                 Slog.w(TAG, "Permission " + p.name + " from package "
                         + p.packageName + " ignored: original from "
-                        + bp.mPackageName);
+                        + bp.mPermissionInfo.packageName);
             }
         } else if (chatty) {
             if (r == null) {
@@ -425,9 +435,6 @@
             r.append("DUP:");
             r.append(p.name);
         }
-        if (bp.mPermissionInfo == p) {
-            bp.mProtectionLevel = p.protectionLevel;
-        }
         if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
             Log.d(TAG, "  Permissions: " + r);
         }
@@ -444,7 +451,7 @@
                 }
                 throw new SecurityException("Calling uid " + callingUid
                         + " is not allowed to add to permission tree "
-                        + bp.mName + " owned by uid " + bp.mUid);
+                        + bp.mPermissionInfo.name + " owned by uid " + bp.mUid);
             }
         }
         throw new SecurityException("No permission tree found for " + permName);
@@ -453,9 +460,9 @@
     private static BasePermission findPermissionTree(
             Collection<BasePermission> permissionTrees, String permName) {
         for (BasePermission bp : permissionTrees) {
-            if (permName.startsWith(bp.mName)
-                    && permName.length() > bp.mName.length()
-                    && permName.charAt(bp.mName.length()) == '.') {
+            if (permName.startsWith(bp.mPermissionInfo.name)
+                    && permName.length() > bp.mPermissionInfo.name.length()
+                    && permName.charAt(bp.mPermissionInfo.name.length()) == '.') {
                 return bp;
             }
         }
@@ -464,20 +471,20 @@
 
     @Nullable
     public String getBackgroundPermission() {
-        return mPermissionInfo != null ? mPermissionInfo.backgroundPermission : null;
+        return mPermissionInfo.backgroundPermission;
     }
 
     @Nullable
     public String getGroup() {
-        return mPermissionInfo != null ? mPermissionInfo.group : null;
+        return mPermissionInfo.group;
     }
 
     public int getProtection() {
-        return mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+        return mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
     }
 
     public int getProtectionFlags() {
-        return mProtectionLevel & PermissionInfo.PROTECTION_MASK_FLAGS;
+        return mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_FLAGS;
     }
 
     @NonNull
@@ -495,17 +502,18 @@
             }
         } else {
             permissionInfo = new PermissionInfo();
-            permissionInfo.name = mName;
-            permissionInfo.packageName = mPackageName;
-            permissionInfo.nonLocalizedLabel = mName;
+            permissionInfo.name = mPermissionInfo.name;
+            permissionInfo.packageName = mPermissionInfo.packageName;
+            permissionInfo.nonLocalizedLabel = mPermissionInfo.name;
         }
         if (targetSdkVersion >= Build.VERSION_CODES.O) {
-            permissionInfo.protectionLevel = mProtectionLevel;
+            permissionInfo.protectionLevel = mPermissionInfo.protectionLevel;
         } else {
-            final int protection = mProtectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+            final int protection = mPermissionInfo.protectionLevel
+                    & PermissionInfo.PROTECTION_MASK_BASE;
             if (protection == PermissionInfo.PROTECTION_SIGNATURE) {
                 // Signature permission's protection flags are always reported.
-                permissionInfo.protectionLevel = mProtectionLevel;
+                permissionInfo.protectionLevel = mPermissionInfo.protectionLevel;
             } else {
                 permissionInfo.protectionLevel = protection;
             }
@@ -520,9 +528,9 @@
             return false;
         }
         final String name = parser.getAttributeValue(null, ATTR_NAME);
-        final String sourcePackage = parser.getAttributeValue(null, ATTR_PACKAGE);
+        final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
         final String ptype = parser.getAttributeValue(null, "type");
-        if (name == null || sourcePackage == null) {
+        if (name == null || packageName == null) {
             PackageManagerService.reportSettingsProblem(Log.WARN,
                     "Error in package manager settings: permissions has" + " no name at "
                             + parser.getPositionDescription());
@@ -531,23 +539,19 @@
         final boolean dynamic = "dynamic".equals(ptype);
         BasePermission bp = out.get(name);
         // If the permission is builtin, do not clobber it.
-        if (bp == null || bp.mType != TYPE_BUILTIN) {
-            bp = new BasePermission(name.intern(), sourcePackage,
-                    dynamic ? TYPE_DYNAMIC : TYPE_NORMAL);
+        if (bp == null || bp.mType != TYPE_CONFIG) {
+            bp = new BasePermission(name.intern(), packageName,
+                    dynamic ? TYPE_DYNAMIC : TYPE_MANIFEST);
         }
-        bp.mProtectionLevel = readInt(parser, null, "protection",
+        bp.mPermissionInfo.protectionLevel = readInt(parser, null, "protection",
                 PermissionInfo.PROTECTION_NORMAL);
-        bp.mProtectionLevel = PermissionInfo.fixProtectionLevel(bp.mProtectionLevel);
+        bp.mPermissionInfo.protectionLevel = PermissionInfo.fixProtectionLevel(
+                bp.mPermissionInfo.protectionLevel);
         if (dynamic) {
-            final PermissionInfo pi = new PermissionInfo();
-            pi.packageName = sourcePackage.intern();
-            pi.name = name.intern();
-            pi.icon = readInt(parser, null, "icon", 0);
-            pi.nonLocalizedLabel = parser.getAttributeValue(null, "label");
-            pi.protectionLevel = bp.mProtectionLevel;
-            bp.mPendingPermissionInfo = pi;
+            bp.mPermissionInfo.icon = readInt(parser, null, "icon", 0);
+            bp.mPermissionInfo.nonLocalizedLabel = parser.getAttributeValue(null, "label");
         }
-        out.put(bp.mName, bp);
+        out.put(bp.mPermissionInfo.name, bp);
         return true;
     }
 
@@ -568,30 +572,23 @@
     }
 
     public void writeLPr(@NonNull XmlSerializer serializer) throws IOException {
-        if (mPackageName == null) {
+        if (mPermissionInfo.packageName == null) {
             return;
         }
         serializer.startTag(null, TAG_ITEM);
-        serializer.attribute(null, ATTR_NAME, mName);
-        serializer.attribute(null, ATTR_PACKAGE, mPackageName);
-        if (mProtectionLevel != PermissionInfo.PROTECTION_NORMAL) {
-            serializer.attribute(null, "protection", Integer.toString(mProtectionLevel));
+        serializer.attribute(null, ATTR_NAME, mPermissionInfo.name);
+        serializer.attribute(null, ATTR_PACKAGE, mPermissionInfo.packageName);
+        if (mPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
+            serializer.attribute(null, "protection",
+                    Integer.toString(mPermissionInfo.protectionLevel));
         }
-        if (mType == BasePermission.TYPE_DYNAMIC) {
-            if (mPermissionInfo != null || mPendingPermissionInfo != null) {
-                serializer.attribute(null, "type", "dynamic");
-                int icon = mPermissionInfo != null ? mPermissionInfo.icon
-                        : mPendingPermissionInfo.icon;
-                CharSequence nonLocalizedLabel = mPermissionInfo != null
-                        ? mPermissionInfo.nonLocalizedLabel
-                        : mPendingPermissionInfo.nonLocalizedLabel;
-
-                if (icon != 0) {
-                    serializer.attribute(null, "icon", Integer.toString(icon));
-                }
-                if (nonLocalizedLabel != null) {
-                    serializer.attribute(null, "label", nonLocalizedLabel.toString());
-                }
+        if (mType == TYPE_DYNAMIC) {
+            serializer.attribute(null, "type", "dynamic");
+            if (mPermissionInfo.icon != 0) {
+                serializer.attribute(null, "icon", Integer.toString(mPermissionInfo.icon));
+            }
+            if (mPermissionInfo.nonLocalizedLabel != null) {
+                serializer.attribute(null, "label", mPermissionInfo.nonLocalizedLabel.toString());
             }
         }
         serializer.endTag(null, TAG_ITEM);
@@ -616,10 +613,10 @@
     public boolean dumpPermissionsLPr(@NonNull PrintWriter pw, @NonNull String packageName,
             @NonNull Set<String> permissionNames, boolean readEnforced,
             boolean printedSomething, @NonNull DumpState dumpState) {
-        if (packageName != null && !packageName.equals(mPackageName)) {
+        if (packageName != null && !packageName.equals(mPermissionInfo.packageName)) {
             return false;
         }
-        if (permissionNames != null && !permissionNames.contains(mName)) {
+        if (permissionNames != null && !permissionNames.contains(mPermissionInfo.name)) {
             return false;
         }
         if (!printedSomething) {
@@ -627,15 +624,15 @@
                 pw.println();
             pw.println("Permissions:");
         }
-        pw.print("  Permission ["); pw.print(mName); pw.print("] (");
+        pw.print("  Permission ["); pw.print(mPermissionInfo.name); pw.print("] (");
                 pw.print(Integer.toHexString(System.identityHashCode(this)));
                 pw.println("):");
-        pw.print("    sourcePackage="); pw.println(mPackageName);
+        pw.print("    sourcePackage="); pw.println(mPermissionInfo.packageName);
         pw.print("    uid="); pw.print(mUid);
         pw.print(" gids="); pw.print(Arrays.toString(computeGids(UserHandle.USER_SYSTEM)));
         pw.print(" type="); pw.print(mType);
         pw.print(" prot=");
-        pw.println(PermissionInfo.protectionToString(mProtectionLevel));
+        pw.println(PermissionInfo.protectionToString(mPermissionInfo.protectionLevel));
         if (mPermissionInfo != null) {
             pw.print("    perm="); pw.println(mPermissionInfo);
             if ((mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0
@@ -643,7 +640,8 @@
                 pw.print("    flags=0x"); pw.println(Integer.toHexString(mPermissionInfo.flags));
             }
         }
-        if (READ_EXTERNAL_STORAGE.equals(mName)) {
+        if (Objects.equals(mPermissionInfo.name,
+                android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
             pw.print("    enforced=");
             pw.println(readEnforced);
         }
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index d871325..4d43969 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -411,7 +411,7 @@
                 final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
                 BasePermission bp = mSettings.getPermissionLocked(perm.name);
                 if (bp == null) {
-                    bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);
+                    bp = new BasePermission(perm.name, "android", BasePermission.TYPE_CONFIG);
                     mSettings.putPermissionLocked(perm.name, bp);
                 }
                 if (perm.gids != null) {
@@ -2988,7 +2988,7 @@
         for (String permission : ps.getGrantedPermissions()) {
             if (!pkg.getImplicitPermissions().contains(permission)) {
                 BasePermission bp = mSettings.getPermissionLocked(permission);
-                if (bp.isRuntime()) {
+                if (bp != null && bp.isRuntime()) {
                     int flags = ps.getPermissionFlags(permission);
 
                     if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
@@ -3300,7 +3300,7 @@
                         PackageParser.SigningDetails.CertCapabilities.PERMISSION);
         final boolean isVendorPrivilegedPermission = bp.isVendorPrivileged();
         final boolean isPrivilegedPermission = bp.isPrivileged() || isVendorPrivilegedPermission;
-        final boolean isOemPermission = bp.isOEM();
+        final boolean isOemPermission = bp.isOem();
         if (!allowed && (isPrivilegedPermission || isOemPermission) && pkg.isSystem()) {
             final String permissionName = bp.getName();
             // For updated system applications, a privileged/oem permission
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsData.java b/services/core/java/com/android/server/powerstats/PowerStatsData.java
deleted file mode 100644
index 755bd5f..0000000
--- a/services/core/java/com/android/server/powerstats/PowerStatsData.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.powerstats;
-
-import android.util.Log;
-import android.util.proto.ProtoInputStream;
-import android.util.proto.ProtoOutputStream;
-import android.util.proto.ProtoUtils;
-import android.util.proto.WireTypeMismatchException;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * PowerStatsData is a class that performs two operations:
- * 1) Unpacks serialized protobuf byte arrays, as defined in powerstatsservice.proto,
- *    into RailInfo or EnergyData object arrays.
- *
- * 2) Packs RailInfo or EnergyData object arrays in protobuf byte arrays as
- *    defined in powerstatsservice.proto.
- *
- * Inside frameworks, proto source is generated with the genstream option
- * and therefore the getter/setter helper functions are not available.
- * The protos need to be packed/unpacked in a more manual way using
- * ProtoOutputStream/ProtoInputStream.
- */
-public class PowerStatsData {
-    private static final String TAG = PowerStatsData.class.getSimpleName();
-
-    private List<Data> mDataList;
-
-    public PowerStatsData(ProtoInputStream pis) throws IOException {
-        mDataList = new ArrayList<Data>();
-        unpackProto(pis);
-    }
-
-    public PowerStatsData(Data[] data) {
-        mDataList = new ArrayList<Data>(Arrays.asList(data));
-    }
-
-    private void unpackProto(ProtoInputStream pis) throws IOException {
-        long token;
-
-        while (true) {
-            try {
-                switch (pis.nextField()) {
-                    case (int) PowerStatsServiceProto.RAIL_INFO:
-                        token = pis.start(PowerStatsServiceProto.RAIL_INFO);
-                        mDataList.add(new RailInfo(pis));
-                        pis.end(token);
-                        break;
-
-                    case (int) PowerStatsServiceProto.ENERGY_DATA:
-                        token = pis.start(PowerStatsServiceProto.ENERGY_DATA);
-                        mDataList.add(new EnergyData(pis));
-                        pis.end(token);
-                        break;
-
-                    case ProtoInputStream.NO_MORE_FIELDS:
-                        return;
-
-                    default:
-                        Log.e(TAG, "Unhandled field in proto: "
-                                + ProtoUtils.currentFieldToString(pis));
-                        break;
-                }
-            } catch (WireTypeMismatchException wtme) {
-                Log.e(TAG, "Wire Type mismatch in proto: " + ProtoUtils.currentFieldToString(pis));
-            }
-        }
-    }
-
-    /**
-     * Write this object to an output stream in protobuf format.
-     *
-     * @param pos ProtoOutputStream of file where data is to be written.  Data is
-     *            written in protobuf format as defined by powerstatsservice.proto.
-     */
-    public void toProto(ProtoOutputStream pos) {
-        long token;
-
-        for (Data data : mDataList) {
-            if (data instanceof RailInfo) {
-                token = pos.start(PowerStatsServiceProto.RAIL_INFO);
-            } else {
-                token = pos.start(PowerStatsServiceProto.ENERGY_DATA);
-            }
-            data.toProto(pos);
-            pos.end(token);
-        }
-    }
-
-    /**
-     * Convert mDataList to proto format and return the serialized byte array.
-     *
-     * @return byte array containing a serialized protobuf of mDataList.
-     */
-    public byte[] getProtoBytes() {
-        ProtoOutputStream pos = new ProtoOutputStream();
-        long token;
-
-        for (Data data : mDataList) {
-            if (data instanceof RailInfo) {
-                token = pos.start(PowerStatsServiceProto.RAIL_INFO);
-            } else {
-                token = pos.start(PowerStatsServiceProto.ENERGY_DATA);
-            }
-            data.toProto(pos);
-            pos.end(token);
-        }
-        return pos.getBytes();
-    }
-
-    /**
-     * Print this object to logcat.
-     */
-    public void print() {
-        for (Data data : mDataList) {
-            Log.d(TAG, data.toString());
-        }
-    }
-
-    /**
-     * RailInfo is a class that stores a description for an individual ODPM
-     * rail.  It provides functionality to unpack a RailInfo object from a
-     * serialized protobuf byte array, and to pack a RailInfo object into
-     * a ProtoOutputStream.
-     */
-    public static class RailInfo extends Data {
-        public String mRailName;
-        public String mSubSysName;
-        public long mSamplingRate;
-
-        public RailInfo(ProtoInputStream pis) throws IOException {
-            unpackProto(pis);
-        }
-
-        public RailInfo(long index, String railName, String subSysName, long samplingRate) {
-            mIndex = index;
-            mRailName = railName;
-            mSubSysName = subSysName;
-            mSamplingRate = samplingRate;
-        }
-
-        @Override
-        protected void unpackProto(ProtoInputStream pis) throws IOException {
-            while (true) {
-                try {
-                    switch (pis.nextField()) {
-                        case (int) RailInfoProto.INDEX:
-                            mIndex = pis.readInt(RailInfoProto.INDEX);
-                            break;
-
-                        case (int) RailInfoProto.RAIL_NAME:
-                            mRailName = pis.readString(RailInfoProto.RAIL_NAME);
-                            break;
-
-                        case (int) RailInfoProto.SUBSYS_NAME:
-                            mSubSysName = pis.readString(RailInfoProto.SUBSYS_NAME);
-                            break;
-
-                        case (int) RailInfoProto.SAMPLING_RATE:
-                            mSamplingRate = pis.readInt(RailInfoProto.SAMPLING_RATE);
-                            break;
-
-                        case ProtoInputStream.NO_MORE_FIELDS:
-                            return;
-
-                        default:
-                            Log.e(TAG, "Unhandled field in RailInfoProto: "
-                                    + ProtoUtils.currentFieldToString(pis));
-                            break;
-                    }
-                } catch (WireTypeMismatchException wtme) {
-                    Log.e(TAG, "Wire Type mismatch in RailInfoProto: "
-                            + ProtoUtils.currentFieldToString(pis));
-                }
-            }
-        }
-
-        @Override
-        public void toProto(ProtoOutputStream pos) {
-            pos.write(RailInfoProto.INDEX, mIndex);
-            pos.write(RailInfoProto.RAIL_NAME, mRailName);
-            pos.write(RailInfoProto.SUBSYS_NAME, mSubSysName);
-            pos.write(RailInfoProto.SAMPLING_RATE, mSamplingRate);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("Index = " + mIndex
-                + ", RailName = " + mRailName
-                + ", SubSysName = " + mSubSysName
-                + ", SamplingRate = " + mSamplingRate);
-        }
-    }
-
-    /**
-     * EnergyData is a class that stores an energy (uWs) data reading for an
-     * individual ODPM rail.  It provides functionality to unpack an EnergyData
-     * object from a serialized protobuf byte array, and to pack an EnergyData
-     * object into a ProtoOutputStream.
-     */
-    public static class EnergyData extends Data {
-        public long mTimestampMs;
-        public long mEnergyUWs;
-
-        public EnergyData(ProtoInputStream pis) throws IOException {
-            unpackProto(pis);
-        }
-
-        public EnergyData(long index, long timestampMs, long energyUWs) {
-            mIndex = index;
-            mTimestampMs = timestampMs;
-            mEnergyUWs = energyUWs;
-        }
-
-        @Override
-        protected void unpackProto(ProtoInputStream pis) throws IOException {
-            while (true) {
-                try {
-                    switch (pis.nextField()) {
-                        case (int) EnergyDataProto.INDEX:
-                            mIndex = pis.readInt(EnergyDataProto.INDEX);
-                            break;
-
-                        case (int) EnergyDataProto.TIMESTAMP_MS:
-                            mTimestampMs = pis.readLong(EnergyDataProto.TIMESTAMP_MS);
-                            break;
-
-                        case (int) EnergyDataProto.ENERGY_UWS:
-                            mEnergyUWs = pis.readLong(EnergyDataProto.ENERGY_UWS);
-                            break;
-
-                        case ProtoInputStream.NO_MORE_FIELDS:
-                            return;
-
-                        default:
-                            Log.e(TAG, "Unhandled field in EnergyDataProto: "
-                                    + ProtoUtils.currentFieldToString(pis));
-                            break;
-                    }
-                } catch (WireTypeMismatchException wtme) {
-                    Log.e(TAG, "Wire Type mismatch in EnergyDataProto: "
-                            + ProtoUtils.currentFieldToString(pis));
-                }
-            }
-        }
-
-        @Override
-        protected void toProto(ProtoOutputStream pos) {
-            pos.write(EnergyDataProto.INDEX, mIndex);
-            pos.write(EnergyDataProto.TIMESTAMP_MS, mTimestampMs);
-            pos.write(EnergyDataProto.ENERGY_UWS, mEnergyUWs);
-        }
-
-        @Override
-        public String toString() {
-            return String.format("Index = " + mIndex
-                + ", Timestamp (ms) = " + mTimestampMs
-                + ", Energy (uWs) = " + mEnergyUWs);
-        }
-    }
-
-    private abstract static class Data {
-        public long mIndex;
-        protected abstract void unpackProto(ProtoInputStream pis) throws IOException;
-        protected abstract void toProto(ProtoOutputStream pos);
-    }
-}
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
index 84a6fc9..5d8afd4 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java
@@ -198,19 +198,21 @@
      *             array and written to on-device storage.
      */
     public void write(byte[] data) {
-        mLock.lock();
+        if (data.length > 0) {
+            mLock.lock();
 
-        long currentTimeMillis = System.currentTimeMillis();
-        try {
-            DataElement dataElement = new DataElement(data);
-            mFileRotator.rewriteActive(new DataRewriter(dataElement.toByteArray()),
-                    currentTimeMillis);
-            mFileRotator.maybeRotate(currentTimeMillis);
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to write to on-device storage: " + e);
+            long currentTimeMillis = System.currentTimeMillis();
+            try {
+                DataElement dataElement = new DataElement(data);
+                mFileRotator.rewriteActive(new DataRewriter(dataElement.toByteArray()),
+                        currentTimeMillis);
+                mFileRotator.maybeRotate(currentTimeMillis);
+            } catch (IOException e) {
+                Log.e(TAG, "Failed to write to on-device storage: " + e);
+            }
+
+            mLock.unlock();
         }
-
-        mLock.unlock();
     }
 
     /**
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java b/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
index dc996a3..18646b9 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsHALWrapper.java
@@ -16,6 +16,17 @@
 
 package com.android.server.powerstats;
 
+import android.hardware.power.stats.IPowerStats;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.function.Supplier;
+
 /**
  * PowerStatsHALWrapper is a wrapper class for the PowerStats HAL API calls.
  */
@@ -27,30 +38,50 @@
      */
     public interface IPowerStatsHALWrapper {
         /**
-         * Returns rail info for all available ODPM rails.
+         * Returns the energy consumer IDs for all available energy consumers (power models) on the
+         *         device.  Examples of subsystems for which energy consumer results (power models)
+         *         may be available are GPS, display, wifi, etc.  The default list of energy
+         *         consumers can be found in the PowerStats HAL definition (EnergyConsumerId.aidl).
+         *         The availability of energy consumer IDs is hardware dependent.
          *
-         * @return array of RailInfo objects containing rail info for all
-         *         available rails.
+         * @return List of EnergyConsumerIds all available energy consumers.
          */
-        PowerStatsData.RailInfo[] readRailInfo();
+        int[] getEnergyConsumerInfo();
 
         /**
-         * Returns energy data for all available ODPM rails.  Available rails can
-         *         be retrieved by calling nativeGetRailInfo.  Energy data and
-         *         rail info can be linked through the index field.
+         * Returns the energy consumer result for all available energy consumers (power models).
+         *         Available consumers can be retrieved by calling getEnergyConsumerInfo().  The
+         *         subsystem corresponding to the energy consumer result is defined by the energy
+         *         consumer ID.
          *
-         * @return array of EnergyData objects containing energy data for all
-         *         available rails.
+         * @return List of EnergyConsumerResult objects containing energy consumer results for all
+         *         available energy consumers (power models).
          */
-        PowerStatsData.EnergyData[] readEnergyData();
+        android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed();
+
+        /**
+         * Returns channel info for all available energy meters.
+         *
+         * @return List of ChannelInfo objects containing channel info for all available energy
+         *         meters.
+         */
+        android.hardware.power.stats.ChannelInfo[] getEnergyMeterInfo();
+
+        /**
+         * Returns energy measurements for all available energy meters.  Available channels can be
+         *         retrieved by calling getEnergyMeterInfo().  Energy measurements and channel info
+         *         can be linked through the channelId field.
+         *
+         * @return List of EnergyMeasurement objects containing energy measurements for all
+         *         available energy meters.
+         */
+        android.hardware.power.stats.EnergyMeasurement[] readEnergyMeters();
 
         /**
          * Returns boolean indicating if connection to power stats HAL was
          *         established.
          *
-         * @return true if connection to power stats HAL was correctly established
-         *         and that energy data and rail info can be read from the interface.
-         *         false otherwise
+         * @return true if connection to power stats HAL was correctly established.
          */
         boolean initialize();
     }
@@ -61,45 +92,108 @@
      * framework and will be passed into the PowerStatsService through an injector.
      */
     public static final class PowerStatsHALWrapperImpl implements IPowerStatsHALWrapper {
-        private static native boolean nativeInit();
-        private static native PowerStatsData.RailInfo[] nativeGetRailInfo();
-        private static native PowerStatsData.EnergyData[] nativeGetEnergyData();
+        private static Supplier<IPowerStats> sVintfPowerStats;
 
-        /**
-         * Returns rail info for all available ODPM rails.
-         *
-         * @return array of RailInfo objects containing rail info for all
-         *         available rails.
-         */
         @Override
-        public PowerStatsData.RailInfo[] readRailInfo() {
-            return nativeGetRailInfo();
+        public int[] getEnergyConsumerInfo() {
+            int[] energyConsumerInfoHAL = null;
+
+            if (sVintfPowerStats != null) {
+                try {
+                    energyConsumerInfoHAL = sVintfPowerStats.get().getEnergyConsumerInfo();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to get energy consumer info from PowerStats HAL");
+                }
+            }
+
+            return energyConsumerInfoHAL;
         }
 
-        /**
-         * Returns energy data for all available ODPM rails.  Available rails can
-         *         be retrieved by calling nativeGetRailInfo.  Energy data and
-         *         rail info can be linked through the index field.
-         *
-         * @return array of EnergyData objects containing energy data for all
-         *         available rails.
-         */
         @Override
-        public PowerStatsData.EnergyData[] readEnergyData() {
-            return nativeGetEnergyData();
+        public android.hardware.power.stats.EnergyConsumerResult[] getEnergyConsumed() {
+            android.hardware.power.stats.EnergyConsumerResult[] energyConsumedHAL = null;
+
+            if (sVintfPowerStats != null) {
+                try {
+                    energyConsumedHAL =
+                        sVintfPowerStats.get().getEnergyConsumed(new int[0]);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to get energy consumer results from PowerStats HAL");
+                }
+            }
+
+            return energyConsumedHAL;
         }
 
-        /**
-         * Returns boolean indicating if connection to power stats HAL was
-         *         established.
-         *
-         * @return true if connection to power stats HAL was correctly established
-         *         and that energy data and rail info can be read from the interface.
-         *         false otherwise
-         */
+        @Override
+        public android.hardware.power.stats.ChannelInfo[] getEnergyMeterInfo() {
+            android.hardware.power.stats.ChannelInfo[] energyMeterInfoHAL = null;
+
+            if (sVintfPowerStats != null) {
+                try {
+                    energyMeterInfoHAL = sVintfPowerStats.get().getEnergyMeterInfo();
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to get energy meter info from PowerStats HAL");
+                }
+            }
+
+            return energyMeterInfoHAL;
+        }
+
+        @Override
+        public android.hardware.power.stats.EnergyMeasurement[] readEnergyMeters() {
+            android.hardware.power.stats.EnergyMeasurement[] energyMeasurementHAL = null;
+
+            if (sVintfPowerStats != null) {
+                try {
+                    energyMeasurementHAL =
+                        sVintfPowerStats.get().readEnergyMeters(new int[0]);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Failed to get energy measurements from PowerStats HAL");
+                }
+            }
+
+            return energyMeasurementHAL;
+        }
+
         @Override
         public boolean initialize() {
-            return nativeInit();
+            Supplier<IPowerStats> service = new VintfHalCache();
+
+            if (service.get() == null) {
+                sVintfPowerStats = null;
+                return false;
+            } else {
+                sVintfPowerStats = service;
+                return true;
+            }
+        }
+    }
+
+    private static class VintfHalCache implements Supplier<IPowerStats>, IBinder.DeathRecipient {
+        @GuardedBy("this")
+        private IPowerStats mInstance = null;
+
+        @Override
+        public synchronized IPowerStats get() {
+            if (mInstance == null) {
+                IBinder binder = Binder.allowBlocking(ServiceManager.waitForDeclaredService(
+                        "android.hardware.power.stats.IPowerStats/default"));
+                if (binder != null) {
+                    mInstance = IPowerStats.Stub.asInterface(binder);
+                    try {
+                        binder.linkToDeath(this, 0);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Unable to register DeathRecipient for " + mInstance);
+                    }
+                }
+            }
+            return mInstance;
+        }
+
+        @Override
+        public synchronized void binderDied() {
+            mInstance = null;
         }
     }
 }
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
index 71a34a4..bec99bc 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java
@@ -17,6 +17,9 @@
 package com.android.server.powerstats;
 
 import android.content.Context;
+import android.hardware.power.stats.ChannelInfo;
+import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyMeasurement;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -25,6 +28,10 @@
 import android.util.proto.ProtoOutputStream;
 
 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
+import com.android.server.powerstats.ProtoStreamUtils.ChannelInfoUtils;
+import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerIdUtils;
+import com.android.server.powerstats.ProtoStreamUtils.EnergyConsumerResultUtils;
+import com.android.server.powerstats.ProtoStreamUtils.EnergyMeasurementUtils;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -32,18 +39,19 @@
 import java.io.IOException;
 
 /**
- * PowerStatsLogger is responsible for logging energy data to on-device
- * storage.  Messages are sent to its message handler to request that energy
- * data be logged, at which time it queries the PowerStats HAL and logs the
- * data to on-device storage.  The on-device storage is dumped to file by
- * calling writeToFile with a file descriptor that points to the output file.
+ * PowerStatsLogger is responsible for logging model and meter energy data to on-device storage.
+ * Messages are sent to its message handler to request that energy data be logged, at which time it
+ * queries the PowerStats HAL and logs the data to on-device storage.  The on-device storage is
+ * dumped to file by calling writeModelDataToFile or writeMeterDataToFile with a file descriptor
+ * that points to the output file.
  */
 public final class PowerStatsLogger extends Handler {
     private static final String TAG = PowerStatsLogger.class.getSimpleName();
     private static final boolean DEBUG = false;
     protected static final int MSG_LOG_TO_DATA_STORAGE = 0;
 
-    private final PowerStatsDataStorage mPowerStatsDataStorage;
+    private final PowerStatsDataStorage mPowerStatsMeterStorage;
+    private final PowerStatsDataStorage mPowerStatsModelStorage;
     private final IPowerStatsHALWrapper mPowerStatsHALWrapper;
 
     @Override
@@ -51,31 +59,40 @@
         switch (msg.what) {
             case MSG_LOG_TO_DATA_STORAGE:
                 if (DEBUG) Log.d(TAG, "Logging to data storage");
-                PowerStatsData energyData =
-                        new PowerStatsData(mPowerStatsHALWrapper.readEnergyData());
-                mPowerStatsDataStorage.write(energyData.getProtoBytes());
+
+                // Log power meter data.
+                EnergyMeasurement[] energyMeasurements = mPowerStatsHALWrapper.readEnergyMeters();
+                mPowerStatsMeterStorage.write(
+                        EnergyMeasurementUtils.getProtoBytes(energyMeasurements));
+                if (DEBUG) EnergyMeasurementUtils.print(energyMeasurements);
+
+                // Log power model data.
+                EnergyConsumerResult[] energyConsumerResults =
+                    mPowerStatsHALWrapper.getEnergyConsumed();
+                mPowerStatsModelStorage.write(
+                        EnergyConsumerResultUtils.getProtoBytes(energyConsumerResults));
+                if (DEBUG) EnergyConsumerResultUtils.print(energyConsumerResults);
                 break;
         }
     }
 
     /**
-     * Writes data stored in PowerStatsDataStorage to a file descriptor.
+     * Writes meter data stored in PowerStatsDataStorage to a file descriptor.
      *
-     * @param fd FileDescriptor where data stored in PowerStatsDataStorage is
-     *           written.  Data is written in protobuf format as defined by
-     *           powerstatsservice.proto.
+     * @param fd FileDescriptor where meter data stored in PowerStatsDataStorage is written.  Data
+     *           is written in protobuf format as defined by powerstatsservice.proto.
      */
-    public void writeToFile(FileDescriptor fd) {
-        if (DEBUG) Log.d(TAG, "Writing to file");
+    public void writeMeterDataToFile(FileDescriptor fd) {
+        if (DEBUG) Log.d(TAG, "Writing meter data to file");
 
         final ProtoOutputStream pos = new ProtoOutputStream(fd);
 
         try {
-            PowerStatsData railInfo = new PowerStatsData(mPowerStatsHALWrapper.readRailInfo());
-            railInfo.toProto(pos);
-            if (DEBUG) railInfo.print();
+            ChannelInfo[] channelInfo = mPowerStatsHALWrapper.getEnergyMeterInfo();
+            ChannelInfoUtils.packProtoMessage(channelInfo, pos);
+            if (DEBUG) ChannelInfoUtils.print(channelInfo);
 
-            mPowerStatsDataStorage.read(new PowerStatsDataStorage.DataElementReadCallback() {
+            mPowerStatsMeterStorage.read(new PowerStatsDataStorage.DataElementReadCallback() {
                 @Override
                 public void onReadDataElement(byte[] data) {
                     try {
@@ -84,26 +101,70 @@
                         // TODO(b/166535853): ProtoOutputStream doesn't provide a method to write
                         // a byte array that already contains a serialized proto, so I have to
                         // deserialize, then re-serialize.  This is computationally inefficient.
-                        final PowerStatsData energyData = new PowerStatsData(pis);
-                        energyData.toProto(pos);
-                        if (DEBUG) energyData.print();
+                        EnergyMeasurement[] energyMeasurement =
+                            EnergyMeasurementUtils.unpackProtoMessage(data);
+                        EnergyMeasurementUtils.packProtoMessage(energyMeasurement, pos);
+                        if (DEBUG) EnergyMeasurementUtils.print(energyMeasurement);
                     } catch (IOException e) {
-                        Log.e(TAG, "Failed to write energy data to incident report.");
+                        Log.e(TAG, "Failed to write energy meter data to incident report.");
                     }
                 }
             });
         } catch (IOException e) {
-            Log.e(TAG, "Failed to write rail info to incident report.");
+            Log.e(TAG, "Failed to write energy meter info to incident report.");
         }
 
         pos.flush();
     }
 
-    public PowerStatsLogger(Context context, File dataStoragePath, String dataStorageFilename,
-            IPowerStatsHALWrapper powerStatsHALWrapper) {
+    /**
+     * Writes model data stored in PowerStatsDataStorage to a file descriptor.
+     *
+     * @param fd FileDescriptor where model data stored in PowerStatsDataStorage is written.  Data
+     *           is written in protobuf format as defined by powerstatsservice.proto.
+     */
+    public void writeModelDataToFile(FileDescriptor fd) {
+        if (DEBUG) Log.d(TAG, "Writing model data to file");
+
+        final ProtoOutputStream pos = new ProtoOutputStream(fd);
+
+        try {
+            int[] energyConsumerId = mPowerStatsHALWrapper.getEnergyConsumerInfo();
+            EnergyConsumerIdUtils.packProtoMessage(energyConsumerId, pos);
+            if (DEBUG) EnergyConsumerIdUtils.print(energyConsumerId);
+
+            mPowerStatsModelStorage.read(new PowerStatsDataStorage.DataElementReadCallback() {
+                @Override
+                public void onReadDataElement(byte[] data) {
+                    try {
+                        final ProtoInputStream pis =
+                                new ProtoInputStream(new ByteArrayInputStream(data));
+                        // TODO(b/166535853): ProtoOutputStream doesn't provide a method to write
+                        // a byte array that already contains a serialized proto, so I have to
+                        // deserialize, then re-serialize.  This is computationally inefficient.
+                        EnergyConsumerResult[] energyConsumerResult =
+                            EnergyConsumerResultUtils.unpackProtoMessage(data);
+                        EnergyConsumerResultUtils.packProtoMessage(energyConsumerResult, pos);
+                        if (DEBUG) EnergyConsumerResultUtils.print(energyConsumerResult);
+                    } catch (IOException e) {
+                        Log.e(TAG, "Failed to write energy model data to incident report.");
+                    }
+                }
+            });
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to write energy model info to incident report.");
+        }
+
+        pos.flush();
+    }
+
+    public PowerStatsLogger(Context context, File dataStoragePath, String meterFilename,
+            String modelFilename, IPowerStatsHALWrapper powerStatsHALWrapper) {
         super(Looper.getMainLooper());
         mPowerStatsHALWrapper = powerStatsHALWrapper;
-        mPowerStatsDataStorage = new PowerStatsDataStorage(context, dataStoragePath,
-            dataStorageFilename);
+        mPowerStatsMeterStorage = new PowerStatsDataStorage(context, dataStoragePath,
+            meterFilename);
+        mPowerStatsModelStorage = new PowerStatsDataStorage(context, dataStoragePath,
+            modelFilename);
     }
 }
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 81883f3..b89464f 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -43,7 +43,8 @@
     private static final boolean DEBUG = false;
     private static final String DATA_STORAGE_SUBDIR = "powerstats";
     private static final int DATA_STORAGE_VERSION = 0;
-    private static final String DATA_STORAGE_FILENAME = "log.powerstats." + DATA_STORAGE_VERSION;
+    private static final String METER_FILENAME = "log.powerstats.meter." + DATA_STORAGE_VERSION;
+    private static final String MODEL_FILENAME = "log.powerstats.model." + DATA_STORAGE_VERSION;
 
     private final Injector mInjector;
 
@@ -63,8 +64,12 @@
                 DATA_STORAGE_SUBDIR);
         }
 
-        String createDataStorageFilename() {
-            return DATA_STORAGE_FILENAME;
+        String createMeterFilename() {
+            return METER_FILENAME;
+        }
+
+        String createModelFilename() {
+            return MODEL_FILENAME;
         }
 
         IPowerStatsHALWrapper createPowerStatsHALWrapperImpl() {
@@ -72,9 +77,10 @@
         }
 
         PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
-                String dataStorageFilename, IPowerStatsHALWrapper powerStatsHALWrapper) {
-            return new PowerStatsLogger(context, dataStoragePath, dataStorageFilename,
-                powerStatsHALWrapper);
+                String meterFilename, String modelFilename,
+                IPowerStatsHALWrapper powerStatsHALWrapper) {
+            return new PowerStatsLogger(context, dataStoragePath, meterFilename,
+                modelFilename, powerStatsHALWrapper);
         }
 
         BatteryTrigger createBatteryTrigger(Context context, PowerStatsLogger powerStatsLogger) {
@@ -91,11 +97,15 @@
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
 
-            if (args.length > 0 && "--proto".equals(args[0])) {
-                if (mPowerStatsLogger == null) {
-                    Log.e(TAG, "PowerStats HAL is not initialized.  No data available.");
-                } else {
-                    mPowerStatsLogger.writeToFile(fd);
+            if (mPowerStatsLogger == null) {
+                Log.e(TAG, "PowerStats HAL is not initialized.  No data available.");
+            } else {
+                if (args.length > 0 && "--proto".equals(args[0])) {
+                    if ("model".equals(args[1])) {
+                        mPowerStatsLogger.writeModelDataToFile(fd);
+                    } else if ("meter".equals(args[1])) {
+                        mPowerStatsLogger.writeMeterDataToFile(fd);
+                    }
                 }
             }
         }
@@ -121,8 +131,8 @@
 
             // Only start logger and triggers if initialization is successful.
             mPowerStatsLogger = mInjector.createPowerStatsLogger(mContext,
-                mInjector.createDataStoragePath(), mInjector.createDataStorageFilename(),
-                mPowerStatsHALWrapper);
+                mInjector.createDataStoragePath(), mInjector.createMeterFilename(),
+                mInjector.createModelFilename(), mPowerStatsHALWrapper);
             mBatteryTrigger = mInjector.createBatteryTrigger(mContext, mPowerStatsLogger);
             mTimerTrigger = mInjector.createTimerTrigger(mContext, mPowerStatsLogger);
         } else {
diff --git a/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
new file mode 100644
index 0000000..c29c5da
--- /dev/null
+++ b/services/core/java/com/android/server/powerstats/ProtoStreamUtils.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.powerstats;
+
+import android.hardware.power.stats.ChannelInfo;
+import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyMeasurement;
+import android.util.Log;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
+import android.util.proto.ProtoUtils;
+import android.util.proto.WireTypeMismatchException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * ProtoStreamUtils provides helper functions for the PowerStats HAL objects returned from calls
+ * to the PowerStats HAL APIs.  It provides functions to pack/unpack object arrays to/from protobuf
+ * format.  These helper functions are required since frameworks code uses the genstream option
+ * when generating source code and therefore, getter/setter helper functions are not available.  The
+ * protobufs need to be packed/unpacked in a more manual way using
+ * ProtoOutputStream/ProtoInputStream.  It also provides print() functions for debugging purposes.
+ */
+public class ProtoStreamUtils {
+    private static final String TAG = ProtoStreamUtils.class.getSimpleName();
+
+    static class ChannelInfoUtils {
+        public static void packProtoMessage(ChannelInfo[] channelInfo, ProtoOutputStream pos) {
+            long token;
+
+            for (int i = 0; i < channelInfo.length; i++) {
+                token = pos.start(PowerStatsServiceMeterProto.CHANNEL_INFO);
+                pos.write(ChannelInfoProto.CHANNEL_ID, channelInfo[i].channelId);
+                pos.write(ChannelInfoProto.CHANNEL_NAME, channelInfo[i].channelName);
+                pos.end(token);
+            }
+
+        }
+
+        public static void print(ChannelInfo[] channelInfo) {
+            for (int i = 0; i < channelInfo.length; i++) {
+                Log.d(TAG, "ChannelId = " + channelInfo[i].channelId
+                        + ", ChannelName = " + channelInfo[i].channelName);
+            }
+        }
+    }
+
+    static class EnergyMeasurementUtils {
+        public static byte[] getProtoBytes(EnergyMeasurement[] energyMeasurement) {
+            ProtoOutputStream pos = new ProtoOutputStream();
+            packProtoMessage(energyMeasurement, pos);
+            return pos.getBytes();
+        }
+
+        public static void packProtoMessage(EnergyMeasurement[] energyMeasurement,
+                ProtoOutputStream pos) {
+            long token;
+
+            for (int i = 0; i < energyMeasurement.length; i++) {
+                token = pos.start(PowerStatsServiceMeterProto.ENERGY_MEASUREMENT);
+                pos.write(EnergyMeasurementProto.CHANNEL_ID, energyMeasurement[i].channelId);
+                pos.write(EnergyMeasurementProto.TIMESTAMP_MS, energyMeasurement[i].timestampMs);
+                pos.write(EnergyMeasurementProto.ENERGY_UWS, energyMeasurement[i].energyUWs);
+                pos.end(token);
+            }
+        }
+
+        public static EnergyMeasurement[] unpackProtoMessage(byte[] data) throws IOException {
+            final ProtoInputStream pis = new ProtoInputStream(new ByteArrayInputStream(data));
+            List<EnergyMeasurement> energyMeasurementList = new ArrayList<EnergyMeasurement>();
+            long token;
+
+            while (true) {
+                try {
+                    int nextField = pis.nextField();
+                    EnergyMeasurement energyMeasurement = new EnergyMeasurement();
+
+                    if (nextField == (int) PowerStatsServiceMeterProto.ENERGY_MEASUREMENT) {
+                        token = pis.start(PowerStatsServiceMeterProto.ENERGY_MEASUREMENT);
+                        energyMeasurementList.add(unpackProtoMessage(pis));
+                        pis.end(token);
+                    } else if (nextField == ProtoInputStream.NO_MORE_FIELDS) {
+                        return energyMeasurementList.toArray(
+                            new EnergyMeasurement[energyMeasurementList.size()]);
+                    } else {
+                        Log.e(TAG, "Unhandled field in proto: "
+                                + ProtoUtils.currentFieldToString(pis));
+                    }
+                } catch (WireTypeMismatchException wtme) {
+                    Log.e(TAG, "Wire Type mismatch in proto: "
+                            + ProtoUtils.currentFieldToString(pis));
+                }
+            }
+        }
+
+        private static EnergyMeasurement unpackProtoMessage(ProtoInputStream pis)
+                throws IOException {
+            EnergyMeasurement energyMeasurement = new EnergyMeasurement();
+
+            while (true) {
+                try {
+                    switch (pis.nextField()) {
+                        case (int) EnergyMeasurementProto.CHANNEL_ID:
+                            energyMeasurement.channelId =
+                                pis.readInt(EnergyMeasurementProto.CHANNEL_ID);
+                            break;
+
+                        case (int) EnergyMeasurementProto.TIMESTAMP_MS:
+                            energyMeasurement.timestampMs =
+                                pis.readLong(EnergyMeasurementProto.TIMESTAMP_MS);
+                            break;
+
+                        case (int) EnergyMeasurementProto.ENERGY_UWS:
+                            energyMeasurement.energyUWs =
+                                pis.readLong(EnergyMeasurementProto.ENERGY_UWS);
+                            break;
+
+                        case ProtoInputStream.NO_MORE_FIELDS:
+                            return energyMeasurement;
+
+                        default:
+                            Log.e(TAG, "Unhandled field in EnergyMeasurementProto: "
+                                    + ProtoUtils.currentFieldToString(pis));
+                            break;
+                    }
+                } catch (WireTypeMismatchException wtme) {
+                    Log.e(TAG, "Wire Type mismatch in EnergyMeasurementProto: "
+                            + ProtoUtils.currentFieldToString(pis));
+                }
+            }
+        }
+
+        public static void print(EnergyMeasurement[] energyMeasurement) {
+            for (int i = 0; i < energyMeasurement.length; i++) {
+                Log.d(TAG, "ChannelId = " + energyMeasurement[i].channelId
+                        + ", Timestamp (ms) = " + energyMeasurement[i].timestampMs
+                        + ", Energy (uWs) = " + energyMeasurement[i].energyUWs);
+            }
+        }
+    }
+
+    static class EnergyConsumerIdUtils {
+        public static void packProtoMessage(int[] energyConsumerId, ProtoOutputStream pos) {
+            long token;
+
+            for (int i = 0; i < energyConsumerId.length; i++) {
+                token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_ID);
+                pos.write(EnergyConsumerIdProto.ENERGY_CONSUMER_ID, energyConsumerId[i]);
+                pos.end(token);
+            }
+        }
+
+        public static void print(int[] energyConsumerId) {
+            for (int i = 0; i < energyConsumerId.length; i++) {
+                Log.d(TAG, "EnergyConsumerId = " + energyConsumerId[i]);
+            }
+        }
+    }
+
+    static class EnergyConsumerResultUtils {
+        public static byte[] getProtoBytes(EnergyConsumerResult[] energyConsumerResult) {
+            ProtoOutputStream pos = new ProtoOutputStream();
+            packProtoMessage(energyConsumerResult, pos);
+            return pos.getBytes();
+        }
+
+        public static void packProtoMessage(EnergyConsumerResult[] energyConsumerResult,
+                ProtoOutputStream pos) {
+            long token;
+
+            for (int i = 0; i < energyConsumerResult.length; i++) {
+                token = pos.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
+                pos.write(EnergyConsumerResultProto.ENERGY_CONSUMER_ID,
+                        energyConsumerResult[i].energyConsumerId);
+                pos.write(EnergyConsumerResultProto.TIMESTAMP_MS,
+                        energyConsumerResult[i].timestampMs);
+                pos.write(EnergyConsumerResultProto.ENERGY_UWS, energyConsumerResult[i].energyUWs);
+                pos.end(token);
+            }
+        }
+
+        public static EnergyConsumerResult[] unpackProtoMessage(byte[] data) throws IOException {
+            final ProtoInputStream pis = new ProtoInputStream(new ByteArrayInputStream(data));
+            List<EnergyConsumerResult> energyConsumerResultList =
+                    new ArrayList<EnergyConsumerResult>();
+            long token;
+
+            while (true) {
+                try {
+                    int nextField = pis.nextField();
+                    EnergyConsumerResult energyConsumerResult = new EnergyConsumerResult();
+
+                    if (nextField == (int) PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT) {
+                        token = pis.start(PowerStatsServiceModelProto.ENERGY_CONSUMER_RESULT);
+                        energyConsumerResultList.add(unpackProtoMessage(pis));
+                        pis.end(token);
+                    } else if (nextField == ProtoInputStream.NO_MORE_FIELDS) {
+                        return energyConsumerResultList.toArray(
+                            new EnergyConsumerResult[energyConsumerResultList.size()]);
+                    } else {
+                        Log.e(TAG, "Unhandled field in proto: "
+                                + ProtoUtils.currentFieldToString(pis));
+                    }
+                } catch (WireTypeMismatchException wtme) {
+                    Log.e(TAG, "Wire Type mismatch in proto: "
+                            + ProtoUtils.currentFieldToString(pis));
+                }
+            }
+        }
+
+        private static EnergyConsumerResult unpackProtoMessage(ProtoInputStream pis)
+                throws IOException {
+            EnergyConsumerResult energyConsumerResult = new EnergyConsumerResult();
+
+            while (true) {
+                try {
+                    switch (pis.nextField()) {
+                        case (int) EnergyConsumerResultProto.ENERGY_CONSUMER_ID:
+                            energyConsumerResult.energyConsumerId =
+                                pis.readInt(EnergyConsumerResultProto.ENERGY_CONSUMER_ID);
+                            break;
+
+                        case (int) EnergyConsumerResultProto.TIMESTAMP_MS:
+                            energyConsumerResult.timestampMs =
+                                pis.readLong(EnergyConsumerResultProto.TIMESTAMP_MS);
+                            break;
+
+                        case (int) EnergyConsumerResultProto.ENERGY_UWS:
+                            energyConsumerResult.energyUWs =
+                                pis.readLong(EnergyConsumerResultProto.ENERGY_UWS);
+                            break;
+
+                        case ProtoInputStream.NO_MORE_FIELDS:
+                            return energyConsumerResult;
+
+                        default:
+                            Log.e(TAG, "Unhandled field in EnergyConsumerResultProto: "
+                                    + ProtoUtils.currentFieldToString(pis));
+                            break;
+                    }
+                } catch (WireTypeMismatchException wtme) {
+                    Log.e(TAG, "Wire Type mismatch in EnergyConsumerResultProto: "
+                            + ProtoUtils.currentFieldToString(pis));
+                }
+            }
+        }
+
+        public static void print(EnergyConsumerResult[] energyConsumerResult) {
+            for (int i = 0; i < energyConsumerResult.length; i++) {
+                Log.d(TAG, "EnergyConsumerId = " + energyConsumerResult[i].energyConsumerId
+                        + ", Timestamp (ms) = " + energyConsumerResult[i].timestampMs
+                        + ", Energy (uWs) = " + energyConsumerResult[i].energyUWs);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
index 5311369..52236a8 100644
--- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java
+++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java
@@ -25,7 +25,6 @@
 import android.content.Intent;
 import android.content.pm.UserInfo;
 import android.debug.AdbManagerInternal;
-import android.debug.AdbTransportType;
 import android.location.LocationManager;
 import android.os.BatteryManager;
 import android.os.Binder;
@@ -162,12 +161,11 @@
     private void configureSettings() {
         ContentResolver cr = getContext().getContentResolver();
 
-        // Stop ADB before we enable it, otherwise on userdebug/eng builds, the keys won't have
-        // registered with adbd, and it will prompt the user to confirm the keys.
-        Settings.Global.putInt(cr, Settings.Global.ADB_ENABLED, 0);
-        AdbManagerInternal adbManager = LocalServices.getService(AdbManagerInternal.class);
-        if (adbManager.isAdbEnabled(AdbTransportType.USB)) {
-            adbManager.stopAdbdForTransport(AdbTransportType.USB);
+        // If adb is already enabled, then we need to restart the daemon to pick up the change in
+        // keys. This is only really useful for userdebug/eng builds.
+        if (Settings.Global.getInt(cr, Settings.Global.ADB_ENABLED, 0) == 1) {
+            SystemProperties.set("ctl.restart", "adbd");
+            Slog.d(TAG, "Restarted adbd");
         }
 
         // Disable the TTL for ADB keys before enabling ADB
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 55697d3..4d670f1 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -15,15 +15,22 @@
  */
 package com.android.server.webkit;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.Signature;
 import android.os.AsyncTask;
 import android.os.UserHandle;
 import android.util.Slog;
+import android.webkit.UserPackage;
+import android.webkit.WebViewFactory;
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Implementation of the WebViewUpdateService.
@@ -33,10 +40,10 @@
  * This class keeps track of and prepares the current WebView implementation, and needs to keep
  * track of a couple of different things such as what package is used as WebView implementation.
  *
- * The public methods in this class are accessed from WebViewUpdateService either on the UI thread
- * or on one of multiple Binder threads. The WebView preparation code shares state between threads
- * meaning that code that chooses a new WebView implementation or checks which implementation is
- * being used needs to hold a lock.
+ * The package-visible methods in this class are accessed from WebViewUpdateService either on the UI
+ * thread or on one of multiple Binder threads. The WebView preparation code shares state between
+ * threads meaning that code that chooses a new WebView implementation or checks which
+ * implementation is being used needs to hold a lock.
  *
  * The WebViewUpdateService can be accessed in a couple of different ways.
  * 1. It is started from the SystemServer at boot - at that point we just initiate some state such
@@ -55,36 +62,133 @@
  *
  * @hide
  */
-public class WebViewUpdateServiceImpl {
+class WebViewUpdateServiceImpl {
     private static final String TAG = WebViewUpdateServiceImpl.class.getSimpleName();
 
-    private SystemInterface mSystemInterface;
-    private WebViewUpdater mWebViewUpdater;
-    final private Context mContext;
+    private static class WebViewPackageMissingException extends Exception {
+        WebViewPackageMissingException(String message) {
+            super(message);
+        }
 
-    private final static int MULTIPROCESS_SETTING_ON_VALUE = Integer.MAX_VALUE;
-    private final static int MULTIPROCESS_SETTING_OFF_VALUE = Integer.MIN_VALUE;
+        WebViewPackageMissingException(Exception e) {
+            super(e);
+        }
+    }
 
-    public WebViewUpdateServiceImpl(Context context, SystemInterface systemInterface) {
+    private static final int WAIT_TIMEOUT_MS = 1000; // KEY_DISPATCHING_TIMEOUT is 5000.
+    private static final long NS_PER_MS = 1000000;
+
+    private static final int VALIDITY_OK = 0;
+    private static final int VALIDITY_INCORRECT_SDK_VERSION = 1;
+    private static final int VALIDITY_INCORRECT_VERSION_CODE = 2;
+    private static final int VALIDITY_INCORRECT_SIGNATURE = 3;
+    private static final int VALIDITY_NO_LIBRARY_FLAG = 4;
+
+    private static final int MULTIPROCESS_SETTING_ON_VALUE = Integer.MAX_VALUE;
+    private static final int MULTIPROCESS_SETTING_OFF_VALUE = Integer.MIN_VALUE;
+
+    private final SystemInterface mSystemInterface;
+    private final Context mContext;
+
+    private long mMinimumVersionCode = -1;
+
+    // Keeps track of the number of running relro creations
+    private int mNumRelroCreationsStarted = 0;
+    private int mNumRelroCreationsFinished = 0;
+    // Implies that we need to rerun relro creation because we are using an out-of-date package
+    private boolean mWebViewPackageDirty = false;
+    private boolean mAnyWebViewInstalled = false;
+
+    private static final int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
+
+    // The WebView package currently in use (or the one we are preparing).
+    private PackageInfo mCurrentWebViewPackage = null;
+
+    private final Object mLock = new Object();
+
+    WebViewUpdateServiceImpl(Context context, SystemInterface systemInterface) {
         mContext = context;
         mSystemInterface = systemInterface;
-        mWebViewUpdater = new WebViewUpdater(mContext, mSystemInterface);
     }
 
     void packageStateChanged(String packageName, int changedState, int userId) {
         // We don't early out here in different cases where we could potentially early-out (e.g. if
         // we receive PACKAGE_CHANGED for another user than the system user) since that would
         // complicate this logic further and open up for more edge cases.
-        mWebViewUpdater.packageStateChanged(packageName, changedState);
+        for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+            String webviewPackage = provider.packageName;
+
+            if (webviewPackage.equals(packageName)) {
+                boolean updateWebView = false;
+                boolean removedOrChangedOldPackage = false;
+                String oldProviderName = null;
+                PackageInfo newPackage = null;
+                synchronized (mLock) {
+                    try {
+                        newPackage = findPreferredWebViewPackage();
+                        if (mCurrentWebViewPackage != null) {
+                            oldProviderName = mCurrentWebViewPackage.packageName;
+                        }
+                        // Only trigger update actions if the updated package is the one
+                        // that will be used, or the one that was in use before the
+                        // update, or if we haven't seen a valid WebView package before.
+                        updateWebView =
+                            provider.packageName.equals(newPackage.packageName)
+                            || provider.packageName.equals(oldProviderName)
+                            || mCurrentWebViewPackage == null;
+                        // We removed the old package if we received an intent to remove
+                        // or replace the old package.
+                        removedOrChangedOldPackage =
+                            provider.packageName.equals(oldProviderName);
+                        if (updateWebView) {
+                            onWebViewProviderChanged(newPackage);
+                        }
+                    } catch (WebViewPackageMissingException e) {
+                        mCurrentWebViewPackage = null;
+                        Slog.e(TAG, "Could not find valid WebView package to create relro with "
+                                + e);
+                    }
+                }
+                if (updateWebView && !removedOrChangedOldPackage
+                        && oldProviderName != null) {
+                    // If the provider change is the result of adding or replacing a
+                    // package that was not the previous provider then we must kill
+                    // packages dependent on the old package ourselves. The framework
+                    // only kills dependents of packages that are being removed.
+                    mSystemInterface.killPackageDependents(oldProviderName);
+                }
+                return;
+            }
+        }
     }
 
     void prepareWebViewInSystemServer() {
-        mWebViewUpdater.prepareWebViewInSystemServer();
+        try {
+            synchronized (mLock) {
+                mCurrentWebViewPackage = findPreferredWebViewPackage();
+                String userSetting = mSystemInterface.getUserChosenWebViewProvider(mContext);
+                if (userSetting != null
+                        && !userSetting.equals(mCurrentWebViewPackage.packageName)) {
+                    // Don't persist the user-chosen setting across boots if the package being
+                    // chosen is not used (could be disabled or uninstalled) so that the user won't
+                    // be surprised by the device switching to using a certain webview package,
+                    // that was uninstalled/disabled a long time ago, if it is installed/enabled
+                    // again.
+                    mSystemInterface.updateUserSetting(mContext,
+                            mCurrentWebViewPackage.packageName);
+                }
+                onWebViewProviderChanged(mCurrentWebViewPackage);
+            }
+        } catch (Throwable t) {
+            // Log and discard errors at this stage as we must not crash the system server.
+            Slog.e(TAG, "error preparing webview provider from system server", t);
+        }
+
         if (getCurrentWebViewPackage() == null) {
             // We didn't find a valid WebView implementation. Try explicitly re-enabling the
             // fallback package for all users in case it was disabled, even if we already did the
-            // one-time migration before. If this actually changes the state, WebViewUpdater will
-            // see the PackageManager broadcast shortly and try again.
+            // one-time migration before. If this actually changes the state, we will see the
+            // PackageManager broadcast shortly and try again.
             WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
             WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
             if (fallbackProvider != null) {
@@ -103,7 +207,7 @@
         }
     }
 
-    void startZygoteWhenReady() {
+    private void startZygoteWhenReady() {
         // Wait on a background thread for RELRO creation to be done. We ignore the return value
         // because even if RELRO creation failed we still want to start the zygote.
         waitForAndGetProvider();
@@ -129,23 +233,231 @@
      */
     private void handleUserChange() {
         // Potentially trigger package-changing logic.
-        mWebViewUpdater.updateCurrentWebViewPackage(null);
+        updateCurrentWebViewPackage(null);
     }
 
     void notifyRelroCreationCompleted() {
-        mWebViewUpdater.notifyRelroCreationCompleted();
+        synchronized (mLock) {
+            mNumRelroCreationsFinished++;
+            checkIfRelrosDoneLocked();
+        }
     }
 
     WebViewProviderResponse waitForAndGetProvider() {
-        return mWebViewUpdater.waitForAndGetProvider();
+        PackageInfo webViewPackage = null;
+        final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
+        boolean webViewReady = false;
+        int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
+        synchronized (mLock) {
+            webViewReady = webViewIsReadyLocked();
+            while (!webViewReady) {
+                final long timeNowMs = System.nanoTime() / NS_PER_MS;
+                if (timeNowMs >= timeoutTimeMs) break;
+                try {
+                    mLock.wait(timeoutTimeMs - timeNowMs);
+                } catch (InterruptedException e) {
+                    // ignore
+                }
+                webViewReady = webViewIsReadyLocked();
+            }
+            // Make sure we return the provider that was used to create the relro file
+            webViewPackage = mCurrentWebViewPackage;
+            if (webViewReady) {
+                // success
+            } else if (!mAnyWebViewInstalled) {
+                webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+            } else {
+                // Either the current relro creation  isn't done yet, or the new relro creatioin
+                // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
+                webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
+                Slog.e(TAG, "Timed out waiting for relro creation, relros started "
+                        + mNumRelroCreationsStarted
+                        + " relros finished " + mNumRelroCreationsFinished
+                        + " package dirty? " + mWebViewPackageDirty);
+            }
+        }
+        if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
+        return new WebViewProviderResponse(webViewPackage, webViewStatus);
     }
 
-    String changeProviderAndSetting(String newProvider) {
-        return mWebViewUpdater.changeProviderAndSetting(newProvider);
+    /**
+     * Change WebView provider and provider setting and kill packages using the old provider.
+     * Return the new provider (in case we are in the middle of creating relro files, or
+     * replacing that provider it will not be in use directly, but will be used when the relros
+     * or the replacement are done).
+     */
+    String changeProviderAndSetting(String newProviderName) {
+        PackageInfo newPackage = updateCurrentWebViewPackage(newProviderName);
+        if (newPackage == null) return "";
+        return newPackage.packageName;
     }
 
+    /**
+     * Update the current WebView package.
+     * @param newProviderName the package to switch to, null if no package has been explicitly
+     * chosen.
+     */
+    private PackageInfo updateCurrentWebViewPackage(@Nullable String newProviderName) {
+        PackageInfo oldPackage = null;
+        PackageInfo newPackage = null;
+        boolean providerChanged = false;
+        synchronized (mLock) {
+            oldPackage = mCurrentWebViewPackage;
+
+            if (newProviderName != null) {
+                mSystemInterface.updateUserSetting(mContext, newProviderName);
+            }
+
+            try {
+                newPackage = findPreferredWebViewPackage();
+                providerChanged = (oldPackage == null)
+                        || !newPackage.packageName.equals(oldPackage.packageName);
+            } catch (WebViewPackageMissingException e) {
+                // If updated the Setting but don't have an installed WebView package, the
+                // Setting will be used when a package is available.
+                mCurrentWebViewPackage = null;
+                Slog.e(TAG, "Couldn't find WebView package to use " + e);
+                return null;
+            }
+            // Perform the provider change if we chose a new provider
+            if (providerChanged) {
+                onWebViewProviderChanged(newPackage);
+            }
+        }
+        // Kill apps using the old provider only if we changed provider
+        if (providerChanged && oldPackage != null) {
+            mSystemInterface.killPackageDependents(oldPackage.packageName);
+        }
+        // Return the new provider, this is not necessarily the one we were asked to switch to,
+        // but the persistent setting will now be pointing to the provider we were asked to
+        // switch to anyway.
+        return newPackage;
+    }
+
+    /**
+     * This is called when we change WebView provider, either when the current provider is
+     * updated or a new provider is chosen / takes precedence.
+     */
+    private void onWebViewProviderChanged(PackageInfo newPackage) {
+        synchronized (mLock) {
+            mAnyWebViewInstalled = true;
+            if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+                mCurrentWebViewPackage = newPackage;
+
+                // The relro creations might 'finish' (not start at all) before
+                // WebViewFactory.onWebViewProviderChanged which means we might not know the
+                // number of started creations before they finish.
+                mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
+                mNumRelroCreationsFinished = 0;
+                mNumRelroCreationsStarted =
+                    mSystemInterface.onWebViewProviderChanged(newPackage);
+                // If the relro creations finish before we know the number of started creations
+                // we will have to do any cleanup/notifying here.
+                checkIfRelrosDoneLocked();
+            } else {
+                mWebViewPackageDirty = true;
+            }
+        }
+    }
+
+    /**
+     * Fetch only the currently valid WebView packages.
+     **/
     WebViewProviderInfo[] getValidWebViewPackages() {
-        return mWebViewUpdater.getValidWebViewPackages();
+        ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
+        WebViewProviderInfo[] providers =
+            new WebViewProviderInfo[providersAndPackageInfos.length];
+        for (int n = 0; n < providersAndPackageInfos.length; n++) {
+            providers[n] = providersAndPackageInfos[n].provider;
+        }
+        return providers;
+    }
+
+    private static class ProviderAndPackageInfo {
+        public final WebViewProviderInfo provider;
+        public final PackageInfo packageInfo;
+
+        ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
+            this.provider = provider;
+            this.packageInfo = packageInfo;
+        }
+    }
+
+    private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
+        WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
+        List<ProviderAndPackageInfo> providers = new ArrayList<>();
+        for (int n = 0; n < allProviders.length; n++) {
+            try {
+                PackageInfo packageInfo =
+                        mSystemInterface.getPackageInfoForProvider(allProviders[n]);
+                if (validityResult(allProviders[n], packageInfo) == VALIDITY_OK) {
+                    providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
+                }
+            } catch (NameNotFoundException e) {
+                // Don't add non-existent packages
+            }
+        }
+        return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
+    }
+
+    /**
+     * Returns either the package info of the WebView provider determined in the following way:
+     * If the user has chosen a provider then use that if it is valid,
+     * otherwise use the first package in the webview priority list that is valid.
+     *
+     */
+    private PackageInfo findPreferredWebViewPackage() throws WebViewPackageMissingException {
+        ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
+
+        String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);
+
+        // If the user has chosen provider, use that (if it's installed and enabled for all
+        // users).
+        for (ProviderAndPackageInfo providerAndPackage : providers) {
+            if (providerAndPackage.provider.packageName.equals(userChosenProvider)) {
+                // userPackages can contain null objects.
+                List<UserPackage> userPackages =
+                        mSystemInterface.getPackageInfoForProviderAllUsers(mContext,
+                                providerAndPackage.provider);
+                if (isInstalledAndEnabledForAllUsers(userPackages)) {
+                    return providerAndPackage.packageInfo;
+                }
+            }
+        }
+
+        // User did not choose, or the choice failed; use the most stable provider that is
+        // installed and enabled for all users, and available by default (not through
+        // user choice).
+        for (ProviderAndPackageInfo providerAndPackage : providers) {
+            if (providerAndPackage.provider.availableByDefault) {
+                // userPackages can contain null objects.
+                List<UserPackage> userPackages =
+                        mSystemInterface.getPackageInfoForProviderAllUsers(mContext,
+                                providerAndPackage.provider);
+                if (isInstalledAndEnabledForAllUsers(userPackages)) {
+                    return providerAndPackage.packageInfo;
+                }
+            }
+        }
+
+        // This should never happen during normal operation (only with modified system images).
+        mAnyWebViewInstalled = false;
+        throw new WebViewPackageMissingException("Could not find a loadable WebView package");
+    }
+
+    /**
+     * Return true iff {@param packageInfos} point to only installed and enabled packages.
+     * The given packages {@param packageInfos} should all be pointing to the same package, but each
+     * PackageInfo representing a different user's package.
+     */
+    private static boolean isInstalledAndEnabledForAllUsers(
+            List<UserPackage> userPackages) {
+        for (UserPackage userPackage : userPackages) {
+            if (!userPackage.isInstalledPackage() || !userPackage.isEnabledPackage()) {
+                return false;
+            }
+        }
+        return true;
     }
 
     WebViewProviderInfo[] getWebViewPackages() {
@@ -153,7 +465,143 @@
     }
 
     PackageInfo getCurrentWebViewPackage() {
-        return mWebViewUpdater.getCurrentWebViewPackage();
+        synchronized (mLock) {
+            return mCurrentWebViewPackage;
+        }
+    }
+
+    /**
+     * Returns whether WebView is ready and is not going to go through its preparation phase
+     * again directly.
+     */
+    private boolean webViewIsReadyLocked() {
+        return !mWebViewPackageDirty
+            && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
+            // The current package might be replaced though we haven't received an intent
+            // declaring this yet, the following flag makes anyone loading WebView to wait in
+            // this case.
+            && mAnyWebViewInstalled;
+    }
+
+    private void checkIfRelrosDoneLocked() {
+        if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+            if (mWebViewPackageDirty) {
+                mWebViewPackageDirty = false;
+                // If we have changed provider since we started the relro creation we need to
+                // redo the whole process using the new package instead.
+                try {
+                    PackageInfo newPackage = findPreferredWebViewPackage();
+                    onWebViewProviderChanged(newPackage);
+                } catch (WebViewPackageMissingException e) {
+                    mCurrentWebViewPackage = null;
+                    // If we can't find any valid WebView package we are now in a state where
+                    // mAnyWebViewInstalled is false, so loading WebView will be blocked and we
+                    // should simply wait until we receive an intent declaring a new package was
+                    // installed.
+                }
+            } else {
+                mLock.notifyAll();
+            }
+        }
+    }
+
+    private int validityResult(WebViewProviderInfo configInfo, PackageInfo packageInfo) {
+        // Ensure the provider targets this framework release (or a later one).
+        if (!UserPackage.hasCorrectTargetSdkVersion(packageInfo)) {
+            return VALIDITY_INCORRECT_SDK_VERSION;
+        }
+        if (!versionCodeGE(packageInfo.getLongVersionCode(), getMinimumVersionCode())
+                && !mSystemInterface.systemIsDebuggable()) {
+            // Webview providers may be downgraded arbitrarily low, prevent that by enforcing
+            // minimum version code. This check is only enforced for user builds.
+            return VALIDITY_INCORRECT_VERSION_CODE;
+        }
+        if (!providerHasValidSignature(configInfo, packageInfo, mSystemInterface)) {
+            return VALIDITY_INCORRECT_SIGNATURE;
+        }
+        if (WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) == null) {
+            return VALIDITY_NO_LIBRARY_FLAG;
+        }
+        return VALIDITY_OK;
+    }
+
+    /**
+     * Both versionCodes should be from a WebView provider package implemented by Chromium.
+     * VersionCodes from other kinds of packages won't make any sense in this method.
+     *
+     * An introduction to Chromium versionCode scheme:
+     * "BBBBPPPXX"
+     * BBBB: 4 digit branch number. It monotonically increases over time.
+     * PPP: patch number in the branch. It is padded with zeroes to the left. These three digits
+     * may change their meaning in the future.
+     * XX: Digits to differentiate different APK builds of the same source version.
+     *
+     * This method takes the "BBBB" of versionCodes and compare them.
+     *
+     * https://www.chromium.org/developers/version-numbers describes general Chromium versioning;
+     * https://source.chromium.org/chromium/chromium/src/+/master:build/util/android_chrome_version.py
+     * is the canonical source for how Chromium versionCodes are calculated.
+     *
+     * @return true if versionCode1 is higher than or equal to versionCode2.
+     */
+    private static boolean versionCodeGE(long versionCode1, long versionCode2) {
+        long v1 = versionCode1 / 100000;
+        long v2 = versionCode2 / 100000;
+
+        return v1 >= v2;
+    }
+
+    /**
+     * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode
+     * of all available-by-default WebView provider packages. If there is no such WebView provider
+     * package on the system, then return -1, which means all positive versionCode WebView packages
+     * are accepted.
+     *
+     * Note that this is a private method that handles a variable (mMinimumVersionCode) which is
+     * shared between threads. Furthermore, this method does not hold mLock meaning that we must
+     * take extra care to ensure this method is thread-safe.
+     */
+    private long getMinimumVersionCode() {
+        if (mMinimumVersionCode > 0) {
+            return mMinimumVersionCode;
+        }
+
+        long minimumVersionCode = -1;
+        for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
+            if (provider.availableByDefault) {
+                try {
+                    long versionCode =
+                            mSystemInterface.getFactoryPackageVersion(provider.packageName);
+                    if (minimumVersionCode < 0 || versionCode < minimumVersionCode) {
+                        minimumVersionCode = versionCode;
+                    }
+                } catch (NameNotFoundException e) {
+                    // Safe to ignore.
+                }
+            }
+        }
+
+        mMinimumVersionCode = minimumVersionCode;
+        return mMinimumVersionCode;
+    }
+
+    private static boolean providerHasValidSignature(WebViewProviderInfo provider,
+            PackageInfo packageInfo, SystemInterface systemInterface) {
+        // Skip checking signatures on debuggable builds, for development purposes.
+        if (systemInterface.systemIsDebuggable()) return true;
+
+        // Allow system apps to be valid providers regardless of signature.
+        if (packageInfo.applicationInfo.isSystemApp()) return true;
+
+        // We don't support packages with multiple signatures.
+        if (packageInfo.signatures.length != 1) return false;
+
+        // If any of the declared signatures match the package signature, it's valid.
+        for (Signature signature : provider.signatures) {
+            if (signature.equals(packageInfo.signatures[0])) return true;
+        }
+
+        return false;
     }
 
     /**
@@ -195,6 +643,88 @@
     void dumpState(PrintWriter pw) {
         pw.println("Current WebView Update Service state");
         pw.println(String.format("  Multiprocess enabled: %b", isMultiProcessEnabled()));
-        mWebViewUpdater.dumpState(pw);
+        synchronized (mLock) {
+            if (mCurrentWebViewPackage == null) {
+                pw.println("  Current WebView package is null");
+            } else {
+                pw.println(String.format("  Current WebView package (name, version): (%s, %s)",
+                        mCurrentWebViewPackage.packageName,
+                        mCurrentWebViewPackage.versionName));
+            }
+            pw.println(String.format("  Minimum targetSdkVersion: %d",
+                    UserPackage.MINIMUM_SUPPORTED_SDK));
+            pw.println(String.format("  Minimum WebView version code: %d",
+                    mMinimumVersionCode));
+            pw.println(String.format("  Number of relros started: %d",
+                    mNumRelroCreationsStarted));
+            pw.println(String.format("  Number of relros finished: %d",
+                        mNumRelroCreationsFinished));
+            pw.println(String.format("  WebView package dirty: %b", mWebViewPackageDirty));
+            pw.println(String.format("  Any WebView package installed: %b",
+                    mAnyWebViewInstalled));
+
+            try {
+                PackageInfo preferredWebViewPackage = findPreferredWebViewPackage();
+                pw.println(String.format(
+                        "  Preferred WebView package (name, version): (%s, %s)",
+                        preferredWebViewPackage.packageName,
+                        preferredWebViewPackage.versionName));
+            } catch (WebViewPackageMissingException e) {
+                pw.println(String.format("  Preferred WebView package: none"));
+            }
+
+            dumpAllPackageInformationLocked(pw);
+        }
+    }
+
+    private void dumpAllPackageInformationLocked(PrintWriter pw) {
+        WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
+        pw.println("  WebView packages:");
+        for (WebViewProviderInfo provider : allProviders) {
+            List<UserPackage> userPackages =
+                    mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider);
+            PackageInfo systemUserPackageInfo =
+                    userPackages.get(UserHandle.USER_SYSTEM).getPackageInfo();
+            if (systemUserPackageInfo == null) {
+                pw.println(String.format("    %s is NOT installed.", provider.packageName));
+                continue;
+            }
+
+            int validity = validityResult(provider, systemUserPackageInfo);
+            String packageDetails = String.format(
+                    "versionName: %s, versionCode: %d, targetSdkVersion: %d",
+                    systemUserPackageInfo.versionName,
+                    systemUserPackageInfo.getLongVersionCode(),
+                    systemUserPackageInfo.applicationInfo.targetSdkVersion);
+            if (validity == VALIDITY_OK) {
+                boolean installedForAllUsers = isInstalledAndEnabledForAllUsers(
+                        mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider));
+                pw.println(String.format(
+                        "    Valid package %s (%s) is %s installed/enabled for all users",
+                        systemUserPackageInfo.packageName,
+                        packageDetails,
+                        installedForAllUsers ? "" : "NOT"));
+            } else {
+                pw.println(String.format("    Invalid package %s (%s), reason: %s",
+                        systemUserPackageInfo.packageName,
+                        packageDetails,
+                        getInvalidityReason(validity)));
+            }
+        }
+    }
+
+    private static String getInvalidityReason(int invalidityReason) {
+        switch (invalidityReason) {
+            case VALIDITY_INCORRECT_SDK_VERSION:
+                return "SDK version too low";
+            case VALIDITY_INCORRECT_VERSION_CODE:
+                return "Version code too low";
+            case VALIDITY_INCORRECT_SIGNATURE:
+                return "Incorrect signature";
+            case VALIDITY_NO_LIBRARY_FLAG:
+                return "No WebView-library manifest flag";
+            default:
+                return "Unexcepted validity-reason";
+        }
     }
 }
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdater.java b/services/core/java/com/android/server/webkit/WebViewUpdater.java
deleted file mode 100644
index 3b58af2..0000000
--- a/services/core/java/com/android/server/webkit/WebViewUpdater.java
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.server.webkit;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.Signature;
-import android.os.UserHandle;
-import android.util.Slog;
-import android.webkit.UserPackage;
-import android.webkit.WebViewFactory;
-import android.webkit.WebViewProviderInfo;
-import android.webkit.WebViewProviderResponse;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Class that decides what WebView implementation to use and prepares that implementation for
- * use.
- */
-class WebViewUpdater {
-    private static final String TAG = WebViewUpdater.class.getSimpleName();
-
-    private static class WebViewPackageMissingException extends Exception {
-        public WebViewPackageMissingException(String message) { super(message); }
-        public WebViewPackageMissingException(Exception e) { super(e); }
-    }
-
-    private static final int WAIT_TIMEOUT_MS = 1000; // KEY_DISPATCHING_TIMEOUT is 5000.
-
-    private final static int VALIDITY_OK = 0;
-    private final static int VALIDITY_INCORRECT_SDK_VERSION = 1;
-    private final static int VALIDITY_INCORRECT_VERSION_CODE = 2;
-    private final static int VALIDITY_INCORRECT_SIGNATURE = 3;
-    private final static int VALIDITY_NO_LIBRARY_FLAG = 4;
-
-    private Context mContext;
-    private SystemInterface mSystemInterface;
-    private long mMinimumVersionCode = -1;
-
-    // Keeps track of the number of running relro creations
-    private int mNumRelroCreationsStarted = 0;
-    private int mNumRelroCreationsFinished = 0;
-    // Implies that we need to rerun relro creation because we are using an out-of-date package
-    private boolean mWebViewPackageDirty = false;
-    private boolean mAnyWebViewInstalled = false;
-
-    private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
-
-    // The WebView package currently in use (or the one we are preparing).
-    private PackageInfo mCurrentWebViewPackage = null;
-
-    private final Object mLock = new Object();
-
-    WebViewUpdater(Context context, SystemInterface systemInterface) {
-        mContext = context;
-        mSystemInterface = systemInterface;
-    }
-
-    void packageStateChanged(String packageName, int changedState) {
-        for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
-            String webviewPackage = provider.packageName;
-
-            if (webviewPackage.equals(packageName)) {
-                boolean updateWebView = false;
-                boolean removedOrChangedOldPackage = false;
-                String oldProviderName = null;
-                PackageInfo newPackage = null;
-                synchronized(mLock) {
-                    try {
-                        newPackage = findPreferredWebViewPackage();
-                        if (mCurrentWebViewPackage != null) {
-                            oldProviderName = mCurrentWebViewPackage.packageName;
-                        }
-                        // Only trigger update actions if the updated package is the one
-                        // that will be used, or the one that was in use before the
-                        // update, or if we haven't seen a valid WebView package before.
-                        updateWebView =
-                            provider.packageName.equals(newPackage.packageName)
-                            || provider.packageName.equals(oldProviderName)
-                            || mCurrentWebViewPackage == null;
-                        // We removed the old package if we received an intent to remove
-                        // or replace the old package.
-                        removedOrChangedOldPackage =
-                            provider.packageName.equals(oldProviderName);
-                        if (updateWebView) {
-                            onWebViewProviderChanged(newPackage);
-                        }
-                    } catch (WebViewPackageMissingException e) {
-                        mCurrentWebViewPackage = null;
-                        Slog.e(TAG, "Could not find valid WebView package to create " +
-                                "relro with " + e);
-                    }
-                }
-                if(updateWebView && !removedOrChangedOldPackage
-                        && oldProviderName != null) {
-                    // If the provider change is the result of adding or replacing a
-                    // package that was not the previous provider then we must kill
-                    // packages dependent on the old package ourselves. The framework
-                    // only kills dependents of packages that are being removed.
-                    mSystemInterface.killPackageDependents(oldProviderName);
-                }
-                return;
-            }
-        }
-    }
-
-    void prepareWebViewInSystemServer() {
-        try {
-            synchronized(mLock) {
-                mCurrentWebViewPackage = findPreferredWebViewPackage();
-                String userSetting = mSystemInterface.getUserChosenWebViewProvider(mContext);
-                if (userSetting != null
-                        && !userSetting.equals(mCurrentWebViewPackage.packageName)) {
-                    // Don't persist the user-chosen setting across boots if the package being
-                    // chosen is not used (could be disabled or uninstalled) so that the user won't
-                    // be surprised by the device switching to using a certain webview package,
-                    // that was uninstalled/disabled a long time ago, if it is installed/enabled
-                    // again.
-                    mSystemInterface.updateUserSetting(mContext,
-                            mCurrentWebViewPackage.packageName);
-                }
-                onWebViewProviderChanged(mCurrentWebViewPackage);
-            }
-        } catch (Throwable t) {
-            // Log and discard errors at this stage as we must not crash the system server.
-            Slog.e(TAG, "error preparing webview provider from system server", t);
-        }
-    }
-
-    /**
-     * Change WebView provider and provider setting and kill packages using the old provider.
-     * Return the new provider (in case we are in the middle of creating relro files, or
-     * replacing that provider it will not be in use directly, but will be used when the relros
-     * or the replacement are done).
-     */
-    String changeProviderAndSetting(String newProviderName) {
-        PackageInfo newPackage = updateCurrentWebViewPackage(newProviderName);
-        if (newPackage == null) return "";
-        return newPackage.packageName;
-    }
-
-    /**
-     * Update the current WebView package.
-     * @param newProviderName the package to switch to, null if no package has been explicitly
-     * chosen.
-     */
-    PackageInfo updateCurrentWebViewPackage(String newProviderName) {
-        PackageInfo oldPackage = null;
-        PackageInfo newPackage = null;
-        boolean providerChanged = false;
-        synchronized(mLock) {
-            oldPackage = mCurrentWebViewPackage;
-
-            if (newProviderName != null) {
-                mSystemInterface.updateUserSetting(mContext, newProviderName);
-            }
-
-            try {
-                newPackage = findPreferredWebViewPackage();
-                providerChanged = (oldPackage == null)
-                        || !newPackage.packageName.equals(oldPackage.packageName);
-            } catch (WebViewPackageMissingException e) {
-                // If updated the Setting but don't have an installed WebView package, the
-                // Setting will be used when a package is available.
-                mCurrentWebViewPackage = null;
-                Slog.e(TAG, "Couldn't find WebView package to use " + e);
-                return null;
-            }
-            // Perform the provider change if we chose a new provider
-            if (providerChanged) {
-                onWebViewProviderChanged(newPackage);
-            }
-        }
-        // Kill apps using the old provider only if we changed provider
-        if (providerChanged && oldPackage != null) {
-            mSystemInterface.killPackageDependents(oldPackage.packageName);
-        }
-        // Return the new provider, this is not necessarily the one we were asked to switch to,
-        // but the persistent setting will now be pointing to the provider we were asked to
-        // switch to anyway.
-        return newPackage;
-    }
-
-    /**
-     * This is called when we change WebView provider, either when the current provider is
-     * updated or a new provider is chosen / takes precedence.
-     */
-    private void onWebViewProviderChanged(PackageInfo newPackage) {
-        synchronized(mLock) {
-            mAnyWebViewInstalled = true;
-            if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
-                mCurrentWebViewPackage = newPackage;
-
-                // The relro creations might 'finish' (not start at all) before
-                // WebViewFactory.onWebViewProviderChanged which means we might not know the
-                // number of started creations before they finish.
-                mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
-                mNumRelroCreationsFinished = 0;
-                mNumRelroCreationsStarted =
-                    mSystemInterface.onWebViewProviderChanged(newPackage);
-                // If the relro creations finish before we know the number of started creations
-                // we will have to do any cleanup/notifying here.
-                checkIfRelrosDoneLocked();
-            } else {
-                mWebViewPackageDirty = true;
-            }
-        }
-    }
-
-    /**
-     * Fetch only the currently valid WebView packages.
-     **/
-    WebViewProviderInfo[] getValidWebViewPackages() {
-        ProviderAndPackageInfo[] providersAndPackageInfos = getValidWebViewPackagesAndInfos();
-        WebViewProviderInfo[] providers =
-            new WebViewProviderInfo[providersAndPackageInfos.length];
-        for(int n = 0; n < providersAndPackageInfos.length; n++) {
-            providers[n] = providersAndPackageInfos[n].provider;
-        }
-        return providers;
-    }
-
-    private static class ProviderAndPackageInfo {
-        public final WebViewProviderInfo provider;
-        public final PackageInfo packageInfo;
-
-        public ProviderAndPackageInfo(WebViewProviderInfo provider, PackageInfo packageInfo) {
-            this.provider = provider;
-            this.packageInfo = packageInfo;
-        }
-    }
-
-    private ProviderAndPackageInfo[] getValidWebViewPackagesAndInfos() {
-        WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
-        List<ProviderAndPackageInfo> providers = new ArrayList<>();
-        for(int n = 0; n < allProviders.length; n++) {
-            try {
-                PackageInfo packageInfo =
-                    mSystemInterface.getPackageInfoForProvider(allProviders[n]);
-                if (isValidProvider(allProviders[n], packageInfo)) {
-                    providers.add(new ProviderAndPackageInfo(allProviders[n], packageInfo));
-                }
-            } catch (NameNotFoundException e) {
-                // Don't add non-existent packages
-            }
-        }
-        return providers.toArray(new ProviderAndPackageInfo[providers.size()]);
-    }
-
-    /**
-     * Returns either the package info of the WebView provider determined in the following way:
-     * If the user has chosen a provider then use that if it is valid,
-     * otherwise use the first package in the webview priority list that is valid.
-     *
-     */
-    private PackageInfo findPreferredWebViewPackage() throws WebViewPackageMissingException {
-        ProviderAndPackageInfo[] providers = getValidWebViewPackagesAndInfos();
-
-        String userChosenProvider = mSystemInterface.getUserChosenWebViewProvider(mContext);
-
-        // If the user has chosen provider, use that (if it's installed and enabled for all
-        // users).
-        for (ProviderAndPackageInfo providerAndPackage : providers) {
-            if (providerAndPackage.provider.packageName.equals(userChosenProvider)) {
-                // userPackages can contain null objects.
-                List<UserPackage> userPackages =
-                        mSystemInterface.getPackageInfoForProviderAllUsers(mContext,
-                                providerAndPackage.provider);
-                if (isInstalledAndEnabledForAllUsers(userPackages)) {
-                    return providerAndPackage.packageInfo;
-                }
-            }
-        }
-
-        // User did not choose, or the choice failed; use the most stable provider that is
-        // installed and enabled for all users, and available by default (not through
-        // user choice).
-        for (ProviderAndPackageInfo providerAndPackage : providers) {
-            if (providerAndPackage.provider.availableByDefault) {
-                // userPackages can contain null objects.
-                List<UserPackage> userPackages =
-                        mSystemInterface.getPackageInfoForProviderAllUsers(mContext,
-                                providerAndPackage.provider);
-                if (isInstalledAndEnabledForAllUsers(userPackages)) {
-                    return providerAndPackage.packageInfo;
-                }
-            }
-        }
-
-        // This should never happen during normal operation (only with modified system images).
-        mAnyWebViewInstalled = false;
-        throw new WebViewPackageMissingException("Could not find a loadable WebView package");
-    }
-
-    /**
-     * Return true iff {@param packageInfos} point to only installed and enabled packages.
-     * The given packages {@param packageInfos} should all be pointing to the same package, but each
-     * PackageInfo representing a different user's package.
-     */
-    static boolean isInstalledAndEnabledForAllUsers(
-            List<UserPackage> userPackages) {
-        for (UserPackage userPackage : userPackages) {
-            if (!userPackage.isInstalledPackage() || !userPackage.isEnabledPackage()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    void notifyRelroCreationCompleted() {
-        synchronized (mLock) {
-            mNumRelroCreationsFinished++;
-            checkIfRelrosDoneLocked();
-        }
-    }
-
-    WebViewProviderResponse waitForAndGetProvider() {
-        PackageInfo webViewPackage = null;
-        final long NS_PER_MS = 1000000;
-        final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
-        boolean webViewReady = false;
-        int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
-        synchronized (mLock) {
-            webViewReady = webViewIsReadyLocked();
-            while (!webViewReady) {
-                final long timeNowMs = System.nanoTime() / NS_PER_MS;
-                if (timeNowMs >= timeoutTimeMs) break;
-                try {
-                    mLock.wait(timeoutTimeMs - timeNowMs);
-                } catch (InterruptedException e) {}
-                webViewReady = webViewIsReadyLocked();
-            }
-            // Make sure we return the provider that was used to create the relro file
-            webViewPackage = mCurrentWebViewPackage;
-            if (webViewReady) {
-            } else if (!mAnyWebViewInstalled) {
-                webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
-            } else {
-                // Either the current relro creation  isn't done yet, or the new relro creatioin
-                // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
-                webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
-                Slog.e(TAG, "Timed out waiting for relro creation, relros started "
-                        + mNumRelroCreationsStarted
-                        + " relros finished " + mNumRelroCreationsFinished
-                        + " package dirty? " + mWebViewPackageDirty);
-            }
-        }
-        if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
-        return new WebViewProviderResponse(webViewPackage, webViewStatus);
-    }
-
-    PackageInfo getCurrentWebViewPackage() {
-        synchronized(mLock) {
-            return mCurrentWebViewPackage;
-        }
-    }
-
-    /**
-     * Returns whether WebView is ready and is not going to go through its preparation phase
-     * again directly.
-     */
-    private boolean webViewIsReadyLocked() {
-        return !mWebViewPackageDirty
-            && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
-            // The current package might be replaced though we haven't received an intent
-            // declaring this yet, the following flag makes anyone loading WebView to wait in
-            // this case.
-            && mAnyWebViewInstalled;
-    }
-
-    private void checkIfRelrosDoneLocked() {
-        if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
-            if (mWebViewPackageDirty) {
-                mWebViewPackageDirty = false;
-                // If we have changed provider since we started the relro creation we need to
-                // redo the whole process using the new package instead.
-                try {
-                    PackageInfo newPackage = findPreferredWebViewPackage();
-                    onWebViewProviderChanged(newPackage);
-                } catch (WebViewPackageMissingException e) {
-                    mCurrentWebViewPackage = null;
-                    // If we can't find any valid WebView package we are now in a state where
-                    // mAnyWebViewInstalled is false, so loading WebView will be blocked and we
-                    // should simply wait until we receive an intent declaring a new package was
-                    // installed.
-                }
-            } else {
-                mLock.notifyAll();
-            }
-        }
-    }
-
-    /**
-     * Returns whether this provider is valid for use as a WebView provider.
-     */
-    boolean isValidProvider(WebViewProviderInfo configInfo, PackageInfo packageInfo) {
-        return VALIDITY_OK == validityResult(configInfo, packageInfo);
-    }
-
-    private int validityResult(WebViewProviderInfo configInfo, PackageInfo packageInfo) {
-        // Ensure the provider targets this framework release (or a later one).
-        if (!UserPackage.hasCorrectTargetSdkVersion(packageInfo)) {
-            return VALIDITY_INCORRECT_SDK_VERSION;
-        }
-        if (!versionCodeGE(packageInfo.getLongVersionCode(), getMinimumVersionCode())
-                && !mSystemInterface.systemIsDebuggable()) {
-            // Webview providers may be downgraded arbitrarily low, prevent that by enforcing
-            // minimum version code. This check is only enforced for user builds.
-            return VALIDITY_INCORRECT_VERSION_CODE;
-        }
-        if (!providerHasValidSignature(configInfo, packageInfo, mSystemInterface)) {
-            return VALIDITY_INCORRECT_SIGNATURE;
-        }
-        if (WebViewFactory.getWebViewLibrary(packageInfo.applicationInfo) == null) {
-            return VALIDITY_NO_LIBRARY_FLAG;
-        }
-        return VALIDITY_OK;
-    }
-
-    /**
-     * Both versionCodes should be from a WebView provider package implemented by Chromium.
-     * VersionCodes from other kinds of packages won't make any sense in this method.
-     *
-     * An introduction to Chromium versionCode scheme:
-     * "BBBBPPPAX"
-     * BBBB: 4 digit branch number. It monotonically increases over time.
-     * PPP: patch number in the branch. It is padded with zeroes to the left. These three digits
-     * may change their meaning in the future.
-     * A: architecture digit.
-     * X: A digit to differentiate APKs for other reasons.
-     *
-     * This method takes the "BBBB" of versionCodes and compare them.
-     *
-     * @return true if versionCode1 is higher than or equal to versionCode2.
-     */
-    private static boolean versionCodeGE(long versionCode1, long versionCode2) {
-        long v1 = versionCode1 / 100000;
-        long v2 = versionCode2 / 100000;
-
-        return v1 >= v2;
-    }
-
-    /**
-     * Gets the minimum version code allowed for a valid provider. It is the minimum versionCode
-     * of all available-by-default WebView provider packages. If there is no such WebView provider
-     * package on the system, then return -1, which means all positive versionCode WebView packages
-     * are accepted.
-     *
-     * Note that this is a private method in WebViewUpdater that handles a variable
-     * (mMinimumVersionCode) which is shared between threads. Furthermore, this method does not
-     * hold mLock meaning that we must take extra care to ensure this method is thread-safe.
-     */
-    private long getMinimumVersionCode() {
-        if (mMinimumVersionCode > 0) {
-            return mMinimumVersionCode;
-        }
-
-        long minimumVersionCode = -1;
-        for (WebViewProviderInfo provider : mSystemInterface.getWebViewPackages()) {
-            if (provider.availableByDefault) {
-                try {
-                    long versionCode =
-                        mSystemInterface.getFactoryPackageVersion(provider.packageName);
-                    if (minimumVersionCode < 0 || versionCode < minimumVersionCode) {
-                        minimumVersionCode = versionCode;
-                    }
-                } catch (NameNotFoundException e) {
-                    // Safe to ignore.
-                }
-            }
-        }
-
-        mMinimumVersionCode = minimumVersionCode;
-        return mMinimumVersionCode;
-    }
-
-    private static boolean providerHasValidSignature(WebViewProviderInfo provider,
-            PackageInfo packageInfo, SystemInterface systemInterface) {
-        // Skip checking signatures on debuggable builds, for development purposes.
-        if (systemInterface.systemIsDebuggable()) return true;
-
-        // Allow system apps to be valid providers regardless of signature.
-        if (packageInfo.applicationInfo.isSystemApp()) return true;
-
-        // We don't support packages with multiple signatures.
-        if (packageInfo.signatures.length != 1) return false;
-
-        // If any of the declared signatures match the package signature, it's valid.
-        for (Signature signature : provider.signatures) {
-            if (signature.equals(packageInfo.signatures[0])) return true;
-        }
-
-        return false;
-    }
-
-    void dumpState(PrintWriter pw) {
-        synchronized (mLock) {
-            if (mCurrentWebViewPackage == null) {
-                pw.println("  Current WebView package is null");
-            } else {
-                pw.println(String.format("  Current WebView package (name, version): (%s, %s)",
-                        mCurrentWebViewPackage.packageName,
-                        mCurrentWebViewPackage.versionName));
-            }
-            pw.println(String.format("  Minimum targetSdkVersion: %d",
-                    UserPackage.MINIMUM_SUPPORTED_SDK));
-            pw.println(String.format("  Minimum WebView version code: %d",
-                  mMinimumVersionCode));
-            pw.println(String.format("  Number of relros started: %d",
-                    mNumRelroCreationsStarted));
-            pw.println(String.format("  Number of relros finished: %d",
-                        mNumRelroCreationsFinished));
-            pw.println(String.format("  WebView package dirty: %b", mWebViewPackageDirty));
-            pw.println(String.format("  Any WebView package installed: %b",
-                    mAnyWebViewInstalled));
-
-            try {
-                PackageInfo preferredWebViewPackage = findPreferredWebViewPackage();
-                pw.println(String.format(
-                        "  Preferred WebView package (name, version): (%s, %s)",
-                        preferredWebViewPackage.packageName,
-                        preferredWebViewPackage.versionName));
-            } catch (WebViewPackageMissingException e) {
-                pw.println(String.format("  Preferred WebView package: none"));
-            }
-
-            dumpAllPackageInformationLocked(pw);
-        }
-    }
-
-    private void dumpAllPackageInformationLocked(PrintWriter pw) {
-        WebViewProviderInfo[] allProviders = mSystemInterface.getWebViewPackages();
-        pw.println("  WebView packages:");
-        for (WebViewProviderInfo provider : allProviders) {
-            List<UserPackage> userPackages =
-                    mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider);
-            PackageInfo systemUserPackageInfo =
-                    userPackages.get(UserHandle.USER_SYSTEM).getPackageInfo();
-            if (systemUserPackageInfo == null) {
-                pw.println(String.format("    %s is NOT installed.", provider.packageName));
-                continue;
-            }
-
-            int validity = validityResult(provider, systemUserPackageInfo);
-            String packageDetails = String.format(
-                    "versionName: %s, versionCode: %d, targetSdkVersion: %d",
-                    systemUserPackageInfo.versionName,
-                    systemUserPackageInfo.getLongVersionCode(),
-                    systemUserPackageInfo.applicationInfo.targetSdkVersion);
-            if (validity == VALIDITY_OK) {
-                boolean installedForAllUsers = isInstalledAndEnabledForAllUsers(
-                        mSystemInterface.getPackageInfoForProviderAllUsers(mContext, provider));
-                pw.println(String.format(
-                        "    Valid package %s (%s) is %s installed/enabled for all users",
-                        systemUserPackageInfo.packageName,
-                        packageDetails,
-                        installedForAllUsers ? "" : "NOT"));
-            } else {
-                pw.println(String.format("    Invalid package %s (%s), reason: %s",
-                        systemUserPackageInfo.packageName,
-                        packageDetails,
-                        getInvalidityReason(validity)));
-            }
-        }
-    }
-
-    private static String getInvalidityReason(int invalidityReason) {
-        switch (invalidityReason) {
-            case VALIDITY_INCORRECT_SDK_VERSION:
-                return "SDK version too low";
-            case VALIDITY_INCORRECT_VERSION_CODE:
-                return "Version code too low";
-            case VALIDITY_INCORRECT_SIGNATURE:
-                return "Incorrect signature";
-            case VALIDITY_NO_LIBRARY_FLAG:
-                return "No WebView-library manifest flag";
-            default:
-                return "Unexcepted validity-reason";
-        }
-    }
-
-}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 4c2d0d0..9e21167 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -489,18 +489,18 @@
         public void onAppWindowTransitionLocked(int displayId, int transition) {
             if (DEBUG_WINDOW_TRANSITIONS) {
                 Slog.i(LOG_TAG, "Window transition: "
-                        + AppTransition.appTransitionToString(transition)
+                        + AppTransition.appTransitionOldToString(transition)
                         + " displayId: " + displayId);
             }
             final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
             if (magnifying) {
                 switch (transition) {
-                    case WindowManager.TRANSIT_ACTIVITY_OPEN:
-                    case WindowManager.TRANSIT_TASK_OPEN:
-                    case WindowManager.TRANSIT_TASK_TO_FRONT:
-                    case WindowManager.TRANSIT_WALLPAPER_OPEN:
-                    case WindowManager.TRANSIT_WALLPAPER_CLOSE:
-                    case WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN: {
+                    case WindowManager.TRANSIT_OLD_ACTIVITY_OPEN:
+                    case WindowManager.TRANSIT_OLD_TASK_OPEN:
+                    case WindowManager.TRANSIT_OLD_TASK_TO_FRONT:
+                    case WindowManager.TRANSIT_OLD_WALLPAPER_OPEN:
+                    case WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE:
+                    case WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN: {
                         mHandler.sendEmptyMessage(MyHandler.MESSAGE_NOTIFY_USER_CONTEXT_CHANGED);
                     }
                 }
@@ -510,7 +510,7 @@
         public void onWindowTransitionLocked(WindowState windowState, int transition) {
             if (DEBUG_WINDOW_TRANSITIONS) {
                 Slog.i(LOG_TAG, "Window transition: "
-                        + AppTransition.appTransitionToString(transition)
+                        + AppTransition.appTransitionOldToString(transition)
                         + " displayId: " + windowState.getDisplayId());
             }
             final boolean magnifying = mMagnifedViewport.isMagnifyingLocked();
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4a7fc7f0..d6a1f4a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -102,10 +102,12 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_OLD_UNSET;
+import static android.view.WindowManager.TransitionOldType;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
@@ -179,6 +181,7 @@
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
 import static com.android.server.wm.Task.ActivityState.DESTROYED;
 import static com.android.server.wm.Task.ActivityState.DESTROYING;
@@ -1313,7 +1316,7 @@
         if (prevDc.mOpeningApps.remove(this)) {
             // Transfer opening transition to new display.
             mDisplayContent.mOpeningApps.add(this);
-            mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
+            mDisplayContent.transferAppTransitionFrom(prevDc);
             mDisplayContent.executeAppTransition();
         }
 
@@ -2574,7 +2577,7 @@
 
             final boolean endTask = task.getActivityBelow(this) == null
                     && !task.isClearingToReuseTask();
-            final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
+            final int transit = endTask ? TRANSIT_OLD_TASK_CLOSE : TRANSIT_OLD_ACTIVITY_CLOSE;
             if (isState(RESUMED)) {
                 if (endTask) {
                     mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
@@ -2587,11 +2590,16 @@
                 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
                     Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
                 }
-                mDisplayContent.prepareAppTransition(transit, false);
+                mDisplayContent.prepareAppTransitionOld(transit, false);
+                mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
 
                 // When finishing the activity preemptively take the snapshot before the app window
                 // is marked as hidden and any configuration changes take place
-                if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
+                // Note that RecentsAnimation will handle task snapshot while switching apps with
+                // the best capture timing (e.g. IME window capture),
+                // No need additional task capture while task is controlled by RecentsAnimation.
+                if (mAtmService.mWindowManager.mTaskSnapshotController != null
+                        && !task.isAnimatingByRecents()) {
                     final ArraySet<Task> tasks = Sets.newArraySet(task);
                     mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
                     mAtmService.mWindowManager.mTaskSnapshotController
@@ -2658,15 +2666,16 @@
         }
     }
 
-    private void prepareActivityHideTransitionAnimationIfOvarlay(int transit) {
+    private void prepareActivityHideTransitionAnimationIfOvarlay(@TransitionOldType int transit) {
         if (mTaskOverlay) {
             prepareActivityHideTransitionAnimation(transit);
         }
     }
 
-    private void prepareActivityHideTransitionAnimation(int transit) {
+    private void prepareActivityHideTransitionAnimation(@TransitionOldType int transit) {
         final DisplayContent dc = mDisplayContent;
-        dc.prepareAppTransition(transit, false);
+        dc.prepareAppTransitionOld(transit, false);
+        dc.prepareAppTransition(TRANSIT_CLOSE);
         setVisibility(false);
         dc.executeAppTransition();
     }
@@ -3583,7 +3592,7 @@
     }
 
     /**
-     * @return {@code true} if the activity windowing mode is not
+     * @return {@code true} if the activity windowing mode is not in
      *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
      *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
      *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
@@ -4217,7 +4226,10 @@
         // Note that we ignore display frozen since we want the opening / closing transition type
         // can be updated correctly even display frozen, and it's safe since in applyAnimation will
         // still check DC#okToAnimate again if the transition animation is fine to apply.
-        if (okToAnimate(true /* ignoreFrozen */) && appTransition.isTransitionSet()) {
+        // TODO(new-app-transition): Rewrite this logic using WM Shell.
+        final boolean recentsAnimating = isAnimating(PARENTS, ANIMATION_TYPE_RECENTS);
+        if (okToAnimate(true /* ignoreFrozen */) && (appTransition.isTransitionSet()
+                || (recentsAnimating && !isActivityTypeHome()))) {
             if (visible) {
                 displayContent.mOpeningApps.add(this);
                 mEnteringAnimation = true;
@@ -4225,7 +4237,7 @@
                 displayContent.mClosingApps.add(this);
                 mEnteringAnimation = false;
             }
-            if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
+            if (appTransition.getAppTransitionOld() == TRANSIT_OLD_TASK_OPEN_BEHIND) {
                 // We're launchingBehind, add the launching activity to mOpeningApps.
                 final WindowState win = getDisplayContent().findFocusedWindow();
                 if (win != null) {
@@ -6086,7 +6098,8 @@
 
     @Override
     void prepareSurfaces() {
-        final boolean show = isVisible() || isAnimating(PARENTS, ANIMATION_TYPE_APP_TRANSITION);
+        final boolean show = isVisible() || isAnimating(PARENTS,
+                ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS);
 
         if (mSurfaceControl != null) {
             if (show && !mLastSurfaceShowing) {
@@ -6193,7 +6206,7 @@
         super.onAnimationFinished(type, anim);
 
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished");
-        mTransit = TRANSIT_UNSET;
+        mTransit = TRANSIT_OLD_UNSET;
         mTransitFlags = 0;
         mNeedsAnimationBoundsLayer = false;
 
@@ -6402,6 +6415,10 @@
         mLastReportedConfiguration.setConfiguration(global, override);
     }
 
+    boolean hasCompatDisplayInsets() {
+        return mCompatDisplayInsets != null;
+    }
+
     /**
      * @return {@code true} if this activity is in size compatibility mode that uses the different
      *         density than its parent or its bounds don't fit in parent naturally.
@@ -6540,7 +6557,9 @@
         mSizeCompatScale = 1f;
         mSizeCompatBounds = null;
         mCompatDisplayInsets = null;
-        onRequestedOverrideConfigurationChanged(EMPTY);
+
+        // Recompute from Task because letterbox can also happen on Task level.
+        task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
     }
 
     @Override
@@ -6649,9 +6668,10 @@
                 ? requestedOrientation
                 : newParentConfiguration.orientation;
         int rotation = newParentConfiguration.windowConfiguration.getRotation();
-        final boolean canChangeOrientation = handlesOrientationChangeFromDescendant();
-        if (canChangeOrientation && !mCompatDisplayInsets.mIsFloating) {
-            // Use parent rotation because the original display can rotate by requested orientation.
+        final boolean isFixedToUserRotation = mDisplayContent == null
+                || mDisplayContent.getDisplayRotation().isFixedToUserRotation();
+        if (!isFixedToUserRotation && !mCompatDisplayInsets.mIsFloating) {
+            // Use parent rotation because the original display can be rotated.
             resolvedConfig.windowConfiguration.setRotation(rotation);
         } else {
             final int overrideRotation = resolvedConfig.windowConfiguration.getRotation();
@@ -6667,7 +6687,7 @@
         final Rect containingAppBounds = new Rect();
         final Rect containingBounds = mTmpBounds;
         mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
-                orientation, orientationRequested, canChangeOrientation);
+                orientation, orientationRequested, isFixedToUserRotation);
         resolvedBounds.set(containingBounds);
         // The size of floating task is fixed (only swap), so the aspect ratio is already correct.
         if (!mCompatDisplayInsets.mIsFloating) {
@@ -7526,7 +7546,7 @@
     /**
      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
      * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
-     * should be visible depending on Keyguard and window state.
+     * should be visible depending on Keyguard state.
      *
      * @return true if the screen can be turned on, false otherwise.
      */
@@ -7535,7 +7555,7 @@
             return false;
         }
         final Task stack = getRootTask();
-        return stack != null && !stack.inMultiWindowMode()
+        return stack != null
                 && mStackSupervisor.getKeyguardController().checkKeyguardVisibility(this);
     }
 
@@ -7736,7 +7756,7 @@
         final Rect[] mStableInsets = new Rect[4];
 
         /** Constructs the environment to simulate the bounds behavior of the given container. */
-        CompatDisplayInsets(DisplayContent display, WindowContainer container) {
+        CompatDisplayInsets(DisplayContent display, ActivityRecord container) {
             mIsFloating = container.getWindowConfiguration().tasksAreFloating();
             if (mIsFloating) {
                 final Rect containerBounds = container.getWindowConfiguration().getBounds();
@@ -7752,16 +7772,23 @@
                 return;
             }
 
-            // If the activity is not floating, assume it fills the display.
-            mWidth = display.mBaseDisplayWidth;
-            mHeight = display.mBaseDisplayHeight;
+            if (container.getTask().isTaskLetterboxed()) {
+                // For apps in Task letterbox, it should fill the task bounds.
+                final Rect taskBounds = container.getTask().getBounds();
+                mWidth = taskBounds.width();
+                mHeight = taskBounds.height();
+            } else {
+                // If the activity is not floating nor letterboxed, assume it fills the display.
+                mWidth = display.mBaseDisplayWidth;
+                mHeight = display.mBaseDisplayHeight;
+            }
             final DisplayPolicy policy = display.getDisplayPolicy();
             for (int rotation = 0; rotation < 4; rotation++) {
                 mNonDecorInsets[rotation] = new Rect();
                 mStableInsets[rotation] = new Rect();
                 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
-                final int dw = rotated ? mHeight : mWidth;
-                final int dh = rotated ? mWidth : mHeight;
+                final int dw = rotated ? display.mBaseDisplayHeight : display.mBaseDisplayWidth;
+                final int dh = rotated ? display.mBaseDisplayWidth : display.mBaseDisplayHeight;
                 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
                         .getDisplayCutout();
                 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
@@ -7787,7 +7814,7 @@
 
         /** Gets the horizontal centered container bounds for size compatibility mode. */
         void getContainerBounds(Rect outAppBounds, Rect outBounds, int rotation, int orientation,
-                boolean orientationRequested, boolean canChangeOrientation) {
+                boolean orientationRequested, boolean isFixedToUserRotation) {
             getFrameByOrientation(outBounds, orientation);
             if (mIsFloating) {
                 outAppBounds.set(outBounds);
@@ -7800,7 +7827,7 @@
             final boolean isOrientationMismatched =
                     ((outBounds.width() > outBounds.height()) != (dW > dH));
 
-            if (isOrientationMismatched && !canChangeOrientation && orientationRequested) {
+            if (isOrientationMismatched && isFixedToUserRotation && orientationRequested) {
                 // The orientation is mismatched but the display cannot rotate. The bounds will fit
                 // to the short side of container.
                 if (orientation == ORIENTATION_LANDSCAPE) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index b4fea90..a8079cf 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2040,6 +2040,11 @@
         final ActivityRecord prevTopActivity = mTopResumedActivity;
         final Task topStack = mRootWindowContainer.getTopDisplayFocusedStack();
         if (topStack == null || topStack.mResumedActivity == prevTopActivity) {
+            if (mService.isSleepingLocked()) {
+                // There won't be a next resumed activity. The top process should still be updated
+                // according to the current top focused activity.
+                mService.updateTopApp(null /* topResumedActivity */);
+            }
             return;
         }
 
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 51f7d01..21b6f62 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -65,6 +65,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -5547,11 +5548,8 @@
     }
 
     void updateTopApp(ActivityRecord topResumedActivity) {
-        // If system is sleeping, use the given record (it should be null) because there won't be
-        // the next resumed activity. Otherwise the process of pausing activity will keep with top
-        // state even the activity has paused and stopped.
-        final ActivityRecord top = mSleeping || topResumedActivity != null ? topResumedActivity
-                // If there is no resumed activity, it will choose the pausing activity.
+        final ActivityRecord top = topResumedActivity != null ? topResumedActivity
+                // If there is no resumed activity, it will choose the pausing or focused activity.
                 : mRootWindowContainer.getTopResumedActivity();
         mTopApp = top != null ? top.app : null;
     }
@@ -6183,10 +6181,10 @@
                 if (dc == null) {
                     return;
                 }
-                final boolean wasTransitionSet =
-                        dc.mAppTransition.getAppTransition() != TRANSIT_NONE;
+                final boolean wasTransitionSet = dc.mAppTransition.isTransitionSet();
                 if (!wasTransitionSet) {
-                    dc.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
+                    dc.prepareAppTransitionOld(TRANSIT_OLD_NONE, false /* alwaysKeepCurrent */);
+                    dc.prepareAppTransition(TRANSIT_NONE);
                 }
                 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
 
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 26c701b..12c2c0e 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -17,31 +17,43 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_UNSET;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH;
+import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_UNSET;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_OPEN;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_RELAUNCH;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation;
 import static com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation;
@@ -104,6 +116,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.ArraySet;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.proto.ProtoOutputStream;
@@ -111,6 +124,7 @@
 import android.view.IAppTransitionAnimationSpecsFuture;
 import android.view.RemoteAnimationAdapter;
 import android.view.WindowManager.TransitionFlags;
+import android.view.WindowManager.TransitionOldType;
 import android.view.WindowManager.TransitionType;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -170,9 +184,10 @@
     private final WindowManagerService mService;
     private final DisplayContent mDisplayContent;
 
-    private @TransitionType int mNextAppTransition = TRANSIT_UNSET;
+    private @TransitionOldType int mNextAppTransitionOld = TRANSIT_OLD_UNSET;
     private @TransitionFlags int mNextAppTransitionFlags = 0;
-    private int mLastUsedAppTransition = TRANSIT_UNSET;
+    private final ArrayList<Integer> mNextAppTransitionRequests = new ArrayList<>();
+    private @TransitionOldType int mLastUsedAppTransition = TRANSIT_OLD_UNSET;
     private String mLastOpeningApp;
     private String mLastClosingApp;
     private String mLastChangingApp;
@@ -315,21 +330,36 @@
     }
 
     boolean isTransitionSet() {
-        return mNextAppTransition != TRANSIT_UNSET;
+        return mNextAppTransitionOld != TRANSIT_OLD_UNSET || !mNextAppTransitionRequests.isEmpty();
     }
 
-    boolean isTransitionEqual(@TransitionType int transit) {
-        return mNextAppTransition == transit;
+    // TODO(new-app-tranistion): Remove this after migrating to new app transition system.
+    boolean isTransitionOldEqual(@TransitionOldType int transit) {
+        return mNextAppTransitionOld == transit;
     }
 
-    @TransitionType int getAppTransition() {
-        return mNextAppTransition;
+    boolean isUnoccluding() {
+        return WindowManagerService.sUseNewAppTransit
+                ? mNextAppTransitionRequests.contains(TRANSIT_OLD_KEYGUARD_UNOCCLUDE)
+                : mNextAppTransitionOld == TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
+    }
+
+    @TransitionOldType
+    int getAppTransitionOld() {
+        return mNextAppTransitionOld;
      }
 
-    private void setAppTransition(int transit, int flags) {
-        mNextAppTransition = transit;
+    boolean transferFrom(AppTransition other) {
+        prepareAppTransitionOld(other.getAppTransitionOld(), true /* alwaysKeepCurrent */,
+                0 /* flags */, false /* forceOverride */);
+        mNextAppTransitionRequests.addAll(other.mNextAppTransitionRequests);
+        return prepare();
+    }
+
+    private void setAppTransitionOld(@TransitionOldType int transit, int flags) {
+        mNextAppTransitionOld = transit;
         mNextAppTransitionFlags |= flags;
-        setLastAppTransition(TRANSIT_UNSET, null, null, null);
+        setLastAppTransition(TRANSIT_OLD_UNSET, null, null, null);
         updateBooster();
         if (isTransitionSet()) {
             removeAppTransitionTimeoutCallbacks();
@@ -431,8 +461,9 @@
      *         layout pass needs to be done
      */
     int goodToGo(int transit, ActivityRecord topOpeningApp, ArraySet<ActivityRecord> openingApps) {
-        mNextAppTransition = TRANSIT_UNSET;
+        mNextAppTransitionOld = TRANSIT_OLD_UNSET;
         mNextAppTransitionFlags = 0;
+        mNextAppTransitionRequests.clear();
         setAppTransitionState(APP_STATE_RUNNING);
         final WindowContainer wc =
                 topOpeningApp != null ? topOpeningApp.getAnimatingContainer() : null;
@@ -463,7 +494,7 @@
     }
 
     void freeze() {
-        final int transit = mNextAppTransition;
+        final int transit = mNextAppTransitionOld;
         // The RemoteAnimationControl didn't register AppTransitionListener and
         // only initialized the finish and timeout callback when goodToGo().
         // So cancel the remote animation here to prevent the animation can't do
@@ -471,7 +502,7 @@
         if (mRemoteAnimationController != null) {
             mRemoteAnimationController.cancelAnimation("freeze");
         }
-        setAppTransition(TRANSIT_UNSET, 0 /* flags */);
+        setAppTransitionOld(TRANSIT_OLD_UNSET, 0 /* flags */);
         clear();
         setReady();
         notifyAppTransitionCancelledLocked(transit);
@@ -493,7 +524,7 @@
 
     private boolean needsBoosting() {
         final boolean recentsAnimRunning = mService.getRecentsAnimationController() != null;
-        return mNextAppTransition != TRANSIT_UNSET
+        return mNextAppTransitionOld != TRANSIT_OLD_UNSET
                 || mAppTransitionState == APP_STATE_READY
                 || mAppTransitionState == APP_STATE_RUNNING
                 || recentsAnimRunning;
@@ -645,11 +676,13 @@
         }
     }
 
-    private int updateToTranslucentAnimIfNeeded(int anim, int transit) {
-        if (transit == TRANSIT_TRANSLUCENT_ACTIVITY_OPEN && anim == R.anim.activity_open_enter) {
+    private int updateToTranslucentAnimIfNeeded(int anim, @TransitionOldType int transit) {
+        if (transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN
+                && anim == R.anim.activity_open_enter) {
             return R.anim.activity_translucent_open_enter;
         }
-        if (transit == TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE && anim == R.anim.activity_close_exit) {
+        if (transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE
+                && anim == R.anim.activity_close_exit) {
             return R.anim.activity_translucent_close_exit;
         }
         return anim;
@@ -752,8 +785,8 @@
             set.addAnimation(alpha);
             set.setDetachWallpaper(true);
             a = set;
-        } else  if (transit == TRANSIT_WALLPAPER_INTRA_OPEN ||
-                    transit == TRANSIT_WALLPAPER_INTRA_CLOSE) {
+        } else  if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN
+                || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE) {
             // If we are on top of the wallpaper, we need an animation that
             // correctly handles the wallpaper staying static behind all of
             // the animated elements.  To do this, will just have the existing
@@ -770,8 +803,8 @@
         // task transition duration.
         final long duration;
         switch (transit) {
-            case TRANSIT_ACTIVITY_OPEN:
-            case TRANSIT_ACTIVITY_CLOSE:
+            case TRANSIT_OLD_ACTIVITY_OPEN:
+            case TRANSIT_OLD_ACTIVITY_CLOSE:
                 duration = mConfigShortAnimTime;
                 break;
             default:
@@ -950,16 +983,16 @@
         } else {
             final long duration;
             switch (transit) {
-                case TRANSIT_ACTIVITY_OPEN:
-                case TRANSIT_ACTIVITY_CLOSE:
+                case TRANSIT_OLD_ACTIVITY_OPEN:
+                case TRANSIT_OLD_ACTIVITY_CLOSE:
                     duration = mConfigShortAnimTime;
                     break;
                 default:
                     duration = DEFAULT_APP_TRANSITION_DURATION;
                     break;
             }
-            if (transit == TRANSIT_WALLPAPER_INTRA_OPEN ||
-                    transit == TRANSIT_WALLPAPER_INTRA_CLOSE) {
+            if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN
+                    || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE) {
                 // If we are on top of the wallpaper, we need an animation that
                 // correctly handles the wallpaper staying static behind all of
                 // the animated elements.  To do this, will just have the existing
@@ -1002,8 +1035,8 @@
         // task transition duration.
         final int duration;
         switch (transit) {
-            case TRANSIT_ACTIVITY_OPEN:
-            case TRANSIT_ACTIVITY_CLOSE:
+            case TRANSIT_OLD_ACTIVITY_OPEN:
+            case TRANSIT_OLD_ACTIVITY_CLOSE:
                 duration = mConfigShortAnimTime;
                 break;
             default:
@@ -1306,7 +1339,7 @@
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
                 // Previous app window during the scale up
-                if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
+                if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) {
                     // Fade out the source activity if we are animating to a wallpaper
                     // activity.
                     a = new AlphaAnimation(1, 0);
@@ -1317,7 +1350,7 @@
             }
             case THUMBNAIL_TRANSITION_ENTER_SCALE_DOWN: {
                 // Target app window during the scale down
-                if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
+                if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) {
                     // Fade in the destination activity if we are animating from a wallpaper
                     // activity.
                     a = new AlphaAnimation(0, 1);
@@ -1452,7 +1485,7 @@
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_UP: {
                 // Exiting app while the thumbnail is scaling up should fade or stay in place
-                if (transit == TRANSIT_WALLPAPER_INTRA_OPEN) {
+                if (transit == TRANSIT_OLD_WALLPAPER_INTRA_OPEN) {
                     // Fade out while bringing up selected activity. This keeps the
                     // current activity from showing through a launching wallpaper
                     // activity.
@@ -1545,7 +1578,7 @@
                 && !mNextAppTransitionOverrideRequested
                 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE
                 && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL
-                && mNextAppTransition != TRANSIT_KEYGUARD_GOING_AWAY;
+                && mNextAppTransitionOld != TRANSIT_OLD_KEYGUARD_GOING_AWAY;
     }
 
     RemoteAnimationController getRemoteAnimationController() {
@@ -1585,35 +1618,35 @@
         Animation a;
         if (isKeyguardGoingAwayTransit(transit) && enter) {
             a = loadKeyguardExitAnimation(transit);
-        } else if (transit == TRANSIT_KEYGUARD_OCCLUDE) {
+        } else if (transit == TRANSIT_OLD_KEYGUARD_OCCLUDE) {
             a = null;
-        } else if (transit == TRANSIT_KEYGUARD_UNOCCLUDE && !enter) {
+        } else if (transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE && !enter) {
             a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit);
-        } else if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
+        } else if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) {
             a = null;
-        } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
-                || transit == TRANSIT_TASK_OPEN
-                || transit == TRANSIT_TASK_TO_FRONT)) {
+        } else if (isVoiceInteraction && (transit == TRANSIT_OLD_ACTIVITY_OPEN
+                || transit == TRANSIT_OLD_TASK_OPEN
+                || transit == TRANSIT_OLD_TASK_TO_FRONT)) {
             a = loadAnimationRes(lp, enter
                     ? com.android.internal.R.anim.voice_activity_open_enter
                     : com.android.internal.R.anim.voice_activity_open_exit);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a,
-                    appTransitionToString(transit), enter, Debug.getCallers(3));
-        } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_CLOSE
-                || transit == TRANSIT_TASK_CLOSE
-                || transit == TRANSIT_TASK_TO_BACK)) {
+                    appTransitionOldToString(transit), enter, Debug.getCallers(3));
+        } else if (isVoiceInteraction && (transit == TRANSIT_OLD_ACTIVITY_CLOSE
+                || transit == TRANSIT_OLD_TASK_CLOSE
+                || transit == TRANSIT_OLD_TASK_TO_BACK)) {
             a = loadAnimationRes(lp, enter
                     ? com.android.internal.R.anim.voice_activity_close_enter
                     : com.android.internal.R.anim.voice_activity_close_exit);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation voice: anim=%s transit=%s isEntrance=%b Callers=%s", a,
-                    appTransitionToString(transit), enter, Debug.getCallers(3));
-        } else if (transit == TRANSIT_ACTIVITY_RELAUNCH) {
+                    appTransitionOldToString(transit), enter, Debug.getCallers(3));
+        } else if (transit == TRANSIT_OLD_ACTIVITY_RELAUNCH) {
             a = createRelaunchAnimation(frame, insets);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s nextAppTransition=%d transit=%s Callers=%s", a,
-                    mNextAppTransition, appTransitionToString(transit),
+                    mNextAppTransitionOld, appTransitionOldToString(transit),
                     Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = loadAnimationRes(mNextAppTransitionPackage, enter ?
@@ -1621,25 +1654,25 @@
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s "
                             + "isEntrance=%b Callers=%s",
-                    a, appTransitionToString(transit), enter, Debug.getCallers(3));
+                    a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE) {
             a = loadAnimationRes(mNextAppTransitionPackage, mNextAppTransitionInPlace);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM_IN_PLACE "
                             + "transit=%s Callers=%s",
-                    a, appTransitionToString(transit), Debug.getCallers(3));
+                    a, appTransitionOldToString(transit), Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL) {
             a = createClipRevealAnimationLocked(transit, enter, frame, displayFrame);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s nextAppTransition=ANIM_CLIP_REVEAL "
                             + "transit=%s Callers=%s",
-                    a, appTransitionToString(transit), Debug.getCallers(3));
+                    a, appTransitionOldToString(transit), Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_SCALE_UP) {
             a = createScaleUpAnimationLocked(transit, enter, frame);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s nextAppTransition=ANIM_SCALE_UP transit=%s "
                             + "isEntrance=%s Callers=%s",
-                    a, appTransitionToString(transit), enter, Debug.getCallers(3));
+                    a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP ||
                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
             mNextAppTransitionScaleUp =
@@ -1651,7 +1684,7 @@
                             + "Callers=%s",
                     a,  mNextAppTransitionScaleUp
                             ? "ANIM_THUMBNAIL_SCALE_UP" : "ANIM_THUMBNAIL_SCALE_DOWN",
-                    appTransitionToString(transit), enter, Debug.getCallers(3));
+                    appTransitionOldToString(transit), enter, Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_UP ||
                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_ASPECT_SCALE_DOWN) {
             mNextAppTransitionScaleUp =
@@ -1665,77 +1698,77 @@
                     a, mNextAppTransitionScaleUp
                             ? "ANIM_THUMBNAIL_ASPECT_SCALE_UP"
                         : "ANIM_THUMBNAIL_ASPECT_SCALE_DOWN",
-                    appTransitionToString(transit), enter, Debug.getCallers(3));
+                    appTransitionOldToString(transit), enter, Debug.getCallers(3));
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS && enter) {
             a = loadAnimationRes("android",
                     com.android.internal.R.anim.task_open_enter_cross_profile_apps);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation NEXT_TRANSIT_TYPE_OPEN_CROSS_PROFILE_APPS: "
                             + "anim=%s transit=%s isEntrance=true Callers=%s",
-                    a, appTransitionToString(transit), Debug.getCallers(3));
-        } else if (transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE) {
+                    a, appTransitionOldToString(transit), Debug.getCallers(3));
+        } else if (transit == TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE) {
             // In the absence of a specific adapter, we just want to keep everything stationary.
             a = new AlphaAnimation(1.f, 1.f);
             a.setDuration(WindowChangeAnimationSpec.ANIMATION_DURATION);
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s transit=%s isEntrance=%b Callers=%s",
-                    a, appTransitionToString(transit), enter, Debug.getCallers(3));
+                    a, appTransitionOldToString(transit), enter, Debug.getCallers(3));
         } else {
             int animAttr = 0;
             switch (transit) {
-                case TRANSIT_ACTIVITY_OPEN:
-                case TRANSIT_TRANSLUCENT_ACTIVITY_OPEN:
+                case TRANSIT_OLD_ACTIVITY_OPEN:
+                case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN:
                     animAttr = enter
                             ? WindowAnimation_activityOpenEnterAnimation
                             : WindowAnimation_activityOpenExitAnimation;
                     break;
-                case TRANSIT_ACTIVITY_CLOSE:
-                case TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE:
+                case TRANSIT_OLD_ACTIVITY_CLOSE:
+                case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE:
                     animAttr = enter
                             ? WindowAnimation_activityCloseEnterAnimation
                             : WindowAnimation_activityCloseExitAnimation;
                     break;
-                case TRANSIT_TASK_OPEN:
+                case TRANSIT_OLD_TASK_OPEN:
                     animAttr = enter
                             ? WindowAnimation_taskOpenEnterAnimation
                             : WindowAnimation_taskOpenExitAnimation;
                     break;
-                case TRANSIT_TASK_CLOSE:
+                case TRANSIT_OLD_TASK_CLOSE:
                     animAttr = enter
                             ? WindowAnimation_taskCloseEnterAnimation
                             : WindowAnimation_taskCloseExitAnimation;
                     break;
-                case TRANSIT_TASK_TO_FRONT:
+                case TRANSIT_OLD_TASK_TO_FRONT:
                     animAttr = enter
                             ? WindowAnimation_taskToFrontEnterAnimation
                             : WindowAnimation_taskToFrontExitAnimation;
                     break;
-                case TRANSIT_TASK_TO_BACK:
+                case TRANSIT_OLD_TASK_TO_BACK:
                     animAttr = enter
                             ? WindowAnimation_taskToBackEnterAnimation
                             : WindowAnimation_taskToBackExitAnimation;
                     break;
-                case TRANSIT_WALLPAPER_OPEN:
+                case TRANSIT_OLD_WALLPAPER_OPEN:
                     animAttr = enter
                             ? WindowAnimation_wallpaperOpenEnterAnimation
                             : WindowAnimation_wallpaperOpenExitAnimation;
                     break;
-                case TRANSIT_WALLPAPER_CLOSE:
+                case TRANSIT_OLD_WALLPAPER_CLOSE:
                     animAttr = enter
                             ? WindowAnimation_wallpaperCloseEnterAnimation
                             : WindowAnimation_wallpaperCloseExitAnimation;
                     break;
-                case TRANSIT_WALLPAPER_INTRA_OPEN:
+                case TRANSIT_OLD_WALLPAPER_INTRA_OPEN:
                     animAttr = enter
                             ? WindowAnimation_wallpaperIntraOpenEnterAnimation
                             : WindowAnimation_wallpaperIntraOpenExitAnimation;
                     break;
-                case TRANSIT_WALLPAPER_INTRA_CLOSE:
+                case TRANSIT_OLD_WALLPAPER_INTRA_CLOSE:
                     animAttr = enter
                             ? WindowAnimation_wallpaperIntraCloseEnterAnimation
                             : WindowAnimation_wallpaperIntraCloseExitAnimation;
                     break;
-                case TRANSIT_TASK_OPEN_BEHIND:
+                case TRANSIT_OLD_TASK_OPEN_BEHIND:
                     animAttr = enter
                             ? WindowAnimation_launchTaskBehindSourceAnimation
                             : WindowAnimation_launchTaskBehindTargetAnimation;
@@ -1744,7 +1777,7 @@
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s animAttr=0x%x transit=%s isEntrance=%b "
                             + "Callers=%s",
-                    a, animAttr, appTransitionToString(transit), enter,
+                    a, animAttr, appTransitionOldToString(transit), enter,
                     Debug.getCallers(3));
         }
         setAppTransitionFinishedCallbackIfNeeded(a);
@@ -1760,14 +1793,16 @@
         final boolean subtle =
                 (mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0;
         return mService.mPolicy.createHiddenByKeyguardExit(
-                transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER, toShade, subtle);
+                transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER, toShade, subtle);
     }
 
     int getAppStackClipMode() {
-        return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
+        return mNextAppTransitionRequests.contains(TRANSIT_RELAUNCH)
+                || mNextAppTransitionRequests.contains(TRANSIT_KEYGUARD_GOING_AWAY)
+                || mNextAppTransitionOld == TRANSIT_OLD_ACTIVITY_RELAUNCH
                 || mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
-                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
-                || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
+                || mNextAppTransitionOld == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+                || mNextAppTransitionOld == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER
                 ? STACK_CLIP_NONE
                 : STACK_CLIP_AFTER_ANIM;
     }
@@ -1965,7 +2000,100 @@
 
     @Override
     public String toString() {
-        return "mNextAppTransition=" + appTransitionToString(mNextAppTransition);
+        StringBuilder sb = new StringBuilder();
+        sb.append("mNextAppTransition=");
+        sb.append(appTransitionOldToString(mNextAppTransitionOld));
+        sb.append(", mNextAppTransitionRequests=[");
+
+        boolean separator = false;
+        for (Integer transit : mNextAppTransitionRequests) {
+            if (separator) {
+                sb.append(", ");
+            }
+            sb.append(appTransitionToString(transit));
+            separator = true;
+        }
+        sb.append("]");
+        sb.append(", mNextAppTransitionFlags="
+                + appTransitionFlagsToString(mNextAppTransitionFlags));
+        return sb.toString();
+    }
+
+    /**
+     * Returns the human readable name of a old window transition.
+     *
+     * @param transition The old window transition.
+     * @return The transition symbolic name.
+     */
+    public static String appTransitionOldToString(@TransitionOldType int transition) {
+        switch (transition) {
+            case TRANSIT_OLD_UNSET: {
+                return "TRANSIT_OLD_UNSET";
+            }
+            case TRANSIT_OLD_NONE: {
+                return "TRANSIT_OLD_NONE";
+            }
+            case TRANSIT_OLD_ACTIVITY_OPEN: {
+                return "TRANSIT_OLD_ACTIVITY_OPEN";
+            }
+            case TRANSIT_OLD_ACTIVITY_CLOSE: {
+                return "TRANSIT_OLD_ACTIVITY_CLOSE";
+            }
+            case TRANSIT_OLD_TASK_OPEN: {
+                return "TRANSIT_OLD_TASK_OPEN";
+            }
+            case TRANSIT_OLD_TASK_CLOSE: {
+                return "TRANSIT_OLD_TASK_CLOSE";
+            }
+            case TRANSIT_OLD_TASK_TO_FRONT: {
+                return "TRANSIT_OLD_TASK_TO_FRONT";
+            }
+            case TRANSIT_OLD_TASK_TO_BACK: {
+                return "TRANSIT_OLD_TASK_TO_BACK";
+            }
+            case TRANSIT_OLD_WALLPAPER_CLOSE: {
+                return "TRANSIT_OLD_WALLPAPER_CLOSE";
+            }
+            case TRANSIT_OLD_WALLPAPER_OPEN: {
+                return "TRANSIT_OLD_WALLPAPER_OPEN";
+            }
+            case TRANSIT_OLD_WALLPAPER_INTRA_OPEN: {
+                return "TRANSIT_OLD_WALLPAPER_INTRA_OPEN";
+            }
+            case TRANSIT_OLD_WALLPAPER_INTRA_CLOSE: {
+                return "TRANSIT_OLD_WALLPAPER_INTRA_CLOSE";
+            }
+            case TRANSIT_OLD_TASK_OPEN_BEHIND: {
+                return "TRANSIT_OLD_TASK_OPEN_BEHIND";
+            }
+            case TRANSIT_OLD_ACTIVITY_RELAUNCH: {
+                return "TRANSIT_OLD_ACTIVITY_RELAUNCH";
+            }
+            case TRANSIT_OLD_KEYGUARD_GOING_AWAY: {
+                return "TRANSIT_OLD_KEYGUARD_GOING_AWAY";
+            }
+            case TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
+                return "TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
+            }
+            case TRANSIT_OLD_KEYGUARD_OCCLUDE: {
+                return "TRANSIT_OLD_KEYGUARD_OCCLUDE";
+            }
+            case TRANSIT_OLD_KEYGUARD_UNOCCLUDE: {
+                return "TRANSIT_OLD_KEYGUARD_UNOCCLUDE";
+            }
+            case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN: {
+                return "TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN";
+            }
+            case TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE: {
+                return "TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE";
+            }
+            case TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE: {
+                return "TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE";
+            }
+            default: {
+                return "<UNKNOWN: " + transition + ">";
+            }
+        }
     }
 
     /**
@@ -1974,71 +2102,38 @@
      * @param transition The window transition.
      * @return The transition symbolic name.
      */
-    public static String appTransitionToString(int transition) {
+    public static String appTransitionToString(@TransitionType int transition) {
         switch (transition) {
-            case TRANSIT_UNSET: {
-                return "TRANSIT_UNSET";
-            }
             case TRANSIT_NONE: {
                 return "TRANSIT_NONE";
             }
-            case TRANSIT_ACTIVITY_OPEN: {
-                return "TRANSIT_ACTIVITY_OPEN";
+            case TRANSIT_OPEN: {
+                return "TRANSIT_OPEN";
             }
-            case TRANSIT_ACTIVITY_CLOSE: {
-                return "TRANSIT_ACTIVITY_CLOSE";
+            case TRANSIT_CLOSE: {
+                return "TRANSIT_CLOSE";
             }
-            case TRANSIT_TASK_OPEN: {
-                return "TRANSIT_TASK_OPEN";
+            case TRANSIT_TO_FRONT: {
+                return "TRANSIT_TO_FRONT";
             }
-            case TRANSIT_TASK_CLOSE: {
-                return "TRANSIT_TASK_CLOSE";
+            case TRANSIT_TO_BACK: {
+                return "TRANSIT_TO_BACK";
             }
-            case TRANSIT_TASK_TO_FRONT: {
-                return "TRANSIT_TASK_TO_FRONT";
+            case TRANSIT_RELAUNCH: {
+                return "TRANSIT_RELAUNCH";
             }
-            case TRANSIT_TASK_TO_BACK: {
-                return "TRANSIT_TASK_TO_BACK";
-            }
-            case TRANSIT_WALLPAPER_CLOSE: {
-                return "TRANSIT_WALLPAPER_CLOSE";
-            }
-            case TRANSIT_WALLPAPER_OPEN: {
-                return "TRANSIT_WALLPAPER_OPEN";
-            }
-            case TRANSIT_WALLPAPER_INTRA_OPEN: {
-                return "TRANSIT_WALLPAPER_INTRA_OPEN";
-            }
-            case TRANSIT_WALLPAPER_INTRA_CLOSE: {
-                return "TRANSIT_WALLPAPER_INTRA_CLOSE";
-            }
-            case TRANSIT_TASK_OPEN_BEHIND: {
-                return "TRANSIT_TASK_OPEN_BEHIND";
-            }
-            case TRANSIT_ACTIVITY_RELAUNCH: {
-                return "TRANSIT_ACTIVITY_RELAUNCH";
+            case TRANSIT_CHANGE_WINDOWING_MODE: {
+                return "TRANSIT_CHANGE_WINDOWING_MODE";
             }
             case TRANSIT_KEYGUARD_GOING_AWAY: {
                 return "TRANSIT_KEYGUARD_GOING_AWAY";
             }
-            case TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
-                return "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
-            }
             case TRANSIT_KEYGUARD_OCCLUDE: {
                 return "TRANSIT_KEYGUARD_OCCLUDE";
             }
             case TRANSIT_KEYGUARD_UNOCCLUDE: {
                 return "TRANSIT_KEYGUARD_UNOCCLUDE";
             }
-            case TRANSIT_TRANSLUCENT_ACTIVITY_OPEN: {
-                return "TRANSIT_TRANSLUCENT_ACTIVITY_OPEN";
-            }
-            case TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE: {
-                return "TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE";
-            }
-            case TRANSIT_CRASHING_ACTIVITY_CLOSE: {
-                return "TRANSIT_CRASHING_ACTIVITY_CLOSE";
-            }
             default: {
                 return "<UNKNOWN: " + transition + ">";
             }
@@ -2085,6 +2180,41 @@
         }
     }
 
+    private static final ArrayList<Pair<Integer, String>> sFlagToString;
+
+    static {
+        sFlagToString = new ArrayList<>();
+        sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE,
+                "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE"));
+        sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION,
+                "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION"));
+        sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER,
+                "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER"));
+        sFlagToString.add(new Pair<>(TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION,
+                "TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION"));
+        sFlagToString.add(new Pair<>(TRANSIT_FLAG_APP_CRASHED,
+                "TRANSIT_FLAG_APP_CRASHED"));
+    }
+
+    /**
+     * Returns the human readable names of transit flags.
+     *
+     * @param flags a bitmask combination of transit flags.
+     * @return The combination of symbolic names.
+     */
+    public static String appTransitionFlagsToString(int flags) {
+        String sep = "";
+        StringBuilder sb = new StringBuilder();
+        for (Pair<Integer, String> pair : sFlagToString) {
+            if ((flags & pair.first) != 0) {
+                sb.append(sep);
+                sb.append(pair.second);
+                sep = " | ";
+            }
+        }
+        return sb.toString();
+    }
+
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         final long token = proto.start(fieldId);
         proto.write(APP_TRANSITION_STATE, mAppTransitionState);
@@ -2145,9 +2275,9 @@
             pw.print(prefix); pw.print("mNextAppTransitionCallback=");
                     pw.println(mNextAppTransitionCallback);
         }
-        if (mLastUsedAppTransition != TRANSIT_NONE) {
+        if (mLastUsedAppTransition != TRANSIT_OLD_NONE) {
             pw.print(prefix); pw.print("mLastUsedAppTransition=");
-                    pw.println(appTransitionToString(mLastUsedAppTransition));
+                    pw.println(appTransitionOldToString(mLastUsedAppTransition));
             pw.print(prefix); pw.print("mLastOpeningApp=");
                     pw.println(mLastOpeningApp);
             pw.print(prefix); pw.print("mLastClosingApp=");
@@ -2165,7 +2295,7 @@
      * @return true if transition is not running and should not be skipped, false if transition is
      *         already running
      */
-    boolean prepareAppTransitionLocked(@TransitionType int transit, boolean alwaysKeepCurrent,
+    boolean prepareAppTransitionOld(@TransitionOldType int transit, boolean alwaysKeepCurrent,
             @TransitionFlags int flags, boolean forceOverride) {
         if (mService.mAtmService.getTransitionController().adaptLegacyPrepare(
                 transit, flags, forceOverride)) {
@@ -2174,78 +2304,88 @@
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                 "Prepare app transition: transit=%s %s alwaysKeepCurrent=%b displayId=%d "
                         + "Callers=%s",
-                appTransitionToString(transit), this, alwaysKeepCurrent,
+                appTransitionOldToString(transit), this, alwaysKeepCurrent,
                 mDisplayContent.getDisplayId(), Debug.getCallers(5));
-        final boolean allowSetCrashing = !isKeyguardTransit(mNextAppTransition)
-                && transit == TRANSIT_CRASHING_ACTIVITY_CLOSE;
+        final boolean allowSetCrashing = !isKeyguardTransit(mNextAppTransitionOld)
+                && transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
         if (forceOverride || isKeyguardTransit(transit) || !isTransitionSet()
-                || mNextAppTransition == TRANSIT_NONE || allowSetCrashing) {
-            setAppTransition(transit, flags);
+                || mNextAppTransitionOld == TRANSIT_OLD_NONE || allowSetCrashing) {
+            setAppTransitionOld(transit, flags);
         }
         // We never want to change from a Keyguard transit to a non-Keyguard transit, as our logic
         // relies on the fact that we always execute a Keyguard transition after preparing one. We
         // also don't want to change away from a crashing transition.
-        else if (!alwaysKeepCurrent && !isKeyguardTransit(mNextAppTransition)
-                && mNextAppTransition != TRANSIT_CRASHING_ACTIVITY_CLOSE) {
-            if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) {
+        else if (!alwaysKeepCurrent && !isKeyguardTransit(mNextAppTransitionOld)
+                && mNextAppTransitionOld != TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) {
+            if (transit == TRANSIT_OLD_TASK_OPEN && isTransitionOldEqual(TRANSIT_OLD_TASK_CLOSE)) {
                 // Opening a new task always supersedes a close for the anim.
-                setAppTransition(transit, flags);
-            } else if (transit == TRANSIT_ACTIVITY_OPEN
-                    && isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) {
+                setAppTransitionOld(transit, flags);
+            } else if (transit == TRANSIT_OLD_ACTIVITY_OPEN
+                    && isTransitionOldEqual(TRANSIT_OLD_ACTIVITY_CLOSE)) {
                 // Opening a new activity always supersedes a close for the anim.
-                setAppTransition(transit, flags);
-            } else if (isTaskTransit(transit) && isActivityTransit(mNextAppTransition)) {
+                setAppTransitionOld(transit, flags);
+            } else if (isTaskTransit(transit) && isActivityTransit(mNextAppTransitionOld)) {
                 // Task animations always supersede activity animations, because if we have both, it
                 // usually means that activity transition were just trampoline activities.
-                setAppTransition(transit, flags);
+                setAppTransitionOld(transit, flags);
             }
         }
         return prepare();
     }
 
+    boolean prepareAppTransition(@TransitionType int transit, @TransitionFlags int flags) {
+        mNextAppTransitionRequests.add(transit);
+        mNextAppTransitionFlags |= flags;
+        updateBooster();
+        removeAppTransitionTimeoutCallbacks();
+        mHandler.postDelayed(mHandleAppTransitionTimeoutRunnable,
+                APP_TRANSITION_TIMEOUT_MS);
+        return prepare();
+    }
+
     /**
      * @return true if {@param transit} is representing a transition in which Keyguard is going
      *         away, false otherwise
      */
     public static boolean isKeyguardGoingAwayTransit(int transit) {
-        return transit == TRANSIT_KEYGUARD_GOING_AWAY
-                || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+        return transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
     }
 
-    static boolean isKeyguardTransit(int transit) {
-        return isKeyguardGoingAwayTransit(transit) || transit == TRANSIT_KEYGUARD_OCCLUDE
-                || transit == TRANSIT_KEYGUARD_UNOCCLUDE;
+    static boolean isKeyguardTransit(@TransitionOldType int transit) {
+        return isKeyguardGoingAwayTransit(transit) || transit == TRANSIT_OLD_KEYGUARD_OCCLUDE
+                || transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
     }
 
-    static boolean isTaskTransit(int transit) {
+    static boolean isTaskTransit(@TransitionOldType int transit) {
         return isTaskOpenTransit(transit)
-                || transit == TRANSIT_TASK_CLOSE
-                || transit == TRANSIT_TASK_TO_BACK;
+                || transit == TRANSIT_OLD_TASK_CLOSE
+                || transit == TRANSIT_OLD_TASK_TO_BACK;
     }
 
-    private static  boolean isTaskOpenTransit(int transit) {
-        return transit == TRANSIT_TASK_OPEN
-                || transit == TRANSIT_TASK_OPEN_BEHIND
-                || transit == TRANSIT_TASK_TO_FRONT;
+    private static  boolean isTaskOpenTransit(@TransitionOldType int transit) {
+        return transit == TRANSIT_OLD_TASK_OPEN
+                || transit == TRANSIT_OLD_TASK_OPEN_BEHIND
+                || transit == TRANSIT_OLD_TASK_TO_FRONT;
     }
 
-    static boolean isActivityTransit(int transit) {
-        return transit == TRANSIT_ACTIVITY_OPEN
-                || transit == TRANSIT_ACTIVITY_CLOSE
-                || transit == TRANSIT_ACTIVITY_RELAUNCH;
+    static boolean isActivityTransit(@TransitionOldType int transit) {
+        return transit == TRANSIT_OLD_ACTIVITY_OPEN
+                || transit == TRANSIT_OLD_ACTIVITY_CLOSE
+                || transit == TRANSIT_OLD_ACTIVITY_RELAUNCH;
     }
 
-    static boolean isChangeTransit(int transit) {
-        return transit == TRANSIT_TASK_CHANGE_WINDOWING_MODE;
+    static boolean isChangeTransit(@TransitionOldType int transit) {
+        return transit == TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
     }
 
-    static boolean isClosingTransit(int transit) {
-        return transit == TRANSIT_ACTIVITY_CLOSE
-                || transit == TRANSIT_TASK_CLOSE
-                || transit == TRANSIT_WALLPAPER_CLOSE
-                || transit == TRANSIT_WALLPAPER_INTRA_CLOSE
-                || transit == TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE
-                || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE;
+    static boolean isClosingTransit(@TransitionOldType int transit) {
+        return transit == TRANSIT_OLD_ACTIVITY_CLOSE
+                || transit == TRANSIT_OLD_TASK_CLOSE
+                || transit == TRANSIT_OLD_WALLPAPER_CLOSE
+                || transit == TRANSIT_OLD_WALLPAPER_INTRA_CLOSE
+                || transit == TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE
+                || transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index 14eedf7..97912c1 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -17,27 +17,27 @@
 package com.android.server.wm;
 
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_RELAUNCH;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
-import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_CLOSE;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_CLOSE;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_INTRA_OPEN;
-import static android.view.WindowManager.TRANSIT_WALLPAPER_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH;
+import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_OPEN;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
@@ -63,7 +63,7 @@
 import android.view.RemoteAnimationDefinition;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
-import android.view.WindowManager.TransitionType;
+import android.view.WindowManager.TransitionOldType;
 import android.view.animation.Animation;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -109,10 +109,12 @@
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
 
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");
+        // TODO(new-app-transition): Compute the best transition from
+        //  appTransition.mNextAppTransitionRequests
         final AppTransition appTransition = mDisplayContent.mAppTransition;
-        int transit = appTransition.getAppTransition();
+        int transit = appTransition.getAppTransitionOld();
         if (mDisplayContent.mSkipAppTransitionAnimation && !isKeyguardGoingAwayTransit(transit)) {
-            transit = WindowManager.TRANSIT_UNSET;
+            transit = WindowManager.TRANSIT_OLD_UNSET;
         }
         mDisplayContent.mSkipAppTransitionAnimation = false;
         mDisplayContent.mNoAnimationNotifyOnTransitionFinished.clear();
@@ -226,7 +228,7 @@
     }
 
     RemoteAnimationAdapter getRemoteAnimationOverride(@NonNull WindowContainer container,
-            @TransitionType int transit, ArraySet<Integer> activityTypes) {
+            @TransitionOldType int transit, ArraySet<Integer> activityTypes) {
         final RemoteAnimationDefinition definition = container.getRemoteAnimationDefinition();
         if (definition != null) {
             final RemoteAnimationAdapter adapter = definition.getAdapter(transit, activityTypes);
@@ -245,8 +247,8 @@
      * set of defined remote animations in the app window token.
      */
     private void overrideWithRemoteAnimationIfSet(ActivityRecord animLpActivity,
-            @TransitionType int transit, ArraySet<Integer> activityTypes) {
-        if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
+            @TransitionOldType int transit, ArraySet<Integer> activityTypes) {
+        if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) {
             // The crash transition has higher priority than any involved remote animations.
             return;
         }
@@ -269,7 +271,7 @@
     /**
      * @return The window token that determines the animation theme.
      */
-    private ActivityRecord findAnimLayoutParamsToken(@TransitionType int transit,
+    private ActivityRecord findAnimLayoutParamsToken(@TransitionOldType int transit,
             ArraySet<Integer> activityTypes) {
         ActivityRecord result;
         final ArraySet<ActivityRecord> closingApps = mDisplayContent.mClosingApps;
@@ -357,7 +359,7 @@
      *                         interaction session driving task.
      */
     private void applyAnimations(ArraySet<WindowContainer> wcs, ArraySet<ActivityRecord> apps,
-            @TransitionType int transit, boolean visible, LayoutParams animLp,
+            @TransitionOldType int transit, boolean visible, LayoutParams animLp,
             boolean voiceInteraction) {
         final int wcsCount = wcs.size();
         for (int i = 0; i < wcsCount; i++) {
@@ -490,9 +492,9 @@
      *                         interaction session driving task.
      */
     private void applyAnimations(ArraySet<ActivityRecord> openingApps,
-            ArraySet<ActivityRecord> closingApps, @TransitionType int transit,
+            ArraySet<ActivityRecord> closingApps, @TransitionOldType int transit,
             LayoutParams animLp, boolean voiceInteraction) {
-        if (transit == WindowManager.TRANSIT_UNSET
+        if (transit == WindowManager.TRANSIT_OLD_UNSET
                 || (openingApps.isEmpty() && closingApps.isEmpty())) {
             return;
         }
@@ -583,7 +585,7 @@
         }
     }
 
-    private void handleChangingApps(@TransitionType int transit) {
+    private void handleChangingApps(@TransitionOldType int transit) {
         final ArraySet<WindowContainer> apps = mDisplayContent.mChangingContainers;
         final int appsCount = apps.size();
         for (int i = 0; i < appsCount; i++) {
@@ -593,8 +595,8 @@
         }
     }
 
-    private void handleNonAppWindowsInTransition(@TransitionType int transit, int flags) {
-        if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
+    private void handleNonAppWindowsInTransition(@TransitionOldType int transit, int flags) {
+        if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY) {
             if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
                     && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
                     && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
@@ -606,10 +608,10 @@
                 }
             }
         }
-        if (transit == TRANSIT_KEYGUARD_GOING_AWAY
-                || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
+        if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
             mDisplayContent.startKeyguardExitOnNonAppWindows(
-                    transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+                    transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
                     (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0,
                     (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0);
         }
@@ -689,13 +691,13 @@
         return true;
     }
 
-    private int maybeUpdateTransitToWallpaper(@TransitionType int transit,
+    private int maybeUpdateTransitToWallpaper(@TransitionOldType int transit,
             boolean openingAppHasWallpaper, boolean closingAppHasWallpaper) {
         // Given no app transition pass it through instead of a wallpaper transition.
         // Never convert the crashing transition.
         // Never convert a change transition since the top activity isn't changing and will likely
         // still be above an opening wallpaper.
-        if (transit == TRANSIT_NONE || transit == TRANSIT_CRASHING_ACTIVITY_CLOSE
+        if (transit == TRANSIT_OLD_NONE || transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE
                 || AppTransition.isChangeTransit(transit)) {
             return transit;
         }
@@ -705,7 +707,7 @@
                 && ((wallpaperTarget.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0
                 // Update task open transition to wallpaper transition when wallpaper is visible.
                 // (i.e.launching app info activity from recent tasks)
-                || ((transit == TRANSIT_TASK_OPEN || transit == TRANSIT_TASK_TO_FRONT)
+                || ((transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT)
                 && mWallpaperControllerLocked.isWallpaperVisible()));
         // If wallpaper is animating or wallpaperTarget doesn't have SHOW_WALLPAPER flag set,
         // don't consider upgrading to wallpaper transition.
@@ -725,10 +727,10 @@
                         "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s",
                         wallpaperTarget, oldWallpaper, openingApps, closingApps);
 
-        if (openingCanBeWallpaperTarget && transit == TRANSIT_KEYGUARD_GOING_AWAY) {
-            transit = TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+        if (openingCanBeWallpaperTarget && transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY) {
+            transit = TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                    "New transit: %s", AppTransition.appTransitionToString(transit));
+                    "New transit: %s", AppTransition.appTransitionOldToString(transit));
         }
         // We never want to change from a Keyguard transit to a non-Keyguard transit, as our logic
         // relies on the fact that we always execute a Keyguard transition after preparing one.
@@ -736,37 +738,37 @@
             if (closingAppHasWallpaper && openingAppHasWallpaper) {
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Wallpaper animation!");
                 switch (transit) {
-                    case TRANSIT_ACTIVITY_OPEN:
-                    case TRANSIT_TASK_OPEN:
-                    case TRANSIT_TASK_TO_FRONT:
-                        transit = TRANSIT_WALLPAPER_INTRA_OPEN;
+                    case TRANSIT_OLD_ACTIVITY_OPEN:
+                    case TRANSIT_OLD_TASK_OPEN:
+                    case TRANSIT_OLD_TASK_TO_FRONT:
+                        transit = TRANSIT_OLD_WALLPAPER_INTRA_OPEN;
                         break;
-                    case TRANSIT_ACTIVITY_CLOSE:
-                    case TRANSIT_TASK_CLOSE:
-                    case TRANSIT_TASK_TO_BACK:
-                        transit = TRANSIT_WALLPAPER_INTRA_CLOSE;
+                    case TRANSIT_OLD_ACTIVITY_CLOSE:
+                    case TRANSIT_OLD_TASK_CLOSE:
+                    case TRANSIT_OLD_TASK_TO_BACK:
+                        transit = TRANSIT_OLD_WALLPAPER_INTRA_CLOSE;
                         break;
                 }
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
-                        "New transit: %s", AppTransition.appTransitionToString(transit));
+                        "New transit: %s", AppTransition.appTransitionOldToString(transit));
             } else if (oldWallpaper != null && !mDisplayContent.mOpeningApps.isEmpty()
                     && !openingApps.contains(oldWallpaper.mActivityRecord)
                     && closingApps.contains(oldWallpaper.mActivityRecord)
                     && topClosingApp == oldWallpaper.mActivityRecord) {
                 // We are transitioning from an activity with a wallpaper to one without.
-                transit = TRANSIT_WALLPAPER_CLOSE;
+                transit = TRANSIT_OLD_WALLPAPER_CLOSE;
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
                         "New transit away from wallpaper: %s",
-                                AppTransition.appTransitionToString(transit));
+                                AppTransition.appTransitionOldToString(transit));
             } else if (wallpaperTarget != null && wallpaperTarget.isVisibleLw()
                     && openingApps.contains(wallpaperTarget.mActivityRecord)
                     && topOpeningApp == wallpaperTarget.mActivityRecord
-                    && transit != TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE) {
+                    && transit != TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE) {
                 // We are transitioning from an activity without
                 // a wallpaper to now showing the wallpaper
-                transit = TRANSIT_WALLPAPER_OPEN;
+                transit = TRANSIT_OLD_WALLPAPER_OPEN;
                 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "New transit into wallpaper: %s",
-                        AppTransition.appTransitionToString(transit));
+                        AppTransition.appTransitionOldToString(transit));
             }
         }
         return transit;
@@ -780,12 +782,12 @@
      *
      * @param transit The current transition type.
      * @return The current transition type or
-     *         {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE}/
-     *         {@link WindowManager#TRANSIT_TRANSLUCENT_ACTIVITY_OPEN} if appropriate for the
+     *         {@link WindowManager#TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE}/
+     *         {@link WindowManager#TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN} if appropriate for the
      *         situation.
      */
     @VisibleForTesting
-    int maybeUpdateTransitToTranslucentAnim(@TransitionType int transit) {
+    int maybeUpdateTransitToTranslucentAnim(@TransitionOldType int transit) {
         if (AppTransition.isChangeTransit(transit)) {
             // There's no special animation to handle change animations with translucent apps
             return transit;
@@ -812,10 +814,10 @@
         }
 
         if (taskOrActivity && allTranslucentClosingApps && allOpeningVisible) {
-            return TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE;
+            return TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE;
         }
         if (taskOrActivity && allTranslucentOpeningApps && mDisplayContent.mClosingApps.isEmpty()) {
-            return TRANSIT_TRANSLUCENT_ACTIVITY_OPEN;
+            return TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN;
         }
         return transit;
     }
@@ -825,16 +827,16 @@
      * to determine whether animations should be clipped to the task bounds instead of stack bounds.
      */
     @VisibleForTesting
-    boolean isTransitWithinTask(@TransitionType int transit, Task task) {
+    boolean isTransitWithinTask(@TransitionOldType int transit, Task task) {
         if (task == null
                 || !mDisplayContent.mChangingContainers.isEmpty()) {
             // if there is no task, then we can't constrain to the task.
             // if anything is changing, it can animate outside its task.
             return false;
         }
-        if (!(transit == TRANSIT_ACTIVITY_OPEN
-                || transit == TRANSIT_ACTIVITY_CLOSE
-                || transit == TRANSIT_ACTIVITY_RELAUNCH)) {
+        if (!(transit == TRANSIT_OLD_ACTIVITY_OPEN
+                || transit == TRANSIT_OLD_ACTIVITY_CLOSE
+                || transit == TRANSIT_OLD_ACTIVITY_RELAUNCH)) {
             // only activity-level transitions will be within-task.
             return false;
         }
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 38ad070..5e1a26b 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -19,7 +19,6 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
@@ -145,6 +144,11 @@
         return super.getOrientation(candidate);
     }
 
+    @Override
+    boolean handlesOrientationChangeFromDescendant() {
+        return !mIgnoreOrientationRequest && super.handlesOrientationChangeFromDescendant();
+    }
+
     /**
      * Sets whether this {@link DisplayArea} should ignore fixed-orientation request from apps and
      * windows below it.
@@ -467,8 +471,7 @@
                 // Consider unoccluding only when all unknown visibilities have been
                 // resolved, as otherwise we just may be starting another occluding activity.
                 final boolean isUnoccluding =
-                        mDisplayContent.mAppTransition.getAppTransition()
-                                == TRANSIT_KEYGUARD_UNOCCLUDE
+                        mDisplayContent.mAppTransition.isUnoccluding()
                                 && mDisplayContent.mUnknownAppVisibilityController.allResolved();
                 // If keyguard is showing, or we're unoccluding, force the keyguard's orientation,
                 // even if SystemUI hasn't updated the attrs yet.
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2de28be..7c5c435 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -70,9 +70,9 @@
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
 
@@ -109,7 +109,6 @@
 import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
 import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
-import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
 import static com.android.server.wm.Task.ActivityState.RESUMED;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -1310,7 +1309,7 @@
         // If display rotation class tells us that it doesn't consider app requested orientation,
         // this display won't rotate just because of an app changes its requested orientation. Thus
         // it indicates that this display chooses not to handle this request.
-        final boolean handled = getDisplayRotation().respectAppRequestedOrientation();
+        final boolean handled = handlesOrientationChangeFromDescendant();
         if (config == null) {
             return handled;
         }
@@ -1334,7 +1333,7 @@
 
     @Override
     boolean handlesOrientationChangeFromDescendant() {
-        return getDisplayRotation().respectAppRequestedOrientation();
+        return !mIgnoreOrientationRequest && !getDisplayRotation().isFixedToUserRotation();
     }
 
     /**
@@ -2346,7 +2345,7 @@
     @Override
     int getOrientation() {
         mLastOrientationSource = null;
-        if (mIgnoreOrientationRequest) {
+        if (!handlesOrientationChangeFromDescendant()) {
             // Return SCREEN_ORIENTATION_UNSPECIFIED so that Display respect sensor rotation
             ProtoLog.v(WM_DEBUG_ORIENTATION,
                     "Display id=%d is ignoring all orientation requests, return %d",
@@ -4499,16 +4498,43 @@
         mPointerEventDispatcher.unregisterInputEventListener(listener);
     }
 
-    void prepareAppTransition(@WindowManager.TransitionType int transit,
+    /**
+     * Transfer app transition from other display to this display.
+     *
+     * @param from Display from where the app transition is transferred.
+     *
+     * TODO(new-app-transition): Remove this once the shell handles app transition.
+     */
+    void transferAppTransitionFrom(DisplayContent from) {
+        final boolean prepared = mAppTransition.transferFrom(from.mAppTransition);
+        if (prepared && okToAnimate()) {
+            mSkipAppTransitionAnimation = false;
+        }
+    }
+
+    void prepareAppTransitionOld(@WindowManager.TransitionOldType int transit,
             boolean alwaysKeepCurrent) {
-        prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
+        prepareAppTransitionOld(transit, alwaysKeepCurrent, 0 /* flags */,
+                false /* forceOverride */);
+    }
+
+    void prepareAppTransitionOld(@WindowManager.TransitionOldType int transit,
+            boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags,
+            boolean forceOverride) {
+        final boolean prepared = mAppTransition.prepareAppTransitionOld(
+                transit, alwaysKeepCurrent, flags, forceOverride);
+        if (prepared && okToAnimate()) {
+            mSkipAppTransitionAnimation = false;
+        }
+    }
+
+    void prepareAppTransition(@WindowManager.TransitionType int transit) {
+        prepareAppTransition(transit, 0 /* flags */);
     }
 
     void prepareAppTransition(@WindowManager.TransitionType int transit,
-            boolean alwaysKeepCurrent, @WindowManager.TransitionFlags int flags,
-            boolean forceOverride) {
-        final boolean prepared = mAppTransition.prepareAppTransitionLocked(
-                transit, alwaysKeepCurrent, flags, forceOverride);
+            @WindowManager.TransitionFlags int flags) {
+        final boolean prepared = mAppTransition.prepareAppTransition(transit, flags);
         if (prepared && okToAnimate()) {
             mSkipAppTransitionAnimation = false;
         }
@@ -4558,10 +4584,10 @@
 
     /** Check if pending app transition is for activity / task launch. */
     boolean isNextTransitionForward() {
-        final int transit = mAppTransition.getAppTransition();
-        return transit == TRANSIT_ACTIVITY_OPEN
-                || transit == TRANSIT_TASK_OPEN
-                || transit == TRANSIT_TASK_TO_FRONT;
+        final int transit = mAppTransition.getAppTransitionOld();
+        return transit == TRANSIT_OLD_ACTIVITY_OPEN
+                || transit == TRANSIT_OLD_TASK_OPEN
+                || transit == TRANSIT_OLD_TASK_TO_FRONT;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index c503431..c4aaf7c 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -857,15 +857,6 @@
         return mFixedToUserRotation;
     }
 
-    /**
-     * Returns {@code true} if this display rotation takes app requested orientation into
-     * consideration; {@code false} otherwise. For the time being the only case where this is {@code
-     * false} is when {@link #isFixedToUserRotation()} is {@code true}.
-     */
-    boolean respectAppRequestedOrientation() {
-        return !isFixedToUserRotation();
-    }
-
     public int getLandscapeRotation() {
         return mLandscapeRotation;
     }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 71eb18c..79b88d8 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
@@ -25,7 +26,10 @@
 import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_OCCLUDE;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
-import static android.view.WindowManager.TRANSIT_UNSET;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_OLD_UNSET;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_SUBTLE_WINDOW_ANIMATIONS;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
@@ -163,7 +167,7 @@
 
         if (keyguardChanged) {
             // Irrelevant to AOD.
-            dismissDockedStackIfNeeded();
+            dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */);
             setKeyguardGoingAway(false);
             if (keyguardShowing) {
                 mDismissalRequested = false;
@@ -199,9 +203,12 @@
                     1 /* keyguardGoingAway */,
                     "keyguardGoingAway");
             mRootWindowContainer.getDefaultDisplay()
-                    .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
+                    .prepareAppTransitionOld(TRANSIT_OLD_KEYGUARD_GOING_AWAY,
                             false /* alwaysKeepCurrent */, convertTransitFlags(flags),
                             false /* forceOverride */);
+            mRootWindowContainer.getDefaultDisplay()
+                    .prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
+                            convertTransitFlags(flags));
             updateKeyguardSleepToken();
 
             // Some stack visibility might change (e.g. docked stack)
@@ -328,8 +335,12 @@
 
     /**
      * Called when occluded state changed.
+     *
+     * @param currentTaskControllingOcclusion the task that controls the state whether keyguard
+     *      should be occluded. That is the task to be shown on top of keyguard if it requests so.
      */
-    private void handleOccludedChanged(int displayId) {
+    private void handleOccludedChanged(
+            int displayId, @Nullable Task currentTaskControllingOcclusion) {
         // TODO(b/113840485): Handle app transition for individual display, and apply occluded
         // state change to secondary displays.
         // For now, only default display fully supports occluded change. Other displays only
@@ -344,16 +355,21 @@
             mService.deferWindowLayout();
             try {
                 mRootWindowContainer.getDefaultDisplay()
-                        .prepareAppTransition(resolveOccludeTransit(),
+                        .prepareAppTransitionOld(resolveOccludeTransit(),
                                 false /* alwaysKeepCurrent */, 0 /* flags */,
                                 true /* forceOverride */);
+                mRootWindowContainer.getDefaultDisplay()
+                        .prepareAppTransition(
+                                isDisplayOccluded(DEFAULT_DISPLAY)
+                                        ? TRANSIT_KEYGUARD_OCCLUDE
+                                        : TRANSIT_KEYGUARD_UNOCCLUDE);
                 updateKeyguardSleepToken(DEFAULT_DISPLAY);
                 mWindowManager.executeAppTransition();
             } finally {
                 mService.continueWindowLayout();
             }
         }
-        dismissDockedStackIfNeeded();
+        dismissMultiWindowModeForTaskIfNeeded(currentTaskControllingOcclusion);
     }
 
     /**
@@ -374,9 +390,10 @@
         // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
         final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
         if (mKeyguardShowing && canDismissKeyguard()
-                && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
-            dc.prepareAppTransition(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
+                && dc.mAppTransition.getAppTransitionOld() == TRANSIT_OLD_KEYGUARD_UNOCCLUDE) {
+            dc.prepareAppTransitionOld(mBeforeUnoccludeTransit, false /* alwaysKeepCurrent */,
                     0 /* flags */, true /* forceOverride */);
+            dc.prepareAppTransition(TRANSIT_KEYGUARD_UNOCCLUDE);
             mWindowManager.executeAppTransition();
         }
     }
@@ -394,9 +411,10 @@
     }
 
     private int resolveOccludeTransit() {
+        // TODO(new-app-transition): Remove after migrating to the enw transit system.
         final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
-        if (mBeforeUnoccludeTransit != TRANSIT_UNSET
-                && dc.mAppTransition.getAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
+        if (mBeforeUnoccludeTransit != TRANSIT_OLD_UNSET
+                && dc.mAppTransition.getAppTransitionOld() == TRANSIT_OLD_KEYGUARD_UNOCCLUDE
                 // TODO(b/113840485): Handle app transition for individual display.
                 && isDisplayOccluded(DEFAULT_DISPLAY)) {
 
@@ -407,27 +425,38 @@
         } else if (!isDisplayOccluded(DEFAULT_DISPLAY)) {
 
             // Save transit in case we dismiss/occlude Keyguard shortly after.
-            mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransition();
-            return TRANSIT_KEYGUARD_UNOCCLUDE;
+            mBeforeUnoccludeTransit = dc.mAppTransition.getAppTransitionOld();
+            return TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
         } else {
-            return TRANSIT_KEYGUARD_OCCLUDE;
+            return TRANSIT_OLD_KEYGUARD_OCCLUDE;
         }
     }
 
-    private void dismissDockedStackIfNeeded() {
+    private void dismissMultiWindowModeForTaskIfNeeded(
+            @Nullable Task currentTaskControllingOcclusion) {
         // TODO(b/113840485): Handle docked stack for individual display.
-        if (mKeyguardShowing && isDisplayOccluded(DEFAULT_DISPLAY)) {
-            // The lock screen is currently showing, but is occluded by a window that can
-            // show on top of the lock screen. In this can we want to dismiss the docked
-            // stack since it will be complicated/risky to try to put the activity on top
-            // of the lock screen in the right fullscreen configuration.
-            final TaskDisplayArea taskDisplayArea = mRootWindowContainer
-                    .getDefaultTaskDisplayArea();
-            if (!taskDisplayArea.isSplitScreenModeActivated()) {
-                return;
-            }
+        if (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY)) {
+            return;
+        }
+
+        // Dismiss split screen
+
+        // The lock screen is currently showing, but is occluded by a window that can
+        // show on top of the lock screen. In this can we want to dismiss the docked
+        // stack since it will be complicated/risky to try to put the activity on top
+        // of the lock screen in the right fullscreen configuration.
+        final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
+        if (taskDisplayArea.isSplitScreenModeActivated()) {
             taskDisplayArea.onSplitScreenModeDismissed();
         }
+
+        // Dismiss freeform windowing mode
+        if (currentTaskControllingOcclusion == null) {
+            return;
+        }
+        if (currentTaskControllingOcclusion.inFreeformWindowingMode()) {
+            currentTaskControllingOcclusion.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        }
     }
 
     private void updateKeyguardSleepToken() {
@@ -559,7 +588,7 @@
             }
 
             if (lastOccluded != mOccluded) {
-                controller.handleOccludedChanged(mDisplayId);
+                controller.handleOccludedChanged(mDisplayId, task);
             }
         }
 
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index 1cf50ab..ca429f8 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -23,7 +23,6 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NO_ANIMATION;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.WindowManager.TRANSIT_NONE;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
@@ -221,7 +220,7 @@
                 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS, "Moved stack=%s behind stack=%s",
                         targetStack, getStackAbove(targetStack));
 
-                mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+                mWindowManager.prepareAppTransitionNone();
                 mWindowManager.executeAppTransition();
 
                 // TODO: Maybe wait for app to draw in this particular case?
@@ -377,7 +376,7 @@
                         return;
                     }
 
-                    mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+                    mWindowManager.prepareAppTransitionNone();
                     mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, false);
                     mService.mRootWindowContainer.resumeFocusedStacksTopActivities();
 
@@ -436,7 +435,7 @@
                 || controller.isTargetApp(stack.getTopNonFinishingActivity()))
                 && controller.shouldDeferCancelUntilNextTransition()) {
             // Always prepare an app transition since we rely on the transition callbacks to cleanup
-            mWindowManager.prepareAppTransition(TRANSIT_NONE, false);
+            mWindowManager.prepareAppTransitionNone();
             controller.setCancelOnNextTransitionStart();
         }
     }
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 4ad2575..1736ac9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -214,6 +214,26 @@
         }
 
         @Override
+        public void setFinishTaskBounds(int taskId, Rect destinationBounds) {
+            ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
+                    "setFinishTaskBounds(%d): bounds=%s", taskId, destinationBounds);
+            final long token = Binder.clearCallingIdentity();
+            try {
+                synchronized (mService.getWindowManagerLock()) {
+                    for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
+                        final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
+                        if (taskAdapter.mTask.mTaskId == taskId) {
+                            taskAdapter.mFinishBounds.set(destinationBounds);
+                            break;
+                        }
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
         public void finish(boolean moveHomeToTop, boolean sendUserLeaveHint) {
             ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
                     "finish(%b): mCanceled=%b", moveHomeToTop, mCanceled);
@@ -739,6 +759,7 @@
                 taskAdapter.mTask.dontAnimateDimExit();
             }
             removeAnimation(taskAdapter);
+            taskAdapter.maybeApplyFinishBounds();
         }
 
         for (int i = mPendingWallpaperAnimations.size() - 1; i >= 0; i--) {
@@ -925,7 +946,9 @@
         private RemoteAnimationTarget mTarget;
         private final Rect mBounds = new Rect();
         // The bounds of the target relative to its parent.
-        private Rect mLocalBounds = new Rect();
+        private final Rect mLocalBounds = new Rect();
+        // The bounds of the target when animation is finished
+        private final Rect mFinishBounds = new Rect();
 
         TaskAnimationAdapter(Task task, boolean isRecentTaskInvisible) {
             mTask = task;
@@ -960,6 +983,17 @@
             return mTarget;
         }
 
+        void maybeApplyFinishBounds() {
+            if (!mFinishBounds.isEmpty()) {
+                final SurfaceControl taskSurface = mTask.getSurfaceControl();
+                mTask.getPendingTransaction()
+                        .setPosition(taskSurface, mFinishBounds.left, mFinishBounds.top)
+                        .setWindowCrop(taskSurface, mFinishBounds.width(), mFinishBounds.height())
+                        .apply();
+                mFinishBounds.setEmpty();
+            }
+        }
+
         @Override
         public boolean getShowWallpaper() {
             return false;
@@ -1005,6 +1039,7 @@
             }
             pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible);
             pw.println("mLocalBounds=" + mLocalBounds);
+            pw.println("mFinishBounds=" + mFinishBounds);
             pw.println("mBounds=" + mBounds);
             pw.println("mIsRecentTaskInvisible=" + mIsRecentTaskInvisible);
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 11718dc..c1e518b 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -36,9 +36,12 @@
 import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
 import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
@@ -511,6 +514,7 @@
     void onChildPositionChanged(WindowContainer child) {
         mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
                 !mWmService.mPerDisplayFocusEnabled /* updateInputWindows */);
+        mStackSupervisor.updateTopResumedActivityIfNeeded();
     }
 
     /**
@@ -2175,7 +2179,8 @@
 
             // Set a transition to ensure that we don't immediately try and update the visibility
             // of the activity entering PIP
-            r.getDisplayContent().prepareAppTransition(TRANSIT_NONE, false);
+            r.getDisplayContent().prepareAppTransitionOld(TRANSIT_OLD_NONE, false);
+            r.getDisplayContent().prepareAppTransition(TRANSIT_NONE);
 
             final boolean singleActivity = task.getChildCount() == 1;
             final Task stack;
@@ -2206,8 +2211,8 @@
                 // to the list of apps being closed, and request its transition to be ran.
                 final ActivityRecord oldTopActivity = task.getTopMostActivity();
                 if (oldTopActivity != null && oldTopActivity.isState(STOPPED)
-                        && task.getDisplayContent().mAppTransition.getAppTransition()
-                        == TRANSIT_TASK_TO_BACK) {
+                        && task.getDisplayContent().mAppTransition.getAppTransitionOld()
+                        == TRANSIT_OLD_TASK_TO_BACK) {
                     task.getDisplayContent().mClosingApps.add(oldTopActivity);
                     oldTopActivity.mRequestForceTransition = true;
                 }
@@ -2626,12 +2631,6 @@
                 + " in=" + taskDisplayArea);
     }
 
-    @Override
-    void positionChildAt(int position, DisplayContent child, boolean includingParents) {
-        super.positionChildAt(position, child, includingParents);
-        mStackSupervisor.updateTopResumedActivityIfNeeded();
-    }
-
     Configuration getDisplayOverrideConfiguration(int displayId) {
         final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
         if (displayContent == null) {
@@ -2799,8 +2798,9 @@
         Slog.w(TAG, "  Force finishing activity "
                 + r.intent.getComponent().flattenToShortString());
         r.detachFromProcess();
-        r.mDisplayContent.prepareAppTransition(
-                TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
+        r.mDisplayContent.prepareAppTransitionOld(TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
+                false /* alwaysKeepCurrent */);
+        r.mDisplayContent.prepareAppTransition(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED);
         r.destroyIfPossible("handleAppCrashed");
     }
 
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1cee9c6..6804684 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -63,16 +63,23 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.SurfaceControl.METADATA_TASK_ID;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
 import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_OPEN;
+import static android.view.WindowManager.TRANSIT_TO_BACK;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
 import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
@@ -113,6 +120,7 @@
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
 import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
 import static com.android.server.wm.Task.ActivityState.PAUSED;
 import static com.android.server.wm.Task.ActivityState.PAUSING;
 import static com.android.server.wm.Task.ActivityState.RESUMED;
@@ -2359,8 +2367,9 @@
      * Initializes a change transition. See {@link SurfaceFreezer} for more information.
      */
     private void initializeChangeTransition(Rect startBounds) {
-        mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+        mDisplayContent.prepareAppTransitionOld(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
                 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
+        mDisplayContent.prepareAppTransition(TRANSIT_CHANGE_WINDOWING_MODE);
         mAtmService.getTransitionController().collect(this);
         mDisplayContent.mChangingContainers.add(this);
 
@@ -2445,7 +2454,7 @@
 
     @Override
     public SurfaceControl getFreezeSnapshotTarget() {
-        final int transit = mDisplayContent.mAppTransition.getAppTransition();
+        final int transit = mDisplayContent.mAppTransition.getAppTransitionOld();
         if (!AppTransition.isChangeTransit(transit)) {
             return null;
         }
@@ -2905,6 +2914,11 @@
             return;
         }
 
+        if (refActivity != null && refActivity.hasCompatDisplayInsets()) {
+            // App prefers to keep its original size.
+            return;
+        }
+
         final int parentWidth = parentBounds.width();
         final int parentHeight = parentBounds.height();
         final float aspect = ((float) parentHeight) / parentWidth;
@@ -3656,14 +3670,9 @@
         super.setInitialSurfaceControlProperties(b);
     }
 
-    boolean isTaskAnimating() {
-        final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
-        if (recentsAnim != null) {
-            if (recentsAnim.isAnimatingTask(this)) {
-                return true;
-            }
-        }
-        return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
+    /** Checking if self or its child tasks are animated by recents animation. */
+    boolean isAnimatingByRecents() {
+        return isAnimating(CHILDREN, ANIMATION_TYPE_RECENTS);
     }
 
     @Override
@@ -3794,6 +3803,10 @@
                 || activityType == ACTIVITY_TYPE_ASSISTANT;
     }
 
+    boolean isTaskLetterboxed() {
+        return getWindowingMode() == WINDOWING_MODE_FULLSCREEN && !matchParentBounds();
+    }
+
     @Override
     boolean fillsParent() {
         // From the perspective of policy, we still want to report that this task fills parent
@@ -3940,10 +3953,10 @@
         if (control != null) {
             // We let the transition to be controlled by RecentsAnimation, and callback task's
             // RemoteAnimationTarget for remote runner to animate.
-            if (enter) {
+            if (enter && !isHomeOrRecentsStack()) {
                 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
                         "applyAnimationUnchecked, control: %s, task: %s, transit: %s",
-                        control, asTask(), AppTransition.appTransitionToString(transit));
+                        control, asTask(), AppTransition.appTransitionOldToString(transit));
                 control.addTaskToTargets(this, (type, anim) -> {
                     for (int i = 0; i < sources.size(); ++i) {
                         sources.get(i).onAnimationFinished(type, anim);
@@ -6052,11 +6065,13 @@
                         "Prepare close transition: prev=" + prev);
                 if (mStackSupervisor.mNoAnimActivities.contains(prev)) {
                     anim = false;
-                    dc.prepareAppTransition(TRANSIT_NONE, false);
+                    dc.prepareAppTransitionOld(TRANSIT_OLD_NONE, false);
+                    dc.prepareAppTransition(TRANSIT_NONE);
                 } else {
-                    dc.prepareAppTransition(
-                            prev.getTask() == next.getTask() ? TRANSIT_ACTIVITY_CLOSE
-                                    : TRANSIT_TASK_CLOSE, false);
+                    dc.prepareAppTransitionOld(
+                            prev.getTask() == next.getTask() ? TRANSIT_OLD_ACTIVITY_CLOSE
+                                    : TRANSIT_OLD_TASK_CLOSE, false);
+                    dc.prepareAppTransition(TRANSIT_CLOSE);
                 }
                 prev.setVisibility(false);
             } else {
@@ -6064,21 +6079,25 @@
                         "Prepare open transition: prev=" + prev);
                 if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                     anim = false;
-                    dc.prepareAppTransition(TRANSIT_NONE, false);
+                    dc.prepareAppTransitionOld(TRANSIT_OLD_NONE, false);
+                    dc.prepareAppTransition(TRANSIT_NONE);
                 } else {
-                    dc.prepareAppTransition(
-                            prev.getTask() == next.getTask() ? TRANSIT_ACTIVITY_OPEN
-                                    : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND
-                                            : TRANSIT_TASK_OPEN, false);
+                    dc.prepareAppTransitionOld(
+                            prev.getTask() == next.getTask() ? TRANSIT_OLD_ACTIVITY_OPEN
+                                    : next.mLaunchTaskBehind ? TRANSIT_OLD_TASK_OPEN_BEHIND
+                                    : TRANSIT_OLD_TASK_OPEN, /* alwaysKeepCurrent */false);
+                    dc.prepareAppTransition(TRANSIT_OPEN);
                 }
             }
         } else {
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous");
             if (mStackSupervisor.mNoAnimActivities.contains(next)) {
                 anim = false;
-                dc.prepareAppTransition(TRANSIT_NONE, false);
+                dc.prepareAppTransitionOld(TRANSIT_OLD_NONE, false);
+                dc.prepareAppTransition(TRANSIT_NONE);
             } else {
-                dc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false);
+                dc.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN, false);
+                dc.prepareAppTransition(TRANSIT_OPEN);
             }
         }
 
@@ -6337,13 +6356,14 @@
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
                     "Prepare open transition: starting " + r);
             if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
-                dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition);
+                dc.prepareAppTransitionOld(TRANSIT_OLD_NONE, keepCurTransition);
+                dc.prepareAppTransition(TRANSIT_NONE);
                 mStackSupervisor.mNoAnimActivities.add(r);
             } else {
-                int transit = TRANSIT_ACTIVITY_OPEN;
+                int transit = TRANSIT_OLD_ACTIVITY_OPEN;
                 if (newTask) {
                     if (r.mLaunchTaskBehind) {
-                        transit = TRANSIT_TASK_OPEN_BEHIND;
+                        transit = TRANSIT_OLD_TASK_OPEN_BEHIND;
                     } else {
                         // If a new task is being launched, then mark the existing top activity as
                         // supporting picture-in-picture while pausing only if the starting activity
@@ -6353,17 +6373,18 @@
                                 null /* toFrontTask */, r, options)) {
                             focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
                         }
-                        transit = TRANSIT_TASK_OPEN;
+                        transit = TRANSIT_OLD_TASK_OPEN;
                     }
                 }
                 if (mAtmService.getTransitionController().isShellTransitionsEnabled()
                         // TODO(shell-transitions): eventually all transitions.
-                        && transit == TRANSIT_TASK_OPEN) {
+                        && transit == TRANSIT_OLD_TASK_OPEN) {
                     Transition transition =
                             mAtmService.getTransitionController().requestTransition(transit);
                     transition.collect(task);
                 } else {
-                    dc.prepareAppTransition(transit, keepCurTransition);
+                    dc.prepareAppTransitionOld(transit, keepCurTransition);
+                    dc.prepareAppTransition(TRANSIT_OPEN);
                 }
                 mStackSupervisor.mNoAnimActivities.remove(r);
             }
@@ -6502,8 +6523,9 @@
         Slog.w(TAG, "  Force finishing activity "
                 + r.intent.getComponent().flattenToShortString());
         Task finishedTask = r.getTask();
-        mDisplayContent.prepareAppTransition(
-                TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
+        mDisplayContent.prepareAppTransitionOld(
+                TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
+        mDisplayContent.prepareAppTransition(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED);
         r.finishIfPossible(reason, false /* oomAdj */);
 
         // Also terminate any activities below it that aren't yet stopped, to avoid a situation
@@ -6734,7 +6756,9 @@
         forAllActivities(ActivityRecord::removeLaunchTickRunnable);
     }
 
-    private void updateTransitLocked(int transit, ActivityOptions options, boolean forceOverride) {
+    private void updateTransitLocked(@WindowManager.TransitionOldType int transit,
+            @WindowManager.TransitionType int transit2, ActivityOptions options,
+            boolean forceOverride) {
         if (options != null) {
             ActivityRecord r = topRunningActivity();
             if (r != null && !r.isState(RESUMED)) {
@@ -6743,8 +6767,9 @@
                 ActivityOptions.abort(options);
             }
         }
-        mDisplayContent.prepareAppTransition(transit, false,
+        mDisplayContent.prepareAppTransitionOld(transit, false,
                 0 /* flags */, forceOverride);
+        mDisplayContent.prepareAppTransition(transit2);
     }
 
     final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
@@ -6765,7 +6790,8 @@
             if (noAnimation) {
                 ActivityOptions.abort(options);
             } else {
-                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options, false /* forceOverride */);
+                updateTransitLocked(TRANSIT_OLD_TASK_TO_FRONT, TRANSIT_TO_FRONT, options,
+                        false /* forceOverride */);
             }
             return;
         }
@@ -6806,13 +6832,16 @@
 
             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
             if (noAnimation) {
-                mDisplayContent.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
+                mDisplayContent.prepareAppTransitionOld(TRANSIT_OLD_NONE,
+                        false /* alwaysKeepCurrent */);
+                mDisplayContent.prepareAppTransition(TRANSIT_NONE);
                 if (r != null) {
                     mStackSupervisor.mNoAnimActivities.add(r);
                 }
                 ActivityOptions.abort(options);
             } else {
-                updateTransitLocked(TRANSIT_TASK_TO_FRONT, options, false /* forceOverride */);
+                updateTransitLocked(TRANSIT_OLD_TASK_TO_FRONT, TRANSIT_TO_FRONT,
+                        options, false /* forceOverride */);
             }
 
             // If a new task is moved to the front, then mark the existing top activity as
@@ -6880,7 +6909,9 @@
         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task="
                 + tr.mTaskId);
 
-        mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false /* alwaysKeepCurrent */);
+        mDisplayContent.prepareAppTransitionOld(TRANSIT_OLD_TASK_TO_BACK,
+                false /* alwaysKeepCurrent */);
+        mDisplayContent.prepareAppTransition(TRANSIT_TO_BACK);
         moveToBack("moveTaskToBackLocked", tr);
 
         if (inPinnedWindowingMode()) {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index c6b9e48..9392666 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -751,7 +751,7 @@
             // The split screen divider anchor is located above the split screen window.
             mTmpLayerForSplitScreenDividerAnchor = layer++;
         }
-        if (s.isTaskAnimating() || s.isAppTransitioning()) {
+        if (s.isAnimatingByRecents() || s.isAppTransitioning()) {
             // The animation layer is located above the highest animating stack and no
             // higher.
             mTmpLayerForAnimationLayer = layer++;
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 6486b78..6504f00 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -389,10 +389,6 @@
     }
 
     void onTaskAppeared(ITaskOrganizer organizer, Task task) {
-        // Don't send onTaskAppeared signal for task created by organizer since we will return it in
-        // the creation call.
-        if (task.mCreatedByOrganizer) return;
-
         final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
         state.addTask(task);
     }
@@ -405,7 +401,7 @@
     }
 
     @Override
-    public TaskAppearedInfo createRootTask(int displayId, int windowingMode) {
+    public RunningTaskInfo createRootTask(int displayId, int windowingMode) {
         enforceStackPermission("createRootTask()");
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -422,11 +418,7 @@
                         true /* createdByOrganizer */);
                 RunningTaskInfo out = task.getTaskInfo();
                 mLastSentTaskInfos.put(task, out);
-                final TaskOrganizerState state =
-                        mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
-                final SurfaceControl outSurfaceControl = state.addTaskWithoutCallback(task,
-                        "TaskOrganizerController.createRootTask");
-                return new TaskAppearedInfo(task.getTaskInfo(), outSurfaceControl);
+                return out;
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 01adb8b..3ce04af 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -157,7 +157,6 @@
         if (shouldDisableSnapshots()) {
             return;
         }
-
         // We need to take a snapshot of the task if and only if all activities of the task are
         // either closing or hidden.
         getClosingTasks(closingApps, mTmpTasks);
@@ -445,10 +444,17 @@
         for (int i = closingApps.size() - 1; i >= 0; i--) {
             final ActivityRecord activity = closingApps.valueAt(i);
             final Task task = activity.getTask();
+            if (task == null) continue;
 
+            // Since RecentsAnimation will handle task snapshot while switching apps with the
+            // best capture timing (e.g. IME window capture),
+            // No need additional task capture while task is controlled by RecentsAnimation.
+            if (task.isAnimatingByRecents()) {
+                mSkipClosingAppSnapshotTasks.add(task);
+            }
             // If the task of the app is not visible anymore, it means no other app in that task
             // is opening. Thus, the task is closing.
-            if (task != null && !task.isVisible() && !mSkipClosingAppSnapshotTasks.contains(task)) {
+            if (!task.isVisible() && !mSkipClosingAppSnapshotTasks.contains(task)) {
                 outClosingTasks.add(task);
             }
         }
@@ -571,7 +577,10 @@
                 synchronized (mService.mGlobalLock) {
                     mTmpTasks.clear();
                     mService.mRoot.forAllTasks(task -> {
-                        if (task.isVisible()) {
+                        // Since RecentsAnimation will handle task snapshot while switching apps
+                        // with the best capture timing (e.g. IME window capture), No need
+                        // additional task capture while task is controlled by RecentsAnimation.
+                        if (task.isVisible() && !task.isAnimatingByRecents()) {
                             mTmpTasks.add(task);
                         }
                     });
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index ac86698..d5322ea 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -22,8 +22,8 @@
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
 
 import android.annotation.NonNull;
 import android.os.Binder;
@@ -65,7 +65,7 @@
      */
     private static final int STATE_PLAYING = 2;
 
-    final @WindowManager.TransitionType int mType;
+    final @WindowManager.TransitionOldType int mType;
     private int mSyncId;
     private @WindowManager.TransitionFlags int mFlags;
     private final TransitionController mController;
@@ -74,7 +74,7 @@
     private int mState = STATE_COLLECTING;
     private boolean mReadyCalled = false;
 
-    Transition(@WindowManager.TransitionType int type,
+    Transition(@WindowManager.TransitionOldType int type,
             @WindowManager.TransitionFlags int flags, TransitionController controller) {
         mType = type;
         mFlags = flags;
@@ -182,7 +182,7 @@
         if (dc == null) {
             return;
         }
-        if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
+        if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY) {
             if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
                     && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0
                     && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) == 0) {
@@ -196,10 +196,10 @@
                 }
             }
         }
-        if (transit == TRANSIT_KEYGUARD_GOING_AWAY
-                || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
+        if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
             dc.startKeyguardExitOnNonAppWindows(
-                    transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+                    transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
                     (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0,
                     (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_SUBTLE_ANIMATION) != 0);
             mController.mAtm.mWindowManager.mPolicy.startKeyguardExitAnimation(transit, 0);
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 7cdc177..c2fb4cd 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -16,13 +16,13 @@
 
 package com.android.server.wm;
 
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
-import static android.view.WindowManager.TRANSIT_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
+import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -44,9 +44,9 @@
 class TransitionController {
     private static final String TAG = "TransitionController";
 
-    private static final int[] SUPPORTED_LEGACY_TRANSIT_TYPES = {TRANSIT_TASK_OPEN,
-            TRANSIT_TASK_CLOSE, TRANSIT_TASK_TO_FRONT, TRANSIT_TASK_TO_BACK,
-            TRANSIT_TASK_OPEN_BEHIND, TRANSIT_KEYGUARD_GOING_AWAY};
+    private static final int[] SUPPORTED_LEGACY_TRANSIT_TYPES = {TRANSIT_OLD_TASK_OPEN,
+            TRANSIT_OLD_TASK_CLOSE, TRANSIT_OLD_TASK_TO_FRONT, TRANSIT_OLD_TASK_TO_BACK,
+            TRANSIT_OLD_TASK_OPEN_BEHIND, TRANSIT_OLD_KEYGUARD_GOING_AWAY};
     static {
         Arrays.sort(SUPPORTED_LEGACY_TRANSIT_TYPES);
     }
@@ -79,7 +79,7 @@
      * Creates a transition. It can immediately collect participants.
      */
     @NonNull
-    Transition createTransition(@WindowManager.TransitionType int type,
+    Transition createTransition(@WindowManager.TransitionOldType int type,
             @WindowManager.TransitionFlags int flags) {
         if (mCollectingTransition != null) {
             throw new IllegalStateException("Simultaneous transitions not supported yet.");
@@ -137,13 +137,13 @@
      * @return the created transition. Collection can start immediately.
      */
     @NonNull
-    Transition requestTransition(@WindowManager.TransitionType int type) {
+    Transition requestTransition(@WindowManager.TransitionOldType int type) {
         return requestTransition(type, 0 /* flags */);
     }
 
     /** @see #requestTransition */
     @NonNull
-    Transition requestTransition(@WindowManager.TransitionType int type,
+    Transition requestTransition(@WindowManager.TransitionOldType int type,
             @WindowManager.TransitionFlags int flags) {
         if (mTransitionPlayer == null) {
             throw new IllegalStateException("Shell Transitions not enabled");
@@ -169,7 +169,7 @@
      *
      * @return {@code true} if the transition is handled.
      */
-    boolean adaptLegacyPrepare(@WindowManager.TransitionType int transit,
+    boolean adaptLegacyPrepare(@WindowManager.TransitionOldType int transit,
             @WindowManager.TransitionFlags int flags, boolean forceOverride) {
         if (!isShellTransitionsEnabled()
                 || Arrays.binarySearch(SUPPORTED_LEGACY_TRANSIT_TYPES, transit) < 0) {
@@ -180,7 +180,7 @@
                 // TODO(shell-transitions): add to flags
             } else if (forceOverride) {
                 // TODO(shell-transitions): sort out these flags
-            } else if (transit == TRANSIT_CRASHING_ACTIVITY_CLOSE) {
+            } else if (transit == TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE) {
                 // TODO(shell-transitions): record crashing
             }
         } else {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index da3a928..1e938a4 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2550,7 +2550,8 @@
         ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
                 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
                         + "surfaceInsets=%s",
-                AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
+                AppTransition.appTransitionOldToString(transit), enter, frame, insets,
+                surfaceInsets);
         final Configuration displayConfig = displayContent.getConfiguration();
         final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
                 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 66f2e4d..0585679 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -78,6 +78,9 @@
 import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
+import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
+import static android.view.WindowManager.TRANSIT_RELAUNCH;
 import static android.view.WindowManagerGlobal.ADD_OKAY;
 import static android.view.WindowManagerGlobal.ADD_TOO_MANY_TOKENS;
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
@@ -254,7 +257,6 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.RemoveContentMode;
-import android.view.WindowManager.TransitionType;
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
 import android.window.ClientWindowFrames;
@@ -419,6 +421,16 @@
             DISABLE_TRIPLE_BUFFERING_PROPERTY, false);
 
     /**
+     * Use new app transit framework.
+     */
+    private static final String USE_NEW_APP_TRANSIT =
+            "persist.wm.use_new_app_transit";
+    /**
+     * @see #USE_NEW_APP_TRANSIT
+     */
+    static boolean sUseNewAppTransit = SystemProperties.getBoolean(USE_NEW_APP_TRANSIT, false);
+
+    /**
      * Allows a fullscreen windowing mode activity to launch in its desired orientation directly
      * when the display has different orientation.
      */
@@ -1860,8 +1872,9 @@
         // animation and piggy-back on existing transition animation infrastructure.
         final DisplayContent dc = activity.getDisplayContent();
         dc.mOpeningApps.add(activity);
-        dc.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_RELAUNCH, ALWAYS_KEEP_CURRENT,
-                0 /* flags */, false /* forceOverride */);
+        dc.prepareAppTransitionOld(WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH,
+                ALWAYS_KEEP_CURRENT, 0 /* flags */, false /* forceOverride */);
+        dc.prepareAppTransition(TRANSIT_RELAUNCH);
         dc.mAppTransition.overridePendingAppTransitionClipReveal(frame.left, frame.top,
                 frame.width(), frame.height());
         dc.executeAppTransition();
@@ -1876,8 +1889,9 @@
         final DisplayContent dc = activity.getDisplayContent();
         if (mDisplayFrozen && !dc.mOpeningApps.contains(activity) && activity.isRelaunching()) {
             dc.mOpeningApps.add(activity);
-            dc.prepareAppTransition(WindowManager.TRANSIT_NONE, !ALWAYS_KEEP_CURRENT, 0 /* flags */,
+            dc.prepareAppTransitionOld(TRANSIT_OLD_NONE, !ALWAYS_KEEP_CURRENT, 0 /* flags */,
                     false /* forceOverride */);
+            dc.prepareAppTransition(TRANSIT_NONE);
             dc.executeAppTransition();
         }
     }
@@ -2757,14 +2771,14 @@
     }
 
     // TODO(multi-display): remove when no default display use case.
-    // (i.e. KeyguardController / RecentsAnimation)
-    @Override
-    public void prepareAppTransition(@TransitionType int transit, boolean alwaysKeepCurrent) {
+    void prepareAppTransitionNone() {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
         }
-        getDefaultDisplayContentLocked().prepareAppTransition(transit,
-                alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
+        getDefaultDisplayContentLocked().prepareAppTransitionOld(TRANSIT_OLD_NONE,
+                false /* alwaysKeepCurrent */,
+                0 /* flags */, false /* forceOverride */);
+        getDefaultDisplayContentLocked().prepareAppTransition(TRANSIT_NONE);
     }
 
     @Override
@@ -2810,7 +2824,6 @@
 
     // TODO(multi-display): remove when no default display use case.
     // (i.e. KeyguardController / RecentsAnimation)
-    @Override
     public void executeAppTransition() {
         if (!checkCallingPermission(MANAGE_APP_TOKENS, "executeAppTransition()")) {
             throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 3011f25..fe312e6 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -111,6 +111,8 @@
                     return runGetIgnoreOrientationRequest(pw);
                 case "dump-visible-window-views":
                     return runDumpVisibleWindowViews(pw);
+                case "reset":
+                    return runReset(pw);
                 default:
                     return handleDefaultCommands(cmd);
             }
@@ -507,6 +509,34 @@
         return 0;
     }
 
+    private int runReset(PrintWriter pw) throws RemoteException {
+        int displayId = getDisplayId(getNextArg());
+
+        // size
+        mInterface.clearForcedDisplaySize(displayId);
+
+        // density
+        mInterface.clearForcedDisplayDensityForUser(displayId, UserHandle.USER_CURRENT);
+
+        // folded-area
+        mInternal.setOverrideFoldedArea(new Rect());
+
+        // scaling
+        mInterface.setForcedDisplayScalingMode(displayId, DisplayContent.FORCE_SCALING_MODE_AUTO);
+
+        // user-rotation
+        mInternal.thawDisplayRotation(displayId);
+
+        // fixed-to-user-rotation
+        mInterface.setFixedToUserRotation(displayId, IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT);
+
+        // set-ignore-orientation-request
+        mInterface.setIgnoreOrientationRequest(displayId, false /* ignoreOrientationRequest */);
+
+        pw.println("Reset all settings for displayId=" + displayId);
+        return 0;
+    }
+
     @Override
     public void onHelp() {
         PrintWriter pw = getOutPrintWriter();
@@ -533,6 +563,8 @@
         pw.println("  set-ignore-orientation-request [-d DISPLAY_ID] [true|1|false|0]");
         pw.println("  get-ignore-orientation-request [-d DISPLAY_ID] ");
         pw.println("    If app requested orientation should be ignored.");
+        pw.println("  reset [-d DISPLAY_ID]");
+        pw.println("    Reset all override settings.");
         if (!IS_USER) {
             pw.println("  tracing (start | stop)");
             pw.println("    Start or stop window tracing.");
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0111d48..8713645 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -27,7 +27,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
-import static android.view.WindowManager.TRANSIT_NONE;
+import static android.view.WindowManager.TRANSIT_OLD_NONE;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
@@ -1075,7 +1075,7 @@
                 }
                 if (attr >= 0) {
                     a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr(
-                            mWin.mAttrs, attr, TRANSIT_NONE);
+                            mWin.mAttrs, attr, TRANSIT_OLD_NONE);
                 }
             }
             if (DEBUG_ANIM) Slog.v(TAG,
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index d6a56ba..9f83baf 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -38,7 +38,6 @@
         "com_android_server_locksettings_SyntheticPasswordManager.cpp",
         "com_android_server_net_NetworkStatsService.cpp",
         "com_android_server_power_PowerManagerService.cpp",
-        "com_android_server_powerstats_PowerStatsService.cpp",
         "com_android_server_security_VerityUtils.cpp",
         "com_android_server_SerialService.cpp",
         "com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.cpp",
diff --git a/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp b/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
deleted file mode 100644
index 5eb6b73..0000000
--- a/services/core/jni/com_android_server_powerstats_PowerStatsService.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2020 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 "PowerStatsService"
-
-#include <android/hardware/power/stats/1.0/IPowerStats.h>
-#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-
-#include <log/log.h>
-
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using android::hardware::power::stats::V1_0::EnergyData;
-using android::hardware::power::stats::V1_0::RailInfo;
-using android::hardware::power::stats::V1_0::Status;
-
-static jclass class_railInfo;
-static jmethodID method_railInfoInit;
-static jclass class_energyData;
-static jmethodID method_energyDataInit;
-
-namespace android {
-
-static std::mutex gPowerStatsHalMutex;
-static sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0_ptr = nullptr;
-
-static void deinitPowerStats() {
-    gPowerStatsHalV1_0_ptr = nullptr;
-}
-
-struct PowerStatsHalDeathRecipient : virtual public hardware::hidl_death_recipient {
-    virtual void serviceDied(uint64_t cookie,
-                             const wp<android::hidl::base::V1_0::IBase> &who) override {
-        // The HAL just died. Reset all handles to HAL services.
-        std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
-        deinitPowerStats();
-    }
-};
-
-sp<PowerStatsHalDeathRecipient> gPowerStatsHalDeathRecipient = new PowerStatsHalDeathRecipient();
-
-static bool connectToPowerStatsHal() {
-    if (gPowerStatsHalV1_0_ptr == nullptr) {
-        gPowerStatsHalV1_0_ptr = android::hardware::power::stats::V1_0::IPowerStats::getService();
-
-        if (gPowerStatsHalV1_0_ptr == nullptr) {
-            ALOGE("Unable to get power.stats HAL service.");
-            return false;
-        }
-
-        // Link death recipient to power.stats service handle
-        hardware::Return<bool> linked =
-                gPowerStatsHalV1_0_ptr->linkToDeath(gPowerStatsHalDeathRecipient, 0);
-        if (!linked.isOk()) {
-            ALOGE("Transaction error in linking to power.stats HAL death: %s",
-                  linked.description().c_str());
-            deinitPowerStats();
-            return false;
-        } else if (!linked) {
-            ALOGW("Unable to link to power.stats HAL death notifications");
-            return false;
-        }
-    }
-    return true;
-}
-
-static bool checkResult(const Return<void> &ret, const char *function) {
-    if (!ret.isOk()) {
-        ALOGE("%s failed: requested HAL service not available. Description: %s", function,
-              ret.description().c_str());
-        if (ret.isDeadObject()) {
-            deinitPowerStats();
-        }
-        return false;
-    }
-    return true;
-}
-
-static jobjectArray nativeGetRailInfo(JNIEnv *env, jclass clazz) {
-    std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
-
-    if (!connectToPowerStatsHal()) {
-        ALOGE("nativeGetRailInfo failed to connect to power.stats HAL");
-        return nullptr;
-    }
-
-    hidl_vec<RailInfo> list;
-    Return<void> ret = gPowerStatsHalV1_0_ptr->getRailInfo([&list](auto rails, auto status) {
-        if (status != Status::SUCCESS) {
-            ALOGW("Rail information is not available");
-        } else {
-            list = std::move(rails);
-        }
-    });
-
-    if (!checkResult(ret, __func__)) {
-        ALOGE("getRailInfo failed");
-        return nullptr;
-    } else {
-        jobjectArray railInfoArray = env->NewObjectArray(list.size(), class_railInfo, nullptr);
-        for (int i = 0; i < list.size(); i++) {
-            jstring railName = env->NewStringUTF(list[i].railName.c_str());
-            jstring subsysName = env->NewStringUTF(list[i].subsysName.c_str());
-            jobject railInfo = env->NewObject(class_railInfo, method_railInfoInit, list[i].index,
-                                              railName, subsysName, list[i].samplingRate);
-            env->SetObjectArrayElement(railInfoArray, i, railInfo);
-            env->DeleteLocalRef(railName);
-            env->DeleteLocalRef(subsysName);
-            env->DeleteLocalRef(railInfo);
-        }
-        return railInfoArray;
-    }
-}
-
-static jobjectArray nativeGetEnergyData(JNIEnv *env, jclass clazz) {
-    std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
-
-    if (!connectToPowerStatsHal()) {
-        ALOGE("nativeGetEnergy failed to connect to power.stats HAL");
-    }
-
-    hidl_vec<EnergyData> list;
-    Return<void> ret =
-            gPowerStatsHalV1_0_ptr->getEnergyData({}, [&list](auto energyData, auto status) {
-                if (status != Status::SUCCESS) {
-                    ALOGW("getEnergyData is not supported");
-                } else {
-                    list = std::move(energyData);
-                }
-            });
-
-    if (!checkResult(ret, __func__)) {
-        ALOGE("getEnergyData failed");
-        return nullptr;
-    } else {
-        jobjectArray energyDataArray = env->NewObjectArray(list.size(), class_energyData, nullptr);
-        for (int i = 0; i < list.size(); i++) {
-            jobject energyData = env->NewObject(class_energyData, method_energyDataInit,
-                                                list[i].index, list[i].timestamp, list[i].energy);
-            env->SetObjectArrayElement(energyDataArray, i, energyData);
-            env->DeleteLocalRef(energyData);
-        }
-        return energyDataArray;
-    }
-}
-
-static jboolean nativeInit(JNIEnv *env, jclass clazz) {
-    std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
-
-    jclass temp = env->FindClass("com/android/server/powerstats/PowerStatsData$RailInfo");
-    if (temp == nullptr) return false;
-
-    class_railInfo = (jclass)env->NewGlobalRef(temp);
-    if (class_railInfo == nullptr) return false;
-
-    method_railInfoInit =
-            env->GetMethodID(class_railInfo, "<init>", "(JLjava/lang/String;Ljava/lang/String;J)V");
-    if (method_railInfoInit == nullptr) return false;
-
-    temp = env->FindClass("com/android/server/powerstats/PowerStatsData$EnergyData");
-    if (temp == nullptr) return false;
-
-    class_energyData = (jclass)env->NewGlobalRef(temp);
-    if (class_energyData == nullptr) return false;
-
-    method_energyDataInit = env->GetMethodID(class_energyData, "<init>", "(JJJ)V");
-    if (method_energyDataInit == nullptr) return false;
-
-    bool rv = true;
-
-    if (!connectToPowerStatsHal()) {
-        ALOGE("nativeInit failed to connect to power.stats HAL");
-        rv = false;
-    } else {
-        Return<void> ret = gPowerStatsHalV1_0_ptr->getRailInfo([&rv](auto rails, auto status) {
-            if (status != Status::SUCCESS) {
-                ALOGE("nativeInit RailInfo is unavailable");
-                rv = false;
-            }
-        });
-
-        ret = gPowerStatsHalV1_0_ptr->getEnergyData({}, [&rv](auto energyData, auto status) {
-            if (status != Status::SUCCESS) {
-                ALOGE("nativeInit EnergyData is unavailable");
-                rv = false;
-            }
-        });
-    }
-
-    return rv;
-}
-
-static const JNINativeMethod method_table[] = {
-        {"nativeInit", "()Z", (void *)nativeInit},
-        {"nativeGetRailInfo", "()[Lcom/android/server/powerstats/PowerStatsData$RailInfo;",
-         (void *)nativeGetRailInfo},
-        {"nativeGetEnergyData", "()[Lcom/android/server/powerstats/PowerStatsData$EnergyData;",
-         (void *)nativeGetEnergyData},
-};
-
-int register_android_server_PowerStatsService(JNIEnv *env) {
-    return jniRegisterNativeMethods(env,
-                                    "com/android/server/powerstats/"
-                                    "PowerStatsHALWrapper$PowerStatsHALWrapperImpl",
-                                    method_table, NELEM(method_table));
-}
-
-}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 48d5244..0ffa5c3 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -29,7 +29,6 @@
 int register_android_server_InputManager(JNIEnv* env);
 int register_android_server_LightsService(JNIEnv* env);
 int register_android_server_PowerManagerService(JNIEnv* env);
-int register_android_server_PowerStatsService(JNIEnv* env);
 int register_android_server_storage_AppFuse(JNIEnv* env);
 int register_android_server_SerialService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
@@ -84,7 +83,6 @@
     register_android_server_broadcastradio_BroadcastRadioService(env);
     register_android_server_broadcastradio_Tuner(vm, env);
     register_android_server_PowerManagerService(env);
-    register_android_server_PowerStatsService(env);
     register_android_server_SerialService(env);
     register_android_server_InputManager(env);
     register_android_server_LightsService(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 745d645..ddda392 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1231,12 +1231,14 @@
             return "/data/system/";
         }
 
+        @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
         PendingIntent pendingIntentGetActivityAsUser(Context context, int requestCode,
                 @NonNull Intent intent, int flags, Bundle options, UserHandle user) {
             return PendingIntent.getActivityAsUser(
                     context, requestCode, intent, flags, options, user);
         }
 
+        @SuppressWarnings("AndroidFrameworkPendingIntentMutability")
         PendingIntent pendingIntentGetBroadcast(
                 Context context, int requestCode, Intent intent, int flags) {
             return PendingIntent.getBroadcast(context, requestCode, intent, flags);
@@ -2215,7 +2217,8 @@
                             caller.getUid(), doAdmin.getUid());
 
         Preconditions.checkCallAuthorization(
-                doAdmin.info.getComponent().equals(caller.getComponentName()),
+                !caller.hasAdminComponent()
+                || doAdmin.info.getComponent().equals(caller.getComponentName()),
                 "Caller component %s is not device owner",
                         caller.getComponentName());
 
@@ -2238,7 +2241,8 @@
                             caller.getUid());
 
         Preconditions.checkCallAuthorization(
-                poAdmin.info.getComponent().equals(caller.getComponentName()),
+                !caller.hasAdminComponent()
+                || poAdmin.info.getComponent().equals(caller.getComponentName()),
                 "Caller component %s is not profile owner",
                         caller.getComponentName());
 
@@ -4423,23 +4427,24 @@
         }
 
         // If caller has PO (or DO) throw or fail silently depending on its target SDK level.
-        Preconditions.checkCallAuthorization(
-                isDeviceOwner(caller) || isProfileOwner(caller),
-                String.format("UID %d is not a device or profile owner", caller.getUid()));
-
-        synchronized (getLockObject()) {
-            ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userHandle);
-            if (admin != null) {
+        if (isDeviceOwner(caller) || isProfileOwner(caller)) {
+            synchronized (getLockObject()) {
+                ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
                 if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) {
                     Slog.e(LOG_TAG, "DPC can no longer call resetPassword()");
                     return false;
                 }
                 throw new SecurityException("Device admin can no longer call resetPassword()");
             }
+        }
 
+        // Caller is not DO or PO, could either be unauthorized or Device Admin.
+        synchronized (getLockObject()) {
             // Legacy device admin cannot call resetPassword either
-            admin = getActiveAdminForCallerLocked(
+            ActiveAdmin admin = getActiveAdminForCallerLocked(
                     null, DeviceAdminInfo.USES_POLICY_RESET_PASSWORD, false);
+            Preconditions.checkCallAuthorization(admin != null,
+                    "Unauthorized caller cannot call resetPassword.");
             if (getTargetSdk(admin.info.getPackageName(),
                     userHandle) <= android.os.Build.VERSION_CODES.M) {
                 Slog.e(LOG_TAG, "Device admin can no longer call resetPassword()");
@@ -5788,8 +5793,9 @@
     public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException {
         Objects.requireNonNull(admin, "ComponentName is null");
 
-        final CallerIdentity caller = getCallerIdentity(admin);
-        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)
+        final CallerIdentity caller = getNonPrivilegedOrAdminCallerIdentity(admin);
+        Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+                && (isDeviceOwner(caller) || isProfileOwner(caller)))
                 || hasCallingPermission(PERMISSION_MAINLINE_NETWORK_STACK));
 
         return mInjector.binderWithCleanCallingIdentity(
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index 7803e78..3e06194 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -22,6 +22,7 @@
 import android.annotation.WorkerThread;
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.app.Person;
 import android.app.people.ConversationChannel;
@@ -98,6 +99,7 @@
 
     private static final String TAG = "DataManager";
 
+    private static final long RECENT_NOTIFICATIONS_MAX_AGE_MS = 10 * DateUtils.DAY_IN_MILLIS;
     private static final long QUERY_EVENTS_MAX_AGE_MS = 5L * DateUtils.MINUTE_IN_MILLIS;
     private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
     @VisibleForTesting static final int MAX_CACHED_RECENT_SHORTCUTS = 30;
@@ -232,8 +234,12 @@
                 if (shortcutInfo == null || parentChannel == null) {
                     return;
                 }
+                NotificationChannelGroup parentChannelGroup =
+                        mNotificationManagerInternal.getNotificationChannelGroup(packageName,
+                                uid, parentChannel.getId());
                 conversationChannels.add(
-                        new ConversationChannel(shortcutInfo, parentChannel,
+                        new ConversationChannel(shortcutInfo, uid, parentChannel,
+                                parentChannelGroup,
                                 conversationInfo.getLastEventTimestamp(),
                                 hasActiveNotifications(packageName, userId, shortcutId)));
             });
@@ -259,6 +265,14 @@
      * notifications.
      */
     public void removeAllRecentConversations(@UserIdInt int callingUserId) {
+        pruneOldRecentConversations(callingUserId, Long.MAX_VALUE);
+    }
+
+    /**
+     * Uncaches the shortcuts for all the recent conversations that haven't been interacted with
+     * recently.
+     */
+    public void pruneOldRecentConversations(@UserIdInt int callingUserId, long currentTimeMs) {
         forPackagesInProfile(callingUserId, packageData -> {
             String packageName = packageData.getPackageName();
             int userId = packageData.getUserId();
@@ -266,12 +280,16 @@
             packageData.forAllConversations(conversationInfo -> {
                 String shortcutId = conversationInfo.getShortcutId();
                 if (isCachedRecentConversation(conversationInfo)
+                        && (currentTimeMs - conversationInfo.getLastEventTimestamp()
+                        > RECENT_NOTIFICATIONS_MAX_AGE_MS)
                         && !hasActiveNotifications(packageName, userId, shortcutId)) {
                     idsToUncache.add(shortcutId);
                 }
             });
-            mShortcutServiceInternal.uncacheShortcuts(callingUserId, mContext.getPackageName(),
-                    packageName, idsToUncache, userId, ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
+            if (!idsToUncache.isEmpty()) {
+                mShortcutServiceInternal.uncacheShortcuts(callingUserId, mContext.getPackageName(),
+                        packageName, idsToUncache, userId, ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
+            }
         });
     }
 
@@ -371,6 +389,7 @@
                 packageData.getEventStore().deleteEventHistories(EventStore.CATEGORY_SMS);
             }
             packageData.pruneOrphanEvents();
+            pruneOldRecentConversations(userId, System.currentTimeMillis());
             cleanupCachedShortcuts(userId, MAX_CACHED_RECENT_SHORTCUTS);
         });
     }
diff --git a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java
index 8a22a2f..044bdba 100644
--- a/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/VibratorManagerServiceTest.java
@@ -16,10 +16,16 @@
 
 package com.android.server;
 
+import static com.android.server.testutils.TestUtils.assertExpectException;
+
 import static org.junit.Assert.assertArrayEquals;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.os.CombinedVibrationEffect;
+import android.os.Process;
+import android.os.VibrationAttributes;
+import android.os.VibrationEffect;
 import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
@@ -40,9 +46,16 @@
 @Presubmit
 public class VibratorManagerServiceTest {
 
-    @Rule public MockitoRule rule = MockitoJUnit.rule();
+    private static final int UID = Process.ROOT_UID;
+    private static final String PACKAGE_NAME = "package";
+    private static final VibrationAttributes ALARM_ATTRS =
+            new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build();
 
-    @Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock;
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+
+    @Mock
+    private VibratorManagerService.NativeWrapper mNativeWrapperMock;
 
     @Before
     public void setUp() throws Exception {
@@ -72,7 +85,26 @@
 
     @Test
     public void getVibratorIds_withNonEmptyResultFromNative_returnsSameArray() {
-        when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{ 1, 2 });
-        assertArrayEquals(new int[]{ 1, 2 }, createService().getVibratorIds());
+        when(mNativeWrapperMock.getVibratorIds()).thenReturn(new int[]{1, 2});
+        assertArrayEquals(new int[]{1, 2}, createService().getVibratorIds());
+    }
+
+    @Test
+    public void vibrate_isUnsupported() {
+        VibratorManagerService service = createService();
+        CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced(
+                VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+        assertExpectException(UnsupportedOperationException.class,
+                "Not implemented",
+                () -> service.vibrate(UID, PACKAGE_NAME, effect, ALARM_ATTRS, "reason", service));
+    }
+
+    @Test
+    public void cancelVibrate_isUnsupported() {
+        VibratorManagerService service = createService();
+        CombinedVibrationEffect effect = CombinedVibrationEffect.createSynced(
+                VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+        assertExpectException(UnsupportedOperationException.class,
+                "Not implemented", () -> service.cancelVibrate(service));
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
index d57fd4b..3b4699e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityManagerInternalTest.java
@@ -62,6 +62,8 @@
                 .getContext();
         doReturn(mServiceThreadRule.getThread().getThreadHandler()).when(mMockInjector)
                 .getUiHandler(any());
+        final ProcessList dummyList = new ProcessList();
+        doReturn(dummyList).when(mMockInjector).getProcessList(any());
         mAms = new ActivityManagerService(mMockInjector, mServiceThreadRule.getThread());
         mAmi = mAms.new LocalService();
     }
diff --git a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
index 4221575..693bc7d 100644
--- a/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/CoreSettingsObserverTest.java
@@ -23,7 +23,7 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -68,6 +68,7 @@
 
     private ActivityManagerService mAms;
     @Mock private Context mContext;
+    @Mock private Resources mResources;
 
     private MockContentResolver mContentResolver;
     private CoreSettingsObserver mCoreSettingsObserver;
@@ -94,7 +95,10 @@
         mContentResolver = new MockContentResolver(mContext);
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
-        when(mContext.getResources()).thenReturn(mock(Resources.class));
+        when(mContext.getResources()).thenReturn(mResources);
+        // To prevent NullPointerException at the constructor of ActivityManagerConstants.
+        when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
+        when(mResources.getIntArray(anyInt())).thenReturn(new int[0]);
 
         mAms = new ActivityManagerService(new TestInjector(mContext),
                 mServiceThreadRule.getThread());
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java
index af2a4be..8fe1f04 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecConfigTest.java
@@ -64,16 +64,53 @@
     }
 
     @Test
-    public void getAvailableCecSettings_Empty() {
+    public void getAllCecSettings_Empty() {
         HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
                 "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
                 + "<cec-settings>"
                 + "</cec-settings>", null);
-        assertThat(hdmiCecConfig.getAvailableSettings()).isEmpty();
+        assertThat(hdmiCecConfig.getAllSettings()).isEmpty();
     }
 
     @Test
-    public void getAvailableCecSettings_OnlyMasterXml() {
+    public void getAllCecSettings_BasicSanity() {
+        HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
+                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+                + "<cec-settings>"
+                + "  <setting name=\"hdmi_cec_enabled\""
+                + "           user-configurable=\"true\">"
+                + "    <allowed-values>"
+                + "      <value string-value=\"0\" />"
+                + "      <value string-value=\"1\" />"
+                + "    </allowed-values>"
+                + "    <default-value string-value=\"1\" />"
+                + "  </setting>"
+                + "  <setting name=\"send_standby_on_sleep\""
+                + "           user-configurable=\"false\">"
+                + "    <allowed-values>"
+                + "      <value string-value=\"to_tv\" />"
+                + "      <value string-value=\"broadcast\" />"
+                + "      <value string-value=\"none\" />"
+                + "    </allowed-values>"
+                + "    <default-value string-value=\"to_tv\" />"
+                + "  </setting>"
+                + "</cec-settings>", null);
+        assertThat(hdmiCecConfig.getAllSettings())
+                .containsExactly(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+                                 HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP);
+    }
+
+    @Test
+    public void getUserCecSettings_Empty() {
+        HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
+                "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
+                + "<cec-settings>"
+                + "</cec-settings>", null);
+        assertThat(hdmiCecConfig.getUserSettings()).isEmpty();
+    }
+
+    @Test
+    public void getUserCecSettings_OnlyMasterXml() {
         HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
                 "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
                 + "<cec-settings>"
@@ -95,13 +132,13 @@
                 + "    <default-value string-value=\"to_tv\" />"
                 + "  </setting>"
                 + "</cec-settings>", null);
-        assertThat(hdmiCecConfig.getAvailableSettings())
-                .containsExactly(HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED,
-                                 HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP);
+        assertThat(hdmiCecConfig.getUserSettings())
+                .containsExactly(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED,
+                                 HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP);
     }
 
     @Test
-    public void getAvailableCecSettings_WithOverride() {
+    public void getUserCecSettings_WithOverride() {
         HdmiCecConfig hdmiCecConfig = createHdmiCecConfig(
                 "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>"
                 + "<cec-settings>"
@@ -135,8 +172,8 @@
                 + "    <default-value string-value=\"to_tv\" />"
                 + "  </setting>"
                 + "</cec-settings>");
-        assertThat(hdmiCecConfig.getAvailableSettings())
-                .containsExactly(HdmiControlManager.SETTING_NAME_HDMI_CEC_ENABLED);
+        assertThat(hdmiCecConfig.getUserSettings())
+                .containsExactly(HdmiControlManager.CEC_SETTING_NAME_HDMI_CEC_ENABLED);
     }
 
     @Test
@@ -165,7 +202,7 @@
                 + "  </setting>"
                 + "</cec-settings>", null);
         assertThat(hdmiCecConfig.getAllowedValues(
-                    HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP))
+                    HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP))
                 .containsExactly(HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV,
                                  HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST,
                                  HdmiControlManager.SEND_STANDBY_ON_SLEEP_NONE);
@@ -197,7 +234,7 @@
                 + "  </setting>"
                 + "</cec-settings>", null);
         assertThat(hdmiCecConfig.getDefaultValue(
-                    HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP))
+                    HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP))
                 .isEqualTo(HdmiControlManager.SEND_STANDBY_ON_SLEEP_TO_TV);
     }
 
@@ -208,7 +245,7 @@
                 + "<cec-settings>"
                 + "</cec-settings>", null);
         assertThrows(IllegalArgumentException.class,
-                () -> hdmiCecConfig.getValue(mContext, "foo"));
+                () -> hdmiCecConfig.getValue("foo"));
     }
 
     @Test
@@ -230,8 +267,8 @@
                 + "    <default-value string-value=\"to_tv\" />"
                 + "  </setting>"
                 + "</cec-settings>", null);
-        assertThat(hdmiCecConfig.getValue(mContext,
-                    HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP))
+        assertThat(hdmiCecConfig.getValue(
+                    HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP))
                 .isEqualTo(HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
     }
 
@@ -255,8 +292,8 @@
                 + "    <default-value string-value=\"none\" />"
                 + "  </setting>"
                 + "</cec-settings>", null);
-        assertThat(hdmiCecConfig.getValue(mContext,
-                    HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST))
+        assertThat(hdmiCecConfig.getValue(
+                    HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST))
                 .isEqualTo(HdmiProperties.power_state_change_on_active_source_lost_values
                         .STANDBY_NOW.name().toLowerCase());
     }
@@ -268,7 +305,7 @@
                 + "<cec-settings>"
                 + "</cec-settings>", null);
         assertThrows(IllegalArgumentException.class,
-                () -> hdmiCecConfig.setValue(mContext, "foo", "bar"));
+                () -> hdmiCecConfig.setValue("foo", "bar"));
     }
 
     @Test
@@ -287,8 +324,8 @@
                 + "  </setting>"
                 + "</cec-settings>", null);
         assertThrows(IllegalArgumentException.class,
-                () -> hdmiCecConfig.setValue(mContext,
-                        HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP,
+                () -> hdmiCecConfig.setValue(
+                        HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP,
                         HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST));
     }
 
@@ -308,8 +345,8 @@
                 + "  </setting>"
                 + "</cec-settings>", null);
         assertThrows(IllegalArgumentException.class,
-                () -> hdmiCecConfig.setValue(mContext,
-                        HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP,
+                () -> hdmiCecConfig.setValue(
+                        HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP,
                         "bar"));
     }
 
@@ -328,8 +365,7 @@
                 + "    <default-value string-value=\"to_tv\" />"
                 + "  </setting>"
                 + "</cec-settings>", null);
-        hdmiCecConfig.setValue(mContext,
-                               HdmiControlManager.SETTING_NAME_SEND_STANDBY_ON_SLEEP,
+        hdmiCecConfig.setValue(HdmiControlManager.CEC_SETTING_NAME_SEND_STANDBY_ON_SLEEP,
                                HdmiControlManager.SEND_STANDBY_ON_SLEEP_BROADCAST);
         verify(mStorageAdapter).storeGlobalSetting(mContext,
                   Global.HDMI_CONTROL_SEND_STANDBY_ON_SLEEP,
@@ -350,10 +386,10 @@
                 + "    <default-value string-value=\"none\" />"
                 + "  </setting>"
                 + "</cec-settings>", null);
-        hdmiCecConfig.setValue(mContext,
-                        HdmiControlManager.SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
-                        HdmiProperties.power_state_change_on_active_source_lost_values
-                            .STANDBY_NOW.name().toLowerCase());
+        hdmiCecConfig.setValue(
+                  HdmiControlManager.CEC_SETTING_NAME_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
+                  HdmiProperties.power_state_change_on_active_source_lost_values
+                      .STANDBY_NOW.name().toLowerCase());
         verify(mStorageAdapter).storeSystemProperty(
                   HdmiCecConfig.SYSPROP_POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST,
                   HdmiProperties.power_state_change_on_active_source_lost_values
@@ -372,6 +408,6 @@
         } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
             Slog.e(TAG, "Encountered an error while reading/parsing CEC config strings", e);
         }
-        return new HdmiCecConfig(productConfig, vendorOverride, mStorageAdapter);
+        return new HdmiCecConfig(mContext, mStorageAdapter, productConfig, vendorOverride);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 9ce4ee0..f823bb9 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -74,6 +74,7 @@
 import android.service.notification.StatusBarNotification;
 import android.telecom.TelecomManager;
 import android.telephony.TelephonyManager;
+import android.text.format.DateUtils;
 import android.util.Range;
 
 import com.android.internal.app.ChooserActivity;
@@ -860,6 +861,30 @@
     }
 
     @Test
+    public void testPruneOldRecentConversations() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        shortcut.setCached(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
+
+        NotificationListenerService listenerService =
+                mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
+        when(mNotification.getShortcutId()).thenReturn(TEST_SHORTCUT_ID);
+        listenerService.onNotificationPosted(mStatusBarNotification);
+        listenerService.onNotificationRemoved(mStatusBarNotification, null,
+                NotificationListenerService.REASON_CLICK);
+
+        mDataManager.pruneOldRecentConversations(USER_ID_PRIMARY,
+                System.currentTimeMillis() + (10 * DateUtils.DAY_IN_MILLIS) + 1);
+
+        verify(mShortcutServiceInternal).uncacheShortcuts(
+                anyInt(), any(), eq(TEST_PKG_NAME), eq(Collections.singletonList(TEST_SHORTCUT_ID)),
+                eq(USER_ID_PRIMARY), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
+    }
+
+    @Test
     public void testGetLastInteraction() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
 
diff --git a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
index 3221a4d..59aff8d 100644
--- a/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/powerstats/PowerStatsServiceTest.java
@@ -20,12 +20,16 @@
 import static org.junit.Assert.fail;
 
 import android.content.Context;
+import android.hardware.power.stats.ChannelInfo;
+import android.hardware.power.stats.EnergyConsumerResult;
+import android.hardware.power.stats.EnergyMeasurement;
 
 import androidx.test.InstrumentationRegistry;
 
 import com.android.server.SystemService;
 import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
-import com.android.server.powerstats.nano.PowerStatsServiceProto;
+import com.android.server.powerstats.nano.PowerStatsServiceMeterProto;
+import com.android.server.powerstats.nano.PowerStatsServiceModelProto;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,11 +52,12 @@
 public class PowerStatsServiceTest {
     private static final String TAG = PowerStatsServiceTest.class.getSimpleName();
     private static final String DATA_STORAGE_SUBDIR = "powerstatstest";
-    private static final String DATA_STORAGE_FILENAME = "test";
+    private static final String METER_FILENAME = "metertest";
+    private static final String MODEL_FILENAME = "modeltest";
     private static final String PROTO_OUTPUT_FILENAME = "powerstats.proto";
-    private static final String RAIL_NAME = "railname";
-    private static final String SUBSYS_NAME = "subsysname";
-    private static final int POWER_RAIL_COUNT = 8;
+    private static final String CHANNEL_NAME = "channelname";
+    private static final int ENERGY_METER_COUNT = 8;
+    private static final int ENERGY_CONSUMER_COUNT = 2;
 
     private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
     private PowerStatsService mService;
@@ -75,8 +80,13 @@
         }
 
         @Override
-        String createDataStorageFilename() {
-            return DATA_STORAGE_FILENAME;
+        String createMeterFilename() {
+            return METER_FILENAME;
+        }
+
+        @Override
+        String createModelFilename() {
+            return MODEL_FILENAME;
         }
 
         @Override
@@ -86,9 +96,10 @@
 
         @Override
         PowerStatsLogger createPowerStatsLogger(Context context, File dataStoragePath,
-                String dataStorageFilename, IPowerStatsHALWrapper powerStatsHALWrapper) {
-            mPowerStatsLogger = new PowerStatsLogger(context, dataStoragePath, dataStorageFilename,
-                powerStatsHALWrapper);
+                String meterFilename, String modelFilename,
+                IPowerStatsHALWrapper powerStatsHALWrapper) {
+            mPowerStatsLogger = new PowerStatsLogger(context, dataStoragePath, meterFilename,
+                modelFilename, powerStatsHALWrapper);
             return mPowerStatsLogger;
         }
 
@@ -107,23 +118,48 @@
 
     public static final class TestPowerStatsHALWrapper implements IPowerStatsHALWrapper {
         @Override
-        public PowerStatsData.RailInfo[] readRailInfo() {
-            PowerStatsData.RailInfo[] railInfoArray = new PowerStatsData.RailInfo[POWER_RAIL_COUNT];
-            for (int i = 0; i < POWER_RAIL_COUNT; i++) {
-                railInfoArray[i] = new PowerStatsData.RailInfo(i, RAIL_NAME + i, SUBSYS_NAME + i,
-                    i);
+        public int[] getEnergyConsumerInfo() {
+            int[] energyConsumerInfoList = new int[ENERGY_CONSUMER_COUNT];
+            for (int i = 0; i < energyConsumerInfoList.length; i++) {
+                energyConsumerInfoList[i] = i;
             }
-            return railInfoArray;
+            return energyConsumerInfoList;
         }
 
         @Override
-        public PowerStatsData.EnergyData[] readEnergyData() {
-            PowerStatsData.EnergyData[] energyDataArray =
-              new PowerStatsData.EnergyData[POWER_RAIL_COUNT];
-            for (int i = 0; i < POWER_RAIL_COUNT; i++) {
-                energyDataArray[i] = new PowerStatsData.EnergyData(i, i, i);
+        public EnergyConsumerResult[] getEnergyConsumed() {
+            EnergyConsumerResult[] energyConsumedList =
+                new EnergyConsumerResult[ENERGY_CONSUMER_COUNT];
+            for (int i = 0; i < energyConsumedList.length; i++) {
+                energyConsumedList[i] = new EnergyConsumerResult();
+                energyConsumedList[i].energyConsumerId = i;
+                energyConsumedList[i].timestampMs = i;
+                energyConsumedList[i].energyUWs = i;
             }
-            return energyDataArray;
+            return energyConsumedList;
+        }
+
+        @Override
+        public ChannelInfo[] getEnergyMeterInfo() {
+            ChannelInfo[] energyMeterInfoList = new ChannelInfo[ENERGY_METER_COUNT];
+            for (int i = 0; i < energyMeterInfoList.length; i++) {
+                energyMeterInfoList[i] = new ChannelInfo();
+                energyMeterInfoList[i].channelId = i;
+                energyMeterInfoList[i].channelName = new String(CHANNEL_NAME + i);
+            }
+            return energyMeterInfoList;
+        }
+
+        @Override
+        public EnergyMeasurement[] readEnergyMeters() {
+            EnergyMeasurement[] energyMeasurementList = new EnergyMeasurement[ENERGY_METER_COUNT];
+            for (int i = 0; i < energyMeasurementList.length; i++) {
+                energyMeasurementList[i] = new EnergyMeasurement();
+                energyMeasurementList[i].channelId = i;
+                energyMeasurementList[i].timestampMs = i;
+                energyMeasurementList[i].energyUWs = i;
+            }
+            return energyMeasurementList;
         }
 
         @Override
@@ -138,7 +174,7 @@
     }
 
     @Test
-    public void testWrittenPowerStatsHALDataMatchesReadIncidentReportData()
+    public void testWrittenMeterDataMatchesReadIncidentReportData()
             throws InterruptedException, IOException {
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
@@ -152,36 +188,74 @@
         // Write on-device storage to an incident report.
         File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME);
         FileOutputStream fos = new FileOutputStream(incidentReport);
-        mPowerStatsLogger.writeToFile(fos.getFD());
+        mPowerStatsLogger.writeMeterDataToFile(fos.getFD());
 
         // Read the incident report in to a byte array.
         FileInputStream fis = new FileInputStream(incidentReport);
         byte[] fileContent = new byte[(int) incidentReport.length()];
         fis.read(fileContent);
 
-        // Parse the incident data into a PowerStatsServiceProto object.
-        PowerStatsServiceProto pssProto = PowerStatsServiceProto.parseFrom(fileContent);
+        // Parse the incident data into a PowerStatsServiceMeterProto object.
+        PowerStatsServiceMeterProto pssProto = PowerStatsServiceMeterProto.parseFrom(fileContent);
 
-        // Validate the railInfo array matches what was written to on-device storage.
-        assertTrue(pssProto.railInfo.length == POWER_RAIL_COUNT);
-        for (int i = 0; i < pssProto.railInfo.length; i++) {
-            assertTrue(pssProto.railInfo[i].index == i);
-            assertTrue(pssProto.railInfo[i].railName.equals(RAIL_NAME + i));
-            assertTrue(pssProto.railInfo[i].subsysName.equals(SUBSYS_NAME + i));
-            assertTrue(pssProto.railInfo[i].samplingRate == i);
+        // Validate the channelInfo array matches what was written to on-device storage.
+        assertTrue(pssProto.channelInfo.length == ENERGY_METER_COUNT);
+        for (int i = 0; i < pssProto.channelInfo.length; i++) {
+            assertTrue(pssProto.channelInfo[i].channelId == i);
+            assertTrue(pssProto.channelInfo[i].channelName.equals(CHANNEL_NAME + i));
         }
 
-        // Validate the energyData array matches what was written to on-device storage.
-        assertTrue(pssProto.energyData.length == POWER_RAIL_COUNT);
-        for (int i = 0; i < pssProto.energyData.length; i++) {
-            assertTrue(pssProto.energyData[i].index == i);
-            assertTrue(pssProto.energyData[i].timestampMs == i);
-            assertTrue(pssProto.energyData[i].energyUws == i);
+        // Validate the energyMeasurement array matches what was written to on-device storage.
+        assertTrue(pssProto.energyMeasurement.length == ENERGY_METER_COUNT);
+        for (int i = 0; i < pssProto.energyMeasurement.length; i++) {
+            assertTrue(pssProto.energyMeasurement[i].channelId == i);
+            assertTrue(pssProto.energyMeasurement[i].timestampMs == i);
+            assertTrue(pssProto.energyMeasurement[i].energyUws == i);
         }
     }
 
     @Test
-    public void testCorruptOnDeviceStorage() throws IOException {
+    public void testWrittenModelDataMatchesReadIncidentReportData()
+            throws InterruptedException, IOException {
+        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+        // Write data to on-device storage.
+        mTimerTrigger.logPowerStatsData();
+
+        // The above call puts a message on a handler.  Wait for
+        // it to be processed.
+        Thread.sleep(100);
+
+        // Write on-device storage to an incident report.
+        File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME);
+        FileOutputStream fos = new FileOutputStream(incidentReport);
+        mPowerStatsLogger.writeModelDataToFile(fos.getFD());
+
+        // Read the incident report in to a byte array.
+        FileInputStream fis = new FileInputStream(incidentReport);
+        byte[] fileContent = new byte[(int) incidentReport.length()];
+        fis.read(fileContent);
+
+        // Parse the incident data into a PowerStatsServiceModelProto object.
+        PowerStatsServiceModelProto pssProto = PowerStatsServiceModelProto.parseFrom(fileContent);
+
+        // Validate the energyConsumerId array matches what was written to on-device storage.
+        assertTrue(pssProto.energyConsumerId.length == ENERGY_CONSUMER_COUNT);
+        for (int i = 0; i < pssProto.energyConsumerId.length; i++) {
+            assertTrue(pssProto.energyConsumerId[i].energyConsumerId == i);
+        }
+
+        // Validate the energyConsumerResult array matches what was written to on-device storage.
+        assertTrue(pssProto.energyConsumerResult.length == ENERGY_CONSUMER_COUNT);
+        for (int i = 0; i < pssProto.energyConsumerResult.length; i++) {
+            assertTrue(pssProto.energyConsumerResult[i].energyConsumerId == i);
+            assertTrue(pssProto.energyConsumerResult[i].timestampMs == i);
+            assertTrue(pssProto.energyConsumerResult[i].energyUws == i);
+        }
+    }
+
+    @Test
+    public void testCorruptOnDeviceMeterStorage() throws IOException {
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
         // Generate random array of bytes to emulate corrupt data.
@@ -191,7 +265,7 @@
 
         // Store corrupt data in on-device storage.  Add fake timestamp to filename
         // to match format expected by FileRotator.
-        File onDeviceStorageFile = new File(mDataStorageDir, DATA_STORAGE_FILENAME + ".1234-2234");
+        File onDeviceStorageFile = new File(mDataStorageDir, METER_FILENAME + ".1234-2234");
         FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile);
         onDeviceStorageFos.write(bytes);
         onDeviceStorageFos.close();
@@ -199,33 +273,72 @@
         // Write on-device storage to an incident report.
         File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME);
         FileOutputStream incidentReportFos = new FileOutputStream(incidentReport);
-        mPowerStatsLogger.writeToFile(incidentReportFos.getFD());
+        mPowerStatsLogger.writeMeterDataToFile(incidentReportFos.getFD());
 
         // Read the incident report in to a byte array.
         FileInputStream fis = new FileInputStream(incidentReport);
         byte[] fileContent = new byte[(int) incidentReport.length()];
         fis.read(fileContent);
 
-        // Parse the incident data into a PowerStatsServiceProto object.
-        PowerStatsServiceProto pssProto = PowerStatsServiceProto.parseFrom(fileContent);
+        // Parse the incident data into a PowerStatsServiceMeterProto object.
+        PowerStatsServiceMeterProto pssProto = PowerStatsServiceMeterProto.parseFrom(fileContent);
 
-        // Valid railInfo data is written to the incident report in the call to
-        // mPowerStatsLogger.writeToFile().
-        assertTrue(pssProto.railInfo.length == POWER_RAIL_COUNT);
-        for (int i = 0; i < pssProto.railInfo.length; i++) {
-            assertTrue(pssProto.railInfo[i].index == i);
-            assertTrue(pssProto.railInfo[i].railName.equals(RAIL_NAME + i));
-            assertTrue(pssProto.railInfo[i].subsysName.equals(SUBSYS_NAME + i));
-            assertTrue(pssProto.railInfo[i].samplingRate == i);
+        // Valid channelInfo data is written to the incident report in the call to
+        // mPowerStatsLogger.writeMeterDataToFile().
+        assertTrue(pssProto.channelInfo.length == ENERGY_METER_COUNT);
+        for (int i = 0; i < pssProto.channelInfo.length; i++) {
+            assertTrue(pssProto.channelInfo[i].channelId == i);
+            assertTrue(pssProto.channelInfo[i].channelName.equals(CHANNEL_NAME + i));
         }
 
-        // No energyData should be written to the incident report since it
+        // No energyMeasurements should be written to the incident report since it
         // is all corrupt (random bytes generated above).
-        assertTrue(pssProto.energyData.length == 0);
+        assertTrue(pssProto.energyMeasurement.length == 0);
     }
 
     @Test
-    public void testNotEnoughBytesAfterLengthField() throws IOException {
+    public void testCorruptOnDeviceModelStorage() throws IOException {
+        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+        // Generate random array of bytes to emulate corrupt data.
+        Random rd = new Random();
+        byte[] bytes = new byte[100];
+        rd.nextBytes(bytes);
+
+        // Store corrupt data in on-device storage.  Add fake timestamp to filename
+        // to match format expected by FileRotator.
+        File onDeviceStorageFile = new File(mDataStorageDir, MODEL_FILENAME + ".1234-2234");
+        FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile);
+        onDeviceStorageFos.write(bytes);
+        onDeviceStorageFos.close();
+
+        // Write on-device storage to an incident report.
+        File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME);
+        FileOutputStream incidentReportFos = new FileOutputStream(incidentReport);
+        mPowerStatsLogger.writeModelDataToFile(incidentReportFos.getFD());
+
+        // Read the incident report in to a byte array.
+        FileInputStream fis = new FileInputStream(incidentReport);
+        byte[] fileContent = new byte[(int) incidentReport.length()];
+        fis.read(fileContent);
+
+        // Parse the incident data into a PowerStatsServiceModelProto object.
+        PowerStatsServiceModelProto pssProto = PowerStatsServiceModelProto.parseFrom(fileContent);
+
+        // Valid energyConsumerId data is written to the incident report in the call to
+        // mPowerStatsLogger.writeModelDataToFile().
+        assertTrue(pssProto.energyConsumerId.length == ENERGY_CONSUMER_COUNT);
+        for (int i = 0; i < pssProto.energyConsumerId.length; i++) {
+            assertTrue(pssProto.energyConsumerId[i].energyConsumerId == i);
+        }
+
+        // No energyConsumerResults should be written to the incident report since it
+        // is all corrupt (random bytes generated above).
+        assertTrue(pssProto.energyConsumerResult.length == 0);
+    }
+
+    @Test
+    public void testNotEnoughBytesAfterMeterLengthField() throws IOException {
         mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
 
         // Create corrupt data.
@@ -236,7 +349,7 @@
 
         // Store corrupt data in on-device storage.  Add fake timestamp to filename
         // to match format expected by FileRotator.
-        File onDeviceStorageFile = new File(mDataStorageDir, DATA_STORAGE_FILENAME + ".1234-2234");
+        File onDeviceStorageFile = new File(mDataStorageDir, METER_FILENAME + ".1234-2234");
         FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile);
         onDeviceStorageFos.write(data.toByteArray());
         onDeviceStorageFos.close();
@@ -244,28 +357,68 @@
         // Write on-device storage to an incident report.
         File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME);
         FileOutputStream incidentReportFos = new FileOutputStream(incidentReport);
-        mPowerStatsLogger.writeToFile(incidentReportFos.getFD());
+        mPowerStatsLogger.writeMeterDataToFile(incidentReportFos.getFD());
 
         // Read the incident report in to a byte array.
         FileInputStream fis = new FileInputStream(incidentReport);
         byte[] fileContent = new byte[(int) incidentReport.length()];
         fis.read(fileContent);
 
-        // Parse the incident data into a PowerStatsServiceProto object.
-        PowerStatsServiceProto pssProto = PowerStatsServiceProto.parseFrom(fileContent);
+        // Parse the incident data into a PowerStatsServiceMeterProto object.
+        PowerStatsServiceMeterProto pssProto = PowerStatsServiceMeterProto.parseFrom(fileContent);
 
-        // Valid railInfo data is written to the incident report in the call to
-        // mPowerStatsLogger.writeToFile().
-        assertTrue(pssProto.railInfo.length == POWER_RAIL_COUNT);
-        for (int i = 0; i < pssProto.railInfo.length; i++) {
-            assertTrue(pssProto.railInfo[i].index == i);
-            assertTrue(pssProto.railInfo[i].railName.equals(RAIL_NAME + i));
-            assertTrue(pssProto.railInfo[i].subsysName.equals(SUBSYS_NAME + i));
-            assertTrue(pssProto.railInfo[i].samplingRate == i);
+        // Valid channelInfo data is written to the incident report in the call to
+        // mPowerStatsLogger.writeMeterDataToFile().
+        assertTrue(pssProto.channelInfo.length == ENERGY_METER_COUNT);
+        for (int i = 0; i < pssProto.channelInfo.length; i++) {
+            assertTrue(pssProto.channelInfo[i].channelId == i);
+            assertTrue(pssProto.channelInfo[i].channelName.equals(CHANNEL_NAME + i));
         }
 
-        // No energyData should be written to the incident report since the
+        // No energyMeasurements should be written to the incident report since the
         // input buffer had only length and no data.
-        assertTrue(pssProto.energyData.length == 0);
+        assertTrue(pssProto.energyMeasurement.length == 0);
+    }
+
+    @Test
+    public void testNotEnoughBytesAfterModelLengthField() throws IOException {
+        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
+
+        // Create corrupt data.
+        // Length field is correct, but there is no data following the length.
+        ByteArrayOutputStream data = new ByteArrayOutputStream();
+        data.write(ByteBuffer.allocate(4).putInt(50).array());
+        byte[] test = data.toByteArray();
+
+        // Store corrupt data in on-device storage.  Add fake timestamp to filename
+        // to match format expected by FileRotator.
+        File onDeviceStorageFile = new File(mDataStorageDir, MODEL_FILENAME + ".1234-2234");
+        FileOutputStream onDeviceStorageFos = new FileOutputStream(onDeviceStorageFile);
+        onDeviceStorageFos.write(data.toByteArray());
+        onDeviceStorageFos.close();
+
+        // Write on-device storage to an incident report.
+        File incidentReport = new File(mDataStorageDir, PROTO_OUTPUT_FILENAME);
+        FileOutputStream incidentReportFos = new FileOutputStream(incidentReport);
+        mPowerStatsLogger.writeModelDataToFile(incidentReportFos.getFD());
+
+        // Read the incident report in to a byte array.
+        FileInputStream fis = new FileInputStream(incidentReport);
+        byte[] fileContent = new byte[(int) incidentReport.length()];
+        fis.read(fileContent);
+
+        // Parse the incident data into a PowerStatsServiceModelProto object.
+        PowerStatsServiceModelProto pssProto = PowerStatsServiceModelProto.parseFrom(fileContent);
+
+        // Valid energyConsumerId data is written to the incident report in the call to
+        // mPowerStatsLogger.writeModelDataToFile().
+        assertTrue(pssProto.energyConsumerId.length == ENERGY_CONSUMER_COUNT);
+        for (int i = 0; i < pssProto.energyConsumerId.length; i++) {
+            assertTrue(pssProto.energyConsumerId[i].energyConsumerId == i);
+        }
+
+        // No energyConsumerResults should be written to the incident report since the
+        // input buffer had only length and no data.
+        assertTrue(pssProto.energyConsumerResult.length == 0);
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 5016710..740505e 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -6691,7 +6691,7 @@
                 orig)));
 
         mBinderService.createConversationNotificationChannelForPackage(
-                PKG, mUid, "key", orig, "friend");
+                PKG, mUid, orig, "friend");
 
         NotificationChannel friendChannel = mBinderService.getConversationNotificationChannel(
                 PKG, 0, PKG, original.getId(), false, "friend");
@@ -6726,10 +6726,10 @@
         String conversationId = "friend";
 
         mBinderService.createConversationNotificationChannelForPackage(
-                PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(msgParcel),
+                PKG, mUid, NotificationChannel.CREATOR.createFromParcel(msgParcel),
                 conversationId);
         mBinderService.createConversationNotificationChannelForPackage(
-                PKG, mUid, "key", NotificationChannel.CREATOR.createFromParcel(callParcel),
+                PKG, mUid, NotificationChannel.CREATOR.createFromParcel(callParcel),
                 conversationId);
 
         NotificationChannel messagesChild = mBinderService.getConversationNotificationChannel(
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index dd4d718..f378345 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -32,7 +32,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.os.Process.NOBODY_UID;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
@@ -114,6 +114,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.invocation.InvocationOnMock;
 
+
 /**
  * Tests for the {@link ActivityRecord} class.
  *
@@ -844,7 +845,8 @@
         assertEquals(PAUSING, mActivity.getState());
         verify(mActivity).setVisibility(eq(false));
         verify(mActivity.mDisplayContent)
-                .prepareAppTransition(eq(TRANSIT_TASK_CLOSE), eq(false) /* alwaysKeepCurrent */);
+                .prepareAppTransitionOld(eq(TRANSIT_OLD_TASK_CLOSE),
+                        eq(false) /* alwaysKeepCurrent */);
     }
 
     /**
@@ -888,7 +890,8 @@
 
         verify(mActivity).setVisibility(eq(false));
         verify(mActivity.mDisplayContent)
-                .prepareAppTransition(eq(TRANSIT_TASK_CLOSE), eq(false) /* alwaysKeepCurrent */);
+                .prepareAppTransitionOld(eq(TRANSIT_OLD_TASK_CLOSE),
+                        eq(false) /* alwaysKeepCurrent */);
         verify(mActivity.mDisplayContent, never()).executeAppTransition();
     }
 
@@ -904,7 +907,8 @@
 
         verify(mActivity, atLeast(1)).setVisibility(eq(false));
         verify(mActivity.mDisplayContent)
-                .prepareAppTransition(eq(TRANSIT_TASK_CLOSE), eq(false) /* alwaysKeepCurrent */);
+                .prepareAppTransitionOld(eq(TRANSIT_OLD_TASK_CLOSE),
+                        eq(false) /* alwaysKeepCurrent */);
         verify(mActivity.mDisplayContent).executeAppTransition();
     }
 
@@ -922,7 +926,8 @@
         mActivity.finishIfPossible("test", false /* oomAdj */);
 
         verify(mActivity.mDisplayContent, never())
-                .prepareAppTransition(eq(TRANSIT_TASK_CLOSE), eq(false) /* alwaysKeepCurrent */);
+                .prepareAppTransitionOld(eq(TRANSIT_OLD_TASK_CLOSE),
+                        eq(false) /* alwaysKeepCurrent */);
     }
 
     /**
@@ -1668,7 +1673,7 @@
     }
 
     @Test
-    public void testCanTurnScreenOn() {
+    public void testFullscreenWindowCanTurnScreenOn() {
         mStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         doReturn(true).when(mActivity).getTurnScreenOnFlag();
 
@@ -1676,11 +1681,11 @@
     }
 
     @Test
-    public void testFreeformWindowCantTurnScreenOn() {
+    public void testFreeformWindowCanTurnScreenOn() {
         mStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
         doReturn(true).when(mActivity).getTurnScreenOnFlag();
 
-        assertFalse(mActivity.canTurnScreenOn());
+        assertTrue(mActivity.canTurnScreenOn());
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 3dc258c..caf8a72 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -70,8 +70,6 @@
 import android.os.Binder;
 import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
-import android.view.SurfaceControl;
-import android.window.ITaskOrganizer;
 
 import androidx.test.filters.SmallTest;
 
@@ -242,24 +240,6 @@
 
     @Test
     public void testRemoveOrganizedTask_UpdateStackReference() {
-        ITaskOrganizer listener = new ITaskOrganizer.Stub() {
-            @Override
-            public void onTaskAppeared(
-                    ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) { }
-
-            @Override
-            public void onTaskVanished(ActivityManager.RunningTaskInfo container) { }
-
-            @Override
-            public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
-            }
-
-            @Override
-            public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
-            }
-        };
-        mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
-
         final Task rootHomeTask = mDefaultTaskDisplayArea.getRootHomeTask();
         final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
                 .setStack(rootHomeTask)
@@ -267,7 +247,7 @@
                 .build();
         final Task secondaryStack = (Task) WindowContainer.fromBinder(
                 mAtm.mTaskOrganizerController.createRootTask(rootHomeTask.getDisplayId(),
-                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo().token.asBinder());
+                        WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token.asBinder());
 
         rootHomeTask.reparent(secondaryStack, POSITION_TOP);
         assertEquals(secondaryStack, rootHomeTask.getParent());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 8292420..3d31824 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -54,6 +54,7 @@
 import org.mockito.MockitoSession;
 
 import java.util.ArrayList;
+import java.util.function.Consumer;
 
 /**
  * Tests for the {@link ActivityTaskManagerService} class.
@@ -261,15 +262,17 @@
     public void testUpdateSleep() {
         doCallRealMethod().when(mWm.mRoot).hasAwakeDisplay();
         mSupervisor.mGoingToSleepWakeLock = mock(PowerManager.WakeLock.class);
+        final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
+                .setTask(mWm.mRoot.getDefaultTaskDisplayArea().getOrCreateRootHomeTask()).build();
         final ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
         topActivity.setState(Task.ActivityState.RESUMED, "test");
 
-        final Runnable assertTopNonSleeping = () -> {
+        final Consumer<ActivityRecord> assertTopNonSleeping = activity -> {
             assertFalse(mAtm.mInternal.isSleeping());
             assertEquals(ActivityManager.PROCESS_STATE_TOP, mAtm.mInternal.getTopProcessState());
-            assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
+            assertEquals(activity.app, mAtm.mInternal.getTopApp());
         };
-        assertTopNonSleeping.run();
+        assertTopNonSleeping.accept(topActivity);
 
         // Sleep all displays.
         mWm.mRoot.forAllDisplays(display -> doReturn(true).when(display).shouldSleep());
@@ -279,13 +282,18 @@
         assertTrue(mAtm.mInternal.isSleeping());
         assertEquals(ActivityManager.PROCESS_STATE_TOP_SLEEPING,
                 mAtm.mInternal.getTopProcessState());
-        assertNull(mAtm.mInternal.getTopApp());
+        // The top app should not change while sleeping.
+        assertEquals(topActivity.app, mAtm.mInternal.getTopApp());
+
+        // Move the current top to back, the top app should update to the next activity.
+        topActivity.getRootTask().moveToBack("test", null /* self */);
+        assertEquals(homeActivity.app, mAtm.mInternal.getTopApp());
 
         // Wake all displays.
         mWm.mRoot.forAllDisplays(display -> doReturn(false).when(display).shouldSleep());
         mAtm.updateSleepIfNeededLocked();
 
-        assertTopNonSleeping.run();
+        assertTopNonSleeping.accept(homeActivity);
     }
 }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 673feb2..30502d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -20,7 +20,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -66,7 +66,7 @@
         RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
         RemoteAnimationAdapter adapter =
                 new RemoteAnimationAdapter(new TestRemoteAnimationRunner(), 10, 1, false);
-        definition.addRemoteAnimation(TRANSIT_TASK_CHANGE_WINDOWING_MODE, adapter);
+        definition.addRemoteAnimation(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE, adapter);
         dc.registerRemoteAnimations(definition);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 1b21920..c1212f5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -20,10 +20,10 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -76,8 +76,9 @@
         translucentOpening.setVisible(false);
         mDisplayContent.mOpeningApps.add(behind);
         mDisplayContent.mOpeningApps.add(translucentOpening);
-        assertEquals(WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_OPEN,
-                mAppTransitionController.maybeUpdateTransitToTranslucentAnim(TRANSIT_TASK_OPEN));
+        assertEquals(WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_OPEN,
+                mAppTransitionController.maybeUpdateTransitToTranslucentAnim(
+                        TRANSIT_OLD_TASK_OPEN));
     }
 
     @Test
@@ -89,8 +90,9 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         translucentClosing.setOccludesParent(false);
         mDisplayContent.mClosingApps.add(translucentClosing);
-        assertEquals(WindowManager.TRANSIT_TRANSLUCENT_ACTIVITY_CLOSE,
-                mAppTransitionController.maybeUpdateTransitToTranslucentAnim(TRANSIT_TASK_CLOSE));
+        assertEquals(WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE,
+                mAppTransitionController.maybeUpdateTransitToTranslucentAnim(
+                        TRANSIT_OLD_TASK_CLOSE));
     }
 
     @Test
@@ -104,9 +106,9 @@
         translucentOpening.setVisible(false);
         mDisplayContent.mOpeningApps.add(behind);
         mDisplayContent.mOpeningApps.add(translucentOpening);
-        assertEquals(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
+        assertEquals(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE,
                 mAppTransitionController.maybeUpdateTransitToTranslucentAnim(
-                        TRANSIT_TASK_CHANGE_WINDOWING_MODE));
+                        TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE));
     }
 
     @Test
@@ -121,11 +123,11 @@
         final Task task = opening.getTask();
         mDisplayContent.mOpeningApps.add(opening);
         mDisplayContent.mClosingApps.add(closing);
-        assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task));
+        assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_ACTIVITY_OPEN, task));
         closing.getTask().removeChild(closing);
         task.addChild(closing, 0);
-        assertTrue(mAppTransitionController.isTransitWithinTask(TRANSIT_ACTIVITY_OPEN, task));
-        assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_TASK_OPEN, task));
+        assertTrue(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_ACTIVITY_OPEN, task));
+        assertFalse(mAppTransitionController.isTransitWithinTask(TRANSIT_OLD_TASK_OPEN, task));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index ee030af..485f92f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -20,11 +20,11 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
-import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
-import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -73,38 +73,40 @@
 
     @Test
     public void testKeyguardOverride() {
-        mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
-        mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
-        assertEquals(TRANSIT_KEYGUARD_GOING_AWAY, mDc.mAppTransition.getAppTransition());
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
+        assertEquals(TRANSIT_OLD_KEYGUARD_GOING_AWAY, mDc.mAppTransition.getAppTransitionOld());
     }
 
     @Test
     public void testKeyguardKeep() {
-        mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
-        mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
-        assertEquals(TRANSIT_KEYGUARD_GOING_AWAY, mDc.mAppTransition.getAppTransition());
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
+        assertEquals(TRANSIT_OLD_KEYGUARD_GOING_AWAY, mDc.mAppTransition.getAppTransitionOld());
     }
 
     @Test
     public void testForceOverride() {
-        mWm.prepareAppTransition(TRANSIT_KEYGUARD_UNOCCLUDE, false /* alwaysKeepCurrent */);
-        mDc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_KEYGUARD_UNOCCLUDE, false /* alwaysKeepCurrent */);
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */);
-        assertEquals(TRANSIT_ACTIVITY_OPEN, mDc.mAppTransition.getAppTransition());
+        assertEquals(TRANSIT_OLD_ACTIVITY_OPEN, mDc.mAppTransition.getAppTransitionOld());
     }
 
     @Test
     public void testCrashing() {
-        mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
-        mWm.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
-        assertEquals(TRANSIT_CRASHING_ACTIVITY_CLOSE, mDc.mAppTransition.getAppTransition());
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
+                false /* alwaysKeepCurrent */);
+        assertEquals(TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE, mDc.mAppTransition.getAppTransitionOld());
     }
 
     @Test
     public void testKeepKeyguard_withCrashing() {
-        mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
-        mWm.prepareAppTransition(TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */);
-        assertEquals(TRANSIT_KEYGUARD_GOING_AWAY, mDc.mAppTransition.getAppTransition());
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
+        mDc.prepareAppTransitionOld(TRANSIT_OLD_CRASHING_ACTIVITY_CLOSE,
+                false /* alwaysKeepCurrent */);
+        assertEquals(TRANSIT_OLD_KEYGUARD_GOING_AWAY, mDc.mAppTransition.getAppTransitionOld());
     }
 
     @Test
@@ -125,12 +127,12 @@
 
         // Simulate activity resume / finish flows to prepare app transition & set visibility,
         // make sure transition is set as expected for each display.
-        dc1.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
+        dc1.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
-        assertEquals(TRANSIT_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransition());
-        dc2.prepareAppTransition(TRANSIT_ACTIVITY_CLOSE,
+        assertEquals(TRANSIT_OLD_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransitionOld());
+        dc2.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_CLOSE,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
-        assertEquals(TRANSIT_ACTIVITY_CLOSE, dc2.mAppTransition.getAppTransition());
+        assertEquals(TRANSIT_OLD_ACTIVITY_CLOSE, dc2.mAppTransition.getAppTransitionOld());
         // One activity window is visible for resuming & the other activity window is invisible
         // for finishing in different display.
         activity1.setVisibility(true, false);
@@ -158,9 +160,9 @@
         dc1.mClosingApps.add(activity1);
         assertTrue(dc1.mClosingApps.size() > 0);
 
-        dc1.prepareAppTransition(TRANSIT_ACTIVITY_OPEN,
+        dc1.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
-        assertEquals(TRANSIT_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransition());
+        assertEquals(TRANSIT_OLD_ACTIVITY_OPEN, dc1.mAppTransition.getAppTransitionOld());
         assertTrue(dc1.mAppTransition.isTransitionSet());
 
         dc1.mOpeningApps.add(activity1);
@@ -201,9 +203,9 @@
 
         // Simulate activity finish flows to prepare app transition & set visibility,
         // make sure transition is set as expected.
-        dc.prepareAppTransition(TRANSIT_ACTIVITY_CLOSE,
+        dc.prepareAppTransitionOld(TRANSIT_OLD_ACTIVITY_CLOSE,
                 false /* alwaysKeepCurrent */, 0 /* flags */, false /* forceOverride */);
-        assertEquals(TRANSIT_ACTIVITY_CLOSE, dc.mAppTransition.getAppTransition());
+        assertEquals(TRANSIT_OLD_ACTIVITY_CLOSE, dc.mAppTransition.getAppTransitionOld());
         dc.mAppTransition.overridePendingAppTransitionRemote(adapter);
         exitingActivity.setVisibility(false, false);
         assertTrue(dc.mClosingApps.size() > 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 085b8de..6837e0e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -32,7 +32,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
@@ -414,7 +414,7 @@
         sources.add(activity2);
         doReturn(true).when(activity2).okToAnimate();
         doReturn(true).when(activity2).isAnimating();
-        assertTrue(activity2.applyAnimation(null, TRANSIT_ACTIVITY_OPEN, true, false, sources));
+        assertTrue(activity2.applyAnimation(null, TRANSIT_OLD_ACTIVITY_OPEN, true, false, sources));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 4d0d3b2..c9e56fd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1169,7 +1169,7 @@
 
         final ActivityRecord app = mAppWindow.mActivityRecord;
         app.setVisible(false);
-        mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
+        mDisplayContent.prepareAppTransitionOld(WindowManager.TRANSIT_OLD_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */);
         mDisplayContent.mOpeningApps.add(app);
         final int newOrientation = getRotatedOrientation(mDisplayContent);
@@ -1355,7 +1355,7 @@
         final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
         app.setVisible(false);
         app.setState(Task.ActivityState.RESUMED, "test");
-        mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
+        mDisplayContent.prepareAppTransitionOld(WindowManager.TRANSIT_OLD_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */);
         mDisplayContent.mOpeningApps.add(app);
         final int newOrientation = getRotatedOrientation(mDisplayContent);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 9b2a2db..e1aca55 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -664,20 +664,20 @@
     // Non-rotation API Tests
     // ========================
     @Test
-    public void testRespectsAppRequestedOrientationByDefault() throws Exception {
+    public void testIsNotFixedToUserRotationByDefault() throws Exception {
         mBuilder.build();
 
-        assertTrue("Display rotation should respect app requested orientation by"
-                + " default.", mTarget.respectAppRequestedOrientation());
+        assertFalse("Display rotation should respect app requested orientation by"
+                + " default.", mTarget.isFixedToUserRotation());
     }
 
     @Test
-    public void testNotRespectAppRequestedOrientation_FixedToUserRotation() throws Exception {
+    public void testIsFixedToUserRotation() throws Exception {
         mBuilder.build();
         mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
 
-        assertFalse("Display rotation shouldn't respect app requested orientation if"
-                + " fixed to user rotation.", mTarget.respectAppRequestedOrientation());
+        assertTrue("Display rotation shouldn't respect app requested orientation if"
+                + " fixed to user rotation.", mTarget.isFixedToUserRotation());
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 7fb7d40..2985796 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -476,6 +476,26 @@
         assertFalse(wallpaperWindowToken.hasFixedRotationTransform());
     }
 
+    @Test
+    public void testIsAnimatingByRecents() {
+        final ActivityRecord homeActivity = createHomeActivity();
+        final Task rootTask = createTaskStackOnDisplay(mDefaultDisplay);
+        final Task childTask = createTaskInStack(rootTask, 0 /* userId */);
+        final Task leafTask = createTaskInStack(childTask, 0 /* userId */);
+        spyOn(leafTask);
+        doReturn(true).when(leafTask).isVisible();
+
+        initializeRecentsAnimationController(mController, homeActivity);
+
+        // Verify RecentsAnimationController will animate visible leaf task by default.
+        verify(mController).addAnimation(eq(leafTask), anyBoolean(), anyBoolean(), eq(null));
+        assertTrue(leafTask.isAnimatingByRecents());
+
+        // Make sure isAnimatingByRecents will also return true when it called by the parent task.
+        assertTrue(rootTask.isAnimatingByRecents());
+        assertTrue(childTask.isAnimatingByRecents());
+    }
+
     private ActivityRecord createHomeActivity() {
         final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService)
                 .setStack(mRootHomeTask)
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index f154073..dffa790 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -539,7 +539,7 @@
         addStatusBar(mActivity.mDisplayContent);
 
         mActivity.setVisible(false);
-        mActivity.mDisplayContent.prepareAppTransition(WindowManager.TRANSIT_ACTIVITY_OPEN,
+        mActivity.mDisplayContent.prepareAppTransitionOld(WindowManager.TRANSIT_OLD_ACTIVITY_OPEN,
                 false /* alwaysKeepCurrent */);
         mActivity.mDisplayContent.mOpeningApps.add(mActivity);
         final float maxAspect = 1.8f;
@@ -584,6 +584,95 @@
         assertTrue(statusBarController.isTransparentAllowed(w));
     }
 
+    @Test
+    public void testDisplayIgnoreOrientationRequest_fixedOrientationAppLaunchedInTaskLetterbox() {
+        // Set up a display in landscape and ignoring orientation request.
+        setUpDisplaySizeWithApp(2800, 1400);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        // Portrait fixed app without max aspect.
+        prepareUnresizable(0, SCREEN_ORIENTATION_PORTRAIT);
+
+        final Rect displayBounds = mActivity.mDisplayContent.getBounds();
+        final Rect taskBounds = mTask.getBounds();
+        final Rect activityBounds = mActivity.getBounds();
+
+        // Display shouldn't be rotated.
+        assertEquals(SCREEN_ORIENTATION_UNSPECIFIED,
+                mActivity.mDisplayContent.getLastOrientation());
+        assertTrue(displayBounds.width() > displayBounds.height());
+
+        // App should launch in task level letterboxing.
+        assertTrue(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.inSizeCompatMode());
+        assertEquals(taskBounds, activityBounds);
+
+        // Task bounds should be 700x1400 with the ratio as the display.
+        assertEquals(displayBounds.height(), taskBounds.height());
+        assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
+                taskBounds.width());
+    }
+
+    @Test
+    public void testDisplayIgnoreOrientationRequest_taskLetterboxBecameSizeCompatAfterRotate() {
+        // Set up a display in landscape and ignoring orientation request.
+        setUpDisplaySizeWithApp(2800, 1400);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        // Portrait fixed app without max aspect.
+        prepareUnresizable(0, SCREEN_ORIENTATION_PORTRAIT);
+
+        final Rect activityBounds = mActivity.getBounds();
+
+        // Rotate display to portrait.
+        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
+
+        final Rect displayBounds = mActivity.mDisplayContent.getBounds();
+        final Rect newTaskBounds = mTask.getBounds();
+        final Rect newActivityBounds = mActivity.getBounds();
+        assertTrue(displayBounds.width() < displayBounds.height());
+
+        // App should be in size compat.
+        assertFalse(mTask.isTaskLetterboxed());
+        assertScaled();
+        assertEquals(activityBounds.width(), newActivityBounds.width());
+        assertEquals(activityBounds.height(), newActivityBounds.height());
+    }
+
+    @Test
+    public void testDisplayIgnoreOrientationRequest_sizeCompatAfterRotate() {
+        // Set up a display in portrait and ignoring orientation request.
+        setUpDisplaySizeWithApp(1400, 2800);
+        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+        // Portrait fixed app without max aspect.
+        prepareUnresizable(0, SCREEN_ORIENTATION_PORTRAIT);
+
+        Rect displayBounds = mActivity.mDisplayContent.getBounds();
+        Rect activityBounds = mActivity.getBounds();
+
+        // App should launch in fullscreen.
+        assertFalse(mTask.isTaskLetterboxed());
+        assertFalse(mActivity.inSizeCompatMode());
+        assertEquals(displayBounds, activityBounds);
+
+        // Rotate display to landscape.
+        rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
+
+        displayBounds = mActivity.mDisplayContent.getBounds();
+        activityBounds = mActivity.getBounds();
+        assertTrue(displayBounds.width() > displayBounds.height());
+
+        // App should be in size compat.
+        assertFalse(mTask.isTaskLetterboxed());
+        assertScaled();
+
+        // App bounds should be 700x1400 with the ratio as the display.
+        assertEquals(displayBounds.height(), activityBounds.height());
+        assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
+                activityBounds.width());
+    }
+
     private static WindowState addWindowToActivity(ActivityRecord activity) {
         final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
         params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 7975899..2fa7589 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -420,8 +420,9 @@
 
         // Without limiting to be inside the parent bounds, the out screen size should keep relative
         // to the input bounds.
+        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
         final ActivityRecord.CompatDisplayInsets compatIntsets =
-                new ActivityRecord.CompatDisplayInsets(display, task);
+                new ActivityRecord.CompatDisplayInsets(display, activity);
         task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets);
 
         assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index ee16a76..e95efe7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -150,7 +150,7 @@
             newDisplay.onRequestedOverrideConfigurationChanged(c);
             if (!mCanRotate) {
                 final DisplayRotation displayRotation = newDisplay.getDisplayRotation();
-                doReturn(false).when(displayRotation).respectAppRequestedOrientation();
+                doReturn(true).when(displayRotation).isFixedToUserRotation();
             }
             // Please add stubbing before this line. Services will start using this display in other
             // threads immediately after adding it to hierarchy. Calling doAnswer() type of stubbing
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index ce22205..feb509c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -18,7 +18,7 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -59,7 +59,7 @@
         opening.mVisibleRequested = true;
         ArrayMap<WindowContainer, Transition.ChangeInfo> participants = new ArrayMap<>();
 
-        int transitType = TRANSIT_TASK_OPEN;
+        int transitType = TRANSIT_OLD_TASK_OPEN;
 
         // Check basic both tasks participating
         participants.put(oldTask, new Transition.ChangeInfo());
@@ -113,7 +113,7 @@
         opening2.mVisibleRequested = true;
         ArrayMap<WindowContainer, Transition.ChangeInfo> participants = new ArrayMap<>();
 
-        int transitType = TRANSIT_TASK_OPEN;
+        int transitType = TRANSIT_OLD_TASK_OPEN;
 
         // Check full promotion from leaf
         participants.put(oldTask, new Transition.ChangeInfo());
@@ -152,7 +152,7 @@
         showing2.mVisibleRequested = true;
         ArrayMap<WindowContainer, Transition.ChangeInfo> participants = new ArrayMap<>();
 
-        int transitType = TRANSIT_TASK_OPEN;
+        int transitType = TRANSIT_OLD_TASK_OPEN;
 
         // Check promotion to DisplayArea
         participants.put(showing, new Transition.ChangeInfo());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 36f3a21..f5d6889 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -22,7 +22,7 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-import static android.view.WindowManager.TRANSIT_TASK_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
@@ -919,7 +919,7 @@
                     }
                 }, 0, 0, false);
         adapter.setCallingPidUid(123, 456);
-        wc.getDisplayContent().prepareAppTransition(TRANSIT_TASK_OPEN, false);
+        wc.getDisplayContent().prepareAppTransitionOld(TRANSIT_OLD_TASK_OPEN, false);
         wc.getDisplayContent().mAppTransition.overridePendingAppTransitionRemote(adapter);
         spyOn(wc);
         doReturn(true).when(wc).okToAnimate();
@@ -930,7 +930,7 @@
         // of the animation.
         ArrayList<WindowContainer<WindowState>> sources = new ArrayList<>();
         sources.add(act);
-        assertTrue(wc.applyAnimation(null, TRANSIT_TASK_OPEN, true, false, sources));
+        assertTrue(wc.applyAnimation(null, TRANSIT_OLD_TASK_OPEN, true, false, sources));
 
         assertEquals(act, wc.getTopMostActivity());
         assertTrue(wc.isAnimating());
@@ -943,7 +943,7 @@
 
         // Make sure animation finish callback will be received and reset animating state after
         // animation finish.
-        wc.getDisplayContent().mAppTransition.goodToGo(TRANSIT_TASK_OPEN, act,
+        wc.getDisplayContent().mAppTransition.goodToGo(TRANSIT_OLD_TASK_OPEN, act,
                 mDisplayContent.mOpeningApps);
         verify(wc).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION), any());
         assertFalse(wc.isAnimating());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index c790f84..7a1f65a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -479,33 +479,16 @@
 
     @Test
     public void testCreateDeleteRootTasks() {
-        ITaskOrganizer listener = new ITaskOrganizer.Stub() {
-            @Override
-            public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
-
-            @Override
-            public void onTaskVanished(RunningTaskInfo container) { }
-
-            @Override
-            public void onTaskInfoChanged(RunningTaskInfo info) {
-            }
-
-            @Override
-            public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
-            }
-        };
-        mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
-
         RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
                 Display.DEFAULT_DISPLAY,
-                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo();
+                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
                 info1.configuration.windowConfiguration.getWindowingMode());
         assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
 
         RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
                 Display.DEFAULT_DISPLAY,
-                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
+                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
                 info2.configuration.windowConfiguration.getWindowingMode());
         assertEquals(ACTIVITY_TYPE_UNDEFINED, info2.topActivityType);
@@ -539,7 +522,7 @@
         };
         mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
         RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
-                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
+                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
 
         final Task stack = createTaskStackOnDisplay(
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
@@ -597,7 +580,7 @@
         };
         mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
         RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
-                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
+                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         lastReportedTiles.clear();
         called[0] = false;
 
@@ -658,9 +641,9 @@
         };
         mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener);
         RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
-                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo();
+                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
         RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
-                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo();
+                mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
 
         final int initialRootTaskCount = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
                 mDisplayContent.mDisplayId, null /* activityTypes */).size();
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 924b286..6237be0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1006,10 +1006,10 @@
             mDisplayId = displayId;
             mService.mTaskOrganizerController.registerTaskOrganizer(this);
             WindowContainerToken primary = mService.mTaskOrganizerController.createRootTask(
-                    displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).getTaskInfo().token;
+                    displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token;
             mPrimary = WindowContainer.fromBinder(primary.asBinder()).asTask();
             WindowContainerToken secondary = mService.mTaskOrganizerController.createRootTask(
-                    displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).getTaskInfo().token;
+                    displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token;
             mSecondary = WindowContainer.fromBinder(secondary.asBinder()).asTask();
         }
         TestSplitOrganizer(ActivityTaskManagerService service) {
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 68c833c..58a01e9 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
@@ -145,7 +147,7 @@
         if (mNetworkId == CellInfo.UNAVAILABLE || mSystemId == CellInfo.UNAVAILABLE
                 || mBasestationId == CellInfo.UNAVAILABLE) return;
 
-        mGlobalCellId = String.format("%04x%04x%04x", mSystemId, mNetworkId,  mBasestationId);
+        mGlobalCellId = formatSimple("%04x%04x%04x", mSystemId, mNetworkId,  mBasestationId);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 849c613..cfb9099 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -147,7 +149,7 @@
 
         if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
 
-        mGlobalCellId = plmn + String.format("%04x%04x", mLac, mCid);
+        mGlobalCellId = plmn + formatSimple("%04x%04x", mLac, mCid);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index e6279dc..bbfab43 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -185,7 +187,7 @@
 
         if (mCi == CellInfo.UNAVAILABLE) return;
 
-        mGlobalCellId = plmn + String.format("%07x", mCi);
+        mGlobalCellId = plmn + formatSimple("%07x", mCi);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 3923c756..2d2420d 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -128,7 +130,7 @@
 
         if (mNci == CellInfo.UNAVAILABLE_LONG) return;
 
-        mGlobalCellId = plmn + String.format("%09x", mNci);
+        mGlobalCellId = plmn + formatSimple("%09x", mNci);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index e74b709..ec07d54 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.Parcel;
@@ -156,7 +158,7 @@
 
         if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
 
-        mGlobalCellId = plmn + String.format("%04x%04x", mLac, mCid);
+        mGlobalCellId = plmn + formatSimple("%04x%04x", mLac, mCid);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 40cb27e..b04a51d 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -155,7 +157,7 @@
 
         if (mLac == CellInfo.UNAVAILABLE || mCid == CellInfo.UNAVAILABLE) return;
 
-        mGlobalCellId = plmn + String.format("%04x%04x", mLac, mCid);
+        mGlobalCellId = plmn + formatSimple("%04x%04x", mLac, mCid);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index d3fca3e..2b17de6 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -1804,6 +1804,7 @@
      *
      * {@hide}
      */
+    @UnsupportedAppUsage
     @RequiresPermission(Manifest.permission.ACCESS_MESSAGES_ON_ICC)
     public boolean deleteMessageFromIcc(int messageIndex) {
         boolean success = false;
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 11667c8..2547392 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import static android.text.TextUtils.formatSimple;
+
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -423,7 +425,7 @@
         // Set text size scaled by density
         paint.setTextSize(TEXT_SIZE * metrics.density);
         // Convert sim slot index to localized string
-        final String index = String.format("%d", mSimSlotIndex + 1);
+        final String index = formatSimple("%d", mSimSlotIndex + 1);
         final Rect textBound = new Rect();
         paint.getTextBounds(index, 0, 1, textBound);
         final float xOffset = (width / 2.f) - textBound.centerX();
diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java
index 12bb366..7773c0a 100644
--- a/telephony/java/android/telephony/UiccAccessRule.java
+++ b/telephony/java/android/telephony/UiccAccessRule.java
@@ -204,13 +204,21 @@
      *     {@link TelephonyManager#CARRIER_PRIVILEGE_STATUS_NO_ACCESS}.
      */
     public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
-        // SHA-1 is for backward compatible support only, strongly discouraged for new use.
-        byte[] certHash = getCertHash(signature, "SHA-1");
         byte[] certHash256 = getCertHash(signature, "SHA-256");
-        if (matches(certHash, packageName) || matches(certHash256, packageName)) {
+        // Check SHA-256 first as it's the new standard.
+        if (matches(certHash256, packageName)) {
             return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
         }
 
+        // Then check SHA-1 for backward compatibility. This should be removed
+        // in the near future when GPD_SPE_068 fully replaces GPD_SPE_013.
+        if (this.mCertificateHash.length == 20) {
+            byte[] certHash = getCertHash(signature, "SHA-1");
+            if (matches(certHash, packageName)) {
+                return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
+            }
+        }
+
         return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
     }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index 8457039..6b974ff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -30,7 +30,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("statusBarWindowIsAlwaysVisible", enabled, bugId) {
+    all("statusBarWindowIsAlwaysVisible", bugId, enabled) {
         this.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE)
     }
 }
@@ -40,7 +40,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("navBarWindowIsAlwaysVisible", enabled, bugId) {
+    all("navBarWindowIsAlwaysVisible", bugId, enabled) {
         this.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE)
     }
 }
@@ -56,7 +56,7 @@
     val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
     val endingBounds = WindowUtils.getDisplayBounds(endRotation)
     if (allStates) {
-        all("noUncoveredRegions", enabled, bugId) {
+        all("noUncoveredRegions", bugId, enabled) {
             if (startingBounds == endingBounds) {
                 this.coversAtLeastRegion(startingBounds)
             } else {
@@ -77,21 +77,43 @@
 
 @JvmOverloads
 fun LayersAssertion.navBarLayerIsAlwaysVisible(
+    rotatesScreen: Boolean = false,
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("navBarLayerIsAlwaysVisible", enabled, bugId) {
-        this.showsLayer(NAVIGATION_BAR_WINDOW_TITLE)
+    if (rotatesScreen) {
+        all("navBarLayerIsAlwaysVisible", bugId, enabled) {
+            this.showsLayer(NAVIGATION_BAR_WINDOW_TITLE)
+                    .then()
+                    .hidesLayer(NAVIGATION_BAR_WINDOW_TITLE)
+                    .then()
+                    .showsLayer(NAVIGATION_BAR_WINDOW_TITLE)
+        }
+    } else {
+        all("navBarLayerIsAlwaysVisible", bugId, enabled) {
+            this.showsLayer(NAVIGATION_BAR_WINDOW_TITLE)
+        }
     }
 }
 
 @JvmOverloads
 fun LayersAssertion.statusBarLayerIsAlwaysVisible(
+    rotatesScreen: Boolean = false,
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("statusBarLayerIsAlwaysVisible", enabled, bugId) {
-        this.showsLayer(STATUS_BAR_WINDOW_TITLE)
+    if (rotatesScreen) {
+        all("statusBarLayerIsAlwaysVisible", bugId, enabled) {
+            this.showsLayer(STATUS_BAR_WINDOW_TITLE)
+                    .then()
+                    hidesLayer(STATUS_BAR_WINDOW_TITLE)
+                    .then()
+                    .showsLayer(STATUS_BAR_WINDOW_TITLE)
+        }
+    } else {
+        all("statusBarLayerIsAlwaysVisible", bugId, enabled) {
+            this.showsLayer(STATUS_BAR_WINDOW_TITLE)
+        }
     }
 }
 
@@ -105,10 +127,10 @@
     val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
     val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
 
-    start("navBarLayerRotatesAndScales_StartingPos", enabled, bugId) {
+    start("navBarLayerRotatesAndScales_StartingPos", bugId, enabled) {
         this.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
     }
-    end("navBarLayerRotatesAndScales_EndingPost", enabled, bugId) {
+    end("navBarLayerRotatesAndScales_EndingPost", bugId, enabled) {
         this.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos)
     }
 
@@ -129,10 +151,10 @@
     val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
     val endingPos = WindowUtils.getStatusBarPosition(endRotation)
 
-    start("statusBarLayerRotatesScales_StartingPos", enabled, bugId) {
+    start("statusBarLayerRotatesScales_StartingPos", bugId, enabled) {
         this.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, startingPos)
     }
-    end("statusBarLayerRotatesScales_EndingPos", enabled, bugId) {
+    end("statusBarLayerRotatesScales_EndingPos", bugId, enabled) {
         this.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, endingPos)
     }
 }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index 7647802..9924931 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -43,7 +43,7 @@
 
 /**
  * Test IME window closing back to app window transitions.
- * To run this test: `atest FlickerTests:CloseImeWindowToAppTest`
+ * To run this test: `atest FlickerTests:CloseImeAutoOpenWindowToHomeTest`
  */
 @Presubmit
 @RequiresDevice
@@ -94,14 +94,16 @@
                         }
 
                         layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
                             noUncoveredRegions(configuration.startRotation, Surface.ROTATION_0,
                                 allStates = false)
                             navBarLayerRotatesAndScales(configuration.startRotation,
                                 Surface.ROTATION_0, bugId = 140855415)
                             statusBarLayerRotatesScales(configuration.startRotation,
                                 Surface.ROTATION_0)
+                            navBarLayerIsAlwaysVisible(configuration.startRotation !=
+                                    Surface.ROTATION_0)
+                            statusBarLayerIsAlwaysVisible(configuration.startRotation !=
+                                    Surface.ROTATION_0)
                             imeLayerBecomesInvisible(bugId = 141458352)
                             imeAppLayerBecomesInvisible(testApp, bugId = 153739621)
                         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index 6cfb282..46f584b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -100,14 +100,16 @@
                         }
 
                         layersTrace {
-                            navBarLayerIsAlwaysVisible(bugId = 140855415)
-                            statusBarLayerIsAlwaysVisible(bugId = 140855415)
                             noUncoveredRegions(configuration.startRotation,
                                 Surface.ROTATION_0, allStates = false)
                             navBarLayerRotatesAndScales(configuration.startRotation,
                                 Surface.ROTATION_0, bugId = 140855415)
                             statusBarLayerRotatesScales(configuration.startRotation,
                                 Surface.ROTATION_0)
+                            navBarLayerIsAlwaysVisible(configuration.startRotation !=
+                                    Surface.ROTATION_0)
+                            statusBarLayerIsAlwaysVisible(configuration.startRotation !=
+                                    Surface.ROTATION_0)
                             imeLayerBecomesInvisible(bugId = 153739621)
                             imeAppLayerBecomesInvisible(testApp, bugId = 153739621)
                         }
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index b2be54f..5798624 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -27,7 +27,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeLayerBecomesVisible", enabled, bugId) {
+    all("imeLayerBecomesVisible", bugId, enabled) {
         this.hidesLayer(IME_WINDOW_TITLE)
                 .then()
                 .showsLayer(IME_WINDOW_TITLE)
@@ -38,7 +38,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeLayerBecomesInvisible", enabled, bugId) {
+    all("imeLayerBecomesInvisible", bugId, enabled) {
         this.showsLayer(IME_WINDOW_TITLE)
                 .then()
                 .hidesLayer(IME_WINDOW_TITLE)
@@ -50,7 +50,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeAppLayerIsAlwaysVisible", enabled, bugId) {
+    all("imeAppLayerIsAlwaysVisible", bugId, enabled) {
         this.showsLayer(testApp.getPackage())
     }
 }
@@ -60,7 +60,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeAppWindowIsAlwaysVisible", enabled, bugId) {
+    all("imeAppWindowIsAlwaysVisible", bugId, enabled) {
         this.showsAppWindowOnTop(testApp.getPackage())
     }
 }
@@ -69,7 +69,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeWindowBecomesInvisible", enabled, bugId) {
+    all("imeWindowBecomesInvisible", bugId, enabled) {
         this.showsNonAppWindow(IME_WINDOW_TITLE)
                 .then()
                 .hidesNonAppWindow(IME_WINDOW_TITLE)
@@ -81,7 +81,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeAppWindowBecomesInvisible", enabled, bugId) {
+    all("imeAppWindowBecomesInvisible", bugId, enabled) {
         this.showsAppWindowOnTop(testApp.getPackage())
                 .then()
                 .appWindowNotOnTop(testApp.getPackage())
@@ -93,7 +93,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("imeAppLayerBecomesInvisible", enabled, bugId) {
+    all("imeAppLayerBecomesInvisible", bugId, enabled) {
         this.skipUntilFirstAssertion()
                 .showsLayer(testApp.getPackage())
                 .then()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
index 7e857f3..d31c4ba 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/CommonAssertions.kt
@@ -24,7 +24,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("wallpaperWindowBecomesInvisible", enabled, bugId) {
+    all("wallpaperWindowBecomesInvisible", bugId, enabled) {
         this.showsBelowAppWindow("Wallpaper")
                 .then()
                 .hidesBelowAppWindow("Wallpaper")
@@ -36,7 +36,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("appWindowReplacesLauncherAsTopWindow", enabled, bugId) {
+    all("appWindowReplacesLauncherAsTopWindow", bugId, enabled) {
         this.showsAppWindowOnTop("Launcher")
                 .then()
                 .showsAppWindowOnTop("Snapshot", testApp.getPackage())
@@ -48,7 +48,7 @@
     bugId: Int = 0,
     enabled: Boolean = bugId == 0
 ) {
-    all("wallpaperLayerBecomesInvisible", enabled, bugId) {
+    all("wallpaperLayerBecomesInvisible", bugId, enabled) {
         this.showsLayer("Wallpaper")
                 .then()
                 .replaceVisibleLayer("Wallpaper", testApp.getPackage())
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 1081414..1194933 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -87,6 +87,7 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
+
                             appWindowReplacesLauncherAsTopWindow(testApp)
                             wallpaperWindowBecomesInvisible()
                         }
@@ -99,9 +100,11 @@
                                 configuration.endRotation)
                             statusBarLayerRotatesScales(Surface.ROTATION_0,
                                 configuration.endRotation)
-                            navBarLayerIsAlwaysVisible(
-                                enabled = configuration.endRotation == Surface.ROTATION_0)
-                            statusBarLayerIsAlwaysVisible(enabled = false)
+                            navBarLayerIsAlwaysVisible(Surface.ROTATION_0 !=
+                                    configuration.endRotation)
+                            statusBarLayerIsAlwaysVisible(Surface.ROTATION_0 !=
+                                    configuration.endRotation)
+
                             wallpaperLayerBecomesInvisible(testApp)
                         }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 2061994..136be29 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -91,6 +91,7 @@
                         windowManagerTrace {
                             navBarWindowIsAlwaysVisible()
                             statusBarWindowIsAlwaysVisible()
+
                             appWindowReplacesLauncherAsTopWindow(testApp)
                             wallpaperWindowBecomesInvisible(enabled = false)
                         }
@@ -103,9 +104,11 @@
                                 configuration.endRotation)
                             statusBarLayerRotatesScales(Surface.ROTATION_0,
                                 configuration.endRotation)
-                            navBarLayerIsAlwaysVisible(
-                                enabled = configuration.endRotation == Surface.ROTATION_0)
-                            statusBarLayerIsAlwaysVisible(enabled = false)
+                            navBarLayerIsAlwaysVisible(Surface.ROTATION_0 !=
+                                    configuration.endRotation)
+                            statusBarLayerIsAlwaysVisible(Surface.ROTATION_0 !=
+                                    configuration.endRotation)
+
                             wallpaperLayerBecomesInvisible(testApp)
                         }
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index b29fae3..d100383 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -173,7 +173,7 @@
                             }
                         }
 
-                        all("noUncoveredRegions"/*, bugId = 147659548*/) {
+                        all("noUncoveredRegions", bugId = 147659548) {
                             if (startingBounds == endingBounds) {
                                 this.coversAtLeastRegion(startingBounds)
                             } else {
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 9d35cbc..0e9f723 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -9,4 +9,5 @@
             "android-support-test",
             "ub-uiautomator",
         ],
+    test_suites: ["device-tests"],
 }
diff --git a/tests/Input/TEST_MAPPING b/tests/Input/TEST_MAPPING
new file mode 100644
index 0000000..15b2bfa
--- /dev/null
+++ b/tests/Input/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "InputTests"
+    }
+  ]
+}
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 1aae6cb..4081346 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -147,6 +147,7 @@
 import android.net.ConnectivityManager.TooManyRequestsException;
 import android.net.ConnectivityThread;
 import android.net.DataStallReportParcelable;
+import android.net.EthernetManager;
 import android.net.IConnectivityDiagnosticsCallback;
 import android.net.IDnsResolver;
 import android.net.IIpConnectivityMetrics;
@@ -358,6 +359,7 @@
     @Mock AppOpsManager mAppOpsManager;
     @Mock TelephonyManager mTelephonyManager;
     @Mock MockableSystemProperties mSystemProperties;
+    @Mock EthernetManager mEthernetManager;
 
     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
             ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -445,6 +447,7 @@
             if (Context.LOCATION_SERVICE.equals(name)) return mLocationManager;
             if (Context.APP_OPS_SERVICE.equals(name)) return mAppOpsManager;
             if (Context.TELEPHONY_SERVICE.equals(name)) return mTelephonyManager;
+            if (Context.ETHERNET_SERVICE.equals(name)) return mEthernetManager;
             return super.getSystemService(name);
         }
 
@@ -1274,7 +1277,6 @@
         doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
         doReturn(mIpConnectivityMetrics).when(deps).getIpConnectivityMetrics();
         doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
-        doReturn(true).when(deps).hasService(Context.ETHERNET_SERVICE);
         doAnswer(inv -> {
             mPolicyTracker = new WrappedMultinetworkPolicyTracker(
                     inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 737665f..aeb142b 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -64,26 +64,6 @@
         } catch (RemoteException e) {
             fail("Unexpected remote exception");
         }
-
-        try {
-            mWm.prepareAppTransition(0, false);
-            fail("IWindowManager.prepareAppTransition did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-
-        try {
-            mWm.executeAppTransition();
-            fail("IWindowManager.executeAppTransition did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
     }
 
     @SmallTest
diff --git a/tools/powerstats/PowerStatsServiceProtoParser.java b/tools/powerstats/PowerStatsServiceProtoParser.java
index 8ab302a..76edd63 100644
--- a/tools/powerstats/PowerStatsServiceProtoParser.java
+++ b/tools/powerstats/PowerStatsServiceProtoParser.java
@@ -25,50 +25,95 @@
  * is output to STDOUT in csv format.
  */
 public class PowerStatsServiceProtoParser {
-    private static void printRailInfo(PowerStatsServiceProto proto) {
+    private static void printEnergyMeterInfo(PowerStatsServiceMeterProto proto) {
         String csvHeader = new String();
-        for (int i = 0; i < proto.getRailInfoCount(); i++) {
-            RailInfoProto railInfo = proto.getRailInfo(i);
-            csvHeader += "Index" + ","
-                + "Timestamp" + ","
-                + railInfo.getRailName() + "/" + railInfo.getSubsysName() + ",";
+        for (int i = 0; i < proto.getChannelInfoCount(); i++) {
+            ChannelInfoProto energyMeterInfo = proto.getChannelInfo(i);
+            csvHeader += "Index,Timestamp," + energyMeterInfo.getChannelId()
+                + "/" + energyMeterInfo.getChannelName() + ",";
         }
         System.out.println(csvHeader);
     }
 
-    private static void printEnergyData(PowerStatsServiceProto proto) {
-        int railInfoCount = proto.getRailInfoCount();
+    private static void printEnergyMeasurements(PowerStatsServiceMeterProto proto) {
+        int energyMeterInfoCount = proto.getChannelInfoCount();
 
-        if (railInfoCount > 0) {
-            int energyDataCount = proto.getEnergyDataCount();
-            int energyDataSetCount = energyDataCount / railInfoCount;
+        if (energyMeterInfoCount > 0) {
+            int energyMeasurementCount = proto.getEnergyMeasurementCount();
+            int energyMeasurementSetCount = energyMeasurementCount / energyMeterInfoCount;
 
-            for (int i = 0; i < energyDataSetCount; i++) {
+            for (int i = 0; i < energyMeasurementSetCount; i++) {
                 String csvRow = new String();
-                for (int j = 0; j < railInfoCount; j++) {
-                    EnergyDataProto energyData = proto.getEnergyData(i * railInfoCount + j);
-                    csvRow += energyData.getIndex() + ","
-                        + energyData.getTimestampMs() + ","
-                        + energyData.getEnergyUws() + ",";
+                for (int j = 0; j < energyMeterInfoCount; j++) {
+                    EnergyMeasurementProto energyMeasurement =
+                            proto.getEnergyMeasurement(i * energyMeterInfoCount + j);
+                    csvRow += energyMeasurement.getChannelId() + ","
+                        + energyMeasurement.getTimestampMs() + ","
+                        + energyMeasurement.getEnergyUws() + ",";
                 }
                 System.out.println(csvRow);
             }
         } else {
-            System.out.println("Error:  railInfoCount is zero");
+            System.out.println("Error:  energyMeterInfoCount is zero");
+        }
+    }
+
+    private static void printEnergyConsumerId(PowerStatsServiceModelProto proto) {
+        String csvHeader = new String();
+        for (int i = 0; i < proto.getEnergyConsumerIdCount(); i++) {
+            EnergyConsumerIdProto energyConsumerId = proto.getEnergyConsumerId(i);
+            csvHeader += "Index,Timestamp," + energyConsumerId.getEnergyConsumerId() + ",";
+        }
+        System.out.println(csvHeader);
+    }
+
+    private static void printEnergyConsumerResults(PowerStatsServiceModelProto proto) {
+        int energyConsumerIdCount = proto.getEnergyConsumerIdCount();
+
+        if (energyConsumerIdCount > 0) {
+            int energyConsumerResultCount = proto.getEnergyConsumerResultCount();
+            int energyConsumerResultSetCount = energyConsumerResultCount / energyConsumerIdCount;
+
+            for (int i = 0; i < energyConsumerResultSetCount; i++) {
+                String csvRow = new String();
+                for (int j = 0; j < energyConsumerIdCount; j++) {
+                    EnergyConsumerResultProto energyConsumerResult =
+                            proto.getEnergyConsumerResult(i * energyConsumerIdCount + j);
+                    csvRow += energyConsumerResult.getEnergyConsumerId() + ","
+                        + energyConsumerResult.getTimestampMs() + ","
+                        + energyConsumerResult.getEnergyUws() + ",";
+                }
+                System.out.println(csvRow);
+            }
+        } else {
+            System.out.println("Error:  energyConsumerIdCount is zero");
         }
     }
 
     private static void generateCsvFile(String pathToIncidentReport) {
         try {
-            IncidentReportProto irProto =
-                    IncidentReportProto.parseFrom(new FileInputStream(pathToIncidentReport));
+            // Print power meter data.
+            IncidentReportMeterProto irMeterProto =
+                    IncidentReportMeterProto.parseFrom(new FileInputStream(pathToIncidentReport));
 
-            if (irProto.hasIncidentReport()) {
-                PowerStatsServiceProto pssProto = irProto.getIncidentReport();
-                printRailInfo(pssProto);
-                printEnergyData(pssProto);
+            if (irMeterProto.hasIncidentReport()) {
+                PowerStatsServiceMeterProto pssMeterProto = irMeterProto.getIncidentReport();
+                printEnergyMeterInfo(pssMeterProto);
+                printEnergyMeasurements(pssMeterProto);
             } else {
-                System.out.println("Incident report not found.  Exiting.");
+                System.out.println("Meter incident report not found.  Exiting.");
+            }
+
+            // Print power model data.
+            IncidentReportModelProto irModelProto =
+                    IncidentReportModelProto.parseFrom(new FileInputStream(pathToIncidentReport));
+
+            if (irModelProto.hasIncidentReport()) {
+                PowerStatsServiceModelProto pssModelProto = irModelProto.getIncidentReport();
+                printEnergyConsumerId(pssModelProto);
+                printEnergyConsumerResults(pssModelProto);
+            } else {
+                System.out.println("Model incident report not found.  Exiting.");
             }
         } catch (IOException e) {
             System.out.println("Unable to open incident report file: " + pathToIncidentReport);