Merge "Set pending client to null after timeout resumes" into rvc-dev
diff --git a/api/test-current.txt b/api/test-current.txt
index 5de6c2a..22b051b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4860,7 +4860,9 @@
   }
 
   public final class SurfaceControl implements android.os.Parcelable {
+    ctor public SurfaceControl(@NonNull android.view.SurfaceControl);
     method public static long acquireFrameRateFlexibilityToken();
+    method public boolean isSameSurface(@NonNull android.view.SurfaceControl);
     method public static void releaseFrameRateFlexibilityToken(long);
   }
 
@@ -5213,10 +5215,10 @@
     method public void onDisplayAreaAppeared(@NonNull android.window.WindowContainerToken);
     method public void onDisplayAreaVanished(@NonNull android.window.WindowContainerToken);
     method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void registerOrganizer(int);
+    field public static final int FEATURE_DEFAULT_TASK_CONTAINER = 1; // 0x1
     field public static final int FEATURE_ROOT = 0; // 0x0
     field public static final int FEATURE_SYSTEM_FIRST = 0; // 0x0
     field public static final int FEATURE_SYSTEM_LAST = 10000; // 0x2710
-    field public static final int FEATURE_TASK_CONTAINER = 1; // 0x1
     field public static final int FEATURE_UNDEFINED = -1; // 0xffffffff
     field public static final int FEATURE_VENDOR_FIRST = 10001; // 0x2711
     field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index bd15264..d1995bc 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -418,7 +418,7 @@
         AppStandbyBucketChanged app_standby_bucket_changed = 258 [(module) = "framework"];
         SharesheetStarted sharesheet_started = 259 [(module) = "framework"];
         RankingSelected ranking_selected = 260 [(module) = "framework"];
-        TvSettingsUIInteracted tvsettings_ui_interacted = 261;
+        TvSettingsUIInteracted tvsettings_ui_interacted = 261 [(module) = "tv_settings"];
         SdkExtensionStatus sdk_extension_status = 354;
     }
 
diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp
index 6d9c644..bbae3fe 100644
--- a/cmds/statsd/src/config/ConfigManager.cpp
+++ b/cmds/statsd/src/config/ConfigManager.cpp
@@ -43,20 +43,23 @@
 using std::unique_ptr;
 
 struct ConfigReceiverDeathCookie {
-    ConfigReceiverDeathCookie(sp<ConfigManager> configManager, const ConfigKey& configKey,
-                              const shared_ptr<IPendingIntentRef>& pir):
-        mConfigManager(configManager),
-        mConfigKey(configKey),
-        mPir(pir) {}
+    ConfigReceiverDeathCookie(const wp<ConfigManager>& configManager, const ConfigKey& configKey,
+                              const shared_ptr<IPendingIntentRef>& pir) :
+            mConfigManager(configManager), mConfigKey(configKey), mPir(pir) {
+    }
 
-    sp<ConfigManager> mConfigManager;
+    wp<ConfigManager> mConfigManager;
     ConfigKey mConfigKey;
     shared_ptr<IPendingIntentRef> mPir;
 };
 
 void ConfigManager::configReceiverDied(void* cookie) {
     auto cookie_ = static_cast<ConfigReceiverDeathCookie*>(cookie);
-    sp<ConfigManager>& thiz = cookie_->mConfigManager;
+    sp<ConfigManager> thiz = cookie_->mConfigManager.promote();
+    if (!thiz) {
+        return;
+    }
+
     ConfigKey& configKey = cookie_->mConfigKey;
     shared_ptr<IPendingIntentRef>& pir = cookie_->mPir;
 
@@ -74,20 +77,23 @@
 }
 
 struct ActiveConfigChangedReceiverDeathCookie {
-    ActiveConfigChangedReceiverDeathCookie(sp<ConfigManager> configManager, const int uid,
-                                           const shared_ptr<IPendingIntentRef>& pir):
-        mConfigManager(configManager),
-        mUid(uid),
-        mPir(pir) {}
+    ActiveConfigChangedReceiverDeathCookie(const wp<ConfigManager>& configManager, const int uid,
+                                           const shared_ptr<IPendingIntentRef>& pir) :
+            mConfigManager(configManager), mUid(uid), mPir(pir) {
+    }
 
-    sp<ConfigManager> mConfigManager;
+    wp<ConfigManager> mConfigManager;
     int mUid;
     shared_ptr<IPendingIntentRef> mPir;
 };
 
 void ConfigManager::activeConfigChangedReceiverDied(void* cookie) {
     auto cookie_ = static_cast<ActiveConfigChangedReceiverDeathCookie*>(cookie);
-    sp<ConfigManager>& thiz = cookie_->mConfigManager;
+    sp<ConfigManager> thiz = cookie_->mConfigManager.promote();
+    if (!thiz) {
+        return;
+    }
+
     int uid = cookie_->mUid;
     shared_ptr<IPendingIntentRef>& pir = cookie_->mPir;
 
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index 79a7e8d..ebe9610 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -44,19 +44,23 @@
 // Stores the puller as a wp to avoid holding a reference in case it is unregistered and
 // pullAtomCallbackDied is never called.
 struct PullAtomCallbackDeathCookie {
-    PullAtomCallbackDeathCookie(sp<StatsPullerManager> pullerManager, const PullerKey& pullerKey,
-                                const wp<StatsPuller>& puller)
-        : mPullerManager(pullerManager), mPullerKey(pullerKey), mPuller(puller) {
+    PullAtomCallbackDeathCookie(const wp<StatsPullerManager>& pullerManager,
+                                const PullerKey& pullerKey, const wp<StatsPuller>& puller) :
+            mPullerManager(pullerManager), mPullerKey(pullerKey), mPuller(puller) {
     }
 
-    sp<StatsPullerManager> mPullerManager;
+    wp<StatsPullerManager> mPullerManager;
     PullerKey mPullerKey;
     wp<StatsPuller> mPuller;
 };
 
 void StatsPullerManager::pullAtomCallbackDied(void* cookie) {
     PullAtomCallbackDeathCookie* cookie_ = static_cast<PullAtomCallbackDeathCookie*>(cookie);
-    sp<StatsPullerManager>& thiz = cookie_->mPullerManager;
+    sp<StatsPullerManager> thiz = cookie_->mPullerManager.promote();
+    if (!thiz) {
+        return;
+    }
+
     const PullerKey& pullerKey = cookie_->mPullerKey;
     wp<StatsPuller> puller = cookie_->mPuller;
 
diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
index 6aff9ef..4b9bac1 100644
--- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp
@@ -190,13 +190,13 @@
     int32_t uid = 123;
     values.push_back(value);
 
-    StatsPullerManager pullerManager;
-    pullerManager.RegisterPullAtomCallback(uid, pullTagId, pullCoolDownNs, pullTimeoutNs,
-                                           vector<int32_t>(), cb);
+    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+    pullerManager->RegisterPullAtomCallback(uid, pullTagId, pullCoolDownNs, pullTimeoutNs,
+                                            vector<int32_t>(), cb);
     vector<shared_ptr<LogEvent>> dataHolder;
     int64_t startTimeNs = getElapsedRealtimeNs();
     // Returns false, since StatsPuller code will evaluate the timeout.
-    EXPECT_FALSE(pullerManager.Pull(pullTagId, {uid}, &dataHolder));
+    EXPECT_FALSE(pullerManager->Pull(pullTagId, {uid}, &dataHolder));
     int64_t endTimeNs = getElapsedRealtimeNs();
     int64_t actualPullDurationNs = endTimeNs - startTimeNs;
 
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 91a8572..e599a5c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -1658,6 +1658,9 @@
         public final T getService(ContextImpl ctx) {
             final Object[] cache = ctx.mServiceCache;
             final int[] gates = ctx.mServiceInitializationStateArray;
+            boolean interrupted = false;
+
+            T ret = null;
 
             for (;;) {
                 boolean doInitialize = false;
@@ -1665,7 +1668,8 @@
                     // Return it if we already have a cached instance.
                     T service = (T) cache[mCacheIndex];
                     if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) {
-                        return service;
+                        ret = service;
+                        break; // exit the for (;;)
                     }
 
                     // If we get here, there's no cached instance.
@@ -1708,24 +1712,33 @@
                             cache.notifyAll();
                         }
                     }
-                    return service;
+                    ret = service;
+                    break; // exit the for (;;)
                 }
                 // The other threads will wait for the first thread to call notifyAll(),
                 // and go back to the top and retry.
                 synchronized (cache) {
+                    // Repeat until the state becomes STATE_READY or STATE_NOT_FOUND.
+                    // We can't respond to interrupts here; just like we can't in the "doInitialize"
+                    // path, so we remember the interrupt state here and re-interrupt later.
                     while (gates[mCacheIndex] < ContextImpl.STATE_READY) {
                         try {
+                            // Clear the interrupt state.
+                            interrupted |= Thread.interrupted();
                             cache.wait();
                         } catch (InterruptedException e) {
                             // This shouldn't normally happen, but if someone interrupts the
                             // thread, it will.
-                            Slog.wtf(TAG, "getService() interrupted");
-                            Thread.currentThread().interrupt();
-                            return null;
+                            Slog.w(TAG, "getService() interrupted");
+                            interrupted = true;
                         }
                     }
                 }
             }
+            if (interrupted) {
+                Thread.currentThread().interrupt();
+            }
+            return ret;
         }
 
         public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index b7b3c4f..5d2c9d1 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -607,6 +607,9 @@
      *                             started.
      * @param pkgDataInfoMap Map from related package names to private data directory
      *                       volume UUID and inode number.
+     * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
+     *                       volume UUID and inode number.
+     * @param bindMountAppsData whether zygote needs to mount CE and DE data.
      * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
@@ -631,13 +634,17 @@
                                            @Nullable long[] disabledCompatChanges,
                                            @Nullable Map<String, Pair<String, Long>>
                                                    pkgDataInfoMap,
+                                           @Nullable Map<String, Pair<String, Long>>
+                                                   whitelistedDataInfoMap,
+                                           boolean bindMountAppsData,
                                            boolean bindMountAppStorageDirs,
                                            @Nullable String[] zygoteArgs) {
         return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
                     zygotePolicyFlags, isTopApp, disabledCompatChanges,
-                    pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
+                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
+                    bindMountAppStorageDirs, zygoteArgs);
     }
 
     /** @hide */
@@ -661,7 +668,8 @@
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, packageName,
                     /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false,
-                disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs);
+                disabledCompatChanges, /* pkgDataInfoMap */ null,
+                /* whitelistedDataInfoMap */ null, false, false, zygoteArgs);
     }
 
     /**
diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java
index 5f3f14f..a4c99c0 100644
--- a/core/java/android/os/ZygoteProcess.java
+++ b/core/java/android/os/ZygoteProcess.java
@@ -333,6 +333,9 @@
      *                             started.
      * @param pkgDataInfoMap Map from related package names to private data directory
      *                       volume UUID and inode number.
+     * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
+     *                       volume UUID and inode number.
+     * @param bindMountAppsData whether zygote needs to mount CE and DE data.
      * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
      *
      * @param zygoteArgs Additional arguments to supply to the Zygote process.
@@ -355,6 +358,9 @@
                                                   @Nullable long[] disabledCompatChanges,
                                                   @Nullable Map<String, Pair<String, Long>>
                                                           pkgDataInfoMap,
+                                                  @Nullable Map<String, Pair<String, Long>>
+                                                          whitelistedDataInfoMap,
+                                                  boolean bindMountAppsData,
                                                   boolean bindMountAppStorageDirs,
                                                   @Nullable String[] zygoteArgs) {
         // TODO (chriswailes): Is there a better place to check this value?
@@ -367,7 +373,8 @@
                     runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                     abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                     packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
-                    pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs);
+                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
+                    bindMountAppStorageDirs, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -608,6 +615,9 @@
      * @param disabledCompatChanges a list of disabled compat changes for the process being started.
      * @param pkgDataInfoMap Map from related package names to private data directory volume UUID
      *                       and inode number.
+     * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory
+     *                       volume UUID and inode number.
+     * @param bindMountAppsData whether zygote needs to mount CE and DE data.
      * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data.
      * @param extraArgs Additional arguments to supply to the zygote process.
      * @return An object that describes the result of the attempt to start the process.
@@ -631,6 +641,9 @@
                                                       @Nullable long[] disabledCompatChanges,
                                                       @Nullable Map<String, Pair<String, Long>>
                                                               pkgDataInfoMap,
+                                                      @Nullable Map<String, Pair<String, Long>>
+                                                              whitelistedDataInfoMap,
+                                                      boolean bindMountAppsData,
                                                       boolean bindMountAppStorageDirs,
                                                       @Nullable String[] extraArgs)
                                                       throws ZygoteStartFailedEx {
@@ -728,11 +741,33 @@
             }
             argsForZygote.add(sb.toString());
         }
+        if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) {
+            StringBuilder sb = new StringBuilder();
+            sb.append(Zygote.WHITELISTED_DATA_INFO_MAP);
+            sb.append("=");
+            boolean started = false;
+            for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) {
+                if (started) {
+                    sb.append(',');
+                }
+                started = true;
+                sb.append(entry.getKey());
+                sb.append(',');
+                sb.append(entry.getValue().first);
+                sb.append(',');
+                sb.append(entry.getValue().second);
+            }
+            argsForZygote.add(sb.toString());
+        }
 
         if (bindMountAppStorageDirs) {
             argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS);
         }
 
+        if (bindMountAppsData) {
+            argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS);
+        }
+
         if (disabledCompatChanges != null && disabledCompatChanges.length > 0) {
             StringBuilder sb = new StringBuilder();
             sb.append("--disabled-compat-changes=");
@@ -1291,6 +1326,7 @@
                     true /* startChildZygote */, null /* packageName */,
                     ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */,
                     null /* disabledCompatChanges */, null /* pkgDataInfoMap */,
+                    null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/,
                     /* bindMountAppStorageDirs */ false, extraArgs);
 
         } catch (ZygoteStartFailedEx ex) {
diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java
index 69bab4d..6cb9374 100644
--- a/core/java/android/view/InsetsSourceConsumer.java
+++ b/core/java/android/view/InsetsSourceConsumer.java
@@ -91,6 +91,8 @@
         if (mSourceControl == control) {
             return;
         }
+        SurfaceControl oldLeash = mSourceControl != null ? mSourceControl.getLeash() : null;
+
         final InsetsSourceControl lastControl = mSourceControl;
         mSourceControl = control;
 
@@ -116,6 +118,12 @@
                 // However make sure that the leash visibility is still up to date.
                 if (applyLocalVisibilityOverride()) {
                     mController.notifyVisibilityChanged();
+                }
+
+                // If we have a new leash, make sure visibility is up-to-date, even though we
+                // didn't want to run an animation above.
+                SurfaceControl newLeash = mSourceControl.getLeash();
+                if (oldLeash == null || newLeash == null || !oldLeash.isSameSurface(newLeash)) {
                     applyHiddenToControl();
                 }
             }
diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java
index f3ec65f..e001b66 100644
--- a/core/java/android/view/InsetsSourceControl.java
+++ b/core/java/android/view/InsetsSourceControl.java
@@ -44,8 +44,7 @@
     public InsetsSourceControl(InsetsSourceControl other) {
         mType = other.mType;
         if (other.mLeash != null) {
-            mLeash = new SurfaceControl();
-            mLeash.copyFrom(other.mLeash);
+            mLeash = new SurfaceControl(other.mLeash);
         } else {
             mLeash = null;
         }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b5f9df7..ab65e3a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -216,6 +216,7 @@
 
     private static native void nativeSetFrameRate(
             long transactionObj, long nativeObject, float frameRate, int compatibility);
+    private static native long nativeGetHandle(long nativeObject);
 
     private static native long nativeAcquireFrameRateFlexibilityToken();
     private static native void nativeReleaseFrameRateFlexibilityToken(long token);
@@ -226,6 +227,7 @@
      * @hide
      */
     public long mNativeObject;
+    private long mNativeHandle;
 
     // TODO: Move this to native.
     private final Object mSizeLock = new Object();
@@ -428,12 +430,13 @@
             mCloseGuard.open("release");
         }
         mNativeObject = nativeObject;
+        mNativeHandle = mNativeObject != 0 ? nativeGetHandle(nativeObject) : 0;
     }
 
     /**
      * @hide
      */
-    public void copyFrom(SurfaceControl other) {
+    public void copyFrom(@NonNull SurfaceControl other) {
         mName = other.mName;
         mWidth = other.mWidth;
         mHeight = other.mHeight;
@@ -853,23 +856,19 @@
             throw new OutOfResourcesException(
                     "Couldn't allocate SurfaceControl native object");
         }
-
+        mNativeHandle = nativeGetHandle(mNativeObject);
         mCloseGuard.open("release");
     }
 
-    /** This is a transfer constructor, useful for transferring a live SurfaceControl native
-     * object to another Java wrapper which could have some different behavior, e.g.
-     * event logging.
+    /**
+     * Copy constructor. Creates a new native object pointing to the same surface as {@code other}.
+     *
+     * @param other The object to copy the surface from.
      * @hide
      */
-    public SurfaceControl(SurfaceControl other) {
-        mName = other.mName;
-        mWidth = other.mWidth;
-        mHeight = other.mHeight;
-        mNativeObject = other.mNativeObject;
-        other.mCloseGuard.close();
-        other.mNativeObject = 0;
-        mCloseGuard.open("release");
+    @TestApi
+    public SurfaceControl(@NonNull SurfaceControl other) {
+        copyFrom(other);
     }
 
     private SurfaceControl(Parcel in) {
@@ -921,6 +920,18 @@
     }
 
     /**
+     * Checks whether two {@link SurfaceControl} objects represent the same surface.
+     *
+     * @param other The other object to check
+     * @return {@code true} if these two {@link SurfaceControl} objects represent the same surface.
+     * @hide
+     */
+    @TestApi
+    public boolean isSameSurface(@NonNull SurfaceControl other) {
+        return other.mNativeHandle == mNativeHandle;
+    }
+
+    /**
      * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link
      * android.view.SurfaceControlProto}.
      *
@@ -977,6 +988,7 @@
         if (mNativeObject != 0) {
             nativeRelease(mNativeObject);
             mNativeObject = 0;
+            mNativeHandle = 0;
             mCloseGuard.close();
         }
     }
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index eee222b..6ae70b7 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -33,8 +33,8 @@
     public static final int FEATURE_SYSTEM_FIRST = 0;
     // The Root display area on a display
     public static final int FEATURE_ROOT = FEATURE_SYSTEM_FIRST;
-    // Display area hosting the task container.
-    public static final int FEATURE_TASK_CONTAINER = FEATURE_SYSTEM_FIRST + 1;
+    // Display area hosting the default task container.
+    public static final int FEATURE_DEFAULT_TASK_CONTAINER = FEATURE_SYSTEM_FIRST + 1;
     // Display area hosting non-activity window tokens.
     public static final int FEATURE_WINDOW_TOKENS = FEATURE_SYSTEM_FIRST + 2;
 
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index ff03f1a..505a05e 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -205,9 +205,15 @@
     /** List of packages with the same uid, and its app data info: volume uuid and inode. */
     public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map";
 
+    /** List of whitelisted packages and its app data info: volume uuid and inode. */
+    public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map";
+
     /** Bind mount app storage dirs to lower fs not via fuse */
     public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs";
 
+    /** Bind mount app storage dirs to lower fs not via fuse */
+    public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs";
+
     /**
      * An extraArg passed when a zygote process is forking a child-zygote, specifying a name
      * in the abstract socket namespace. This socket name is what the new child zygote
@@ -313,6 +319,8 @@
      * @param isTopApp true if the process is for top (high priority) application.
      * @param pkgDataInfoList A list that stores related packages and its app data
      * info: volume uuid and inode.
+     * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
+     * @param bindMountAppDataDirs  True if the zygote needs to mount data dirs.
      * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
      *
      * @return 0 if this is the child, pid of the child
@@ -321,13 +329,15 @@
     static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
             int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
-            boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
+            boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
+            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
         ZygoteHooks.preFork();
 
         int pid = nativeForkAndSpecialize(
                 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                 fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
-                pkgDataInfoList, bindMountAppStorageDirs);
+                pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
+                bindMountAppStorageDirs);
         if (pid == 0) {
             // Note that this event ends at the end of handleChildProc,
             Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -344,6 +354,7 @@
             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
             int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet,
             String appDataDir, boolean isTopApp, String[] pkgDataInfoList,
+            String[] whitelistedDataInfoList, boolean bindMountAppDataDirs,
             boolean bindMountAppStorageDirs);
 
     /**
@@ -371,15 +382,19 @@
      * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
      * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
      * app_b_ce_inode, ...];
+     * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps.
+     * @param bindMountAppDataDirs  True if the zygote needs to mount data dirs.
      * @param bindMountAppStorageDirs  True if the zygote needs to mount storage dirs.
      */
     private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, int mountExternal, String seInfo, String niceName,
             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
-            String[] pkgDataInfoList, boolean bindMountAppStorageDirs) {
+            String[] pkgDataInfoList, String[] whitelistedDataInfoList,
+            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
         nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo,
                 niceName, startChildZygote, instructionSet, appDataDir, isTopApp,
-                pkgDataInfoList, bindMountAppStorageDirs);
+                pkgDataInfoList, whitelistedDataInfoList,
+                bindMountAppDataDirs, bindMountAppStorageDirs);
 
         // Note that this event ends at the end of handleChildProc.
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
@@ -399,7 +414,8 @@
     private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids,
             int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName,
             boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp,
-            String[] pkgDataInfoList, boolean bindMountAppStorageDirs);
+            String[] pkgDataInfoList, String[] whitelistedDataInfoList,
+            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs);
 
     /**
      * Called to do any initialization before starting an application.
@@ -724,7 +740,8 @@
                                  args.mRuntimeFlags, rlimits, args.mMountExternal,
                                  args.mSeInfo, args.mNiceName, args.mStartChildZygote,
                                  args.mInstructionSet, args.mAppDataDir, args.mIsTopApp,
-                                 args.mPkgDataInfoList, args.mBindMountAppStorageDirs);
+                                 args.mPkgDataInfoList, args.mWhitelistedDataInfoList,
+                                 args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs);
 
             Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
@@ -1060,4 +1077,11 @@
      */
     @FastNative
     public static native int nativeParseSigChld(byte[] in, int length, int[] out);
+
+    /**
+     * Returns whether the kernel supports tagged pointers. Present in the
+     * Android Common Kernel from 4.14 and up. By default, you should prefer
+     * fully-feature Memory Tagging, rather than the static Tagged Pointers.
+     */
+    public static native boolean nativeSupportsTaggedPointers();
 }
diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java
index 1a63765..94c1f71 100644
--- a/core/java/com/android/internal/os/ZygoteArguments.java
+++ b/core/java/com/android/internal/os/ZygoteArguments.java
@@ -227,11 +227,22 @@
     String[] mPkgDataInfoList;
 
     /**
+     * A list that stores all whitelisted app data info: volume uuid and inode.
+     * Null if it does need to do app data isolation.
+     */
+    String[] mWhitelistedDataInfoList;
+
+    /**
      * @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS
      */
     boolean mBindMountAppStorageDirs;
 
     /**
+     * @see Zygote#BIND_MOUNT_APP_DATA_DIRS
+     */
+    boolean mBindMountAppDataDirs;
+
+    /**
      * Constructs instance and parses args
      *
      * @param args zygote command-line args
@@ -452,8 +463,12 @@
                 }
             } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) {
                 mPkgDataInfoList = getAssignmentList(arg);
+            } else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) {
+                mWhitelistedDataInfoList = getAssignmentList(arg);
             } else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) {
                 mBindMountAppStorageDirs = true;
+            } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) {
+                mBindMountAppDataDirs = true;
             } else {
                 break;
             }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index bc8dfd4..e6a3029 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -258,7 +258,8 @@
                 parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                 parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                 parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
-                parsedArgs.mPkgDataInfoList, parsedArgs.mBindMountAppStorageDirs);
+                parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
+                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
 
         try {
             if (pid == 0) {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ec1f516..c2b13c9 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -757,9 +757,11 @@
             Zygote.applyDebuggerSystemProperty(parsedArgs);
             Zygote.applyInvokeWithSystemProperty(parsedArgs);
 
-            /* Enable pointer tagging in the system server unconditionally. Hardware support for
-             * this is present in all ARMv8 CPUs; this flag has no effect on other platforms. */
-            parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+            if (Zygote.nativeSupportsTaggedPointers()) {
+                /* Enable pointer tagging in the system server. Hardware support for this is present
+                 * in all ARMv8 CPUs. */
+                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+            }
 
             /* Enable gwp-asan on the system server with a small probability. This is the same
              * policy as applied to native processes and system apps. */
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index b11c4c9..1cfa12d 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -1430,6 +1430,12 @@
 
     client->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius);
 }
+
+static jlong nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    SurfaceControl *surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject);
+    return reinterpret_cast<jlong>(surfaceControl->getHandle().get());
+}
+
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod sSurfaceControlMethods[] = {
@@ -1606,6 +1612,8 @@
             (void*)nativeMirrorSurface },
     {"nativeSetGlobalShadowSettings", "([F[FFFF)V",
             (void*)nativeSetGlobalShadowSettings },
+    {"nativeGetHandle", "(J)J",
+            (void*)nativeGetHandle },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index ea3c0fa..4b30359 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -110,7 +110,6 @@
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 using android::base::GetBoolProperty;
-using android::base::GetProperty;
 
 #define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
                               append(StringPrintf(__VA_ARGS__))
@@ -170,18 +169,6 @@
 
 static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751;
 
-/**
- * Property to control if app data isolation is enabled.
- */
-static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
-    "persist.zygote.app_data_isolation";
-
-/**
- * Property to enable app data isolation for sdcard obb or data in vold.
- */
-static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
-    "persist.sys.vold_app_data_isolation_enabled";
-
 static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
 static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
 
@@ -1319,20 +1306,13 @@
  * be decrypted after storage is decrypted.
  *
  */
-static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
-    uid_t uid, const char* process_name, jstring managed_nice_name,
-    fail_fn_t fail_fn) {
+static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
+    uid_t uid, const char* process_name,
+    jstring managed_nice_name, fail_fn_t fail_fn) {
 
   const userid_t userId = multiuser_get_user_id(uid);
 
-  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
-
-  int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
-  // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
-  if ((size % 3) != 0) {
-    fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size));
-  }
-  ensureInAppMountNamespace(fail_fn);
+  int size = merged_data_info_list.size();
 
   // Mount tmpfs on all possible data directories, so app no longer see the original apps data.
   char internalCePath[PATH_MAX];
@@ -1377,14 +1357,10 @@
   bool legacySymlinkCreated = false;
 
   for (int i = 0; i < size; i += 3) {
-    jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
-    std::string packageName = extract_fn(package_str).value();
+    std::string const & packageName = merged_data_info_list[i];
+    std::string const & volUuid  = merged_data_info_list[i + 1];
+    std::string const & inode = merged_data_info_list[i + 2];
 
-    jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1));
-    std::string volUuid = extract_fn(vol_str).value();
-
-    jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2));
-    std::string inode = extract_fn(inode_str).value();
     std::string::size_type sz;
     long long ceDataInode = std::stoll(inode, &sz);
 
@@ -1482,6 +1458,48 @@
   freecon(dataDataContext);
 }
 
+static void insertPackagesToMergedList(JNIEnv* env,
+  std::vector<std::string>& merged_data_info_list,
+  jobjectArray data_info_list, const char* process_name,
+  jstring managed_nice_name, fail_fn_t fail_fn) {
+
+  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+
+  int size = (data_info_list != nullptr) ? env->GetArrayLength(data_info_list) : 0;
+  // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode>
+  if ((size % 3) != 0) {
+    fail_fn(CREATE_ERROR("Wrong data_info_list size %d", size));
+  }
+
+  for (int i = 0; i < size; i += 3) {
+    jstring package_str = (jstring) (env->GetObjectArrayElement(data_info_list, i));
+    std::string packageName = extract_fn(package_str).value();
+    merged_data_info_list.push_back(packageName);
+
+    jstring vol_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 1));
+    std::string volUuid = extract_fn(vol_str).value();
+    merged_data_info_list.push_back(volUuid);
+
+    jstring inode_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 2));
+    std::string inode = extract_fn(inode_str).value();
+    merged_data_info_list.push_back(inode);
+  }
+}
+
+static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list,
+    jobjectArray whitelisted_data_info_list, uid_t uid, const char* process_name,
+    jstring managed_nice_name, fail_fn_t fail_fn) {
+
+  ensureInAppMountNamespace(fail_fn);
+  std::vector<std::string> merged_data_info_list;
+  insertPackagesToMergedList(env, merged_data_info_list, pkg_data_info_list,
+          process_name, managed_nice_name, fail_fn);
+  insertPackagesToMergedList(env, merged_data_info_list, whitelisted_data_info_list,
+          process_name, managed_nice_name, fail_fn);
+
+  isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn);
+}
+
 /**
  * Like isolateAppData(), isolate jit profile directories, so apps don't see what
  * other apps are installed by reading content inside /data/misc/profiles/cur.
@@ -1594,7 +1612,9 @@
                              jstring managed_nice_name, bool is_system_server,
                              bool is_child_zygote, jstring managed_instruction_set,
                              jstring managed_app_data_dir, bool is_top_app,
-                             jobjectArray pkg_data_info_list, bool mount_storage_dirs) {
+                             jobjectArray pkg_data_info_list,
+                             jobjectArray whitelisted_data_info_list,
+                             bool mount_data_dirs, bool mount_storage_dirs) {
   const char* process_name = is_system_server ? "system_server" : "zygote";
   auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1);
   auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
@@ -1628,9 +1648,9 @@
   // give a null in same_uid_pkgs and private_volumes so they don't need app data isolation.
   // Isolated process / webview / app zygote should be gated by SELinux and file permission
   // so they can't even traverse CE / DE directories.
-  if (pkg_data_info_list != nullptr
-      && GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) {
-    isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
+  if (mount_data_dirs) {
+    isolateAppData(env, pkg_data_info_list, whitelisted_data_info_list,
+            uid, process_name, managed_nice_name, fail_fn);
     isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
   }
   if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) {
@@ -2003,7 +2023,8 @@
         jint mount_external, jstring se_info, jstring nice_name,
         jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote,
         jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
-        jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
+        jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
+        jboolean mount_data_dirs, jboolean mount_storage_dirs) {
     jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
     if (UNLIKELY(managed_fds_to_close == nullptr)) {
@@ -2041,6 +2062,8 @@
                        mount_external, se_info, nice_name, false,
                        is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
                        is_top_app == JNI_TRUE, pkg_data_info_list,
+                       whitelisted_data_info_list,
+                       mount_data_dirs == JNI_TRUE,
                        mount_storage_dirs == JNI_TRUE);
     }
     return pid;
@@ -2076,7 +2099,8 @@
                        permitted_capabilities, effective_capabilities,
                        MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                        false, nullptr, nullptr, /* is_top_app= */ false,
-                       /* pkg_data_info_list */ nullptr, false);
+                       /* pkg_data_info_list */ nullptr,
+                       /* whitelisted_data_info_list */ nullptr, false, false);
   } else if (pid > 0) {
       // The zygote process checks whether the child process has died or not.
       ALOGI("System server process %d has been created", pid);
@@ -2206,15 +2230,16 @@
     jint runtime_flags, jobjectArray rlimits,
     jint mount_external, jstring se_info, jstring nice_name,
     jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app,
-    jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) {
+    jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list,
+    jboolean mount_data_dirs, jboolean mount_storage_dirs) {
   jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote);
 
   SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
                    capabilities, capabilities,
                    mount_external, se_info, nice_name, false,
                    is_child_zygote == JNI_TRUE, instruction_set, app_data_dir,
-                   is_top_app == JNI_TRUE, pkg_data_info_list,
-                   mount_storage_dirs == JNI_TRUE);
+                   is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list,
+                   mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE);
 }
 
 /**
@@ -2405,10 +2430,19 @@
     return -1;
 }
 
+static jboolean com_android_internal_os_Zygote_nativeSupportsTaggedPointers(JNIEnv* env, jclass) {
+#ifdef __aarch64__
+  int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+  return res >= 0 && res & PR_TAGGED_ADDR_ENABLE;
+#else
+  return false;
+#endif
+}
+
 static const JNINativeMethod gMethods[] = {
         {"nativeForkAndSpecialize",
          "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/"
-         "String;Z[Ljava/lang/String;Z)I",
+         "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I",
          (void*)com_android_internal_os_Zygote_nativeForkAndSpecialize},
         {"nativeForkSystemServer", "(II[II[[IJJ)I",
          (void*)com_android_internal_os_Zygote_nativeForkSystemServer},
@@ -2421,7 +2455,7 @@
         {"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap},
         {"nativeSpecializeAppProcess",
          "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/"
-         "String;Z[Ljava/lang/String;Z)V",
+         "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V",
          (void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess},
         {"nativeInitNativeState", "(Z)V",
          (void*)com_android_internal_os_Zygote_nativeInitNativeState},
@@ -2440,6 +2474,8 @@
          (void*)com_android_internal_os_Zygote_nativeBoostUsapPriority},
         {"nativeParseSigChld", "([BI[I)I",
          (void*)com_android_internal_os_Zygote_nativeParseSigChld},
+        {"nativeSupportsTaggedPointers", "()Z",
+         (void*)com_android_internal_os_Zygote_nativeSupportsTaggedPointers},
 };
 
 int register_com_android_internal_os_Zygote(JNIEnv* env) {
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index cbb379b..d432dda 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -696,8 +696,7 @@
 
         // Simulate binder behavior by copying SurfaceControl. Otherwise, InsetsController will
         // attempt to release mLeash directly.
-        SurfaceControl copy = new SurfaceControl();
-        copy.copyFrom(mLeash);
+        SurfaceControl copy = new SurfaceControl(mLeash);
         return new InsetsSourceControl(type, copy, new Point());
     }
 
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 59bdf3d..0389639 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -137,6 +137,7 @@
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
         <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
         <permission name="android.permission.PACKAGE_USAGE_STATS" />
+        <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.phone">
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 4150926..75ea0cb 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -47,10 +47,10 @@
     Location getLastLocation(in LocationRequest request, String packageName, String featureId);
     boolean getCurrentLocation(in LocationRequest request,
             in ICancellationSignal cancellationSignal, in ILocationListener listener,
-            String packageName, String featureId);
+            String packageName, String featureId, String listenerId);
 
     void requestLocationUpdates(in LocationRequest request, in ILocationListener listener,
-            in PendingIntent intent, String packageName, String featureId);
+            in PendingIntent intent, String packageName, String featureId, String listenerId);
     void removeUpdates(in ILocationListener listener, in PendingIntent intent);
 
     void requestGeofence(in LocationRequest request, in Geofence geofence,
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index fcbd3e5..d1b41df 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -718,7 +718,7 @@
             currentLocationRequest.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS);
         }
 
-        GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor,
+        GetCurrentLocationTransport transport = new GetCurrentLocationTransport(executor,
                 consumer);
 
         if (cancellationSignal != null) {
@@ -729,14 +729,15 @@
 
         try {
             if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal,
-                    listenerTransport, mContext.getPackageName(), mContext.getAttributionTag())) {
-                listenerTransport.register(mContext.getSystemService(AlarmManager.class),
+                    transport, mContext.getPackageName(), mContext.getAttributionTag(),
+                    transport.getListenerId())) {
+                transport.register(mContext.getSystemService(AlarmManager.class),
                         remoteCancellationSignal);
                 if (cancellationSignal != null) {
-                    cancellationSignal.setOnCancelListener(listenerTransport::cancel);
+                    cancellationSignal.setOnCancelListener(transport::cancel);
                 }
             } else {
-                listenerTransport.fail();
+                transport.fail();
             }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -1175,7 +1176,8 @@
             boolean registered = false;
             try {
                 mService.requestLocationUpdates(locationRequest, transport, null,
-                        mContext.getPackageName(), mContext.getAttributionTag());
+                        mContext.getPackageName(), mContext.getAttributionTag(),
+                        transport.getListenerId());
                 registered = true;
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
@@ -1220,7 +1222,7 @@
 
         try {
             mService.requestLocationUpdates(locationRequest, null, pendingIntent,
-                    mContext.getPackageName(), mContext.getAttributionTag());
+                    mContext.getPackageName(), mContext.getAttributionTag(), null);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2558,6 +2560,10 @@
             mRemoteCancellationSignal = null;
         }
 
+        public String getListenerId() {
+            return mConsumer.getClass().getName() + "@" + System.identityHashCode(mConsumer);
+        }
+
         public synchronized void register(AlarmManager alarmManager,
                 ICancellationSignal remoteCancellationSignal) {
             if (mConsumer == null) {
@@ -2683,6 +2689,10 @@
             return mListener;
         }
 
+        public String getListenerId() {
+            return mListener.getClass().getName() + "@" + System.identityHashCode(mListener);
+        }
+
         public void register(@NonNull Executor executor) {
             Preconditions.checkArgument(executor != null, "invalid null executor");
             mExecutor = executor;
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 23fa645..5442299 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -120,7 +120,7 @@
         private void init(DozeParameters dozeParameters) {
             mIsHighEndGfx = ActivityManager.isHighEndGfx();
             mDisplayNeedsBlanking = dozeParameters.getDisplayNeedsBlanking();
-            mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking;
+            mNeedTransition = false;
 
             // We will preserve EGL context when we are in lock screen or aod
             // to avoid janking in following transition, we need to release when back to home.
@@ -137,7 +137,7 @@
             mRenderer = getRendererInstance();
             getDisplayContext().getDisplay().getDisplayInfo(mDisplayInfo);
             setFixedSizeAllowed(true);
-            setOffsetNotificationsEnabled(true);
+            setOffsetNotificationsEnabled(mNeedTransition);
             updateSurfaceSize();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
index d33cd94..8fd840e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
@@ -56,13 +56,12 @@
             enabled: Boolean,
             offset: Int = 0
         ): RenderInfo {
-            val (fg, bg) = deviceColorMap.getValue(deviceType)
-
-            val iconKey = if (offset > 0) {
+            val key = if (offset > 0) {
                 deviceType * BUCKET_SIZE + offset
             } else deviceType
 
-            val iconState = deviceIconMap.getValue(iconKey)
+            val (fg, bg) = deviceColorMap.getValue(key)
+            val iconState = deviceIconMap.getValue(key)
             val resourceId = iconState[enabled]
             var icon: Drawable?
             if (resourceId == APP_ICON_ID) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index 55d3e83..729f934 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -38,6 +38,7 @@
 import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
 import com.android.systemui.statusbar.phone.PanelExpansionListener
+import com.android.systemui.statusbar.phone.ScrimController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import java.io.FileDescriptor
 import java.io.PrintWriter
@@ -107,6 +108,16 @@
         }
 
     /**
+     * Force stop blur effect when necessary.
+     */
+    private var scrimsVisible: Boolean = false
+        set(value) {
+            if (field == value) return
+            field = value
+            scheduleUpdate()
+        }
+
+    /**
      * Blur radius of the wake-up animation on this frame.
      */
     private var wakeAndUnlockBlurRadius = 0
@@ -142,7 +153,13 @@
         if (showingHomeControls) {
             globalActionsRadius = 0
         }
-        val blur = max(shadeRadius.toInt(), globalActionsRadius)
+        var blur = max(shadeRadius.toInt(), globalActionsRadius)
+
+        // Make blur be 0 if it is necessary to stop blur effect.
+        if (scrimsVisible) {
+            blur = 0
+        }
+
         blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur)
         try {
             wallpaperManager.setWallpaperZoomOut(root.windowToken,
@@ -202,6 +219,10 @@
                 brightnessMirrorSpring.finishIfRunning()
             }
         }
+
+        override fun onDozeAmountChanged(linear: Float, eased: Float) {
+            wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased)
+        }
     }
 
     init {
@@ -210,6 +231,10 @@
             keyguardStateController.addCallback(keyguardStateCallback)
         }
         statusBarStateController.addCallback(statusBarStateCallback)
+        notificationShadeWindowController.setScrimsVisibilityListener {
+            // Stop blur effect when scrims is opaque to avoid unnecessary GPU composition.
+            visibility -> scrimsVisible = visibility == ScrimController.OPAQUE
+        }
     }
 
     /**
@@ -225,7 +250,8 @@
 
     private fun updateShadeBlur() {
         var newBlur = 0
-        if (statusBarStateController.state == StatusBarState.SHADE) {
+        val state = statusBarStateController.state
+        if (state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) {
             val animatedBlur =
                     Interpolators.SHADE_ANIMATION.getInterpolation(
                             MathUtils.constrain(shadeExpansion / 0.15f, 0f, 1f))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index e1e679f..462b42a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -61,6 +61,7 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.function.Consumer;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -92,6 +93,7 @@
     private final State mCurrentState = new State();
     private OtherwisedCollapsedListener mListener;
     private ForcePluginOpenListener mForcePluginOpenListener;
+    private Consumer<Integer> mScrimsVisibilityListener;
     private final ArrayList<WeakReference<StatusBarWindowCallback>>
             mCallbacks = Lists.newArrayList();
 
@@ -150,6 +152,16 @@
         mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback));
     }
 
+    /**
+     * Register a listener to monitor scrims visibility
+     * @param listener A listener to monitor scrims visibility
+     */
+    public void setScrimsVisibilityListener(Consumer<Integer> listener) {
+        if (listener != null && mScrimsVisibilityListener != listener) {
+            mScrimsVisibilityListener = listener;
+        }
+    }
+
     private boolean shouldEnableKeyguardScreenRotation() {
         Resources res = mContext.getResources();
         return SystemProperties.getBoolean("lockscreen.rot_override", false)
@@ -477,6 +489,7 @@
     public void setScrimsVisibility(int scrimsVisibility) {
         mCurrentState.mScrimsVisibility = scrimsVisibility;
         apply(mCurrentState);
+        mScrimsVisibilityListener.accept(scrimsVisibility);
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
index 475023e..5227aaf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -160,7 +160,7 @@
                 LOW_BMP_HEIGHT /* bmpHeight */,
                 LOW_BMP_WIDTH /* surfaceWidth */,
                 LOW_BMP_HEIGHT /* surfaceHeight */,
-                true /* assertion */);
+                false /* assertion */);
     }
 
     @Test
@@ -172,7 +172,7 @@
                 INVALID_BMP_HEIGHT /* bmpHeight */,
                 ImageWallpaper.GLEngine.MIN_SURFACE_WIDTH /* surfaceWidth */,
                 ImageWallpaper.GLEngine.MIN_SURFACE_HEIGHT /* surfaceHeight */,
-                true /* assertion */);
+                false /* assertion */);
     }
 
     private void verifySurfaceSizeAndAssertTransition(int bmpWidth, int bmpHeight,
diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp
index 1a1c30d..620261b 100644
--- a/packages/Tethering/tests/integration/Android.bp
+++ b/packages/Tethering/tests/integration/Android.bp
@@ -39,4 +39,9 @@
         "android.test.base",
         "android.test.mock",
     ],
+    jni_libs: [
+        // For mockito extended
+        "libdexmakerjvmtiagent",
+        "libstaticjvmtiagent",
+    ],
 }
diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index dbd68ef..b02bb23 100644
--- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -205,7 +205,7 @@
                 requestWithStaticIpv4(localAddr, clientAddr));
 
         mTetheringEventCallback.awaitInterfaceTethered();
-        assertInterfaceHasIpAddress(iface, clientAddr);
+        assertInterfaceHasIpAddress(iface, localAddr);
 
         byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray();
         byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray();
diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
index 93bffe9..52a82dd 100644
--- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
+++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java
@@ -36,10 +36,12 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.PackageMonitor;
 
 import libcore.io.IoUtils;
 
@@ -261,22 +263,7 @@
 
             // And reset to the wallpaper service we should be using
             ComponentName wpService = parseWallpaperComponent(infoStage, "wp");
-            if (servicePackageExists(wpService)) {
-                Slog.i(TAG, "Using wallpaper service " + wpService);
-                mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
-                if (!lockImageStage.exists()) {
-                    // We have a live wallpaper and no static lock image,
-                    // allow live wallpaper to show "through" on lock screen.
-                    mWm.clear(FLAG_LOCK);
-                }
-            } else {
-                // If we've restored a live wallpaper, but the component doesn't exist,
-                // we should log it as an error so we can easily identify the problem
-                // in reports from users
-                if (wpService != null) {
-                    Slog.e(TAG, "Wallpaper service " + wpService + " isn't available.");
-                }
-            }
+            updateWallpaperComponent(wpService, !lockImageStage.exists());
         } catch (Exception e) {
             Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
         } finally {
@@ -293,6 +280,28 @@
         }
     }
 
+    @VisibleForTesting
+    void updateWallpaperComponent(ComponentName wpService, boolean applyToLock) throws IOException {
+        if (servicePackageExists(wpService)) {
+            Slog.i(TAG, "Using wallpaper service " + wpService);
+            mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
+            if (applyToLock) {
+                // We have a live wallpaper and no static lock image,
+                // allow live wallpaper to show "through" on lock screen.
+                mWm.clear(FLAG_LOCK);
+            }
+        } else {
+            // If we've restored a live wallpaper, but the component doesn't exist,
+            // we should log it as an error so we can easily identify the problem
+            // in reports from users
+            if (wpService != null) {
+                applyComponentAtInstall(wpService, applyToLock);
+                Slog.w(TAG, "Wallpaper service " + wpService + " isn't available. "
+                        + " Will try to apply later");
+            }
+        }
+    }
+
     private void restoreFromStage(File stage, File info, String hintTag, int which)
             throws IOException {
         if (stage.exists()) {
@@ -372,7 +381,8 @@
         return (value == null) ? defValue : Integer.parseInt(value);
     }
 
-    private boolean servicePackageExists(ComponentName comp) {
+    @VisibleForTesting
+    boolean servicePackageExists(ComponentName comp) {
         try {
             if (comp != null) {
                 final IPackageManager pm = AppGlobals.getPackageManager();
@@ -401,4 +411,53 @@
             throws IOException {
         // Intentionally blank
     }
+
+    private void applyComponentAtInstall(ComponentName componentName, boolean applyToLock) {
+        PackageMonitor packageMonitor = getWallpaperPackageMonitor(componentName, applyToLock);
+        packageMonitor.register(getBaseContext(), null, UserHandle.ALL, true);
+    }
+
+    @VisibleForTesting
+    PackageMonitor getWallpaperPackageMonitor(ComponentName componentName, boolean applyToLock) {
+        return new PackageMonitor() {
+            @Override
+            public void onPackageAdded(String packageName, int uid) {
+                if (!isDeviceInRestore()) {
+                    // We don't want to reapply the wallpaper outside a restore.
+                    unregister();
+                    return;
+                }
+
+                if (componentName.getPackageName().equals(packageName)) {
+                    Slog.d(TAG, "Applying component " + componentName);
+                    mWm.setWallpaperComponent(componentName);
+                    if (applyToLock) {
+                        try {
+                            mWm.clear(FLAG_LOCK);
+                        } catch (IOException e) {
+                            Slog.w(TAG, "Failed to apply live wallpaper to lock screen: " + e);
+                        }
+                    }
+                    // We're only expecting to restore the wallpaper component once.
+                    unregister();
+                }
+            }
+        };
+    }
+
+    @VisibleForTesting
+    boolean isDeviceInRestore() {
+        try {
+            boolean isInSetup = Settings.Secure.getInt(getBaseContext().getContentResolver(),
+                    Settings.Secure.USER_SETUP_COMPLETE) == 0;
+            boolean isInDeferredSetup = Settings.Secure.getInt(getBaseContext()
+                            .getContentResolver(),
+                    Settings.Secure.USER_SETUP_PERSONALIZATION_STATE) ==
+                    Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED;
+            return isInSetup || isInDeferredSetup;
+        } catch (Settings.SettingNotFoundException e) {
+            Slog.w(TAG, "Failed to check if the user is in restore: " + e);
+            return false;
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
similarity index 65%
rename from packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java
rename to packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
index 255fdef..4367075 100644
--- a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java
+++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.wallpaperbackup.tests;
+package com.android.wallpaperbackup;
 
 import static android.app.WallpaperManager.FLAG_LOCK;
 import static android.app.WallpaperManager.FLAG_SYSTEM;
@@ -26,17 +26,22 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.WallpaperManager;
 import android.app.backup.FullBackupDataOutput;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.SharedPreferences;
 import android.os.UserHandle;
 
 import androidx.test.core.app.ApplicationProvider;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.content.PackageMonitor;
 import com.android.wallpaperbackup.WallpaperBackupAgent;
 import com.android.wallpaperbackup.utils.ContextWithServiceOverrides;
 
@@ -58,6 +63,7 @@
 public class WallpaperBackupAgentTest {
     private static final String SYSTEM_GENERATION = "system_gen";
     private static final String LOCK_GENERATION = "lock_gen";
+    private static final String TEST_WALLPAPER_PACKAGE = "wallpaper_package";
 
     private static final int TEST_SYSTEM_WALLPAPER_ID = 1;
     private static final int TEST_LOCK_WALLPAPER_ID = 2;
@@ -66,11 +72,13 @@
     @Mock private WallpaperManager mWallpaperManager;
     @Mock private SharedPreferences mSharedPreferences;
     @Mock private SharedPreferences.Editor mSharedPreferenceEditor;
+    @Mock private Context mMockContext;
 
     @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
 
     private ContextWithServiceOverrides mContext;
     private IsolatedWallpaperBackupAgent mWallpaperBackupAgent;
+    private ComponentName mWallpaperComponent;
 
     @Before
     public void setUp() {
@@ -88,6 +96,8 @@
         mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot());
         mWallpaperBackupAgent.attach(mContext);
         mWallpaperBackupAgent.onCreate();
+
+        mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, "");
     }
 
     @Test
@@ -130,6 +140,69 @@
         inOrder.verify(mSharedPreferenceEditor).apply();
     }
 
+    @Test
+    public void updateWallpaperComponent_doesApplyLater() throws IOException {
+        mWallpaperBackupAgent.mIsDeviceInRestore = true;
+
+        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
+                /* applyToLock */ true);
+
+        // Imitate wallpaper component installation.
+        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
+                /* uid */0);
+
+        verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent);
+        verify(mWallpaperManager, times(1)).clear(eq(FLAG_LOCK));
+    }
+
+    @Test
+    public void updateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen()
+            throws IOException {
+        mWallpaperBackupAgent.mIsDeviceInRestore = true;
+
+        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
+                /* applyToLock */ false);
+
+        // Imitate wallpaper component installation.
+        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
+                /* uid */0);
+
+        verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent);
+        verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
+    }
+
+    @Test
+    public void updateWallpaperComponent_deviceNotInRestore_doesNotApply()
+            throws IOException {
+        mWallpaperBackupAgent.mIsDeviceInRestore = false;
+
+        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
+                /* applyToLock */ true);
+
+        // Imitate wallpaper component installation.
+        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
+                /* uid */0);
+
+        verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent);
+        verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
+    }
+
+    @Test
+    public void updateWallpaperComponent_differentPackageInstalled_doesNotApply()
+            throws IOException {
+        mWallpaperBackupAgent.mIsDeviceInRestore = false;
+
+        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
+                /* applyToLock */ true);
+
+        // Imitate "wrong" wallpaper component installation.
+        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(/* packageName */"",
+                /* uid */0);
+
+        verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent);
+        verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
+    }
+
     private void mockUnbackedUpState() {
         mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
         when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(-1);
@@ -162,6 +235,8 @@
     private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent {
         File mWallpaperBaseDirectory;
         List<File> mBackedUpFiles = new ArrayList<>();
+        PackageMonitor mWallpaperPackageMonitor;
+        boolean mIsDeviceInRestore = false;
 
         IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory) {
             mWallpaperBaseDirectory = wallpaperBaseDirectory;
@@ -181,5 +256,27 @@
         public SharedPreferences getSharedPreferences(File file, int mode) {
             return mSharedPreferences;
         }
+
+        @Override
+        boolean servicePackageExists(ComponentName comp) {
+            return false;
+        }
+
+        @Override
+        boolean isDeviceInRestore() {
+            return mIsDeviceInRestore;
+        }
+
+        @Override
+        PackageMonitor getWallpaperPackageMonitor(ComponentName componentName,
+                boolean applyToLock) {
+            mWallpaperPackageMonitor = super.getWallpaperPackageMonitor(componentName, applyToLock);
+            return mWallpaperPackageMonitor;
+        }
+
+        @Override
+        public Context getBaseContext() {
+            return mMockContext;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 192ea72..3c0d880 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -119,8 +119,6 @@
     private static final int MESSAGE_DISABLE = 2;
     private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3;
     private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4;
-    private static final int MESSAGE_REGISTER_ADAPTER = 20;
-    private static final int MESSAGE_UNREGISTER_ADAPTER = 21;
     private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30;
     private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31;
     private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40;
@@ -642,10 +640,9 @@
             Slog.w(TAG, "Callback is null in registerAdapter");
             return null;
         }
-        Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER);
-        msg.obj = callback;
-        mHandler.sendMessage(msg);
-
+        synchronized (mCallbacks) {
+            mCallbacks.register(callback);
+        }
         return mBluetooth;
     }
 
@@ -655,9 +652,9 @@
             return;
         }
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER);
-        msg.obj = callback;
-        mHandler.sendMessage(msg);
+        synchronized (mCallbacks) {
+            mCallbacks.unregister(callback);
+        }
     }
 
     public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
@@ -1559,18 +1556,20 @@
      * Inform BluetoothAdapter instances that Adapter service is up
      */
     private void sendBluetoothServiceUpCallback() {
-        try {
-            int n = mCallbacks.beginBroadcast();
-            Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
-            for (int i = 0; i < n; i++) {
-                try {
-                    mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+        synchronized (mCallbacks) {
+            try {
+                int n = mCallbacks.beginBroadcast();
+                Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers.");
+                for (int i = 0; i < n; i++) {
+                    try {
+                        mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e);
+                    }
                 }
+            } finally {
+                mCallbacks.finishBroadcast();
             }
-        } finally {
-            mCallbacks.finishBroadcast();
         }
     }
 
@@ -1578,18 +1577,20 @@
      * Inform BluetoothAdapter instances that Adapter service is down
      */
     private void sendBluetoothServiceDownCallback() {
-        try {
-            int n = mCallbacks.beginBroadcast();
-            Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
-            for (int i = 0; i < n; i++) {
-                try {
-                    mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
+        synchronized (mCallbacks) {
+            try {
+                int n = mCallbacks.beginBroadcast();
+                Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers.");
+                for (int i = 0; i < n; i++) {
+                    try {
+                        mCallbacks.getBroadcastItem(i).onBluetoothServiceDown();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e);
+                    }
                 }
+            } finally {
+                mCallbacks.finishBroadcast();
             }
-        } finally {
-            mCallbacks.finishBroadcast();
         }
     }
 
@@ -1917,17 +1918,6 @@
                                 mContext.getPackageName());
                     }
                     break;
-
-                case MESSAGE_REGISTER_ADAPTER: {
-                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
-                    mCallbacks.register(callback);
-                    break;
-                }
-                case MESSAGE_UNREGISTER_ADAPTER: {
-                    IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj;
-                    mCallbacks.unregister(callback);
-                    break;
-                }
                 case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: {
                     IBluetoothStateChangeCallback callback =
                             (IBluetoothStateChangeCallback) msg.obj;
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index a9c3079..7f25de6b 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1836,12 +1836,13 @@
 
     @Override
     public void requestLocationUpdates(LocationRequest request, ILocationListener listener,
-            PendingIntent intent, String packageName, String featureId) {
+            PendingIntent intent, String packageName, String featureId, String listenerId) {
         if (request == null) {
             request = DEFAULT_LOCATION_REQUEST;
         }
 
-        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId);
+        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId,
+                listenerId);
         identity.enforceLocationPermission();
 
         WorkSource workSource = request.getWorkSource();
@@ -2027,7 +2028,7 @@
     @Override
     public boolean getCurrentLocation(LocationRequest locationRequest,
             ICancellationSignal remoteCancellationSignal, ILocationListener listener,
-            String packageName, String featureId) {
+            String packageName, String featureId, String listenerId) {
         // side effect of validating locationRequest and packageName
         Location lastLocation = getLastLocation(locationRequest, packageName, featureId);
         if (lastLocation != null) {
@@ -2052,7 +2053,7 @@
             }
         }
 
-        requestLocationUpdates(locationRequest, listener, null, packageName, featureId);
+        requestLocationUpdates(locationRequest, listener, null, packageName, featureId, listenerId);
         CancellationSignal cancellationSignal = CancellationSignal.fromTransport(
                 remoteCancellationSignal);
         if (cancellationSignal != null) {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 0671477..9aefc8d 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4468,9 +4468,8 @@
                             String.format("/storage/emulated/%d/Android/data/%s/",
                                     userId, pkg);
 
-                    int appUid =
-                            UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
                     // Create package obb and data dir if it doesn't exist.
+                    int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid());
                     File file = new File(packageObbDir);
                     if (!file.exists()) {
                         vold.setupAppDir(packageObbDir, appUid);
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index dbcb3da..2d6ef81 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -231,7 +231,8 @@
         final ServiceThread adjusterThread =
                 new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST, false /* allowIo */);
         adjusterThread.start();
-        Process.setThreadGroupAndCpuset(adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP);
+        adjusterThread.getThreadHandler().post(() -> Process.setThreadGroupAndCpuset(
+                adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP));
         return adjusterThread;
     }
 
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 595275d..786e9cf 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -97,6 +97,7 @@
 import android.system.Os;
 import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.EventLog;
 import android.util.LongSparseArray;
 import android.util.Pair;
@@ -137,6 +138,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * Activity manager code dealing with processes.
@@ -1846,11 +1848,13 @@
                 runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE;
             }
 
-            // Enable heap pointer tagging, unless disabled by the app manifest, target sdk level,
-            // or the compat feature.
-            if (app.info.allowsNativeHeapPointerTagging()
-                    && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
-                runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+            if (Zygote.nativeSupportsTaggedPointers()) {
+                // Enable heap pointer tagging if supported by the kernel, unless disabled by the
+                // app manifest, target sdk level, or compat feature.
+                if (app.info.allowsNativeHeapPointerTagging()
+                        && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) {
+                    runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
+                }
             }
 
             runtimeFlags |= decideGwpAsanLevel(app);
@@ -2127,18 +2131,11 @@
         for (String packageName : packages) {
             String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
             long inode = pmInt.getCeDataInode(packageName, userId);
-            if (inode != 0) {
-                result.put(packageName, Pair.create(volumeUuid, inode));
+            if (inode == 0) {
+                Slog.w(TAG, packageName + " inode == 0 (b/152760674)");
+                return null;
             }
-        }
-        if (mAppDataIsolationWhitelistedApps != null) {
-            for (String packageName : mAppDataIsolationWhitelistedApps) {
-                String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid();
-                long inode = pmInt.getCeDataInode(packageName, userId);
-                if (inode != 0) {
-                    result.put(packageName, Pair.create(volumeUuid, inode));
-                }
-            }
+            result.put(packageName, Pair.create(volumeUuid, inode));
         }
 
         return result;
@@ -2160,35 +2157,56 @@
                 app.setHasForegroundActivities(true);
             }
 
+            final Map<String, Pair<String, Long>> pkgDataInfoMap;
+            final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap;
+            boolean bindMountAppStorageDirs = false;
+            boolean bindMountAppsData = mAppDataIsolationEnabled
+                    && UserHandle.isApp(app.uid)
+                    && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info);
+
+            // Get all packages belongs to the same shared uid. sharedPackages is empty array
+            // if it doesn't have shared uid.
+            final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
+            final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
+                    app.info.packageName, app.userId);
+            final String[] targetPackagesList = sharedPackages.length == 0
+                    ? new String[]{app.info.packageName} : sharedPackages;
+
+            pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
+            if (pkgDataInfoMap == null) {
+                // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
+                // tmp free pass.
+                bindMountAppsData = false;
+            }
+
+            // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so
+            // it won't be mounted twice.
+            final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps);
+            for (String pkg : targetPackagesList) {
+                whitelistedApps.remove(pkg);
+            }
+
+            whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt,
+                    whitelistedApps.toArray(new String[0]), uid);
+            if (whitelistedAppDataInfoMap == null) {
+                // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
+                // tmp free pass.
+                bindMountAppsData = false;
+            }
+
+            int userId = UserHandle.getUserId(uid);
             StorageManagerInternal storageManagerInternal = LocalServices.getService(
                     StorageManagerInternal.class);
-            final Map<String, Pair<String, Long>> pkgDataInfoMap;
-            boolean bindMountAppStorageDirs = false;
-
-            if (mAppDataIsolationEnabled && UserHandle.isApp(app.uid)
-                    && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info)) {
-                // Get all packages belongs to the same shared uid. sharedPackages is empty array
-                // if it doesn't have shared uid.
-                final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked();
-                final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage(
-                        app.info.packageName, app.userId);
-                pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
-                        ? new String[]{app.info.packageName} : sharedPackages, uid);
-
-                int userId = UserHandle.getUserId(uid);
-                if (mVoldAppDataIsolationEnabled
-                        && !storageManagerInternal.isExternalStorageService(uid)) {
-                    bindMountAppStorageDirs = true;
-                    if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
-                            app.processName)) {
-                        // Cannot prepare Android/app and Android/obb directory,
-                        // so we won't mount it in zygote.
-                        app.bindMountPending = true;
-                        bindMountAppStorageDirs = false;
-                    }
+            if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid)
+                    && !storageManagerInternal.isExternalStorageService(uid)) {
+                bindMountAppStorageDirs = true;
+                if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(),
+                        app.processName)) {
+                    // Cannot prepare Android/app and Android/obb directory,
+                    // so we won't mount it in zygote.
+                    app.bindMountPending = true;
+                    bindMountAppStorageDirs = false;
                 }
-            } else {
-                pkgDataInfoMap = null;
             }
 
             final Process.ProcessStartResult startResult;
@@ -2206,7 +2224,8 @@
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, null, app.info.packageName,
                         /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
-                        app.mDisabledCompatChanges, pkgDataInfoMap, bindMountAppStorageDirs,
+                        app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
+                        bindMountAppsData, bindMountAppStorageDirs,
                         new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             } else {
                 startResult = Process.start(entryPoint,
@@ -2214,7 +2233,7 @@
                         app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                         app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                         isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
-                        bindMountAppStorageDirs,
+                        whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                         new String[]{PROC_START_SEQ_IDENT + app.startSeq});
             }
             checkSlow(startTime, "startProcess: returned from zygote!");
diff --git a/services/core/java/com/android/server/display/color/AppSaturationController.java b/services/core/java/com/android/server/display/color/AppSaturationController.java
index e42be02..6a685bf 100644
--- a/services/core/java/com/android/server/display/color/AppSaturationController.java
+++ b/services/core/java/com/android/server/display/color/AppSaturationController.java
@@ -17,6 +17,7 @@
 package com.android.server.display.color;
 
 import android.annotation.UserIdInt;
+import android.util.ArrayMap;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -61,11 +62,12 @@
      * Set the saturation level ({@code ColorDisplayManager#SaturationLevel} constant for a given
      * package name and userId.
      */
-    public boolean setSaturationLevel(String packageName, @UserIdInt int userId,
+    public boolean setSaturationLevel(String callingPackageName, String affectedPackageName,
+            @UserIdInt int userId,
             int saturationLevel) {
         synchronized (mLock) {
-            return getSaturationControllerLocked(packageName, userId)
-                    .setSaturationLevel(saturationLevel);
+            return getSaturationControllerLocked(affectedPackageName, userId)
+                    .setSaturationLevel(callingPackageName, saturationLevel);
         }
     }
 
@@ -148,13 +150,19 @@
 
     private static class SaturationController {
 
+        private static final int FULL_SATURATION = 100;
+
         private final List<WeakReference<ColorTransformController>> mControllerRefs =
                 new ArrayList<>();
-        private int mSaturationLevel = 100;
+        private final ArrayMap<String, Integer> mSaturationLevels = new ArrayMap<>();
         private float[] mTransformMatrix = new float[9];
 
-        private boolean setSaturationLevel(int saturationLevel) {
-            mSaturationLevel = saturationLevel;
+        private boolean setSaturationLevel(String callingPackageName, int saturationLevel) {
+            if (saturationLevel == FULL_SATURATION) {
+                mSaturationLevels.remove(callingPackageName);
+            } else {
+                mSaturationLevels.put(callingPackageName, saturationLevel);
+            }
             if (!mControllerRefs.isEmpty()) {
                 return updateState();
             }
@@ -163,17 +171,27 @@
 
         private boolean addColorTransformController(
                 WeakReference<ColorTransformController> controller) {
+            clearExpiredReferences();
             mControllerRefs.add(controller);
-            if (mSaturationLevel != 100) {
+            if (!mSaturationLevels.isEmpty()) {
                 return updateState();
-            } else {
-                clearExpiredReferences();
             }
             return false;
         }
 
+        private int calculateSaturationLevel() {
+            int saturationLevel = FULL_SATURATION;
+            for (int i = 0; i < mSaturationLevels.size(); i++) {
+                final int level = mSaturationLevels.valueAt(i);
+                if (level < saturationLevel) {
+                    saturationLevel = level;
+                }
+            }
+            return saturationLevel;
+        }
+
         private boolean updateState() {
-            computeGrayscaleTransformMatrix(mSaturationLevel / 100f, mTransformMatrix);
+            computeGrayscaleTransformMatrix(calculateSaturationLevel() / 100f, mTransformMatrix);
 
             boolean updated = false;
             final Iterator<WeakReference<ColorTransformController>> iterator = mControllerRefs
@@ -190,7 +208,6 @@
                 }
             }
             return updated;
-
         }
 
         private void clearExpiredReferences() {
@@ -206,7 +223,7 @@
         }
 
         private void dump(PrintWriter pw) {
-            pw.println("            mSaturationLevel: " + mSaturationLevel);
+            pw.println("            mSaturationLevels: " + mSaturationLevels);
             pw.println("            mControllerRefs count: " + mControllerRefs.size());
         }
     }
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 2dc2cf0..95a98f1 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -44,6 +44,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.hardware.display.ColorDisplayManager;
@@ -73,6 +74,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.DumpUtils;
 import com.android.server.DisplayThread;
+import com.android.server.LocalServices;
 import com.android.server.SystemService;
 import com.android.server.twilight.TwilightListener;
 import com.android.server.twilight.TwilightManager;
@@ -817,9 +819,11 @@
         return LocalDateTime.MIN;
     }
 
-    private boolean setAppSaturationLevelInternal(String packageName, int saturationLevel) {
+    private boolean setAppSaturationLevelInternal(String callingPackageName,
+            String affectedPackageName, int saturationLevel) {
         return mAppSaturationController
-                .setSaturationLevel(packageName, mCurrentUser, saturationLevel);
+                .setSaturationLevel(callingPackageName, affectedPackageName, mCurrentUser,
+                        saturationLevel);
     }
 
     private void setColorModeInternal(@ColorMode int colorMode) {
@@ -1533,9 +1537,11 @@
             getContext().enforceCallingPermission(
                     Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
                     "Permission required to set display saturation level");
+            final String callingPackageName = LocalServices.getService(PackageManagerInternal.class)
+                    .getNameForUid(Binder.getCallingUid());
             final long token = Binder.clearCallingIdentity();
             try {
-                return setAppSaturationLevelInternal(packageName, level);
+                return setAppSaturationLevelInternal(callingPackageName, packageName, level);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 846d099..e6cb371 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -3106,14 +3106,10 @@
                     MSG_SHOW_SOFT_INPUT, getImeShowFlags(), reason, mCurMethod, resultReceiver,
                     showInputToken));
             mInputShown = true;
-
             if (mHaveConnection && !mVisibleBound) {
                 bindCurrentInputMethodServiceLocked(
                         mCurIntent, mVisibleConnection, IME_VISIBLE_BIND_FLAGS);
                 mVisibleBound = true;
-            } else {
-                // Clear the show request after the input shown.
-                mShowRequested = false;
             }
             res = true;
         } else if (mHaveConnection && SystemClock.uptimeMillis()
diff --git a/services/core/java/com/android/server/location/AppOpsHelper.java b/services/core/java/com/android/server/location/AppOpsHelper.java
index 9c27916..cb64c50 100644
--- a/services/core/java/com/android/server/location/AppOpsHelper.java
+++ b/services/core/java/com/android/server/location/AppOpsHelper.java
@@ -191,7 +191,7 @@
                     callerIdentity.uid,
                     callerIdentity.packageName,
                     callerIdentity.featureId,
-                    null) == AppOpsManager.MODE_ALLOWED;
+                    callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -210,7 +210,7 @@
                     callerIdentity.packageName,
                     false,
                     callerIdentity.featureId,
-                    null) == AppOpsManager.MODE_ALLOWED;
+                    callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -245,7 +245,7 @@
                     callerIdentity.uid,
                     callerIdentity.packageName,
                     callerIdentity.featureId,
-                    null) == AppOpsManager.MODE_ALLOWED;
+                    callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED;
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java
index b84fd13..8d508bb 100644
--- a/services/core/java/com/android/server/location/CallerIdentity.java
+++ b/services/core/java/com/android/server/location/CallerIdentity.java
@@ -83,12 +83,22 @@
      */
     public static CallerIdentity fromBinder(Context context, String packageName,
             @Nullable String featureId) {
+        return fromBinder(context, packageName, featureId, null);
+    }
+
+    /**
+     * Creates a CallerIdentity from the current binder identity, using the given package, feature
+     * id, and listener id. The package will be checked to enforce it belongs to the calling uid,
+     * and a security exception will be thrown if it is invalid.
+     */
+    public static CallerIdentity fromBinder(Context context, String packageName,
+            @Nullable String featureId, @Nullable String listenerId) {
         int uid = Binder.getCallingUid();
         if (!ArrayUtils.contains(context.getPackageManager().getPackagesForUid(uid), packageName)) {
             throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid);
         }
 
-        return fromBinderUnsafe(context, packageName, featureId);
+        return fromBinderUnsafe(context, packageName, featureId, listenerId);
     }
 
     /**
@@ -99,8 +109,19 @@
      */
     public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
             @Nullable String featureId) {
+        return fromBinderUnsafe(context, packageName, featureId, null);
+    }
+
+    /**
+     * Creates a CallerIdentity from the current binder identity, using the given package, feature
+     * id, and listener id. The package will not be checked to enforce that it belongs to the
+     * calling uid - this method should only be used if the package will be validated by some other
+     * means, such as an appops call.
+     */
+    public static CallerIdentity fromBinderUnsafe(Context context, String packageName,
+            @Nullable String featureId, @Nullable String listenerId) {
         return new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(),
-                UserHandle.getCallingUserId(), packageName, featureId,
+                UserHandle.getCallingUserId(), packageName, featureId, listenerId,
                 getBinderPermissionLevel(context));
     }
 
@@ -157,6 +178,9 @@
     /** The calling feature id. */
     public final @Nullable String featureId;
 
+    /** The calling listener id. */
+    public final @Nullable String listenerId;
+
     /**
      * The calling location permission level. This field should only be used for validating
      * permissions for API access. It should not be used for validating permissions for location
@@ -167,11 +191,18 @@
     @VisibleForTesting
     public CallerIdentity(int uid, int pid, int userId, String packageName,
             @Nullable String featureId, @PermissionLevel int permissionLevel) {
+        this(uid, pid, userId, packageName, featureId, null, permissionLevel);
+    }
+
+    private CallerIdentity(int uid, int pid, int userId, String packageName,
+            @Nullable String featureId, @Nullable String listenerId,
+            @PermissionLevel int permissionLevel) {
         this.uid = uid;
         this.pid = pid;
         this.userId = userId;
         this.packageName = Objects.requireNonNull(packageName);
         this.featureId = featureId;
+        this.listenerId = listenerId;
         this.permissionLevel = Preconditions.checkArgumentInRange(permissionLevel, PERMISSION_NONE,
                 PERMISSION_FINE, "permissionLevel");
     }
@@ -216,7 +247,8 @@
         return uid == that.uid
                 && pid == that.pid
                 && packageName.equals(that.packageName)
-                && Objects.equals(featureId, that.featureId);
+                && Objects.equals(featureId, that.featureId)
+                && Objects.equals(listenerId, that.listenerId);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
new file mode 100644
index 0000000..0bdf3f2
--- /dev/null
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -0,0 +1,211 @@
+/*
+ * 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.net;
+
+import static android.net.NetworkTemplate.getCollapsedRatType;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.telephony.Annotation;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executor;
+
+/**
+ * Helper class that watches for events that are triggered per subscription.
+ */
+// TODO (b/152176562): Write tests to verify subscription changes generate corresponding
+//  register/unregister calls.
+public class NetworkStatsSubscriptionsMonitor extends
+        SubscriptionManager.OnSubscriptionsChangedListener {
+
+    /**
+     * Interface that this monitor uses to delegate event handling to NetworkStatsService.
+     */
+    public interface Delegate {
+        /**
+         * Notify that the collapsed RAT type has been changed for any subscription. The method
+         * will also be triggered for any existing sub when start and stop monitoring.
+         *
+         * @param subscriberId IMSI of the subscription.
+         * @param collapsedRatType collapsed RAT type.
+         *                         @see android.net.NetworkTemplate#getCollapsedRatType(int).
+         */
+        void onCollapsedRatTypeChanged(@NonNull String subscriberId,
+                @Annotation.NetworkType int collapsedRatType);
+    }
+    private final Delegate mDelegate;
+
+    /**
+     * Receivers that watches for {@link ServiceState} changes for each subscription, to
+     * monitor the transitioning between Radio Access Technology(RAT) types for each sub.
+     */
+    @NonNull
+    private final CopyOnWriteArrayList<RatTypeListener> mRatListeners =
+            new CopyOnWriteArrayList<>();
+
+    @NonNull
+    private final SubscriptionManager mSubscriptionManager;
+    @NonNull
+    private final TelephonyManager mTeleManager;
+
+    @NonNull
+    private final Executor mExecutor;
+
+    NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor,
+            @NonNull Delegate delegate) {
+        super();
+        mSubscriptionManager = (SubscriptionManager) context.getSystemService(
+                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+        mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        mExecutor = executor;
+        mDelegate = delegate;
+    }
+
+    @Override
+    public void onSubscriptionsChanged() {
+        // Collect active subId list, hidden subId such as opportunistic subscriptions are
+        // also needed to track CBRS.
+        final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager);
+
+        for (final int subId : newSubs) {
+            final RatTypeListener match = CollectionUtils.find(mRatListeners,
+                    it -> it.mSubId == subId);
+            if (match != null) continue;
+
+            // Create listener for every newly added sub. Also store subscriberId into it to
+            // prevent binder call to telephony when querying RAT.
+            final String subscriberId = mTeleManager.getSubscriberId(subId);
+            if (TextUtils.isEmpty(subscriberId)) {
+                Log.wtf(NetworkStatsService.TAG,
+                        "Empty subscriberId for newly added sub: " + subId);
+            }
+            final RatTypeListener listener =
+                    new RatTypeListener(mExecutor, this, subId, subscriberId);
+            mRatListeners.add(listener);
+
+            // Register listener to the telephony manager that associated with specific sub.
+            mTeleManager.createForSubscriptionId(subId)
+                    .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
+        }
+
+        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
+            // If the new list contains the subId of the listener, keeps it.
+            final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId);
+            if (match != null) continue;
+
+            handleRemoveRatTypeListener(listener);
+        }
+    }
+
+    @NonNull
+    private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) {
+        final ArrayList<Integer> ret = new ArrayList<>();
+        final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList();
+        for (int id : ids) ret.add(id);
+        return ret;
+    }
+
+    /**
+     * Get a collapsed RatType for the given subscriberId.
+     *
+     * @param subscriberId the target subscriberId
+     * @return collapsed RatType for the given subscriberId
+     */
+    public int getRatTypeForSubscriberId(@NonNull String subscriberId) {
+        final RatTypeListener match = CollectionUtils.find(mRatListeners,
+                it -> TextUtils.equals(subscriberId, it.mSubscriberId));
+        return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+    }
+
+    /**
+     * Start monitoring events that triggered per subscription.
+     */
+    public void start() {
+        mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this);
+    }
+
+    /**
+     * Unregister subscription changes and all listeners for each subscription.
+     */
+    public void stop() {
+        mSubscriptionManager.removeOnSubscriptionsChangedListener(this);
+
+        for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
+            handleRemoveRatTypeListener(listener);
+        }
+    }
+
+    private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
+        mTeleManager.createForSubscriptionId(listener.mSubId)
+                .listen(listener, PhoneStateListener.LISTEN_NONE);
+        mRatListeners.remove(listener);
+
+        // Removal of subscriptions doesn't generate RAT changed event, fire it for every
+        // RatTypeListener.
+        mDelegate.onCollapsedRatTypeChanged(
+                listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+    }
+
+    static class RatTypeListener extends PhoneStateListener {
+        // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}.
+        @NonNull
+        private final int mSubId;
+
+        // IMSI to identifying the corresponding network from {@link NetworkState}.
+        // See {@link TelephonyManager#getSubscriberId}.
+        @NonNull
+        private final String mSubscriberId;
+
+        private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        @NonNull
+        private final NetworkStatsSubscriptionsMonitor mMonitor;
+
+        RatTypeListener(@NonNull Executor executor,
+                @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId,
+                @NonNull String subscriberId) {
+            super(executor);
+            mSubId = subId;
+            mSubscriberId = subscriberId;
+            mMonitor = monitor;
+        }
+
+        @Override
+        public void onServiceStateChanged(@NonNull ServiceState ss) {
+            final int networkType = ss.getDataNetworkType();
+            final int collapsedRatType = getCollapsedRatType(networkType);
+            if (collapsedRatType == mLastCollapsedRatType) return;
+
+            if (NetworkStatsService.LOGD) {
+                Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): "
+                        + mLastCollapsedRatType + " -> " + collapsedRatType);
+            }
+            mLastCollapsedRatType = collapsedRatType;
+            mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index ba7583f..dab4bfd 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -46,6 +46,7 @@
 
 import java.io.File;
 import java.nio.file.Paths;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -106,6 +107,8 @@
     private static final long mDowngradeUnusedAppsThresholdInMillis =
             getDowngradeUnusedAppsThresholdInMillis();
 
+    private static List<PackagesUpdatedListener> sPackagesUpdatedListeners = new ArrayList<>();
+
     public static void schedule(Context context) {
         if (isBackgroundDexoptDisabled()) {
             return;
@@ -244,6 +247,7 @@
             }
         }
         notifyPinService(updatedPackages);
+        notifyPackagesUpdated(updatedPackages);
         // Ran to completion, so we abandon our timeslice and do not reschedule.
         jobFinished(jobParams, /* reschedule */ false);
     }
@@ -391,6 +395,7 @@
         } finally {
             // Always let the pinner service know about changes.
             notifyPinService(updatedPackages);
+            notifyPackagesUpdated(updatedPackages);
         }
     }
 
@@ -642,6 +647,32 @@
         }
     }
 
+    public static interface PackagesUpdatedListener {
+        /** Callback when packages have been updated by the bg-dexopt service. */
+        public void onPackagesUpdated(ArraySet<String> updatedPackages);
+    }
+
+    public static void addPackagesUpdatedListener(PackagesUpdatedListener listener) {
+        synchronized (sPackagesUpdatedListeners) {
+            sPackagesUpdatedListeners.add(listener);
+        }
+    }
+
+    public static void removePackagesUpdatedListener(PackagesUpdatedListener listener) {
+        synchronized (sPackagesUpdatedListeners) {
+            sPackagesUpdatedListeners.remove(listener);
+        }
+    }
+
+    /** Notify all listeners (#addPackagesUpdatedListener) that packages have been updated. */
+    private void notifyPackagesUpdated(ArraySet<String> updatedPackages) {
+        synchronized (sPackagesUpdatedListeners) {
+            for (PackagesUpdatedListener listener : sPackagesUpdatedListeners) {
+                listener.onPackagesUpdated(updatedPackages);
+            }
+        }
+    }
+
     private static long getDowngradeUnusedAppsThresholdInMillis() {
         final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days";
         String sysPropValue = SystemProperties.get(sysPropKey);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index f37af3a..9fb468e 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -724,6 +724,30 @@
     }
 
     /**
+     * Deletes all snapshots of credential encrypted user data, where the snapshot id is not
+     * included in {@code retainSnapshotIds}.
+     *
+     * @param userId id of the user whose user data snapshots to delete.
+     * @param retainSnapshotIds ids of the snapshots that should not be deleted.
+     *
+     * @return {@code true} if the operation was successful, or {@code false} if a remote call
+     * shouldn't be continued. See {@link #checkBeforeRemote}.
+     *
+     * @throws InstallerException if failed to delete user data snapshot.
+     */
+    public boolean destroyCeSnapshotsNotSpecified(@UserIdInt int userId,
+            int[] retainSnapshotIds) throws InstallerException {
+        if (!checkBeforeRemote()) return false;
+
+        try {
+            mInstalld.destroyCeSnapshotsNotSpecified(null, userId, retainSnapshotIds);
+            return true;
+        } catch (Exception e) {
+            throw InstallerException.from(e);
+        }
+    }
+
+    /**
      * Migrates obb data from its legacy location {@code /data/media/obb} to
      * {@code /data/media/0/Android/obb}. This call is idempotent and a fast no-op if data has
      * already been migrated.
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 5f871ad4..83e99b0 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -505,6 +505,11 @@
             rollbackIds[i] = mRollbacks.get(i).info.getRollbackId();
         }
         ApexManager.getInstance().destroyCeSnapshotsNotSpecified(userId, rollbackIds);
+        try {
+            mInstaller.destroyCeSnapshotsNotSpecified(userId, rollbackIds);
+        } catch (Installer.InstallerException ie) {
+            Slog.e(TAG, "Failed to delete snapshots for user: " + userId, ie);
+        }
     }
 
     @WorkerThread
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 1e5a924..0470ffa 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -1469,7 +1469,7 @@
             if (toDisplay.getDisplayId() != stack.getDisplayId()) {
                 stack.reparent(toDisplay.getDefaultTaskDisplayArea(), false /* onTop */);
             } else {
-                toDisplay.mTaskContainers.positionStackAtBottom(stack);
+                toDisplay.getDefaultTaskDisplayArea().positionStackAtBottom(stack);
             }
 
             mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index edd14b7..a512337 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -54,7 +54,6 @@
  * - BELOW_TASKS: Can only contain BELOW_TASK DisplayAreas and WindowTokens that go below tasks.
  * - ABOVE_TASKS: Can only contain ABOVE_TASK DisplayAreas and WindowTokens that go above tasks.
  * - ANY: Can contain any kind of DisplayArea, and any kind of WindowToken or the Task container.
- *        Cannot have a sibling that is of type ANY.
  *
  * @param <T> type of the children of the DisplayArea.
  */
@@ -274,7 +273,6 @@
         ANY;
 
         static void checkSiblings(Type bottom, Type top) {
-            checkState(!(bottom == ANY && top == ANY), "ANY cannot be a sibling of ANY");
             checkState(!(bottom != BELOW_TASKS && top == BELOW_TASKS),
                     bottom + " must be above BELOW_TASKS");
             checkState(!(bottom == ABOVE_TASKS && top != ABOVE_TASKS),
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index 9821573..15b6f973 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -16,9 +16,14 @@
 
 package com.android.server.wm;
 
+import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
+
 import android.content.res.Resources;
 import android.text.TextUtils;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Policy that manages DisplayAreas.
  */
@@ -37,9 +42,9 @@
     protected final DisplayArea<? extends WindowContainer> mImeContainer;
 
     /**
-     * The Tasks container. Tasks etc. are automatically added to this container.
+     * The task display areas. Tasks etc. are automatically added to these containers.
      */
-    protected final DisplayArea<? extends ActivityStack> mTaskContainers;
+    protected final List<TaskDisplayArea> mTaskDisplayAreas;
 
     /**
      * Construct a new {@link DisplayAreaPolicy}
@@ -48,19 +53,19 @@
      * @param content the display content for which the policy applies
      * @param root the root display area under which the policy operates
      * @param imeContainer the ime container that the policy must attach
-     * @param taskDisplayArea the task container that the policy must attach
+     * @param taskDisplayAreas the task display areas that the policy must attach
      *
      * @see #attachDisplayAreas()
      */
     protected DisplayAreaPolicy(WindowManagerService wmService,
             DisplayContent content, DisplayArea.Root root,
             DisplayArea<? extends WindowContainer> imeContainer,
-            DisplayArea<? extends ActivityStack> taskDisplayArea) {
+            List<TaskDisplayArea> taskDisplayAreas) {
         mWmService = wmService;
         mContent = content;
         mRoot = root;
         mImeContainer = imeContainer;
-        mTaskContainers = taskDisplayArea;
+        mTaskDisplayAreas = taskDisplayAreas;
     }
 
     /**
@@ -80,15 +85,32 @@
      */
     public abstract void addWindow(WindowToken token);
 
+    /**
+     * @return the number of task display areas on the display.
+     */
+    public int getTaskDisplayAreaCount() {
+        return mTaskDisplayAreas.size();
+    }
+
+    /**
+     * @return the task display area at index.
+     */
+    public TaskDisplayArea getTaskDisplayAreaAt(int index) {
+        return mTaskDisplayAreas.get(index);
+    }
+
     /** Provider for platform-default display area policy. */
     static final class DefaultProvider implements DisplayAreaPolicy.Provider {
         @Override
         public DisplayAreaPolicy instantiate(WindowManagerService wmService,
                 DisplayContent content, DisplayArea.Root root,
-                DisplayArea<? extends WindowContainer> imeContainer,
-                TaskDisplayArea taskDisplayArea) {
+                DisplayArea<? extends WindowContainer> imeContainer) {
+            final TaskDisplayArea defaultTaskDisplayArea = new TaskDisplayArea(content, wmService,
+                    "DefaultTaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER);
+            final List<TaskDisplayArea> tdaList = new ArrayList<>();
+            tdaList.add(defaultTaskDisplayArea);
             return new DisplayAreaPolicyBuilder()
-                    .build(wmService, content, root, imeContainer, taskDisplayArea);
+                    .build(wmService, content, root, imeContainer, tdaList);
         }
     }
 
@@ -107,8 +129,7 @@
          */
         DisplayAreaPolicy instantiate(WindowManagerService wmService,
                 DisplayContent content, DisplayArea.Root root,
-                DisplayArea<? extends WindowContainer> imeContainer,
-                TaskDisplayArea taskDisplayArea);
+                DisplayArea<? extends WindowContainer> imeContainer);
 
         /**
          * Instantiate the device-specific {@link Provider}.
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index e8becfa..2c2f433 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -201,8 +201,8 @@
 
         Result(WindowManagerService wmService, DisplayContent content, DisplayArea.Root root,
                 DisplayArea<? extends WindowContainer> imeContainer,
-                DisplayArea<? extends ActivityStack> taskDisplayArea, ArrayList<Feature> features) {
-            super(wmService, content, root, imeContainer, taskDisplayArea);
+                List<TaskDisplayArea> taskDisplayAreas, ArrayList<Feature> features) {
+            super(wmService, content, root, imeContainer, taskDisplayAreas);
             mFeatures = features;
             mAreas = new HashMap<>(features.size());
             for (int i = 0; i < mFeatures.size(); i++) {
@@ -267,7 +267,7 @@
                     areaForLayer[layer].mChildren.add(leafArea);
                     leafType = type;
                     if (leafType == LEAF_TYPE_TASK_CONTAINERS) {
-                        leafArea.mExisting = mTaskContainers;
+                        addTaskDisplayAreasToLayer(areaForLayer[layer], layer);
                     } else if (leafType == LEAF_TYPE_IME_CONTAINERS) {
                         leafArea.mExisting = mImeContainer;
                     }
@@ -278,6 +278,17 @@
             root.instantiateChildren(mRoot, mAreaForLayer, 0, mAreas);
         }
 
+        /** Adds all task display areas to the specified layer */
+        private void addTaskDisplayAreasToLayer(PendingArea parentPendingArea, int layer) {
+            final int count = mTaskDisplayAreas.size();
+            for (int i = 0; i < count; i++) {
+                PendingArea leafArea = new PendingArea(null, layer, parentPendingArea);
+                leafArea.mExisting = mTaskDisplayAreas.get(i);
+                leafArea.mMaxLayer = layer;
+                parentPendingArea.mChildren.add(leafArea);
+            }
+        }
+
         @Override
         public void addWindow(WindowToken token) {
             DisplayArea.Tokens area = findAreaForToken(token);
@@ -317,12 +328,16 @@
         return this;
     }
 
+    protected List<Feature> getFeatures() {
+        return mFeatures;
+    }
+
     Result build(WindowManagerService wmService,
             DisplayContent content, DisplayArea.Root root,
             DisplayArea<? extends WindowContainer> imeContainer,
-            DisplayArea<? extends ActivityStack> taskDisplayArea) {
+            List<TaskDisplayArea> taskDisplayAreas) {
 
-        return new Result(wmService, content, root, imeContainer, taskDisplayArea, new ArrayList<>(
+        return new Result(wmService, content, root, imeContainer, taskDisplayAreas, new ArrayList<>(
                 mFeatures));
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8111c0e..98d4b55 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -72,6 +72,7 @@
 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.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
@@ -268,8 +269,6 @@
             new NonAppWindowContainers("mOverlayContainers", mWmService);
 
     /** The containers below are the only child containers {@link #mWindowContainers} can have. */
-    // Contains all window containers that are related to apps (Activities)
-    final TaskDisplayArea mTaskContainers = new TaskDisplayArea(this, mWmService);
 
     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
@@ -971,7 +970,7 @@
         super.addChild(mOverlayContainers, null);
 
         mDisplayAreaPolicy = mWmService.mDisplayAreaPolicyProvider.instantiate(
-                mWmService, this, mRootDisplayArea, mImeWindowsContainers, mTaskContainers);
+                mWmService, this, mRootDisplayArea, mImeWindowsContainers);
         mWindowContainers.addChildren();
 
         // Sets the display content for the children.
@@ -1081,8 +1080,7 @@
             return null;
         }
         mShellRoots.put(windowType, root);
-        SurfaceControl out = new SurfaceControl();
-        out.copyFrom(rootLeash);
+        SurfaceControl out = new SurfaceControl(rootLeash);
         return out;
     }
 
@@ -2070,13 +2068,11 @@
     }
 
     protected int getTaskDisplayAreaCount() {
-        // TODO(multi-display-area): Report actual display area count
-        return 1;
+        return mDisplayAreaPolicy.getTaskDisplayAreaCount();
     }
 
     protected TaskDisplayArea getTaskDisplayAreaAt(int index) {
-        // TODO(multi-display-area): Report actual display area values
-        return mTaskContainers;
+        return mDisplayAreaPolicy.getTaskDisplayAreaAt(index);
     }
 
     ActivityStack getStack(int rootTaskId) {
@@ -2402,7 +2398,7 @@
      * or for cases when multi-instance is not supported yet (like Split-screen, PiP or Recents).
      */
     TaskDisplayArea getDefaultTaskDisplayArea() {
-        return mTaskContainers;
+        return mDisplayAreaPolicy.getTaskDisplayAreaAt(0);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index ec3c99b..11cfad2 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -31,7 +31,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.window.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
 
 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
@@ -141,8 +140,9 @@
      */
     private boolean mRemoved;
 
-    TaskDisplayArea(DisplayContent displayContent, WindowManagerService service) {
-        super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
+    TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
+            int displayAreaFeature) {
+        super(service, Type.ANY, name, displayAreaFeature);
         mDisplayContent = displayContent;
         mRootWindowContainer = service.mRoot;
         mAtmService = service.mAtmService;
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index f9955fa..f6e952c 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2510,9 +2510,7 @@
             // We need to copy the SurfaceControl instead of returning the original
             // because the Parcel FLAGS PARCELABLE_WRITE_RETURN_VALUE cause SurfaceControls
             // to release themselves.
-            SurfaceControl sc = new SurfaceControl();
-            sc.copyFrom(wc.getSurfaceControl());
-            return sc;
+            return new SurfaceControl(wc.getSurfaceControl());
         }
 
         WindowContainerToken toWindowContainerToken() {
diff --git a/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java b/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java
index 7c9a81d..a525814 100644
--- a/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java
@@ -43,7 +43,9 @@
 @RunWith(AndroidJUnit4.class)
 public class AppSaturationControllerTest {
 
-    private static final String TEST_PACKAGE_NAME = "com.android.test";
+    private static final String TEST_CALLER_PACKAGE_NAME = "com.android.test.caller";
+    private static final String TEST_CALLER_PACKAGE_NAME_TWO = "com.android.test.caller.two";
+    private static final String TEST_AFFECTED_PACKAGE_NAME = "com.android.test.affected";
 
     private int mUserId;
     private AppSaturationController mAppSaturationController;
@@ -70,8 +72,11 @@
     public void addColorTransformController_appliesExistingSaturation() {
         final WeakReference<ColorTransformController> ref = new WeakReference<>(
                 mColorTransformController);
-        mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30);
-        mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref);
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        30);
+        mAppSaturationController
+                .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
         AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix);
         verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
     }
@@ -80,14 +85,19 @@
     public void setSaturationLevel_resetToDefault() {
         final WeakReference<ColorTransformController> ref = new WeakReference<>(
                 mColorTransformController);
-        mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref);
+        mAppSaturationController
+                .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
         verify(mColorTransformController, never())
                 .applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
-        mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30);
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        30);
         AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix);
         verify(mColorTransformController, times(1))
                 .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
-        mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100);
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        100);
         AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix);
         verify(mColorTransformController, times(2))
                 .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
@@ -97,19 +107,76 @@
     public void setSaturationLevel_updateLevel() {
         final WeakReference<ColorTransformController> ref = new WeakReference<>(
                 mColorTransformController);
-        mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref);
+        mAppSaturationController
+                .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
         verify(mColorTransformController, never())
                 .applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
-        mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30);
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        30);
         AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix);
         verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
-        mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 70);
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        70);
         AppSaturationController.computeGrayscaleTransformMatrix(.7f, mMatrix);
         verify(mColorTransformController, times(2))
                 .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
-        mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100);
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        100);
         AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix);
         verify(mColorTransformController, times(3))
                 .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
     }
+
+    @Test
+    public void setSaturationLevel_multipleCallers_appliesStrongest() {
+        final WeakReference<ColorTransformController> ref = new WeakReference<>(
+                mColorTransformController);
+        mAppSaturationController
+                .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
+        verify(mColorTransformController, never())
+                .applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        30);
+        AppSaturationController.computeGrayscaleTransformMatrix(0.3f, mMatrix);
+        verify(mColorTransformController, times(1))
+                .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME,
+                        mUserId,
+                        70);
+        verify(mColorTransformController, times(2))
+                .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
+    }
+
+    @Test
+    public void setSaturationLevel_multipleCallers_removingOneDoesNotAffectTheOther() {
+        final WeakReference<ColorTransformController> ref = new WeakReference<>(
+                mColorTransformController);
+        mAppSaturationController
+                .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
+        verify(mColorTransformController, never())
+                .applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
+                        70);
+        AppSaturationController.computeGrayscaleTransformMatrix(0.7f, mMatrix);
+        verify(mColorTransformController, times(1))
+                .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME,
+                        mUserId,
+                        30);
+        AppSaturationController.computeGrayscaleTransformMatrix(0.3f, mMatrix);
+        verify(mColorTransformController, times(2))
+                .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
+        mAppSaturationController
+                .setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME,
+                        mUserId,
+                        100);
+        AppSaturationController.computeGrayscaleTransformMatrix(0.7f, mMatrix);
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index 12bdec6..0568be8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -22,6 +22,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
+import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER;
 
 import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
 import static com.android.server.wm.DisplayArea.Type.ANY;
@@ -72,7 +73,11 @@
         WindowManagerService wms = mSystemServices.getWindowManagerService();
         DisplayArea.Root root = new SurfacelessDisplayAreaRoot(wms);
         DisplayArea<WindowContainer> ime = new DisplayArea<>(wms, ABOVE_TASKS, "Ime");
-        DisplayArea<ActivityStack> tasks = new DisplayArea<>(wms, ANY, "Tasks");
+        DisplayContent displayContent = mock(DisplayContent.class);
+        TaskDisplayArea taskDisplayArea = new TaskDisplayArea(displayContent, wms, "Tasks",
+                FEATURE_DEFAULT_TASK_CONTAINER);
+        List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>();
+        taskDisplayAreaList.add(taskDisplayArea);
 
         final Feature foo;
         final Feature bar;
@@ -86,7 +91,7 @@
                         .all()
                         .except(TYPE_STATUS_BAR)
                         .build())
-                .build(wms, mock(DisplayContent.class), root, ime, tasks);
+                .build(wms, displayContent, root, ime, taskDisplayAreaList);
 
         policy.attachDisplayAreas();
 
@@ -98,9 +103,9 @@
         assertThat(policy.findAreaForToken(tokenOfType(TYPE_STATUS_BAR)),
                 is(not(decendantOfOneOf(policy.getDisplayAreas(bar)))));
 
-        assertThat(tasks,
+        assertThat(taskDisplayArea,
                 is(decendantOfOneOf(policy.getDisplayAreas(foo))));
-        assertThat(tasks,
+        assertThat(taskDisplayArea,
                 is(decendantOfOneOf(policy.getDisplayAreas(bar))));
 
         assertThat(ime,
@@ -109,7 +114,8 @@
                 is(decendantOfOneOf(policy.getDisplayAreas(bar))));
 
         List<DisplayArea<?>> actualOrder = collectLeafAreas(root);
-        Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, root, ime, tasks);
+        Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, root, ime,
+                taskDisplayArea);
         actualOrder = actualOrder.stream().filter(zSets::containsKey).collect(toList());
 
         Map<DisplayArea<?>, Integer> expectedByMinLayer = mapValues(zSets,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
index 4e4627b..6834ee5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
@@ -77,8 +77,7 @@
 
         @Override
         public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content,
-                DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer,
-                TaskDisplayArea taskDisplayArea) {
+                DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer) {
             throw new RuntimeException("test stub");
         }
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
index 618e608..880c486 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java
@@ -54,17 +54,6 @@
     }
 
     @Test
-    public void testDisplayArea_positionChanged_throwsIfIncompatibleSibling() {
-        WindowManagerService wms = mWmsRule.getWindowManagerService();
-        DisplayArea<WindowContainer> parent = new SurfacelessDisplayArea<>(wms, ANY, "Parent");
-        DisplayArea<WindowContainer> child1 = new DisplayArea<>(wms, ANY, "Child1");
-        DisplayArea<WindowContainer> child2 = new DisplayArea<>(wms, ANY, "Child2");
-
-        parent.addChild(child1, 0);
-        assertThrows(IllegalStateException.class, () -> parent.addChild(child2, 0));
-    }
-
-    @Test
     public void testType_typeOf() {
         WindowManagerService wms = mWmsRule.getWindowManagerService();
 
@@ -87,10 +76,10 @@
         checkSiblings(BELOW_TASKS, ABOVE_TASKS);
         checkSiblings(ANY, ABOVE_TASKS);
         checkSiblings(ABOVE_TASKS, ABOVE_TASKS);
+        checkSiblings(ANY, ANY);
 
         assertThrows(IllegalStateException.class, () -> checkSiblings(ABOVE_TASKS, BELOW_TASKS));
         assertThrows(IllegalStateException.class, () -> checkSiblings(ABOVE_TASKS, ANY));
-        assertThrows(IllegalStateException.class, () -> checkSiblings(ANY, ANY));
         assertThrows(IllegalStateException.class, () -> checkSiblings(ANY, BELOW_TASKS));
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 9625ffd..a708533 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -51,10 +51,10 @@
 import org.junit.runner.RunWith;
 
 /**
- * Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}.
+ * Tests for the {@link TaskDisplayArea} container.
  *
  * Build/Install/Run:
- *  atest WmTests:TaskStackContainersTests
+ *  atest WmTests:TaskDisplayAreaTests
  */
 @SmallTest
 @Presubmit
@@ -154,8 +154,9 @@
                 ACTIVITY_TYPE_STANDARD, mDisplayContent);
         final Task newStack = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN,
                 ACTIVITY_TYPE_STANDARD, mDisplayContent);
-        doReturn(newStack).when(mDisplayContent.mTaskContainers).createStack(anyInt(),
-                anyInt(), anyBoolean(), any(), any(), anyBoolean());
+        final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea();
+        doReturn(newStack).when(taskDisplayArea).createStack(anyInt(), anyInt(), anyBoolean(),
+                any(), any(), anyBoolean());
 
         final int type = ACTIVITY_TYPE_STANDARD;
         assertGetOrCreateStack(WINDOWING_MODE_FULLSCREEN, type, candidateTask,
@@ -186,7 +187,7 @@
 
     private void assertGetOrCreateStack(int windowingMode, int activityType, Task candidateTask,
             boolean reuseCandidate) {
-        final TaskDisplayArea taskDisplayArea = (TaskDisplayArea) candidateTask.getParent();
+        final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea();
         final ActivityStack stack = taskDisplayArea.getOrCreateStack(windowingMode, activityType,
                 false /* onTop */, null /* intent */, candidateTask /* candidateTask */);
         assertEquals(reuseCandidate, stack == candidateTask);
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 18737c2..57c7504 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -43,7 +43,9 @@
         // hard-code to FULLSCREEN for tests.
         setWindowingMode(WINDOWING_MODE_FULLSCREEN);
         spyOn(this);
-        spyOn(mTaskContainers);
+        for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) {
+            spyOn(getTaskDisplayAreaAt(i));
+        }
 
         final DisplayRotation displayRotation = getDisplayRotation();
         spyOn(displayRotation);
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
index d5851d8..0c25cfb 100644
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
@@ -34,18 +34,21 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.BackgroundDexOptService;
 import com.android.server.wm.ActivityMetricsLaunchObserver;
 import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
 import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature;
 import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
+import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 import java.util.HashMap;
 
@@ -286,6 +289,7 @@
 
     private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
     private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator();
+    private final DexOptPackagesUpdated mDexOptPackagesUpdated = new DexOptPackagesUpdated();
     private boolean mRegisteredListeners = false;
 
     private void registerInProcessListenersLocked() {
@@ -308,9 +312,22 @@
         launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
         launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
 
+        BackgroundDexOptService.addPackagesUpdatedListener(mDexOptPackagesUpdated);
+
+
         mRegisteredListeners = true;
     }
 
+    private class DexOptPackagesUpdated implements BackgroundDexOptService.PackagesUpdatedListener {
+        @Override
+        public void onPackagesUpdated(ArraySet<String> updatedPackages) {
+            String[] updated = updatedPackages.toArray(new String[0]);
+            for (String packageName : updated) {
+                Log.d(TAG, "onPackagesUpdated: " + packageName);
+            }
+        }
+    }
+
     private class AppLaunchObserver implements ActivityMetricsLaunchObserver {
         // We add a synthetic sequence ID here to make it easier to differentiate new
         // launch sequences on the native side.
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 327e8b3..1a4b9d7 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1147,6 +1147,21 @@
             "support_ims_conference_event_package_bool";
 
     /**
+     * Determines whether processing of conference event package data received on a device other
+     * than the conference host is supported.
+     * <p>
+     * When a device A merges calls B and C into a conference it is considered the conference host
+     * and B and C are considered the conference peers.
+     * <p>
+     * When {@code true}, the conference peer will display the conference state if it receives
+     * conference event package data from the network.  When {@code false}, the conference peer will
+     * ignore conference event package data received from the network.
+     * @hide
+     */
+    public static final String KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_ON_PEER_BOOL =
+            "support_ims_conference_event_package_on_peer_bool";
+
+    /**
      * Determines whether High Definition audio property is displayed in the dialer UI.
      * If {@code false}, remove the HD audio property from the connection so that HD audio related
      * UI is not displayed. If {@code true}, keep HD audio property as it is configured.
@@ -3780,6 +3795,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_MANAGE_IMS_CONFERENCE_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_BOOL, true);
+        sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_ON_PEER_BOOL, true);
         sDefaults.putBoolean(KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL, false);
         sDefaults.putBoolean(KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL, false);
         sDefaults.putInt(KEY_IMS_CONFERENCE_SIZE_LIMIT_INT, 5);
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 2b1d9e5..18e2592 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -113,6 +113,7 @@
     public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
     public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
     public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55;
+    public static final int EVENT_SIM_STATE_UPDATED = BASE + 56;
 
     /***** Constants *****/
 
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 12d80fc..3f8261d 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -875,6 +875,11 @@
         } catch (IllegalArgumentException e) { }
     }
 
+    private class TestTransportInfo implements TransportInfo {
+        TestTransportInfo() {
+        }
+    }
+
     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
     public void testBuilder() {
         final int ownerUid = 1001;
@@ -882,6 +887,7 @@
         final int requestUid = 10100;
         final int[] administratorUids = {ownerUid, 10001};
         final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1);
+        final TestTransportInfo transportInfo = new TestTransportInfo();
         final String ssid = "TEST_SSID";
         final String packageName = "com.google.test.networkcapabilities";
         final NetworkCapabilities nc = new NetworkCapabilities.Builder()
@@ -896,7 +902,7 @@
                 .setLinkDownstreamBandwidthKbps(512)
                 .setLinkUpstreamBandwidthKbps(128)
                 .setNetworkSpecifier(specifier)
-                .setTransportInfo(null)
+                .setTransportInfo(transportInfo)
                 .setSignalStrength(signalStrength)
                 .setSsid(ssid)
                 .setRequestorUid(requestUid)
@@ -913,7 +919,7 @@
         assertEquals(128, nc.getLinkUpstreamBandwidthKbps());
         assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps());
         assertEquals(specifier, nc.getNetworkSpecifier());
-        assertNull(nc.getTransportInfo());
+        assertEquals(transportInfo, nc.getTransportInfo());
         assertEquals(signalStrength, nc.getSignalStrength());
         assertNotEquals(-50, nc.getSignalStrength());
         assertEquals(ssid, nc.getSsid());