Snap for 6345044 from d6503d5cfd3b65e3ee7925c94f111480d321aec3 to rvc-d1-release

Change-Id: I8d6652bff70b310c0fd3e1b56325f21358d93f1a
diff --git a/Android.bp b/Android.bp
index be1aefc..30d4409 100644
--- a/Android.bp
+++ b/Android.bp
@@ -548,33 +548,9 @@
     ],
 }
 
-java_library {
-    name: "framework-annotation-proc",
-    srcs: [
-        ":framework-all-sources",
-        "core/java/**/*.logtags",
-    ],
-    sdk_version: "core_platform",
-    libs: [
-        "app-compat-annotations",
-        "ext",
-        "unsupportedappusage",
-    ],
-
-    installable: false,
-    plugins: [
-        "compat-changeid-annotation-processor",
-    ],
-    static_libs: [
-        "framework-internal-utils",
-        "exoplayer2-extractor",
-        "android.hardware.wifi-V1.0-java-constants",
-    ]
-}
-
 platform_compat_config {
     name: "framework-platform-compat-config",
-    src: ":framework-annotation-proc",
+    src: ":framework-minus-apex",
 }
 
 // A temporary build target that is conditionally included on the bootclasspath if
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 61744e42..ef55f06 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -60,7 +60,9 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -119,6 +121,9 @@
      */
     public static final String SERVICE_META_DATA = "android.content_capture";
 
+    private final LocalDataShareAdapterResourceManager mDataShareAdapterResourceManager =
+            new LocalDataShareAdapterResourceManager();
+
     private Handler mHandler;
     private IContentCaptureServiceCallback mCallback;
 
@@ -546,7 +551,8 @@
                 Preconditions.checkNotNull(executor);
 
                 DataShareReadAdapterDelegate delegate =
-                        new DataShareReadAdapterDelegate(executor, adapter);
+                        new DataShareReadAdapterDelegate(executor, adapter,
+                                mDataShareAdapterResourceManager);
 
                 try {
                     callback.accept(delegate);
@@ -653,16 +659,17 @@
 
     private static class DataShareReadAdapterDelegate extends IDataShareReadAdapter.Stub {
 
+        private final WeakReference<LocalDataShareAdapterResourceManager> mResourceManagerReference;
         private final Object mLock = new Object();
-        private final WeakReference<DataShareReadAdapter> mAdapterReference;
-        private final WeakReference<Executor> mExecutorReference;
 
-        DataShareReadAdapterDelegate(Executor executor, DataShareReadAdapter adapter) {
+        DataShareReadAdapterDelegate(Executor executor, DataShareReadAdapter adapter,
+                LocalDataShareAdapterResourceManager resourceManager) {
             Preconditions.checkNotNull(executor);
             Preconditions.checkNotNull(adapter);
+            Preconditions.checkNotNull(resourceManager);
 
-            mExecutorReference = new WeakReference<>(executor);
-            mAdapterReference = new WeakReference<>(adapter);
+            resourceManager.initializeForDelegate(this, adapter, executor);
+            mResourceManagerReference = new WeakReference<>(resourceManager);
         }
 
         @Override
@@ -670,6 +677,10 @@
                 throws RemoteException {
             synchronized (mLock) {
                 executeAdapterMethodLocked(adapter -> adapter.onStart(fd), "onStart");
+
+                // Client app and Service successfully connected, so this object would be kept alive
+                // until the session has finished.
+                clearHardReferences();
             }
         }
 
@@ -678,16 +689,23 @@
             synchronized (mLock) {
                 executeAdapterMethodLocked(
                         adapter -> adapter.onError(errorCode), "onError");
+                clearHardReferences();
             }
         }
 
         private void executeAdapterMethodLocked(Consumer<DataShareReadAdapter> adapterFn,
                 String methodName) {
-            DataShareReadAdapter adapter = mAdapterReference.get();
-            Executor executor = mExecutorReference.get();
+            LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+            if (resourceManager == null) {
+                Slog.w(TAG, "Can't execute " + methodName + "(), resource manager has been GC'ed");
+                return;
+            }
+
+            DataShareReadAdapter adapter = resourceManager.getAdapter(this);
+            Executor executor = resourceManager.getExecutor(this);
 
             if (adapter == null || executor == null) {
-                Slog.w(TAG, "Can't execute " + methodName + "(), references have been GC'ed");
+                Slog.w(TAG, "Can't execute " + methodName + "(), references are null");
                 return;
             }
 
@@ -698,5 +716,51 @@
                 Binder.restoreCallingIdentity(identity);
             }
         }
+
+        private void clearHardReferences() {
+            LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+            if (resourceManager == null) {
+                Slog.w(TAG, "Can't clear references, resource manager has been GC'ed");
+                return;
+            }
+
+            resourceManager.clearHardReferences(this);
+        }
+    }
+
+    /**
+     * Wrapper class making sure dependencies on the current application stay in the application
+     * context.
+     */
+    private static class LocalDataShareAdapterResourceManager {
+
+        // Keeping hard references to the remote objects in the current process (static context)
+        // to prevent them to be gc'ed during the lifetime of the application. This is an
+        // artifact of only operating with weak references remotely: there has to be at least 1
+        // hard reference in order for this to not be killed.
+        private Map<DataShareReadAdapterDelegate, DataShareReadAdapter>
+                mDataShareReadAdapterHardReferences = new HashMap<>();
+        private Map<DataShareReadAdapterDelegate, Executor> mExecutorHardReferences =
+                new HashMap<>();
+
+
+        void initializeForDelegate(DataShareReadAdapterDelegate delegate,
+                DataShareReadAdapter adapter, Executor executor) {
+            mDataShareReadAdapterHardReferences.put(delegate, adapter);
+            mExecutorHardReferences.remove(delegate, executor);
+        }
+
+        Executor getExecutor(DataShareReadAdapterDelegate delegate) {
+            return mExecutorHardReferences.get(delegate);
+        }
+
+        DataShareReadAdapter getAdapter(DataShareReadAdapterDelegate delegate) {
+            return mDataShareReadAdapterHardReferences.get(delegate);
+        }
+
+        void clearHardReferences(DataShareReadAdapterDelegate delegate) {
+            mDataShareReadAdapterHardReferences.remove(delegate);
+            mExecutorHardReferences.remove(delegate);
+        }
     }
 }
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 954b83b..edc6b12 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -54,6 +54,8 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -360,6 +362,9 @@
     @NonNull
     private final IContentCaptureManager mService;
 
+    @GuardedBy("mLock")
+    private final LocalDataShareAdapterResourceManager mDataShareAdapterResourceManager;
+
     @NonNull
     final ContentCaptureOptions mOptions;
 
@@ -399,6 +404,8 @@
         // do, then we should optimize it to run the tests after the Choreographer finishes the most
         // important steps of the frame.
         mHandler = Handler.createAsync(Looper.getMainLooper());
+
+        mDataShareAdapterResourceManager = new LocalDataShareAdapterResourceManager();
     }
 
     /**
@@ -681,7 +688,8 @@
 
         try {
             mService.shareData(request,
-                    new DataShareAdapterDelegate(executor, dataShareWriteAdapter));
+                    new DataShareAdapterDelegate(executor, dataShareWriteAdapter,
+                            mDataShareAdapterResourceManager));
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
@@ -737,40 +745,53 @@
 
     private static class DataShareAdapterDelegate extends IDataShareWriteAdapter.Stub {
 
-        private final WeakReference<DataShareWriteAdapter> mAdapterReference;
-        private final WeakReference<Executor> mExecutorReference;
+        private final WeakReference<LocalDataShareAdapterResourceManager> mResourceManagerReference;
 
-        private DataShareAdapterDelegate(Executor executor, DataShareWriteAdapter adapter) {
+        private DataShareAdapterDelegate(Executor executor, DataShareWriteAdapter adapter,
+                LocalDataShareAdapterResourceManager resourceManager) {
             Preconditions.checkNotNull(executor);
             Preconditions.checkNotNull(adapter);
+            Preconditions.checkNotNull(resourceManager);
 
-            mExecutorReference = new WeakReference<>(executor);
-            mAdapterReference = new WeakReference<>(adapter);
+            resourceManager.initializeForDelegate(this, adapter, executor);
+            mResourceManagerReference = new WeakReference<>(resourceManager);
         }
 
         @Override
         public void write(ParcelFileDescriptor destination)
                 throws RemoteException {
             executeAdapterMethodLocked(adapter -> adapter.onWrite(destination), "onWrite");
+
+            // Client app and Service successfully connected, so this object would be kept alive
+            // until the session has finished.
+            clearHardReferences();
         }
 
         @Override
         public void error(int errorCode) throws RemoteException {
             executeAdapterMethodLocked(adapter -> adapter.onError(errorCode), "onError");
+            clearHardReferences();
         }
 
         @Override
         public void rejected() throws RemoteException {
             executeAdapterMethodLocked(DataShareWriteAdapter::onRejected, "onRejected");
+            clearHardReferences();
         }
 
         private void executeAdapterMethodLocked(Consumer<DataShareWriteAdapter> adapterFn,
                 String methodName) {
-            DataShareWriteAdapter adapter = mAdapterReference.get();
-            Executor executor = mExecutorReference.get();
+            LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+            if (resourceManager == null) {
+                Slog.w(TAG, "Can't execute " + methodName + "(), resource manager has been GC'ed");
+                return;
+            }
+
+            DataShareWriteAdapter adapter = resourceManager.getAdapter(this);
+            Executor executor = resourceManager.getExecutor(this);
 
             if (adapter == null || executor == null) {
-                Slog.w(TAG, "Can't execute " + methodName + "(), references have been GC'ed");
+                Slog.w(TAG, "Can't execute " + methodName + "(), references are null");
                 return;
             }
 
@@ -781,5 +802,50 @@
                 Binder.restoreCallingIdentity(identity);
             }
         }
+
+        private void clearHardReferences() {
+            LocalDataShareAdapterResourceManager resourceManager = mResourceManagerReference.get();
+            if (resourceManager == null) {
+                Slog.w(TAG, "Can't clear references, resource manager has been GC'ed");
+                return;
+            }
+
+            resourceManager.clearHardReferences(this);
+        }
+    }
+
+    /**
+     * Wrapper class making sure dependencies on the current application stay in the application
+     * context.
+     */
+    private static class LocalDataShareAdapterResourceManager {
+
+        // Keeping hard references to the remote objects in the current process (static context)
+        // to prevent them to be gc'ed during the lifetime of the application. This is an
+        // artifact of only operating with weak references remotely: there has to be at least 1
+        // hard reference in order for this to not be killed.
+        private Map<DataShareAdapterDelegate, DataShareWriteAdapter> mWriteAdapterHardReferences =
+                new HashMap<>();
+        private Map<DataShareAdapterDelegate, Executor> mExecutorHardReferences =
+                new HashMap<>();
+
+        void initializeForDelegate(DataShareAdapterDelegate delegate, DataShareWriteAdapter adapter,
+                Executor executor) {
+            mWriteAdapterHardReferences.put(delegate, adapter);
+            mExecutorHardReferences.remove(delegate, executor);
+        }
+
+        Executor getExecutor(DataShareAdapterDelegate delegate) {
+            return mExecutorHardReferences.get(delegate);
+        }
+
+        DataShareWriteAdapter getAdapter(DataShareAdapterDelegate delegate) {
+            return mWriteAdapterHardReferences.get(delegate);
+        }
+
+        void clearHardReferences(DataShareAdapterDelegate delegate) {
+            mWriteAdapterHardReferences.remove(delegate);
+            mExecutorHardReferences.remove(delegate);
+        }
     }
 }
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 99605ad..a871047 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -193,12 +193,6 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
-    "-1741065110": {
-      "message": "No app is requesting an orientation, return %d for display id=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "-1730156332": {
       "message": "Display id=%d rotation changed to %d from %d, lastOrientation=%d",
       "level": "VERBOSE",
@@ -547,6 +541,12 @@
       "group": "WM_DEBUG_APP_TRANSITIONS",
       "at": "com\/android\/server\/wm\/AppTransitionController.java"
     },
+    "-993446393": {
+      "message": "App is requesting an orientation, return %d for display id=%d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/TaskContainers.java"
+    },
     "-993378225": {
       "message": "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s",
       "level": "VERBOSE",
@@ -715,12 +715,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "-650040763": {
-      "message": "rotationForOrientation(orient=%d, last=%d); user=%d %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayRotation.java"
-    },
     "-639305784": {
       "message": "Could not report config changes to the window token client.",
       "level": "WARN",
@@ -1021,12 +1015,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "44438983": {
-      "message": "performLayout: Activity exiting now removed %s",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ADD_REMOVE",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "45285419": {
       "message": "startingWindow was set but startingSurface==null, couldn't remove",
       "level": "VERBOSE",
@@ -1087,6 +1075,12 @@
       "group": "WM_SHOW_TRANSACTIONS",
       "at": "com\/android\/server\/wm\/WindowSurfaceController.java"
     },
+    "137835146": {
+      "message": "No app is requesting an orientation, return %d for display id=%d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ORIENTATION",
+      "at": "com\/android\/server\/wm\/TaskContainers.java"
+    },
     "140319294": {
       "message": "IME target changed within ActivityRecord",
       "level": "DEBUG",
@@ -1531,12 +1525,6 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/RemoteAnimationController.java"
     },
-    "845234215": {
-      "message": "App is requesting an orientation, return %d for display id=%d",
-      "level": "VERBOSE",
-      "group": "WM_DEBUG_ORIENTATION",
-      "at": "com\/android\/server\/wm\/DisplayContent.java"
-    },
     "853091290": {
       "message": "Moved stack=%s behind stack=%s",
       "level": "DEBUG",
@@ -1927,6 +1915,12 @@
       "group": "WM_DEBUG_STARTING_WINDOW",
       "at": "com\/android\/server\/wm\/ActivityRecord.java"
     },
+    "1685441447": {
+      "message": "performLayout: Activity exiting now removed %s",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_ADD_REMOVE",
+      "at": "com\/android\/server\/wm\/TaskContainers.java"
+    },
     "1720229827": {
       "message": "Creating animation bounds layer",
       "level": "INFO",
diff --git a/services/Android.bp b/services/Android.bp
index 1ce7dcf..730b9a5 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -81,10 +81,6 @@
         "framework-tethering-stubs-module_libs_api",
     ],
 
-    plugins: [
-        "compat-changeid-annotation-processor",
-    ],
-
     // Uncomment to enable output of certain warnings (deprecated, unchecked)
     //javacflags: ["-Xlint"],
 
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 5d2b9f3..ce539da 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -89,7 +89,6 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -919,35 +918,24 @@
     private static class DataShareCallbackDelegate extends IDataShareCallback.Stub {
 
         @NonNull private final DataShareRequest mDataShareRequest;
-        @NonNull private final WeakReference<IDataShareWriteAdapter> mClientAdapterReference;
-        @NonNull private final WeakReference<ContentCaptureManagerService> mParentServiceReference;
+        @NonNull private final IDataShareWriteAdapter mClientAdapter;
+        @NonNull private final ContentCaptureManagerService mParentService;
 
         DataShareCallbackDelegate(@NonNull DataShareRequest dataShareRequest,
                 @NonNull IDataShareWriteAdapter clientAdapter,
                 ContentCaptureManagerService parentService) {
             mDataShareRequest = dataShareRequest;
-            mClientAdapterReference = new WeakReference<>(clientAdapter);
-            mParentServiceReference = new WeakReference<>(parentService);
+            mClientAdapter = clientAdapter;
+            mParentService = parentService;
         }
 
         @Override
         public void accept(IDataShareReadAdapter serviceAdapter) throws RemoteException {
             Slog.i(TAG, "Data share request accepted by Content Capture service");
 
-            final ContentCaptureManagerService parentService = mParentServiceReference.get();
-            final IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
-            if (parentService == null || clientAdapter == null) {
-                Slog.w(TAG, "Can't fulfill accept() request, because remote objects have been "
-                        + "GC'ed");
-                return;
-            }
-
-            final WeakReference<IDataShareReadAdapter> serviceAdapterReference =
-                    new WeakReference<>(serviceAdapter);
-
             Pair<ParcelFileDescriptor, ParcelFileDescriptor> clientPipe = createPipe();
             if (clientPipe == null) {
-                clientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+                mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
                 serviceAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
                 return;
             }
@@ -959,7 +947,7 @@
             if (servicePipe == null) {
                 bestEffortCloseFileDescriptors(sourceIn, sinkIn);
 
-                clientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
+                mClientAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
                 serviceAdapter.error(ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
                 return;
             }
@@ -967,9 +955,9 @@
             ParcelFileDescriptor sourceOut = servicePipe.second;
             ParcelFileDescriptor sinkOut = servicePipe.first;
 
-            parentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
+            mParentService.mPackagesWithShareRequests.add(mDataShareRequest.getPackageName());
 
-            clientAdapter.write(sourceIn);
+            mClientAdapter.write(sourceIn);
             serviceAdapter.start(sinkOut);
 
             // File descriptor received by the client app will be a copy of the current one. Close
@@ -977,7 +965,7 @@
             // current pipe.
             bestEffortCloseFileDescriptor(sourceIn);
 
-            parentService.mDataShareExecutor.execute(() -> {
+            mParentService.mDataShareExecutor.execute(() -> {
                 try (InputStream fis =
                              new ParcelFileDescriptor.AutoCloseInputStream(sinkIn);
                      OutputStream fos =
@@ -996,23 +984,23 @@
                 } catch (IOException e) {
                     Slog.e(TAG, "Failed to pipe client and service streams", e);
 
-                    sendErrorSignal(mClientAdapterReference, serviceAdapterReference,
+                    sendErrorSignal(mClientAdapter, serviceAdapter,
                             ContentCaptureManager.DATA_SHARE_ERROR_UNKNOWN);
                 } finally {
-                    synchronized (parentService.mLock) {
-                        parentService.mPackagesWithShareRequests
+                    synchronized (mParentService.mLock) {
+                        mParentService.mPackagesWithShareRequests
                                 .remove(mDataShareRequest.getPackageName());
                     }
                 }
             });
 
-            parentService.mHandler.postDelayed(() ->
+            mParentService.mHandler.postDelayed(() ->
                     enforceDataSharingTtl(
                             sourceIn,
                             sinkIn,
                             sourceOut,
                             sinkOut,
-                            serviceAdapterReference),
+                            serviceAdapter),
                     MAX_DATA_SHARE_FILE_DESCRIPTORS_TTL_MS);
         }
 
@@ -1020,31 +1008,17 @@
         public void reject() throws RemoteException {
             Slog.i(TAG, "Data share request rejected by Content Capture service");
 
-            IDataShareWriteAdapter clientAdapter = mClientAdapterReference.get();
-            if (clientAdapter == null) {
-                Slog.w(TAG, "Can't fulfill reject() request, because remote objects have been "
-                        + "GC'ed");
-                return;
-            }
-
-            clientAdapter.rejected();
+            mClientAdapter.rejected();
         }
 
         private void enforceDataSharingTtl(ParcelFileDescriptor sourceIn,
                 ParcelFileDescriptor sinkIn,
                 ParcelFileDescriptor sourceOut,
                 ParcelFileDescriptor sinkOut,
-                WeakReference<IDataShareReadAdapter> serviceAdapterReference) {
+                IDataShareReadAdapter serviceAdapter) {
 
-            final ContentCaptureManagerService parentService = mParentServiceReference.get();
-            if (parentService == null) {
-                Slog.w(TAG, "Can't enforce data sharing TTL, because remote objects have been "
-                        + "GC'ed");
-                return;
-            }
-
-            synchronized (parentService.mLock) {
-                parentService.mPackagesWithShareRequests
+            synchronized (mParentService.mLock) {
+                mParentService.mPackagesWithShareRequests
                         .remove(mDataShareRequest.getPackageName());
 
                 // Interaction finished successfully <=> all data has been written to Content
@@ -1069,7 +1043,7 @@
                 bestEffortCloseFileDescriptors(sourceIn, sinkIn, sourceOut, sinkOut);
 
                 if (!finishedSuccessfully) {
-                    sendErrorSignal(mClientAdapterReference, serviceAdapterReference,
+                    sendErrorSignal(mClientAdapter, serviceAdapter,
                             ContentCaptureManager.DATA_SHARE_ERROR_TIMEOUT_INTERRUPTED);
                 }
             }
@@ -1115,19 +1089,9 @@
         }
 
         private static void sendErrorSignal(
-                WeakReference<IDataShareWriteAdapter> clientAdapterReference,
-                WeakReference<IDataShareReadAdapter> serviceAdapterReference,
+                IDataShareWriteAdapter clientAdapter,
+                IDataShareReadAdapter serviceAdapter,
                 int errorCode) {
-
-            final IDataShareWriteAdapter clientAdapter = clientAdapterReference.get();
-            final IDataShareReadAdapter serviceAdapter = serviceAdapterReference.get();
-
-            if (clientAdapter == null || serviceAdapter == null) {
-                Slog.w(TAG, "Can't propagate error() to read/write data share adapters, because "
-                        + "remote objects have been GC'ed");
-                return;
-            }
-
             try {
                 clientAdapter.error(errorCode);
             } catch (RemoteException e) {
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 7a26b21..dcf7615 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -130,10 +130,6 @@
         "netd_event_listener_interface-java",
         "overlayable_policy_aidl-java",
     ],
-
-    plugins: [
-        "compat-changeid-annotation-processor",
-    ],
 }
 
 java_genrule {
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
index 0ec0c7b..3c083e1 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java
@@ -19,8 +19,6 @@
 import android.content.res.Resources;
 import android.text.TextUtils;
 
-import com.android.server.wm.DisplayContent.TaskContainers;
-
 /**
  * Policy that manages DisplayAreas.
  */
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 9fc90da..5900ae8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -32,9 +32,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
-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.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -79,7 +77,6 @@
 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.WindowOrganizer.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
 
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
@@ -108,7 +105,6 @@
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
 import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
 import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
-import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
@@ -289,7 +285,7 @@
 
     /** The containers below are the only child containers {@link #mWindowContainers} can have. */
     // Contains all window containers that are related to apps (Activities)
-    private final TaskContainers mTaskContainers = new TaskContainers(mWmService);
+    private final TaskContainers mTaskContainers = new TaskContainers(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
@@ -579,10 +575,6 @@
     // Last systemUiVisibility we dispatched to windows.
     private int mLastDispatchedSystemUiVisibility = 0;
 
-    private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
-    private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>();
-    private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>();
-
     /** Corner radius that windows should have in order to match the display. */
     private final float mWindowCornerRadius;
 
@@ -4260,531 +4252,6 @@
         }
     }
 
-    /**
-     * Window container class that contains all containers on this display relating to Apps.
-     * I.e Activities.
-     */
-    final class TaskContainers extends DisplayArea<ActivityStack> {
-        /**
-         * A control placed at the appropriate level for transitions to occur.
-         */
-        SurfaceControl mAppAnimationLayer = null;
-        SurfaceControl mBoostedAppAnimationLayer = null;
-        SurfaceControl mHomeAppAnimationLayer = null;
-
-        /**
-         * Given that the split-screen divider does not have an AppWindowToken, it
-         * will have to live inside of a "NonAppWindowContainer". However, in visual Z order
-         * it will need to be interleaved with some of our children, appearing on top of
-         * both docked stacks but underneath any assistant stacks.
-         *
-         * To solve this problem we have this anchor control, which will always exist so
-         * we can always assign it the correct value in our {@link #assignChildLayers}.
-         * Likewise since it always exists, we can always
-         * assign the divider a layer relative to it. This way we prevent linking lifecycle
-         * events between tasks and the divider window.
-         */
-        SurfaceControl mSplitScreenDividerAnchor = null;
-
-        // Cached reference to some special tasks we tend to get a lot so we don't need to loop
-        // through the list to find them.
-        private ActivityStack mRootHomeTask = null;
-        private ActivityStack mRootPinnedTask = null;
-        private ActivityStack mRootSplitScreenPrimaryTask = null;
-
-        TaskContainers(WindowManagerService service) {
-            super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
-        }
-
-        /**
-         * Returns the topmost stack on the display that is compatible with the input windowing mode
-         * and activity type. Null is no compatible stack on the display.
-         */
-        ActivityStack getStack(int windowingMode, int activityType) {
-            if (activityType == ACTIVITY_TYPE_HOME) {
-                return mRootHomeTask;
-            }
-            if (windowingMode == WINDOWING_MODE_PINNED) {
-                return mRootPinnedTask;
-            } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                return mRootSplitScreenPrimaryTask;
-            }
-            for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack stack = mTaskContainers.getChildAt(i);
-                if (activityType == ACTIVITY_TYPE_UNDEFINED
-                        && windowingMode == stack.getWindowingMode()) {
-                    // Passing in undefined type means we want to match the topmost stack with the
-                    // windowing mode.
-                    return stack;
-                }
-                if (stack.isCompatible(windowingMode, activityType)) {
-                    return stack;
-                }
-            }
-            return null;
-        }
-
-        @VisibleForTesting
-        ActivityStack getTopStack() {
-            final int count = mTaskContainers.getChildCount();
-            return count > 0 ? mTaskContainers.getChildAt(count - 1) : null;
-        }
-
-        int getIndexOf(ActivityStack stack) {
-            return mTaskContainers.mChildren.indexOf(stack);
-        }
-
-        ActivityStack getRootHomeTask() {
-            return mRootHomeTask;
-        }
-
-        ActivityStack getRootPinnedTask() {
-            return mRootPinnedTask;
-        }
-
-        ActivityStack getRootSplitScreenPrimaryTask() {
-            return mRootSplitScreenPrimaryTask;
-        }
-
-        ArrayList<Task> getVisibleTasks() {
-            final ArrayList<Task> visibleTasks = new ArrayList<>();
-            forAllTasks(task -> {
-                if (task.isLeafTask() && task.isVisible()) {
-                    visibleTasks.add(task);
-                }
-            });
-            return visibleTasks;
-        }
-
-        void onStackWindowingModeChanged(ActivityStack stack) {
-            removeStackReferenceIfNeeded(stack);
-            addStackReferenceIfNeeded(stack);
-            if (stack == mRootPinnedTask && getTopStack() != stack) {
-                // Looks like this stack changed windowing mode to pinned. Move it to the top.
-                positionChildAt(POSITION_TOP, stack, false /* includingParents */);
-            }
-        }
-
-        private void addStackReferenceIfNeeded(ActivityStack stack) {
-            if (stack.isActivityTypeHome()) {
-                if (mRootHomeTask != null) {
-                    if (!stack.isDescendantOf(mRootHomeTask)) {
-                        throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
-                                + mRootHomeTask + " already exist on display=" + this
-                                + " stack=" + stack);
-                    }
-                } else {
-                    mRootHomeTask = stack;
-                }
-            }
-
-            if (!stack.isRootTask()) {
-                return;
-            }
-            final int windowingMode = stack.getWindowingMode();
-            if (windowingMode == WINDOWING_MODE_PINNED) {
-                if (mRootPinnedTask != null) {
-                    throw new IllegalArgumentException(
-                            "addStackReferenceIfNeeded: pinned stack=" + mRootPinnedTask
-                                    + " already exist on display=" + this + " stack=" + stack);
-                }
-                mRootPinnedTask = stack;
-            } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                if (mRootSplitScreenPrimaryTask != null) {
-                    throw new IllegalArgumentException(
-                            "addStackReferenceIfNeeded: split screen primary stack="
-                                    + mRootSplitScreenPrimaryTask
-                                    + " already exist on display=" + this + " stack=" + stack);
-                }
-                mRootSplitScreenPrimaryTask = stack;
-            }
-        }
-
-        void removeStackReferenceIfNeeded(ActivityStack stack) {
-            if (stack == mRootHomeTask) {
-                mRootHomeTask = null;
-            } else if (stack == mRootPinnedTask) {
-                mRootPinnedTask = null;
-            } else if (stack == mRootSplitScreenPrimaryTask) {
-                mRootSplitScreenPrimaryTask = null;
-            }
-        }
-
-        @Override
-        void addChild(ActivityStack stack, int position) {
-            addStackReferenceIfNeeded(stack);
-            position = findPositionForStack(position, stack, true /* adding */);
-
-            super.addChild(stack, position);
-            mAtmService.updateSleepIfNeededLocked();
-
-            // The reparenting case is handled in WindowContainer.
-            if (!stack.mReparenting) {
-                setLayoutNeeded();
-            }
-        }
-
-        @Override
-        protected void removeChild(ActivityStack stack) {
-            super.removeChild(stack);
-            mDisplayContent.onStackRemoved(stack);
-            mAtmService.updateSleepIfNeededLocked();
-            removeStackReferenceIfNeeded(stack);
-        }
-
-        @Override
-        boolean isOnTop() {
-            // Considered always on top
-            return true;
-        }
-
-        @Override
-        void positionChildAt(int position, ActivityStack child, boolean includingParents) {
-            final boolean moveToTop = (position == POSITION_TOP || position == getChildCount());
-            final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0);
-            if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
-                // This stack is always-on-top, override the default behavior.
-                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
-
-                // Moving to its current position, as we must call super but we don't want to
-                // perform any meaningful action.
-                final int currentPosition = mChildren.indexOf(child);
-                super.positionChildAt(currentPosition, child, false /* includingParents */);
-                return;
-            }
-            // We don't allow untrusted display to top when task stack moves to top,
-            // until user tapping this display to change display position as top intentionally.
-            if (isUntrustedVirtualDisplay() && !getParent().isOnTop()) {
-                includingParents = false;
-            }
-            final int targetPosition = findPositionForStack(position, child, false /* adding */);
-            super.positionChildAt(targetPosition, child, false /* includingParents */);
-
-            if (includingParents && (moveToTop || moveToBottom)) {
-                // The DisplayContent children do not re-order, but we still want to move the
-                // display of this stack container because the intention of positioning is to have
-                // higher z-order to gain focus.
-                positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
-                        true /* includingParents */);
-            }
-
-            child.updateTaskMovement(moveToTop);
-
-            setLayoutNeeded();
-        }
-
-        /**
-         * When stack is added or repositioned, find a proper position for it.
-         * This will make sure that pinned stack always stays on top.
-         * @param requestedPosition Position requested by caller.
-         * @param stack Stack to be added or positioned.
-         * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
-         * @return The proper position for the stack.
-         */
-        private int findPositionForStack(int requestedPosition, ActivityStack stack,
-                boolean adding) {
-            if (stack.isActivityTypeDream()) {
-                return POSITION_TOP;
-            }
-
-            if (stack.inPinnedWindowingMode()) {
-                return POSITION_TOP;
-            }
-
-            final int topChildPosition = mChildren.size() - 1;
-            int belowAlwaysOnTopPosition = POSITION_BOTTOM;
-            for (int i = topChildPosition; i >= 0; --i) {
-                // Since a stack could be repositioned while being one of the child, return
-                // current index if that's the same stack we are positioning and it is always on
-                // top.
-                final boolean sameStack = getStacks().get(i) == stack;
-                if ((sameStack && stack.isAlwaysOnTop())
-                        || (!sameStack && !getStacks().get(i).isAlwaysOnTop())) {
-                    belowAlwaysOnTopPosition = i;
-                    break;
-                }
-            }
-
-            // The max possible position we can insert the stack at.
-            int maxPosition = POSITION_TOP;
-            // The min possible position we can insert the stack at.
-            int minPosition = POSITION_BOTTOM;
-
-            if (stack.isAlwaysOnTop()) {
-                if (hasPinnedTask()) {
-                    // Always-on-top stacks go below the pinned stack.
-                    maxPosition = getStacks().indexOf(mRootPinnedTask) - 1;
-                }
-                // Always-on-top stacks need to be above all other stacks.
-                minPosition = belowAlwaysOnTopPosition !=
-                        POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
-            } else {
-                // Other stacks need to be below the always-on-top stacks.
-                maxPosition = belowAlwaysOnTopPosition !=
-                        POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
-            }
-
-            // Cap the requested position to something reasonable for the previous position check
-            // below.
-            if (requestedPosition == POSITION_TOP) {
-                requestedPosition = mChildren.size();
-            } else if (requestedPosition == POSITION_BOTTOM) {
-                requestedPosition = 0;
-            }
-
-            int targetPosition = requestedPosition;
-            targetPosition = Math.min(targetPosition, maxPosition);
-            targetPosition = Math.max(targetPosition, minPosition);
-
-            int prevPosition = getStacks().indexOf(stack);
-            // The positions we calculated above (maxPosition, minPosition) do not take into
-            // consideration the following edge cases.
-            // 1) We need to adjust the position depending on the value "adding".
-            // 2) When we are moving a stack to another position, we also need to adjust the
-            //    position depending on whether the stack is moving to a higher or lower position.
-            if ((targetPosition != requestedPosition) &&
-                    (adding || targetPosition < prevPosition)) {
-                targetPosition++;
-            }
-
-            return targetPosition;
-        }
-
-        @Override
-        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
-                boolean traverseTopToBottom) {
-            if (traverseTopToBottom) {
-                if (super.forAllWindows(callback, traverseTopToBottom)) {
-                    return true;
-                }
-                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
-                    return true;
-                }
-            } else {
-                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
-                    return true;
-                }
-                if (super.forAllWindows(callback, traverseTopToBottom)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
-                boolean traverseTopToBottom) {
-            // For legacy reasons we process the TaskStack.mExitingActivities first here before the
-            // app tokens.
-            // TODO: Investigate if we need to continue to do this or if we can just process them
-            // in-order.
-            if (traverseTopToBottom) {
-                for (int i = mChildren.size() - 1; i >= 0; --i) {
-                    final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
-                    for (int j = activities.size() - 1; j >= 0; --j) {
-                        if (activities.get(j).forAllWindowsUnchecked(callback,
-                                traverseTopToBottom)) {
-                            return true;
-                        }
-                    }
-                }
-            } else {
-                final int count = mChildren.size();
-                for (int i = 0; i < count; ++i) {
-                    final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
-                    final int appTokensCount = activities.size();
-                    for (int j = 0; j < appTokensCount; j++) {
-                        if (activities.get(j).forAllWindowsUnchecked(callback,
-                                traverseTopToBottom)) {
-                            return true;
-                        }
-                    }
-                }
-            }
-            return false;
-        }
-
-        void setExitingTokensHasVisible(boolean hasVisible) {
-            for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
-                for (int j = activities.size() - 1; j >= 0; --j) {
-                    activities.get(j).hasVisible = hasVisible;
-                }
-            }
-        }
-
-        void removeExistingAppTokensIfPossible() {
-            for (int i = mChildren.size() - 1; i >= 0; --i) {
-                final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
-                for (int j = activities.size() - 1; j >= 0; --j) {
-                    final ActivityRecord activity = activities.get(j);
-                    if (!activity.hasVisible && !mClosingApps.contains(activity)
-                            && (!activity.mIsExiting || activity.isEmpty())) {
-                        // Make sure there is no animation running on this activity, so any windows
-                        // associated with it will be removed as soon as their animations are
-                        // complete.
-                        cancelAnimation();
-                        ProtoLog.v(WM_DEBUG_ADD_REMOVE,
-                                "performLayout: Activity exiting now removed %s", activity);
-                        activity.removeIfPossible();
-                    }
-                }
-            }
-        }
-
-        @Override
-        int getOrientation(int candidate) {
-            if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
-                // Apps and their containers are not allowed to specify an orientation while using
-                // root tasks...except for the home stack if it is not resizable and currently
-                // visible (top of) its root task.
-                if (mRootHomeTask != null && mRootHomeTask.isVisible()) {
-                    final Task topMost = mRootHomeTask.getTopMostTask();
-                    final boolean resizable = topMost != null && topMost.isResizeable();
-                    if (!(resizable && mRootHomeTask.matchParentBounds())) {
-                        final int orientation = mRootHomeTask.getOrientation();
-                        if (orientation != SCREEN_ORIENTATION_UNSET) {
-                            return orientation;
-                        }
-                    }
-                }
-                return SCREEN_ORIENTATION_UNSPECIFIED;
-            }
-
-            final int orientation = super.getOrientation(candidate);
-            if (orientation != SCREEN_ORIENTATION_UNSET
-                    && orientation != SCREEN_ORIENTATION_BEHIND) {
-                ProtoLog.v(WM_DEBUG_ORIENTATION,
-                        "App is requesting an orientation, return %d for display id=%d",
-                        orientation, mDisplayId);
-                return orientation;
-            }
-
-            ProtoLog.v(WM_DEBUG_ORIENTATION,
-                    "No app is requesting an orientation, return %d for display id=%d",
-                    getLastOrientation(), mDisplayId);
-            // The next app has not been requested to be visible, so we keep the current orientation
-            // to prevent freezing/unfreezing the display too early.
-            return getLastOrientation();
-        }
-
-        @Override
-        void assignChildLayers(SurfaceControl.Transaction t) {
-            assignStackOrdering(t);
-
-            for (int i = 0; i < mChildren.size(); i++) {
-                final ActivityStack s = mChildren.get(i);
-                s.assignChildLayers(t);
-            }
-        }
-
-        void assignStackOrdering(SurfaceControl.Transaction t) {
-            if (getParent() == null) {
-                return;
-            }
-            mTmpAlwaysOnTopStacks.clear();
-            mTmpHomeStacks.clear();
-            mTmpNormalStacks.clear();
-            for (int i = 0; i < mChildren.size(); ++i) {
-                final ActivityStack s = mChildren.get(i);
-                if (s.isAlwaysOnTop()) {
-                    mTmpAlwaysOnTopStacks.add(s);
-                } else if (s.isActivityTypeHome()) {
-                    mTmpHomeStacks.add(s);
-                } else {
-                    mTmpNormalStacks.add(s);
-                }
-            }
-
-            int layer = 0;
-            // Place home stacks to the bottom.
-            for (int i = 0; i < mTmpHomeStacks.size(); i++) {
-                mTmpHomeStacks.get(i).assignLayer(t, layer++);
-            }
-            // The home animation layer is between the home stacks and the normal stacks.
-            final int layerForHomeAnimationLayer = layer++;
-            int layerForSplitScreenDividerAnchor = layer++;
-            int layerForAnimationLayer = layer++;
-            for (int i = 0; i < mTmpNormalStacks.size(); i++) {
-                final ActivityStack s = mTmpNormalStacks.get(i);
-                s.assignLayer(t, layer++);
-                if (s.inSplitScreenWindowingMode()) {
-                    // The split screen divider anchor is located above the split screen window.
-                    layerForSplitScreenDividerAnchor = layer++;
-                }
-                if (s.isTaskAnimating() || s.isAppTransitioning()) {
-                    // The animation layer is located above the highest animating stack and no
-                    // higher.
-                    layerForAnimationLayer = layer++;
-                }
-            }
-            // The boosted animation layer is between the normal stacks and the always on top
-            // stacks.
-            final int layerForBoostedAnimationLayer = layer++;
-            for (int i = 0; i < mTmpAlwaysOnTopStacks.size(); i++) {
-                mTmpAlwaysOnTopStacks.get(i).assignLayer(t, layer++);
-            }
-
-            t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
-            t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
-            t.setLayer(mSplitScreenDividerAnchor, layerForSplitScreenDividerAnchor);
-            t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
-        }
-
-        @Override
-        SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
-            switch (animationLayer) {
-                case ANIMATION_LAYER_BOOSTED:
-                    return mBoostedAppAnimationLayer;
-                case ANIMATION_LAYER_HOME:
-                    return mHomeAppAnimationLayer;
-                case ANIMATION_LAYER_STANDARD:
-                default:
-                    return mAppAnimationLayer;
-            }
-        }
-
-        SurfaceControl getSplitScreenDividerAnchor() {
-            return mSplitScreenDividerAnchor;
-        }
-
-        @Override
-        void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
-            if (getParent() != null) {
-                super.onParentChanged(newParent, oldParent, () -> {
-                    mAppAnimationLayer = makeChildSurface(null)
-                            .setName("animationLayer")
-                            .build();
-                    mBoostedAppAnimationLayer = makeChildSurface(null)
-                            .setName("boostedAnimationLayer")
-                            .build();
-                    mHomeAppAnimationLayer = makeChildSurface(null)
-                            .setName("homeAnimationLayer")
-                            .build();
-                    mSplitScreenDividerAnchor = makeChildSurface(null)
-                            .setName("splitScreenDividerAnchor")
-                            .build();
-                    getPendingTransaction()
-                            .show(mAppAnimationLayer)
-                            .show(mBoostedAppAnimationLayer)
-                            .show(mHomeAppAnimationLayer)
-                            .show(mSplitScreenDividerAnchor);
-                });
-            } else {
-                super.onParentChanged(newParent, oldParent);
-                mWmService.mTransactionFactory.get()
-                        .remove(mAppAnimationLayer)
-                        .remove(mBoostedAppAnimationLayer)
-                        .remove(mHomeAppAnimationLayer)
-                        .remove(mSplitScreenDividerAnchor)
-                        .apply();
-                mAppAnimationLayer = null;
-                mBoostedAppAnimationLayer = null;
-                mHomeAppAnimationLayer = null;
-                mSplitScreenDividerAnchor = null;
-            }
-        }
-    }
-
     private class WindowContainers extends DisplayChildWindowContainer<WindowContainer> {
         private final String mName;
 
diff --git a/services/core/java/com/android/server/wm/TaskContainers.java b/services/core/java/com/android/server/wm/TaskContainers.java
new file mode 100644
index 0000000..a959942
--- /dev/null
+++ b/services/core/java/com/android/server/wm/TaskContainers.java
@@ -0,0 +1,570 @@
+/*
+ * 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.wm;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+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.WindowOrganizer.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER;
+
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
+import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.util.Slog;
+import android.view.SurfaceControl;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ToBooleanFunction;
+import com.android.server.protolog.common.ProtoLog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Window container class that contains all containers on this display relating to Apps.
+ * I.e Activities.
+ */
+final class TaskContainers extends DisplayArea<ActivityStack> {
+    private DisplayContent mDisplayContent;
+    /**
+     * A control placed at the appropriate level for transitions to occur.
+     */
+    private SurfaceControl mAppAnimationLayer;
+    private SurfaceControl mBoostedAppAnimationLayer;
+    private SurfaceControl mHomeAppAnimationLayer;
+
+    /**
+     * Given that the split-screen divider does not have an AppWindowToken, it
+     * will have to live inside of a "NonAppWindowContainer". However, in visual Z order
+     * it will need to be interleaved with some of our children, appearing on top of
+     * both docked stacks but underneath any assistant stacks.
+     *
+     * To solve this problem we have this anchor control, which will always exist so
+     * we can always assign it the correct value in our {@link #assignChildLayers}.
+     * Likewise since it always exists, we can always
+     * assign the divider a layer relative to it. This way we prevent linking lifecycle
+     * events between tasks and the divider window.
+     */
+    private SurfaceControl mSplitScreenDividerAnchor;
+
+    // Cached reference to some special tasks we tend to get a lot so we don't need to loop
+    // through the list to find them.
+    private ActivityStack mRootHomeTask;
+    private ActivityStack mRootPinnedTask;
+    private ActivityStack mRootSplitScreenPrimaryTask;
+
+    private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
+    private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>();
+    private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>();
+
+    TaskContainers(DisplayContent displayContent, WindowManagerService service) {
+        super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER);
+        mDisplayContent = displayContent;
+    }
+
+    /**
+     * Returns the topmost stack on the display that is compatible with the input windowing mode
+     * and activity type. Null is no compatible stack on the display.
+     */
+    ActivityStack getStack(int windowingMode, int activityType) {
+        if (activityType == ACTIVITY_TYPE_HOME) {
+            return mRootHomeTask;
+        }
+        if (windowingMode == WINDOWING_MODE_PINNED) {
+            return mRootPinnedTask;
+        } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+            return mRootSplitScreenPrimaryTask;
+        }
+        for (int i = getChildCount() - 1; i >= 0; --i) {
+            final ActivityStack stack = getChildAt(i);
+            if (activityType == ACTIVITY_TYPE_UNDEFINED
+                    && windowingMode == stack.getWindowingMode()) {
+                // Passing in undefined type means we want to match the topmost stack with the
+                // windowing mode.
+                return stack;
+            }
+            if (stack.isCompatible(windowingMode, activityType)) {
+                return stack;
+            }
+        }
+        return null;
+    }
+
+    @VisibleForTesting
+    ActivityStack getTopStack() {
+        final int count = getChildCount();
+        return count > 0 ? getChildAt(count - 1) : null;
+    }
+
+    int getIndexOf(ActivityStack stack) {
+        return mChildren.indexOf(stack);
+    }
+
+    ActivityStack getRootHomeTask() {
+        return mRootHomeTask;
+    }
+
+    ActivityStack getRootPinnedTask() {
+        return mRootPinnedTask;
+    }
+
+    ActivityStack getRootSplitScreenPrimaryTask() {
+        return mRootSplitScreenPrimaryTask;
+    }
+
+    ArrayList<Task> getVisibleTasks() {
+        final ArrayList<Task> visibleTasks = new ArrayList<>();
+        forAllTasks(task -> {
+            if (task.isLeafTask() && task.isVisible()) {
+                visibleTasks.add(task);
+            }
+        });
+        return visibleTasks;
+    }
+
+    void onStackWindowingModeChanged(ActivityStack stack) {
+        removeStackReferenceIfNeeded(stack);
+        addStackReferenceIfNeeded(stack);
+        if (stack == mRootPinnedTask && getTopStack() != stack) {
+            // Looks like this stack changed windowing mode to pinned. Move it to the top.
+            positionChildAt(POSITION_TOP, stack, false /* includingParents */);
+        }
+    }
+
+    void addStackReferenceIfNeeded(ActivityStack stack) {
+        if (stack.isActivityTypeHome()) {
+            if (mRootHomeTask != null) {
+                if (!stack.isDescendantOf(mRootHomeTask)) {
+                    throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+                            + mRootHomeTask + " already exist on display=" + this
+                            + " stack=" + stack);
+                }
+            } else {
+                mRootHomeTask = stack;
+            }
+        }
+
+        if (!stack.isRootTask()) {
+            return;
+        }
+        final int windowingMode = stack.getWindowingMode();
+        if (windowingMode == WINDOWING_MODE_PINNED) {
+            if (mRootPinnedTask != null) {
+                throw new IllegalArgumentException(
+                        "addStackReferenceIfNeeded: pinned stack=" + mRootPinnedTask
+                                + " already exist on display=" + this + " stack=" + stack);
+            }
+            mRootPinnedTask = stack;
+        } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+            if (mRootSplitScreenPrimaryTask != null) {
+                throw new IllegalArgumentException(
+                        "addStackReferenceIfNeeded: split screen primary stack="
+                                + mRootSplitScreenPrimaryTask
+                                + " already exist on display=" + this + " stack=" + stack);
+            }
+            mRootSplitScreenPrimaryTask = stack;
+        }
+    }
+
+    void removeStackReferenceIfNeeded(ActivityStack stack) {
+        if (stack == mRootHomeTask) {
+            mRootHomeTask = null;
+        } else if (stack == mRootPinnedTask) {
+            mRootPinnedTask = null;
+        } else if (stack == mRootSplitScreenPrimaryTask) {
+            mRootSplitScreenPrimaryTask = null;
+        }
+    }
+
+    @Override
+    void addChild(ActivityStack stack, int position) {
+        addStackReferenceIfNeeded(stack);
+        position = findPositionForStack(position, stack, true /* adding */);
+
+        super.addChild(stack, position);
+        mDisplayContent.mAtmService.updateSleepIfNeededLocked();
+
+        // The reparenting case is handled in WindowContainer.
+        if (!stack.mReparenting) {
+            mDisplayContent.setLayoutNeeded();
+        }
+    }
+
+    @Override
+    protected void removeChild(ActivityStack stack) {
+        super.removeChild(stack);
+        mDisplayContent.onStackRemoved(stack);
+        mDisplayContent.mAtmService.updateSleepIfNeededLocked();
+        removeStackReferenceIfNeeded(stack);
+    }
+
+    @Override
+    boolean isOnTop() {
+        // Considered always on top
+        return true;
+    }
+
+    @Override
+    void positionChildAt(int position, ActivityStack child, boolean includingParents) {
+        final boolean moveToTop = (position == POSITION_TOP || position == getChildCount());
+        final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0);
+        if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
+            // This stack is always-on-top, override the default behavior.
+            Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
+
+            // Moving to its current position, as we must call super but we don't want to
+            // perform any meaningful action.
+            final int currentPosition = mChildren.indexOf(child);
+            super.positionChildAt(currentPosition, child, false /* includingParents */);
+            return;
+        }
+        // We don't allow untrusted display to top when task stack moves to top,
+        // until user tapping this display to change display position as top intentionally.
+        if (mDisplayContent.isUntrustedVirtualDisplay() && !getParent().isOnTop()) {
+            includingParents = false;
+        }
+        final int targetPosition = findPositionForStack(position, child, false /* adding */);
+        super.positionChildAt(targetPosition, child, false /* includingParents */);
+
+        if (includingParents && (moveToTop || moveToBottom)) {
+            // The DisplayContent children do not re-order, but we still want to move the
+            // display of this stack container because the intention of positioning is to have
+            // higher z-order to gain focus.
+            mDisplayContent.positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
+                    true /* includingParents */);
+        }
+
+        child.updateTaskMovement(moveToTop);
+
+        mDisplayContent.setLayoutNeeded();
+    }
+
+    /**
+     * When stack is added or repositioned, find a proper position for it.
+     * This will make sure that pinned stack always stays on top.
+     * @param requestedPosition Position requested by caller.
+     * @param stack Stack to be added or positioned.
+     * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
+     * @return The proper position for the stack.
+     */
+    private int findPositionForStack(int requestedPosition, ActivityStack stack,
+            boolean adding) {
+        if (stack.isActivityTypeDream()) {
+            return POSITION_TOP;
+        }
+
+        if (stack.inPinnedWindowingMode()) {
+            return POSITION_TOP;
+        }
+
+        final int topChildPosition = mChildren.size() - 1;
+        int belowAlwaysOnTopPosition = POSITION_BOTTOM;
+        for (int i = topChildPosition; i >= 0; --i) {
+            // Since a stack could be repositioned while being one of the child, return
+            // current index if that's the same stack we are positioning and it is always on
+            // top.
+            final boolean sameStack = mDisplayContent.getStacks().get(i) == stack;
+            if ((sameStack && stack.isAlwaysOnTop())
+                    || (!sameStack && !mDisplayContent.getStacks().get(i).isAlwaysOnTop())) {
+                belowAlwaysOnTopPosition = i;
+                break;
+            }
+        }
+
+        // The max possible position we can insert the stack at.
+        int maxPosition = POSITION_TOP;
+        // The min possible position we can insert the stack at.
+        int minPosition = POSITION_BOTTOM;
+
+        if (stack.isAlwaysOnTop()) {
+            if (mDisplayContent.hasPinnedTask()) {
+                // Always-on-top stacks go below the pinned stack.
+                maxPosition = mDisplayContent.getStacks().indexOf(mRootPinnedTask) - 1;
+            }
+            // Always-on-top stacks need to be above all other stacks.
+            minPosition = belowAlwaysOnTopPosition
+                    != POSITION_BOTTOM ? belowAlwaysOnTopPosition : topChildPosition;
+        } else {
+            // Other stacks need to be below the always-on-top stacks.
+            maxPosition = belowAlwaysOnTopPosition
+                    != POSITION_BOTTOM ? belowAlwaysOnTopPosition : 0;
+        }
+
+        // Cap the requested position to something reasonable for the previous position check
+        // below.
+        if (requestedPosition == POSITION_TOP) {
+            requestedPosition = mChildren.size();
+        } else if (requestedPosition == POSITION_BOTTOM) {
+            requestedPosition = 0;
+        }
+
+        int targetPosition = requestedPosition;
+        targetPosition = Math.min(targetPosition, maxPosition);
+        targetPosition = Math.max(targetPosition, minPosition);
+
+        int prevPosition = mDisplayContent.getStacks().indexOf(stack);
+        // The positions we calculated above (maxPosition, minPosition) do not take into
+        // consideration the following edge cases.
+        // 1) We need to adjust the position depending on the value "adding".
+        // 2) When we are moving a stack to another position, we also need to adjust the
+        //    position depending on whether the stack is moving to a higher or lower position.
+        if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
+            targetPosition++;
+        }
+
+        return targetPosition;
+    }
+
+    @Override
+    boolean forAllWindows(ToBooleanFunction<WindowState> callback,
+            boolean traverseTopToBottom) {
+        if (traverseTopToBottom) {
+            if (super.forAllWindows(callback, traverseTopToBottom)) {
+                return true;
+            }
+            if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
+                return true;
+            }
+        } else {
+            if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
+                return true;
+            }
+            if (super.forAllWindows(callback, traverseTopToBottom)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
+            boolean traverseTopToBottom) {
+        // For legacy reasons we process the TaskStack.mExitingActivities first here before the
+        // app tokens.
+        // TODO: Investigate if we need to continue to do this or if we can just process them
+        // in-order.
+        if (traverseTopToBottom) {
+            for (int i = mChildren.size() - 1; i >= 0; --i) {
+                final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                for (int j = activities.size() - 1; j >= 0; --j) {
+                    if (activities.get(j).forAllWindowsUnchecked(callback,
+                            traverseTopToBottom)) {
+                        return true;
+                    }
+                }
+            }
+        } else {
+            final int count = mChildren.size();
+            for (int i = 0; i < count; ++i) {
+                final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+                final int appTokensCount = activities.size();
+                for (int j = 0; j < appTokensCount; j++) {
+                    if (activities.get(j).forAllWindowsUnchecked(callback,
+                            traverseTopToBottom)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    void setExitingTokensHasVisible(boolean hasVisible) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+            for (int j = activities.size() - 1; j >= 0; --j) {
+                activities.get(j).hasVisible = hasVisible;
+            }
+        }
+    }
+
+    void removeExistingAppTokensIfPossible() {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
+            for (int j = activities.size() - 1; j >= 0; --j) {
+                final ActivityRecord activity = activities.get(j);
+                if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity)
+                        && (!activity.mIsExiting || activity.isEmpty())) {
+                    // Make sure there is no animation running on this activity, so any windows
+                    // associated with it will be removed as soon as their animations are
+                    // complete.
+                    cancelAnimation();
+                    ProtoLog.v(WM_DEBUG_ADD_REMOVE,
+                            "performLayout: Activity exiting now removed %s", activity);
+                    activity.removeIfPossible();
+                }
+            }
+        }
+    }
+
+    @Override
+    int getOrientation(int candidate) {
+        if (mDisplayContent.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
+            // Apps and their containers are not allowed to specify an orientation while using
+            // root tasks...except for the home stack if it is not resizable and currently
+            // visible (top of) its root task.
+            if (mRootHomeTask != null && mRootHomeTask.isVisible()) {
+                final Task topMost = mRootHomeTask.getTopMostTask();
+                final boolean resizable = topMost != null && topMost.isResizeable();
+                if (!(resizable && mRootHomeTask.matchParentBounds())) {
+                    final int orientation = mRootHomeTask.getOrientation();
+                    if (orientation != SCREEN_ORIENTATION_UNSET) {
+                        return orientation;
+                    }
+                }
+            }
+            return SCREEN_ORIENTATION_UNSPECIFIED;
+        }
+
+        final int orientation = super.getOrientation(candidate);
+        if (orientation != SCREEN_ORIENTATION_UNSET
+                && orientation != SCREEN_ORIENTATION_BEHIND) {
+            ProtoLog.v(WM_DEBUG_ORIENTATION,
+                    "App is requesting an orientation, return %d for display id=%d",
+                    orientation, mDisplayContent.mDisplayId);
+            return orientation;
+        }
+
+        ProtoLog.v(WM_DEBUG_ORIENTATION,
+                "No app is requesting an orientation, return %d for display id=%d",
+                mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
+        // The next app has not been requested to be visible, so we keep the current orientation
+        // to prevent freezing/unfreezing the display too early.
+        return mDisplayContent.getLastOrientation();
+    }
+
+    @Override
+    void assignChildLayers(SurfaceControl.Transaction t) {
+        assignStackOrdering(t);
+
+        for (int i = 0; i < mChildren.size(); i++) {
+            final ActivityStack s = mChildren.get(i);
+            s.assignChildLayers(t);
+        }
+    }
+
+    void assignStackOrdering(SurfaceControl.Transaction t) {
+        if (getParent() == null) {
+            return;
+        }
+        mTmpAlwaysOnTopStacks.clear();
+        mTmpHomeStacks.clear();
+        mTmpNormalStacks.clear();
+        for (int i = 0; i < mChildren.size(); ++i) {
+            final ActivityStack s = mChildren.get(i);
+            if (s.isAlwaysOnTop()) {
+                mTmpAlwaysOnTopStacks.add(s);
+            } else if (s.isActivityTypeHome()) {
+                mTmpHomeStacks.add(s);
+            } else {
+                mTmpNormalStacks.add(s);
+            }
+        }
+
+        int layer = 0;
+        // Place home stacks to the bottom.
+        for (int i = 0; i < mTmpHomeStacks.size(); i++) {
+            mTmpHomeStacks.get(i).assignLayer(t, layer++);
+        }
+        // The home animation layer is between the home stacks and the normal stacks.
+        final int layerForHomeAnimationLayer = layer++;
+        int layerForSplitScreenDividerAnchor = layer++;
+        int layerForAnimationLayer = layer++;
+        for (int i = 0; i < mTmpNormalStacks.size(); i++) {
+            final ActivityStack s = mTmpNormalStacks.get(i);
+            s.assignLayer(t, layer++);
+            if (s.inSplitScreenWindowingMode()) {
+                // The split screen divider anchor is located above the split screen window.
+                layerForSplitScreenDividerAnchor = layer++;
+            }
+            if (s.isTaskAnimating() || s.isAppTransitioning()) {
+                // The animation layer is located above the highest animating stack and no
+                // higher.
+                layerForAnimationLayer = layer++;
+            }
+        }
+        // The boosted animation layer is between the normal stacks and the always on top
+        // stacks.
+        final int layerForBoostedAnimationLayer = layer++;
+        for (int i = 0; i < mTmpAlwaysOnTopStacks.size(); i++) {
+            mTmpAlwaysOnTopStacks.get(i).assignLayer(t, layer++);
+        }
+
+        t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
+        t.setLayer(mAppAnimationLayer, layerForAnimationLayer);
+        t.setLayer(mSplitScreenDividerAnchor, layerForSplitScreenDividerAnchor);
+        t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
+    }
+
+    @Override
+    SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
+        switch (animationLayer) {
+            case ANIMATION_LAYER_BOOSTED:
+                return mBoostedAppAnimationLayer;
+            case ANIMATION_LAYER_HOME:
+                return mHomeAppAnimationLayer;
+            case ANIMATION_LAYER_STANDARD:
+            default:
+                return mAppAnimationLayer;
+        }
+    }
+
+    SurfaceControl getSplitScreenDividerAnchor() {
+        return mSplitScreenDividerAnchor;
+    }
+
+    @Override
+    void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+        if (getParent() != null) {
+            super.onParentChanged(newParent, oldParent, () -> {
+                mAppAnimationLayer = makeChildSurface(null)
+                        .setName("animationLayer")
+                        .build();
+                mBoostedAppAnimationLayer = makeChildSurface(null)
+                        .setName("boostedAnimationLayer")
+                        .build();
+                mHomeAppAnimationLayer = makeChildSurface(null)
+                        .setName("homeAnimationLayer")
+                        .build();
+                mSplitScreenDividerAnchor = makeChildSurface(null)
+                        .setName("splitScreenDividerAnchor")
+                        .build();
+                getPendingTransaction()
+                        .show(mAppAnimationLayer)
+                        .show(mBoostedAppAnimationLayer)
+                        .show(mHomeAppAnimationLayer)
+                        .show(mSplitScreenDividerAnchor);
+            });
+        } else {
+            super.onParentChanged(newParent, oldParent);
+            mWmService.mTransactionFactory.get()
+                    .remove(mAppAnimationLayer)
+                    .remove(mBoostedAppAnimationLayer)
+                    .remove(mHomeAppAnimationLayer)
+                    .remove(mSplitScreenDividerAnchor)
+                    .apply();
+            mAppAnimationLayer = null;
+            mBoostedAppAnimationLayer = null;
+            mHomeAppAnimationLayer = null;
+            mSplitScreenDividerAnchor = null;
+        }
+    }
+}
diff --git a/services/devicepolicy/Android.bp b/services/devicepolicy/Android.bp
index cdbe77a..2f6592b 100644
--- a/services/devicepolicy/Android.bp
+++ b/services/devicepolicy/Android.bp
@@ -13,8 +13,4 @@
         "services.core",
         "app-compat-annotations",
     ],
-
-    plugins: [
-        "compat-changeid-annotation-processor",
-    ],
 }
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index ae27c7a..25da8fe 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -157,7 +157,6 @@
 
 IncrementalService::IncFsMount::~IncFsMount() {
     incrementalService.mDataLoaderManager->destroyDataLoader(mountId);
-    control.reset();
     LOG(INFO) << "Unmounting and cleaning up mount " << mountId << " with root '" << root << '\'';
     for (auto&& [target, _] : bindPoints) {
         LOG(INFO) << "\tbind: " << target;
@@ -424,9 +423,10 @@
             LOG(ERROR) << "Vold::mountIncFs() returned invalid control parcel.";
             return kInvalidStorageId;
         }
-        control.cmd = controlParcel.cmd.release().release();
-        control.pendingReads = controlParcel.pendingReads.release().release();
-        control.logs = controlParcel.log.release().release();
+        int cmd = controlParcel.cmd.release().release();
+        int pendingReads = controlParcel.pendingReads.release().release();
+        int logs = controlParcel.log.release().release();
+        control = mIncFs->createControl(cmd, pendingReads, logs);
     }
 
     std::unique_lock l(mLock);
@@ -965,16 +965,17 @@
     auto mountTarget = path::join(root, constants().mount);
     const auto backing = path::join(root, constants().backing);
 
-    IncFsMount::Control control;
     IncrementalFileSystemControlParcel controlParcel;
     auto status = mVold->mountIncFs(backing, mountTarget, 0, &controlParcel);
     if (!status.isOk()) {
         LOG(ERROR) << "Vold::mountIncFs() failed: " << status.toString8();
         return false;
     }
-    control.cmd = controlParcel.cmd.release().release();
-    control.pendingReads = controlParcel.pendingReads.release().release();
-    control.logs = controlParcel.log.release().release();
+
+    int cmd = controlParcel.cmd.release().release();
+    int pendingReads = controlParcel.pendingReads.release().release();
+    int logs = controlParcel.log.release().release();
+    IncFsMount::Control control = mIncFs->createControl(cmd, pendingReads, logs);
 
     auto ifs = std::make_shared<IncFsMount>(std::string(root), -1, std::move(control), *this);
 
@@ -1084,10 +1085,10 @@
     }
     FileSystemControlParcel fsControlParcel;
     fsControlParcel.incremental = aidl::make_nullable<IncrementalFileSystemControlParcel>();
-    fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd)));
+    fsControlParcel.incremental->cmd.reset(base::unique_fd(::dup(ifs.control.cmd())));
     fsControlParcel.incremental->pendingReads.reset(
-            base::unique_fd(::dup(ifs.control.pendingReads)));
-    fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs)));
+            base::unique_fd(::dup(ifs.control.pendingReads())));
+    fsControlParcel.incremental->log.reset(base::unique_fd(::dup(ifs.control.logs())));
     sp<IncrementalDataLoaderListener> listener =
             new IncrementalDataLoaderListener(*this,
                                               externalListener ? *externalListener
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index 5349ebf..c70a47d 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -66,15 +66,17 @@
 class IncFsWrapper {
 public:
     virtual ~IncFsWrapper() = default;
-    virtual ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+    virtual Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const = 0;
+    virtual ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
                                NewFileParams params) const = 0;
-    virtual ErrorCode makeDir(Control control, std::string_view path, int mode) const = 0;
-    virtual RawMetadata getMetadata(Control control, FileId fileid) const = 0;
-    virtual RawMetadata getMetadata(Control control, std::string_view path) const = 0;
-    virtual FileId getFileId(Control control, std::string_view path) const = 0;
-    virtual ErrorCode link(Control control, std::string_view from, std::string_view to) const = 0;
-    virtual ErrorCode unlink(Control control, std::string_view path) const = 0;
-    virtual base::unique_fd openWrite(Control control, FileId id) const = 0;
+    virtual ErrorCode makeDir(const Control& control, std::string_view path, int mode) const = 0;
+    virtual RawMetadata getMetadata(const Control& control, FileId fileid) const = 0;
+    virtual RawMetadata getMetadata(const Control& control, std::string_view path) const = 0;
+    virtual FileId getFileId(const Control& control, std::string_view path) const = 0;
+    virtual ErrorCode link(const Control& control, std::string_view from,
+                           std::string_view to) const = 0;
+    virtual ErrorCode unlink(const Control& control, std::string_view path) const = 0;
+    virtual base::unique_fd openWrite(const Control& control, FileId id) const = 0;
     virtual ErrorCode writeBlocks(Span<const DataBlock> blocks) const = 0;
 };
 
@@ -149,29 +151,33 @@
 public:
     RealIncFs() = default;
     ~RealIncFs() = default;
-    ErrorCode makeFile(Control control, std::string_view path, int mode, FileId id,
+    Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs) const override {
+        return incfs::createControl(cmd, pendingReads, logs);
+    }
+    ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
                        NewFileParams params) const override {
         return incfs::makeFile(control, path, mode, id, params);
     }
-    ErrorCode makeDir(Control control, std::string_view path, int mode) const override {
+    ErrorCode makeDir(const Control& control, std::string_view path, int mode) const override {
         return incfs::makeDir(control, path, mode);
     }
-    RawMetadata getMetadata(Control control, FileId fileid) const override {
+    RawMetadata getMetadata(const Control& control, FileId fileid) const override {
         return incfs::getMetadata(control, fileid);
     }
-    RawMetadata getMetadata(Control control, std::string_view path) const override {
+    RawMetadata getMetadata(const Control& control, std::string_view path) const override {
         return incfs::getMetadata(control, path);
     }
-    FileId getFileId(Control control, std::string_view path) const override {
+    FileId getFileId(const Control& control, std::string_view path) const override {
         return incfs::getFileId(control, path);
     }
-    ErrorCode link(Control control, std::string_view from, std::string_view to) const override {
+    ErrorCode link(const Control& control, std::string_view from,
+                   std::string_view to) const override {
         return incfs::link(control, from, to);
     }
-    ErrorCode unlink(Control control, std::string_view path) const override {
+    ErrorCode unlink(const Control& control, std::string_view path) const override {
         return incfs::unlink(control, path);
     }
-    base::unique_fd openWrite(Control control, FileId id) const override {
+    base::unique_fd openWrite(const Control& control, FileId id) const override {
         return base::unique_fd{incfs::openWrite(control, id)};
     }
     ErrorCode writeBlocks(Span<const DataBlock> blocks) const override {
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index f5b88d9..c4b4d17 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -164,22 +164,23 @@
 
 class MockIncFs : public IncFsWrapper {
 public:
+    MOCK_CONST_METHOD3(createControl, Control(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs));
     MOCK_CONST_METHOD5(makeFile,
-                       ErrorCode(Control control, std::string_view path, int mode, FileId id,
+                       ErrorCode(const Control& control, std::string_view path, int mode, FileId id,
                                  NewFileParams params));
-    MOCK_CONST_METHOD3(makeDir, ErrorCode(Control control, std::string_view path, int mode));
-    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, FileId fileid));
-    MOCK_CONST_METHOD2(getMetadata, RawMetadata(Control control, std::string_view path));
-    MOCK_CONST_METHOD2(getFileId, FileId(Control control, std::string_view path));
+    MOCK_CONST_METHOD3(makeDir, ErrorCode(const Control& control, std::string_view path, int mode));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(const Control& control, FileId fileid));
+    MOCK_CONST_METHOD2(getMetadata, RawMetadata(const Control& control, std::string_view path));
+    MOCK_CONST_METHOD2(getFileId, FileId(const Control& control, std::string_view path));
     MOCK_CONST_METHOD3(link,
-                       ErrorCode(Control control, std::string_view from, std::string_view to));
-    MOCK_CONST_METHOD2(unlink, ErrorCode(Control control, std::string_view path));
-    MOCK_CONST_METHOD2(openWrite, base::unique_fd(Control control, FileId id));
+                       ErrorCode(const Control& control, std::string_view from, std::string_view to));
+    MOCK_CONST_METHOD2(unlink, ErrorCode(const Control& control, std::string_view path));
+    MOCK_CONST_METHOD2(openWrite, base::unique_fd(const Control& control, FileId id));
     MOCK_CONST_METHOD1(writeBlocks, ErrorCode(Span<const DataBlock> blocks));
 
     void makeFileFails() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(-1)); }
     void makeFileSuccess() { ON_CALL(*this, makeFile(_, _, _, _, _)).WillByDefault(Return(0)); }
-    RawMetadata getMountInfoMetadata(Control control, std::string_view path) {
+    RawMetadata getMountInfoMetadata(const Control& control, std::string_view path) {
         metadata::Mount m;
         m.mutable_storage()->set_id(100);
         m.mutable_loader()->set_package_name("com.test");
@@ -189,13 +190,13 @@
         m.mutable_loader()->release_package_name();
         return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getStorageMetadata(Control control, std::string_view path) {
+    RawMetadata getStorageMetadata(const Control& control, std::string_view path) {
         metadata::Storage st;
         st.set_id(100);
         auto metadata = st.SerializeAsString();
         return {metadata.begin(), metadata.end()};
     }
-    RawMetadata getBindPointMetadata(Control control, std::string_view path) {
+    RawMetadata getBindPointMetadata(const Control& control, std::string_view path) {
         metadata::BindPoint bp;
         std::string destPath = "dest";
         std::string srcPath = "src";
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 3120631..32d7a077 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java
@@ -78,7 +78,7 @@
         @Override
         public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content,
                 DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer,
-                DisplayContent.TaskContainers taskContainers) {
+                TaskContainers taskContainers) {
             throw new RuntimeException("test stub");
         }
     }