Add TestApi interfaces for window organizers

Enables testing the API surfaces from CTS.

Bug: 149338177
Test: they pass!
Change-Id: I7e1f2852585a10c20d299bd87e9a87f828d06d6a
diff --git a/api/test-current.txt b/api/test-current.txt
index 93cedf1..0ca8b2d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5158,3 +5158,75 @@
 
 }
 
+package android.window {
+
+  public class DisplayAreaOrganizer extends android.window.WindowOrganizer {
+    ctor public DisplayAreaOrganizer();
+    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_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
+  }
+
+  public class TaskOrganizer extends android.window.WindowOrganizer {
+    ctor public TaskOrganizer();
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.app.ActivityManager.RunningTaskInfo createRootTask(int, int);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static boolean deleteRootTask(@NonNull android.window.WindowContainerToken);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.window.WindowContainerToken getImeTarget(int);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getRootTasks(int, @NonNull int[]);
+    method public void onBackPressedOnTaskRoot(@NonNull android.app.ActivityManager.RunningTaskInfo);
+    method public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo);
+    method public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
+    method public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void registerOrganizer(int);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(boolean);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void unregisterOrganizer();
+  }
+
+  public final class WindowContainerToken implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.view.SurfaceControl getLeash();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.window.WindowContainerToken> CREATOR;
+  }
+
+  public final class WindowContainerTransaction implements android.os.Parcelable {
+    ctor public WindowContainerTransaction();
+    method public int describeContents();
+    method @NonNull public android.window.WindowContainerTransaction reorder(@NonNull android.window.WindowContainerToken, boolean);
+    method @NonNull public android.window.WindowContainerTransaction reparent(@NonNull android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, boolean);
+    method @NonNull public android.window.WindowContainerTransaction scheduleFinishEnterPip(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
+    method @NonNull public android.window.WindowContainerTransaction setActivityWindowingMode(@NonNull android.window.WindowContainerToken, int);
+    method @NonNull public android.window.WindowContainerTransaction setAppBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
+    method @NonNull public android.window.WindowContainerTransaction setBounds(@NonNull android.window.WindowContainerToken, @NonNull android.graphics.Rect);
+    method @NonNull public android.window.WindowContainerTransaction setBoundsChangeTransaction(@NonNull android.window.WindowContainerToken, @NonNull android.view.SurfaceControl.Transaction);
+    method @NonNull public android.window.WindowContainerTransaction setFocusable(@NonNull android.window.WindowContainerToken, boolean);
+    method @NonNull public android.window.WindowContainerTransaction setHidden(@NonNull android.window.WindowContainerToken, boolean);
+    method @NonNull public android.window.WindowContainerTransaction setScreenSizeDp(@NonNull android.window.WindowContainerToken, int, int);
+    method @NonNull public android.window.WindowContainerTransaction setSmallestScreenWidthDp(@NonNull android.window.WindowContainerToken, int);
+    method @NonNull public android.window.WindowContainerTransaction setWindowingMode(@NonNull android.window.WindowContainerToken, int);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.window.WindowContainerTransaction> CREATOR;
+  }
+
+  public abstract class WindowContainerTransactionCallback {
+    ctor public WindowContainerTransactionCallback();
+    method public abstract void onTransactionReady(int, @NonNull android.view.SurfaceControl.Transaction);
+  }
+
+  public class WindowOrganizer {
+    ctor public WindowOrganizer();
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public int applySyncTransaction(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.WindowContainerTransactionCallback);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void applyTransaction(@NonNull android.window.WindowContainerTransaction);
+  }
+
+}
+
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 556f841..2531c89 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -73,7 +73,7 @@
 import android.util.DisplayMetrics;
 import android.util.Singleton;
 import android.util.Size;
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 import android.view.Surface;
 
 import com.android.internal.app.LocalePicker;
@@ -2759,7 +2759,7 @@
         // Index of the stack in the display's stack list, can be used for comparison of stack order
         @UnsupportedAppUsage
         public int position;
-        public IWindowContainer stackToken;
+        public WindowContainerToken stackToken;
         /**
          * The full configuration the stack is currently running in.
          * @hide
@@ -2793,7 +2793,7 @@
             dest.writeInt(userId);
             dest.writeInt(visible ? 1 : 0);
             dest.writeInt(position);
-            dest.writeStrongInterface(stackToken);
+            stackToken.writeToParcel(dest, 0);
             if (topActivity != null) {
                 dest.writeInt(1);
                 topActivity.writeToParcel(dest, 0);
@@ -2825,7 +2825,7 @@
             userId = source.readInt();
             visible = source.readInt() > 0;
             position = source.readInt();
-            stackToken = IWindowContainer.Stub.asInterface(source.readStrongBinder());
+            stackToken = WindowContainerToken.CREATOR.createFromParcel(source);
             if (source.readInt() > 0) {
                 topActivity = ComponentName.readFromParcel(source);
             }
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 073b8d0..ab7925c 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -42,6 +42,9 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.window.TaskEmbedder;
+import android.window.TaskOrganizerTaskEmbedder;
+import android.window.VirtualDisplayTaskEmbedder;
 
 import dalvik.system.CloseGuard;
 
@@ -52,11 +55,11 @@
  * @hide
  */
 @TestApi
-public class ActivityView extends ViewGroup implements TaskEmbedder.Host {
+public class ActivityView extends ViewGroup implements android.window.TaskEmbedder.Host {
 
     private static final String TAG = "ActivityView";
 
-    private TaskEmbedder mTaskEmbedder;
+    private android.window.TaskEmbedder mTaskEmbedder;
 
     private final SurfaceView mSurfaceView;
     private final SurfaceCallback mSurfaceCallback;
@@ -487,7 +490,7 @@
 
     /** @hide */
     @Override
-    public void onTaskBackgroundColorChanged(TaskEmbedder ts, int bgColor) {
+    public void onTaskBackgroundColorChanged(android.window.TaskEmbedder ts, int bgColor) {
         if (mSurfaceView != null) {
             mSurfaceView.setResizeBackgroundColor(bgColor);
         }
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 7c0fc42..0173731 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -28,7 +28,7 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.util.Log;
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 
 /**
  * Stores information about a particular Task.
@@ -147,7 +147,7 @@
      * @hide
      */
     @NonNull
-    public IWindowContainer token;
+    public WindowContainerToken token;
 
     /**
      * The PictureInPictureParams for the Task, if set.
@@ -222,7 +222,7 @@
         supportsSplitScreenMultiWindow = source.readBoolean();
         resizeMode = source.readInt();
         configuration.readFromParcel(source);
-        token = IWindowContainer.Stub.asInterface(source.readStrongBinder());
+        token = WindowContainerToken.CREATOR.createFromParcel(source);
         topActivityType = source.readInt();
         pictureInPictureParams = source.readInt() != 0
                 ? PictureInPictureParams.CREATOR.createFromParcel(source)
@@ -265,7 +265,7 @@
         dest.writeBoolean(supportsSplitScreenMultiWindow);
         dest.writeInt(resizeMode);
         configuration.writeToParcel(dest, flags);
-        dest.writeStrongInterface(token);
+        token.writeToParcel(dest, flags);
         dest.writeInt(topActivityType);
         if (pictureInPictureParams == null) {
             dest.writeInt(0);
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
new file mode 100644
index 0000000..eee222b
--- /dev/null
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
+import android.os.RemoteException;
+import android.util.Singleton;
+
+/**
+ * Interface for WindowManager to delegate control of display areas.
+ * @hide
+ */
+@TestApi
+public class DisplayAreaOrganizer extends WindowOrganizer {
+
+    public static final int FEATURE_UNDEFINED = -1;
+    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 non-activity window tokens.
+    public static final int FEATURE_WINDOW_TOKENS = FEATURE_SYSTEM_FIRST + 2;
+
+    public static final int FEATURE_SYSTEM_LAST = 10_000;
+
+    // Vendor specific display area definition can start with this value.
+    public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1;
+
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void registerOrganizer(int displayAreaFeature) {
+        try {
+            getController().registerOrganizer(mInterface, displayAreaFeature);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    public void onDisplayAreaAppeared(@NonNull WindowContainerToken displayArea) {}
+
+    public void onDisplayAreaVanished(@NonNull WindowContainerToken displayArea) {}
+
+
+    private final IDisplayAreaOrganizer mInterface = new IDisplayAreaOrganizer.Stub() {
+
+        @Override
+        public void onDisplayAreaAppeared(@NonNull WindowContainerToken displayArea) {
+            DisplayAreaOrganizer.this.onDisplayAreaAppeared(displayArea);
+        }
+
+        @Override
+        public void onDisplayAreaVanished(@NonNull WindowContainerToken displayArea) {
+            DisplayAreaOrganizer.this.onDisplayAreaVanished(displayArea);
+        }
+    };
+
+    private static IDisplayAreaOrganizerController getController() {
+        return IDisplayAreaOrganizerControllerSingleton.get();
+    }
+
+    private static final Singleton<IDisplayAreaOrganizerController>
+            IDisplayAreaOrganizerControllerSingleton =
+            new Singleton<IDisplayAreaOrganizerController>() {
+                @Override
+                protected IDisplayAreaOrganizerController create() {
+                    try {
+                        return getWindowOrganizerController()
+                                .getDisplayAreaOrganizerController();
+                    } catch (RemoteException e) {
+                        return null;
+                    }
+                }
+            };
+
+}
diff --git a/core/java/android/window/IDisplayAreaOrganizer.aidl b/core/java/android/window/IDisplayAreaOrganizer.aidl
index 1045ab2..9c72e60 100644
--- a/core/java/android/window/IDisplayAreaOrganizer.aidl
+++ b/core/java/android/window/IDisplayAreaOrganizer.aidl
@@ -16,13 +16,13 @@
 
 package android.window;
 
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 
 /**
  * Interface for WindowManager to delegate control of display areas.
  * {@hide}
  */
 oneway interface IDisplayAreaOrganizer {
-    void onDisplayAreaAppeared(in IWindowContainer displayArea);
-    void onDisplayAreaVanished(in IWindowContainer displayArea);
+    void onDisplayAreaAppeared(in WindowContainerToken displayArea);
+    void onDisplayAreaVanished(in WindowContainerToken displayArea);
 }
diff --git a/core/java/android/window/ITaskOrganizer.aidl b/core/java/android/window/ITaskOrganizer.aidl
index b038b0f..b4f0162 100644
--- a/core/java/android/window/ITaskOrganizer.aidl
+++ b/core/java/android/window/ITaskOrganizer.aidl
@@ -18,7 +18,7 @@
 
 import android.view.SurfaceControl;
 import android.app.ActivityManager;
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 
 /**
  * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
diff --git a/core/java/android/window/ITaskOrganizerController.aidl b/core/java/android/window/ITaskOrganizerController.aidl
index ba65915..1c03b2f 100644
--- a/core/java/android/window/ITaskOrganizerController.aidl
+++ b/core/java/android/window/ITaskOrganizerController.aidl
@@ -18,7 +18,7 @@
 
 import android.app.ActivityManager;
 import android.window.ITaskOrganizer;
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
 /** @hide */
@@ -40,23 +40,23 @@
     ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode);
 
     /** Deletes a persistent root task in WM */
-    boolean deleteRootTask(IWindowContainer task);
+    boolean deleteRootTask(in WindowContainerToken task);
 
     /** Gets direct child tasks (ordered from top-to-bottom) */
-    List<ActivityManager.RunningTaskInfo> getChildTasks(in IWindowContainer parent,
+    List<ActivityManager.RunningTaskInfo> getChildTasks(in WindowContainerToken parent,
             in int[] activityTypes);
 
     /** Gets all root tasks on a display (ordered from top-to-bottom) */
     List<ActivityManager.RunningTaskInfo> getRootTasks(int displayId, in int[] activityTypes);
 
     /** Get the root task which contains the current ime target */
-    IWindowContainer getImeTarget(int display);
+    WindowContainerToken getImeTarget(int display);
 
     /**
      * Set's the root task to launch new tasks into on a display. {@code null} means no launch root
      * and thus new tasks just end up directly on the display.
      */
-    void setLaunchRoot(int displayId, in IWindowContainer root);
+    void setLaunchRoot(int displayId, in WindowContainerToken root);
 
     /**
      * Requests that the given task organizer is notified when back is pressed on the root activity
diff --git a/core/java/android/window/IWindowContainer.aidl b/core/java/android/window/IWindowContainerToken.aidl
similarity index 96%
rename from core/java/android/window/IWindowContainer.aidl
rename to core/java/android/window/IWindowContainerToken.aidl
index f2960f6..57c7abf 100644
--- a/core/java/android/window/IWindowContainer.aidl
+++ b/core/java/android/window/IWindowContainerToken.aidl
@@ -23,7 +23,7 @@
  * token.
  * @hide
  */
-interface IWindowContainer {
+interface IWindowContainerToken {
 
     /**
      * Gets a persistent leash for this container or {@code null}.
diff --git a/core/java/android/window/IWindowContainerTransactionCallback.aidl b/core/java/android/window/IWindowContainerTransactionCallback.aidl
index 0579932..eb07965 100644
--- a/core/java/android/window/IWindowContainerTransactionCallback.aidl
+++ b/core/java/android/window/IWindowContainerTransactionCallback.aidl
@@ -24,5 +24,5 @@
  */
 oneway interface IWindowContainerTransactionCallback {
     /** Called upon completion of WindowOrganizer#applyTransaction */
-    void transactionReady(int id, in SurfaceControl.Transaction t);
+    void onTransactionReady(int id, in SurfaceControl.Transaction t);
 }
diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/window/TaskEmbedder.java
similarity index 97%
rename from core/java/android/app/TaskEmbedder.java
rename to core/java/android/window/TaskEmbedder.java
index 10c11f2..45ab310 100644
--- a/core/java/android/app/TaskEmbedder.java
+++ b/core/java/android/window/TaskEmbedder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,13 +14,19 @@
  * limitations under the License.
  */
 
-package android.app;
+package android.window;
 
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.CallSuper;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
+import android.app.ActivityView;
+import android.app.IActivityTaskManager;
+import android.app.PendingIntent;
+import android.app.TaskStackListener;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
new file mode 100644
index 0000000..5098b44
--- /dev/null
+++ b/core/java/android/window/TaskOrganizer.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
+import android.app.ActivityManager;
+import android.os.RemoteException;
+import android.util.Singleton;
+
+import java.util.List;
+
+/**
+ * Interface for ActivityTaskManager/WindowManager to delegate control of tasks.
+ * @hide
+ */
+@TestApi
+public class TaskOrganizer extends WindowOrganizer {
+
+    /**
+     * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
+     * If there was already a TaskOrganizer for this windowing mode it will be evicted
+     * and receive taskVanished callbacks in the process.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void registerOrganizer(int windowingMode) {
+        try {
+            getController().registerTaskOrganizer(mInterface, windowingMode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Unregisters a previously registered task organizer. */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void unregisterOrganizer() {
+        try {
+            getController().unregisterTaskOrganizer(mInterface);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
+
+    public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
+
+    public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo info) {}
+
+    public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo info) {}
+
+    /** Creates a persistent root task in WM for a particular windowing-mode. */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    @Nullable
+    public static ActivityManager.RunningTaskInfo createRootTask(int displayId, int windowingMode) {
+        try {
+            return getController().createRootTask(displayId, windowingMode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Deletes a persistent root task in WM */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public static boolean deleteRootTask(@NonNull WindowContainerToken task) {
+        try {
+            return getController().deleteRootTask(task);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Gets direct child tasks (ordered from top-to-bottom) */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    @Nullable
+    public static List<ActivityManager.RunningTaskInfo> getChildTasks(
+            @NonNull WindowContainerToken parent, @NonNull int[] activityTypes) {
+        try {
+            return getController().getChildTasks(parent, activityTypes);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Gets all root tasks on a display (ordered from top-to-bottom) */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    @Nullable
+    public static List<ActivityManager.RunningTaskInfo> getRootTasks(
+            int displayId, @NonNull int[] activityTypes) {
+        try {
+            return getController().getRootTasks(displayId, activityTypes);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Get the root task which contains the current ime target */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    @Nullable
+    public static WindowContainerToken getImeTarget(int display) {
+        try {
+            return getController().getImeTarget(display);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Set's the root task to launch new tasks into on a display. {@code null} means no launch
+     * root and thus new tasks just end up directly on the display.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public static void setLaunchRoot(int displayId, @NonNull WindowContainerToken root) {
+        try {
+            getController().setLaunchRoot(displayId, root);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Requests that the given task organizer is notified when back is pressed on the root activity
+     * of one of its controlled tasks.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
+    public void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
+        try {
+            getController().setInterceptBackPressedOnTaskRoot(mInterface, interceptBackPressed);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private final ITaskOrganizer mInterface = new ITaskOrganizer.Stub() {
+
+        @Override
+        public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
+            TaskOrganizer.this.onTaskAppeared(taskInfo);
+        }
+
+        @Override
+        public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
+            TaskOrganizer.this.onTaskVanished(taskInfo);
+        }
+
+        @Override
+        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
+            TaskOrganizer.this.onTaskInfoChanged(info);
+        }
+
+        @Override
+        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo info) {
+            TaskOrganizer.this.onBackPressedOnTaskRoot(info);
+        }
+    };
+
+    private static ITaskOrganizerController getController() {
+        return ITaskOrganizerControllerSingleton.get();
+    }
+
+    private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
+            new Singleton<ITaskOrganizerController>() {
+                @Override
+                protected ITaskOrganizerController create() {
+                    try {
+                        return getWindowOrganizerController().getTaskOrganizerController();
+                    } catch (RemoteException e) {
+                        return null;
+                    }
+                }
+            };
+}
diff --git a/core/java/android/app/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java
similarity index 79%
rename from core/java/android/app/TaskOrganizerTaskEmbedder.java
rename to core/java/android/window/TaskOrganizerTaskEmbedder.java
index adc0792..2091c93 100644
--- a/core/java/android/app/TaskOrganizerTaskEmbedder.java
+++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,22 +14,20 @@
  * limitations under the License.
  */
 
-package android.app;
+package android.window;
 
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.ActivityView;
+import android.app.TaskStackListener;
 import android.content.Context;
 import android.graphics.Rect;
-import android.os.RemoteException;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.SurfaceControl;
-import android.window.ITaskOrganizer;
-import android.window.IWindowContainer;
-import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
-import android.window.WindowOrganizer.TaskOrganizer;
 
 /**
  * A component which handles embedded display of tasks within another window. The embedded task can
@@ -41,9 +39,9 @@
     private static final String TAG = "TaskOrgTaskEmbedder";
     private static final boolean DEBUG = false;
 
-    private ITaskOrganizer.Stub mTaskOrganizer;
+    private TaskOrganizer mTaskOrganizer;
     private ActivityManager.RunningTaskInfo mTaskInfo;
-    private IWindowContainer mTaskToken;
+    private WindowContainerToken mTaskToken;
     private SurfaceControl mTaskLeash;
     private boolean mPendingNotifyBoundsChanged;
 
@@ -79,16 +77,11 @@
         }
         // Register the task organizer
         mTaskOrganizer =  new TaskOrganizerImpl();
-        try {
-            // TODO(wm-shell): This currently prevents other organizers from controlling MULT_WINDOW
-            // windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that
-            // infrastructure is ready.
-            TaskOrganizer.registerOrganizer(mTaskOrganizer, WINDOWING_MODE_MULTI_WINDOW);
-            TaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskOrganizer, true);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to initialize TaskEmbedder", e);
-            return false;
-        }
+        // TODO(wm-shell): This currently prevents other organizers from controlling MULT_WINDOW
+        // windowing mode tasks. Plan is to migrate this to a wm-shell front-end when that
+        // infrastructure is ready.
+        mTaskOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW);
+        mTaskOrganizer.setInterceptBackPressedOnTaskRoot(true);
         return true;
     }
 
@@ -100,11 +93,7 @@
         if (!isInitialized()) {
             return false;
         }
-        try {
-            TaskOrganizer.unregisterOrganizer(mTaskOrganizer);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to remove task");
-        }
+        mTaskOrganizer.unregisterOrganizer();
         resetTaskInfo();
         return true;
     }
@@ -125,11 +114,7 @@
         }
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setHidden(mTaskToken, false /* hidden */);
-        try {
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to unset hidden in transaction");
-        }
+        WindowOrganizer.applyTransaction(wct);
         // TODO(b/151449487): Only call callback once we enable synchronization
         if (mListener != null) {
             mListener.onTaskVisibilityChanged(getTaskId(), true);
@@ -152,11 +137,7 @@
         }
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setHidden(mTaskToken, true /* hidden */);
-        try {
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to set hidden in transaction");
-        }
+        WindowOrganizer.applyTransaction(wct);
         // TODO(b/151449487): Only call callback once we enable synchronization
         if (mListener != null) {
             mListener.onTaskVisibilityChanged(getTaskId(), false);
@@ -186,12 +167,8 @@
 
         WindowContainerTransaction wct = new WindowContainerTransaction();
         wct.setBounds(mTaskToken, screenBounds);
-        try {
-            // TODO(b/151449487): Enable synchronization
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to set bounds in transaction");
-        }
+        // TODO(b/151449487): Enable synchronization
+        WindowOrganizer.applyTransaction(wct);
     }
 
     /**
@@ -253,8 +230,7 @@
     private class TaskStackListenerImpl extends TaskStackListener {
 
         @Override
-        public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo)
-                throws RemoteException {
+        public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
             if (!isInitialized()) {
                 return;
             }
@@ -266,10 +242,9 @@
         }
     }
 
-    private class TaskOrganizerImpl extends ITaskOrganizer.Stub {
+    private class TaskOrganizerImpl extends TaskOrganizer {
         @Override
-        public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo)
-                throws RemoteException {
+        public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
             if (DEBUG) {
                 log("taskAppeared: " + taskInfo.taskId);
             }
@@ -293,8 +268,7 @@
         }
 
         @Override
-        public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo)
-                throws RemoteException {
+        public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
             if (DEBUG) {
                 log("taskVanished: " + taskInfo.taskId);
             }
@@ -309,14 +283,7 @@
         }
 
         @Override
-        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo)
-                throws RemoteException {
-            // Do nothing
-        }
-
-        @Override
-        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo)
-                throws RemoteException {
+        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
             if (mListener != null) {
                 mListener.onBackPressedOnTaskRoot(taskInfo.taskId);
             }
diff --git a/core/java/android/app/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java
similarity index 97%
rename from core/java/android/app/VirtualDisplayTaskEmbedder.java
rename to core/java/android/window/VirtualDisplayTaskEmbedder.java
index 7ad8f22..0b2dcd8 100644
--- a/core/java/android/app/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.app;
+package android.window;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
@@ -23,6 +23,11 @@
 import static android.view.Display.INVALID_DISPLAY;
 
 import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
+import android.app.ActivityView;
+import android.app.TaskStackListener;
 import android.content.ComponentName;
 import android.content.Context;
 import android.graphics.Insets;
@@ -72,7 +77,7 @@
      * @param singleTaskInstance whether to apply a single-task constraint to this container,
      *                           only applicable if virtual displays are used
      */
-    VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
+    public VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
             boolean singleTaskInstance) {
         super(context, host);
         mSingleTaskInstance = singleTaskInstance;
diff --git a/core/java/android/window/IWindowContainer.aidl b/core/java/android/window/WindowContainerToken.aidl
similarity index 62%
copy from core/java/android/window/IWindowContainer.aidl
copy to core/java/android/window/WindowContainerToken.aidl
index f2960f6..f22786b 100644
--- a/core/java/android/window/IWindowContainer.aidl
+++ b/core/java/android/window/WindowContainerToken.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -16,17 +16,4 @@
 
 package android.window;
 
-import android.view.SurfaceControl;
-
-/**
- * Interface for a window container to communicate with the window manager. This also acts as a
- * token.
- * @hide
- */
-interface IWindowContainer {
-
-    /**
-     * Gets a persistent leash for this container or {@code null}.
-     */
-    SurfaceControl getLeash();
-}
+parcelable WindowContainerToken;
diff --git a/core/java/android/window/WindowContainerToken.java b/core/java/android/window/WindowContainerToken.java
new file mode 100644
index 0000000..dde98da
--- /dev/null
+++ b/core/java/android/window/WindowContainerToken.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.TestApi;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.view.SurfaceControl;
+import android.window.IWindowContainerToken;
+
+/**
+ * Interface for a window container to communicate with the window manager. This also acts as a
+ * token.
+ * @hide
+ */
+@TestApi
+public final class WindowContainerToken implements Parcelable {
+
+    private final IWindowContainerToken mRealToken;
+
+    /** @hide */
+    public WindowContainerToken(IWindowContainerToken realToken) {
+        mRealToken = realToken;
+    }
+
+    private WindowContainerToken(Parcel in) {
+        mRealToken = IWindowContainerToken.Stub.asInterface(in.readStrongBinder());
+    }
+
+    @Nullable
+    public SurfaceControl getLeash() {
+        try {
+            return mRealToken.getLeash();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** @hide */
+    public IBinder asBinder() {
+        return mRealToken.asBinder();
+    }
+
+    @Override
+    /** @hide */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeStrongBinder(mRealToken.asBinder());
+    }
+
+    @NonNull
+    public static final Creator<WindowContainerToken> CREATOR =
+            new Creator<WindowContainerToken>() {
+                @Override
+                public WindowContainerToken createFromParcel(Parcel in) {
+                    return new WindowContainerToken(in);
+                }
+
+                @Override
+                public WindowContainerToken[] newArray(int size) {
+                    return new WindowContainerToken[size];
+                }
+            };
+
+    @Override
+    /** @hide */
+    public int describeContents() {
+        return 0;
+    }
+}
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index 483dec6..231e024 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.app.WindowConfiguration;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -26,7 +27,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
-import android.window.IWindowContainer;
 import android.view.SurfaceControl;
 
 import java.util.ArrayList;
@@ -39,7 +39,8 @@
  *
  * @hide
  */
-public class WindowContainerTransaction implements Parcelable {
+@TestApi
+public final class WindowContainerTransaction implements Parcelable {
     private final ArrayMap<IBinder, Change> mChanges = new ArrayMap<>();
 
     // Flat list because re-order operations are order-dependent
@@ -47,7 +48,7 @@
 
     public WindowContainerTransaction() {}
 
-    protected WindowContainerTransaction(Parcel in) {
+    private WindowContainerTransaction(Parcel in) {
         in.readMap(mChanges, null /* loader */);
         in.readList(mHierarchyOps, null /* loader */);
     }
@@ -64,7 +65,9 @@
     /**
      * Resize a container.
      */
-    public WindowContainerTransaction setBounds(IWindowContainer container, Rect bounds) {
+    @NonNull
+    public WindowContainerTransaction setBounds(
+            @NonNull WindowContainerToken container,@NonNull Rect bounds) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mConfiguration.windowConfiguration.setBounds(bounds);
         chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
@@ -77,7 +80,9 @@
      * app's DisplayInfo. It is derived by subtracting the overlapping portion of the navbar from
      * the full bounds.
      */
-    public WindowContainerTransaction setAppBounds(IWindowContainer container, Rect appBounds) {
+    @NonNull
+    public WindowContainerTransaction setAppBounds(
+            @NonNull WindowContainerToken container,@NonNull Rect appBounds) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mConfiguration.windowConfiguration.setAppBounds(appBounds);
         chg.mConfigSetMask |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
@@ -91,7 +96,9 @@
      * derived by subtracting the overlapping portions of both the statusbar and the navbar from
      * the full bounds.
      */
-    public WindowContainerTransaction setScreenSizeDp(IWindowContainer container, int w, int h) {
+    @NonNull
+    public WindowContainerTransaction setScreenSizeDp(
+            @NonNull WindowContainerToken container, int w, int h) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mConfiguration.screenWidthDp = w;
         chg.mConfiguration.screenHeightDp = h;
@@ -100,11 +107,12 @@
     }
 
     /**
-     * Notify activies within the hiearchy of a container that they have entered picture-in-picture
+     * Notify activities within the hierarchy of a container that they have entered picture-in-picture
      * mode with the given bounds.
      */
-    public WindowContainerTransaction scheduleFinishEnterPip(IWindowContainer container,
-            Rect bounds) {
+    @NonNull
+    public WindowContainerTransaction scheduleFinishEnterPip(
+            @NonNull WindowContainerToken container,@NonNull Rect bounds) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mPinnedBounds = new Rect(bounds);
         chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK;
@@ -123,8 +131,9 @@
      * that you can call this, apply the WindowContainer transaction, and then later call
      * dismissPip() to achieve synchronization.
      */
-    public WindowContainerTransaction setBoundsChangeTransaction(IWindowContainer container,
-            SurfaceControl.Transaction t) {
+    @NonNull
+    public WindowContainerTransaction setBoundsChangeTransaction(
+            @NonNull WindowContainerToken container,@NonNull SurfaceControl.Transaction t) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mBoundsChangeTransaction = t;
         chg.mChangeMask |= Change.CHANGE_BOUNDS_TRANSACTION;
@@ -139,8 +148,9 @@
      *
      * TODO(b/134365562): Can be removed once TaskOrg drives full-screen
      */
-    public WindowContainerTransaction setActivityWindowingMode(IWindowContainer container,
-            int windowingMode) {
+    @NonNull
+    public WindowContainerTransaction setActivityWindowingMode(
+            @NonNull WindowContainerToken container, int windowingMode) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mActivityWindowingMode = windowingMode;
         return this;
@@ -149,8 +159,9 @@
     /**
      * Sets the windowing mode of the given container.
      */
-    public WindowContainerTransaction setWindowingMode(IWindowContainer container,
-            int windowingMode) {
+    @NonNull
+    public WindowContainerTransaction setWindowingMode(
+            @NonNull WindowContainerToken container, int windowingMode) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mWindowingMode = windowingMode;
         return this;
@@ -161,7 +172,9 @@
      * child can be focused; however, when {@code true}, it is still possible for children to be
      * non-focusable due to WM policy.
      */
-    public WindowContainerTransaction setFocusable(IWindowContainer container, boolean focusable) {
+    @NonNull
+    public WindowContainerTransaction setFocusable(
+            @NonNull WindowContainerToken container, boolean focusable) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mFocusable = focusable;
         chg.mChangeMask |= Change.CHANGE_FOCUSABLE;
@@ -173,7 +186,9 @@
      * visibility of the container applies, but when {@code true} the container will be forced
      * to be hidden.
      */
-    public WindowContainerTransaction setHidden(IWindowContainer container, boolean hidden) {
+    @NonNull
+    public WindowContainerTransaction setHidden(
+            @NonNull WindowContainerToken container, boolean hidden) {
         Change chg = getOrCreateChange(container.asBinder());
         chg.mHidden = hidden;
         chg.mChangeMask |= Change.CHANGE_HIDDEN;
@@ -183,8 +198,9 @@
     /**
      * Set the smallestScreenWidth of a container.
      */
-    public WindowContainerTransaction setSmallestScreenWidthDp(IWindowContainer container,
-            int widthDp) {
+    @NonNull
+    public WindowContainerTransaction setSmallestScreenWidthDp(
+            @NonNull WindowContainerToken container, int widthDp) {
         Change cfg = getOrCreateChange(container.asBinder());
         cfg.mConfiguration.smallestScreenWidthDp = widthDp;
         cfg.mConfigSetMask |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
@@ -198,8 +214,9 @@
      * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
      *              the bottom.
      */
-    public WindowContainerTransaction reparent(@NonNull IWindowContainer child,
-            @Nullable IWindowContainer parent, boolean onTop) {
+    @NonNull
+    public WindowContainerTransaction reparent(@NonNull WindowContainerToken child,
+            @Nullable WindowContainerToken parent, boolean onTop) {
         mHierarchyOps.add(new HierarchyOp(child.asBinder(),
                 parent == null ? null : parent.asBinder(), onTop));
         return this;
@@ -211,36 +228,43 @@
      * @param onTop When {@code true}, the child goes to the top of parent; otherwise it goes to
      *              the bottom.
      */
-    public WindowContainerTransaction reorder(@NonNull IWindowContainer child, boolean onTop) {
+    @NonNull
+    public WindowContainerTransaction reorder(@NonNull WindowContainerToken child, boolean onTop) {
         mHierarchyOps.add(new HierarchyOp(child.asBinder(), onTop));
         return this;
     }
 
+    /** @hide */
     public Map<IBinder, Change> getChanges() {
         return mChanges;
     }
 
+    /** @hide */
     public List<HierarchyOp> getHierarchyOps() {
         return mHierarchyOps;
     }
 
     @Override
+    @NonNull
     public String toString() {
         return "WindowContainerTransaction { changes = " + mChanges + " hops = " + mHierarchyOps
                 + " }";
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    /** @hide */
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeMap(mChanges);
         dest.writeList(mHierarchyOps);
     }
 
     @Override
+    /** @hide */
     public int describeContents() {
         return 0;
     }
 
+    @NonNull
     public static final Creator<WindowContainerTransaction> CREATOR =
             new Creator<WindowContainerTransaction>() {
                 @Override
@@ -256,7 +280,6 @@
 
     /**
      * Holds changes on a single WindowContainer including Configuration changes.
-     *
      * @hide
      */
     public static class Change implements Parcelable {
@@ -430,6 +453,7 @@
     /**
      * Holds information about a reparent/reorder operation in the hierarchy. This is separate from
      * Changes because they must be executed in the same order that they are added.
+     * @hide
      */
     public static class HierarchyOp implements Parcelable {
         private final IBinder mContainer;
diff --git a/core/java/android/window/WindowContainerTransactionCallback.java b/core/java/android/window/WindowContainerTransactionCallback.java
new file mode 100644
index 0000000..67cb1e7
--- /dev/null
+++ b/core/java/android/window/WindowContainerTransactionCallback.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.window;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.view.SurfaceControl;
+
+
+/**
+ * See WindowOrganizer#applyTransaction.
+ * {@hide}
+ */
+@TestApi
+public abstract class WindowContainerTransactionCallback {
+
+    public abstract void onTransactionReady(int id, @NonNull SurfaceControl.Transaction t);
+
+    /** @hide */
+    final IWindowContainerTransactionCallback mInterface =
+            new IWindowContainerTransactionCallback.Stub() {
+        @Override
+        public void onTransactionReady(int id, SurfaceControl.Transaction t) {
+            WindowContainerTransactionCallback.this.onTransactionReady(id, t);
+        }
+    };
+}
diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java
index 5590e72..4578271 100644
--- a/core/java/android/window/WindowOrganizer.java
+++ b/core/java/android/window/WindowOrganizer.java
@@ -16,29 +16,32 @@
 
 package android.window;
 
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
-import android.app.ActivityManager;
+import android.annotation.TestApi;
 import android.app.ActivityTaskManager;
 import android.os.RemoteException;
 import android.util.Singleton;
 
-import java.util.List;
-
 /**
- * Class for organizing specific types of windows like Tasks and DisplayAreas
+ * Base class for organizing specific types of windows like Tasks and DisplayAreas
  *
  * @hide
  */
+@TestApi
 public class WindowOrganizer {
 
     /**
      * Apply multiple WindowContainer operations at once.
      * @param t The transaction to apply.
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-    public static void applyTransaction(WindowContainerTransaction t) throws RemoteException {
-        getWindowOrganizerController().applyTransaction(t);
+    public static void applyTransaction(@NonNull WindowContainerTransaction t) {
+        try {
+            getWindowOrganizerController().applyTransaction(t);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -49,17 +52,19 @@
      *        WindowContainer transaction will be passed to this callback when ready.
      * @return An ID for the sync operation which will later be passed to transactionReady callback.
      *         This lets the caller differentiate overlapping sync operations.
-     * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-    public static int applySyncTransaction(WindowContainerTransaction t,
-            IWindowContainerTransactionCallback callback) throws RemoteException {
-        return getWindowOrganizerController().applySyncTransaction(t, callback);
+    public int applySyncTransaction(@NonNull WindowContainerTransaction t,
+            @NonNull WindowContainerTransactionCallback callback) {
+        try {
+            return getWindowOrganizerController().applySyncTransaction(t, callback.mInterface);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
     }
 
-    /** @hide */
     @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-    private static IWindowOrganizerController getWindowOrganizerController() {
+    static IWindowOrganizerController getWindowOrganizerController() {
         return IWindowOrganizerControllerSingleton.get();
     }
 
@@ -74,138 +79,4 @@
                     }
                 }
             };
-
-    public static class TaskOrganizer {
-
-        /**
-         * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
-         * If there was already a TaskOrganizer for this windowing mode it will be evicted
-         * and receive taskVanished callbacks in the process.
-         */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static void registerOrganizer(ITaskOrganizer organizer, int windowingMode)
-                throws RemoteException {
-            getController().registerTaskOrganizer(organizer, windowingMode);
-        }
-
-        /** Unregisters a previously registered task organizer. */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static void unregisterOrganizer(ITaskOrganizer organizer) throws RemoteException {
-            getController().unregisterTaskOrganizer(organizer);
-        }
-
-        /** Creates a persistent root task in WM for a particular windowing-mode. */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static ActivityManager.RunningTaskInfo createRootTask(
-                int displayId, int windowingMode) throws RemoteException {
-            return getController().createRootTask(displayId, windowingMode);
-        }
-
-        /** Deletes a persistent root task in WM */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static boolean deleteRootTask(IWindowContainer task) throws RemoteException {
-            return getController().deleteRootTask(task);
-        }
-
-        /** Gets direct child tasks (ordered from top-to-bottom) */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static List<ActivityManager.RunningTaskInfo> getChildTasks(IWindowContainer parent,
-                int[] activityTypes) throws RemoteException {
-            return getController().getChildTasks(parent, activityTypes);
-        }
-
-        /** Gets all root tasks on a display (ordered from top-to-bottom) */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static List<ActivityManager.RunningTaskInfo> getRootTasks(
-                int displayId, int[] activityTypes) throws RemoteException {
-            return getController().getRootTasks(displayId, activityTypes);
-        }
-
-        /** Get the root task which contains the current ime target */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static IWindowContainer getImeTarget(int display) throws RemoteException {
-            return getController().getImeTarget(display);
-        }
-
-        /**
-         * Set's the root task to launch new tasks into on a display. {@code null} means no launch
-         * root and thus new tasks just end up directly on the display.
-         */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static void setLaunchRoot(int displayId, IWindowContainer root)
-                throws RemoteException {
-            getController().setLaunchRoot(displayId, root);
-        }
-
-        /**
-         * Requests that the given task organizer is notified when back is pressed on the root
-         * activity of one of its controlled tasks.
-         */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
-                boolean interceptBackPressed) throws RemoteException {
-            getController().setInterceptBackPressedOnTaskRoot(organizer, interceptBackPressed);
-        }
-
-        private static ITaskOrganizerController getController() {
-            return ITaskOrganizerControllerSingleton.get();
-        }
-
-        private static final Singleton<ITaskOrganizerController> ITaskOrganizerControllerSingleton =
-                new Singleton<ITaskOrganizerController>() {
-                    @Override
-                    protected ITaskOrganizerController create() {
-                        try {
-                            return getWindowOrganizerController().getTaskOrganizerController();
-                        } catch (RemoteException e) {
-                            return null;
-                        }
-                    }
-                };
-    }
-
-    /** Class for organizing display areas. */
-    public static class DisplayAreaOrganizer {
-
-        public static final int FEATURE_UNDEFINED = -1;
-        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 non-activity window tokens.
-        public static final int FEATURE_WINDOW_TOKENS = FEATURE_SYSTEM_FIRST + 2;
-
-        public static final int FEATURE_SYSTEM_LAST = 10_000;
-
-        // Vendor specific display area definition can start with this value.
-        public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1;
-
-        /** @hide */
-        @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
-        public static void registerOrganizer(
-                IDisplayAreaOrganizer organizer, int displayAreaFeature) throws RemoteException {
-            getController().registerOrganizer(organizer, displayAreaFeature);
-        }
-
-        /** @hide */
-        private static IDisplayAreaOrganizerController getController() {
-            return IDisplayAreaOrganizerControllerSingleton.get();
-        }
-
-        private static final Singleton<IDisplayAreaOrganizerController>
-                IDisplayAreaOrganizerControllerSingleton =
-                new Singleton<IDisplayAreaOrganizerController>() {
-                    @Override
-                    protected IDisplayAreaOrganizerController create() {
-                        try {
-                            return getWindowOrganizerController()
-                                    .getDisplayAreaOrganizerController();
-                        } catch (RemoteException e) {
-                            return null;
-                        }
-                    }
-                };
-
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTaskView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTaskView.java
index 0d6d137..06205c5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTaskView.java
@@ -23,8 +23,8 @@
 import android.annotation.Nullable;
 import android.app.ActivityOptions;
 import android.app.PendingIntent;
-import android.app.TaskEmbedder;
-import android.app.TaskOrganizerTaskEmbedder;
+import android.window.TaskEmbedder;
+import android.window.TaskOrganizerTaskEmbedder;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ShortcutInfo;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index c40e9c0..15c9dba 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -41,8 +41,8 @@
 import android.util.Log;
 import android.util.Size;
 import android.view.SurfaceControl;
-import android.window.ITaskOrganizer;
-import android.window.IWindowContainer;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 import android.window.WindowOrganizer;
 
@@ -60,7 +60,7 @@
 /**
  * Manages PiP tasks such as resize and offset.
  *
- * This class listens on {@link ITaskOrganizer} callbacks for windowing mode change
+ * This class listens on {@link TaskOrganizer} callbacks for windowing mode change
  * both to and from PiP and issues corresponding animation if applicable.
  * Normally, we apply series of {@link SurfaceControl.Transaction} when the animator is running
  * and files a final {@link WindowContainerTransaction} at the end of the transition.
@@ -68,7 +68,7 @@
  * This class is also responsible for general resize/offset PiP operations within SysUI component,
  * see also {@link com.android.systemui.pip.phone.PipMotionHelper}.
  */
-public class PipTaskOrganizer extends ITaskOrganizer.Stub {
+public class PipTaskOrganizer extends TaskOrganizer {
     private static final String TAG = PipTaskOrganizer.class.getSimpleName();
 
     private static final int MSG_RESIZE_IMMEDIATE = 1;
@@ -182,7 +182,7 @@
     };
 
     private ActivityManager.RunningTaskInfo mTaskInfo;
-    private IWindowContainer mToken;
+    private WindowContainerToken mToken;
     private SurfaceControl mLeash;
     private boolean mInPip;
     private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
@@ -234,13 +234,9 @@
      * @param animationDurationMs duration in millisecond for the exiting PiP transition
      */
     public void dismissPip(int animationDurationMs) {
-        try {
-            final WindowContainerTransaction wct = new WindowContainerTransaction();
-            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to apply container transaction", e);
-        }
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
+        WindowOrganizer.applyTransaction(wct);
         final Rect destinationBounds = mBoundsToRestore.remove(mToken.asBinder());
         scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
                 TRANSITION_DIRECTION_TO_FULLSCREEN, animationDurationMs,
@@ -258,11 +254,8 @@
         mTaskInfo = info;
         mToken = mTaskInfo.token;
         mInPip = true;
-        try {
-            mLeash = mToken.getLeash();
-        } catch (RemoteException e) {
-            throw new RuntimeException("Unable to get leash", e);
-        }
+        mLeash = mToken.getLeash();
+
         final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
         mBoundsToRestore.put(mToken.asBinder(), currentBounds);
         if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
@@ -290,8 +283,8 @@
      */
     @Override
     public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
-        IWindowContainer token = info.token;
-        Objects.requireNonNull(token, "Requires valid IWindowContainer");
+        WindowContainerToken token = info.token;
+        Objects.requireNonNull(token, "Requires valid WindowContainerToken");
         if (token.asBinder() != mToken.asBinder()) {
             Log.wtf(TAG, "Unrecognized token: " + token);
             return;
@@ -502,30 +495,26 @@
                     + "directly");
         }
         mLastReportedBounds.set(destinationBounds);
-        try {
-            final WindowContainerTransaction wct = new WindowContainerTransaction();
-            final Rect taskBounds;
-            if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
-                // If we are animating to fullscreen, then we need to reset the override bounds
-                // on the task to ensure that the task "matches" the parent's bounds, this applies
-                // also to the final windowing mode, which should be reset to undefined rather than
-                // fullscreen.
-                taskBounds = null;
-                wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
-                        .setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
-            } else {
-                taskBounds = destinationBounds;
-            }
-            if (direction == TRANSITION_DIRECTION_TO_PIP) {
-                wct.scheduleFinishEnterPip(mToken, taskBounds);
-            } else {
-                wct.setBounds(mToken, taskBounds);
-            }
-            wct.setBoundsChangeTransaction(mToken, tx);
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed to apply container transaction", e);
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        final Rect taskBounds;
+        if (direction == TRANSITION_DIRECTION_TO_FULLSCREEN) {
+            // If we are animating to fullscreen, then we need to reset the override bounds
+            // on the task to ensure that the task "matches" the parent's bounds, this applies
+            // also to the final windowing mode, which should be reset to undefined rather than
+            // fullscreen.
+            taskBounds = null;
+            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED)
+                    .setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
+        } else {
+            taskBounds = destinationBounds;
         }
+        if (direction == TRANSITION_DIRECTION_TO_PIP) {
+            wct.scheduleFinishEnterPip(mToken, taskBounds);
+        } else {
+            wct.setBounds(mToken, taskBounds);
+        }
+        wct.setBoundsChangeTransaction(mToken, tx);
+        WindowOrganizer.applyTransaction(wct);
     }
 
     private void animateResizePip(Rect currentBounds, Rect destinationBounds,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 8a25f4d..99d6df5 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -18,7 +18,6 @@
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
 import static com.android.systemui.pip.PipAnimationController.TRANSITION_DIRECTION_TO_FULLSCREEN;
 
@@ -234,7 +233,7 @@
         mPipBoundsHandler.onDisplayInfoChanged(displayInfo);
 
         try {
-            TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
+            mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
             ActivityManager.StackInfo stackInfo = activityTaskManager.getStackInfo(
                     WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
             if (stackInfo != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index c6e6da1..52c8960 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -19,7 +19,6 @@
 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackInfo;
@@ -294,7 +293,7 @@
 
         try {
             WindowManagerWrapper.getInstance().addPinnedStackListener(mPinnedStackListener);
-            TaskOrganizer.registerOrganizer(mPipTaskOrganizer, WINDOWING_MODE_PINNED);
+            mPipTaskOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
         } catch (RemoteException | UnsupportedOperationException e) {
             Log.e(TAG, "Failed to register pinned stack listener", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 66e3211..b71c4eb 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -20,7 +20,6 @@
 import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
 import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -33,11 +32,12 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.Slog;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
-import android.window.IWindowContainer;
 import android.window.WindowContainerTransaction;
 import android.window.WindowOrganizer;
 
@@ -181,14 +181,9 @@
         private boolean mPausedTargetAdjusted = false;
 
         private boolean getSecondaryHasFocus(int displayId) {
-            try {
-                IWindowContainer imeSplit = TaskOrganizer.getImeTarget(displayId);
-                return imeSplit != null
-                        && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Failed to get IME target", e);
-            }
-            return false;
+            WindowContainerToken imeSplit = TaskOrganizer.getImeTarget(displayId);
+            return imeSplit != null
+                    && (imeSplit.asBinder() == mSplits.mSecondary.token.asBinder());
         }
 
         private void updateDimTargets() {
@@ -270,10 +265,8 @@
                 wct.setScreenSizeDp(mSplits.mSecondary.token,
                         SCREEN_WIDTH_DP_UNDEFINED, SCREEN_HEIGHT_DP_UNDEFINED);
             }
-            try {
-                WindowOrganizer.applyTransaction(wct);
-            } catch (RemoteException e) {
-            }
+
+            WindowOrganizer.applyTransaction(wct);
 
             // Update all the adjusted-for-ime states
             if (!mPaused) {
@@ -506,12 +499,8 @@
             int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
             final WindowContainerTransaction tct = new WindowContainerTransaction();
             mSplitLayout.resizeSplits(midPos, tct);
-            try {
-                WindowOrganizer.applyTransaction(tct);
-            } catch (RemoteException e) {
-            }
-        } else if (mRotateSplitLayout != null
-                && mSplitLayout.mDisplayLayout.rotation()
+            WindowOrganizer.applyTransaction(tct);
+        } else if (mSplitLayout.mDisplayLayout.rotation()
                         == mRotateSplitLayout.mDisplayLayout.rotation()) {
             mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
             mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
@@ -653,7 +642,7 @@
             }
         }
         updateTouchable();
-        WindowManagerProxy.applyContainerTransaction(wct);
+        WindowOrganizer.applyTransaction(wct);
     }
 
     void setAdjustedForIme(boolean adjustedForIme) {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index a6f6741..91d638e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -22,7 +22,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.WindowConfiguration;
@@ -32,11 +31,11 @@
 import android.view.Display;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
-import android.window.ITaskOrganizer;
+import android.window.TaskOrganizer;
 
 import java.util.ArrayList;
 
-class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
+class SplitScreenTaskOrganizer extends TaskOrganizer {
     private static final String TAG = "SplitScreenTaskOrganizer";
     private static final boolean DEBUG = Divider.DEBUG;
 
@@ -56,8 +55,8 @@
     }
 
     void init(SurfaceSession session) throws RemoteException {
-        TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
-        TaskOrganizer.registerOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        registerOrganizer(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
         try {
             mPrimary = TaskOrganizer.createRootTask(Display.DEFAULT_DISPLAY,
                     WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
@@ -65,9 +64,9 @@
                     WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
             mPrimarySurface = mPrimary.token.getLeash();
             mSecondarySurface = mSecondary.token.getLeash();
-        } catch (RemoteException e) {
+        } catch (Exception e) {
             // teardown to prevent callbacks
-            TaskOrganizer.unregisterOrganizer(this);
+            unregisterOrganizer();
             throw e;
         }
         mSplitScreenSupported = true;
@@ -99,14 +98,6 @@
     }
 
     @Override
-    public void onTaskAppeared(RunningTaskInfo taskInfo) {
-    }
-
-    @Override
-    public void onTaskVanished(RunningTaskInfo taskInfo) {
-    }
-
-    @Override
     public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
         if (taskInfo.displayId != DEFAULT_DISPLAY) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 6ed7afe..85dcbb6 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -20,7 +20,6 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
 import android.annotation.NonNull;
 import android.app.ActivityManager;
@@ -30,7 +29,8 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.WindowManagerGlobal;
-import android.window.IWindowContainer;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 import android.window.WindowOrganizer;
 
@@ -112,27 +112,21 @@
     static void applyResizeSplits(int position, SplitDisplayLayout splitLayout) {
         WindowContainerTransaction t = new WindowContainerTransaction();
         splitLayout.resizeSplits(position, t);
-        try {
-            WindowOrganizer.applyTransaction(t);
-        } catch (RemoteException e) {
-        }
+        WindowOrganizer.applyTransaction(t);
     }
 
-    private static boolean getHomeAndRecentsTasks(List<IWindowContainer> out,
-            IWindowContainer parent) {
+    private static boolean getHomeAndRecentsTasks(List<WindowContainerToken> out,
+            WindowContainerToken parent) {
         boolean resizable = false;
-        try {
-            List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
-                    ? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
-                    : TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
-            for (int i = 0, n = rootTasks.size(); i < n; ++i) {
-                final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
-                out.add(ti.token);
-                if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
-                    resizable = ti.isResizable();
-                }
+        List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
+                ? TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
+                : TaskOrganizer.getChildTasks(parent, HOME_AND_RECENTS);
+        for (int i = 0, n = rootTasks.size(); i < n; ++i) {
+            final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
+            out.add(ti.token);
+            if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
+                resizable = ti.isResizable();
             }
-        } catch (RemoteException e) {
         }
         return resizable;
     }
@@ -142,11 +136,11 @@
      * split is minimized. This actually "sticks out" of the secondary split area, but when in
      * minimized mode, the secondary split gets a 'negative' crop to expose it.
      */
-    static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent,
+    static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, WindowContainerToken parent,
             @NonNull WindowContainerTransaction wct) {
         // Resize the home/recents stacks to the larger minimized-state size
         final Rect homeBounds;
-        final ArrayList<IWindowContainer> homeStacks = new ArrayList<>();
+        final ArrayList<WindowContainerToken> homeStacks = new ArrayList<>();
         boolean isHomeResizable = getHomeAndRecentsTasks(homeStacks, parent);
         if (isHomeResizable) {
             homeBounds = layout.calcMinimizedHomeStackBounds();
@@ -170,36 +164,31 @@
      * @return whether the home stack is resizable
      */
     static boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) {
-        try {
-            // Set launchtile first so that any stack created after
-            // getAllStackInfos and before reparent (even if unlikely) are placed
-            // correctly.
-            TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
-            List<ActivityManager.RunningTaskInfo> rootTasks =
-                    TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
-            WindowContainerTransaction wct = new WindowContainerTransaction();
-            if (rootTasks.isEmpty()) {
-                return false;
-            }
-            tiles.mHomeAndRecentsSurfaces.clear();
-            for (int i = rootTasks.size() - 1; i >= 0; --i) {
-                final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
-                if (isHomeOrRecentTask(rootTask)) {
-                    tiles.mHomeAndRecentsSurfaces.add(rootTask.token.getLeash());
-                }
-                if (rootTask.configuration.windowConfiguration.getWindowingMode()
-                        != WINDOWING_MODE_FULLSCREEN) {
-                    continue;
-                }
-                wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */);
-            }
-            boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
-            WindowOrganizer.applyTransaction(wct);
-            return isHomeResizable;
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error moving fullscreen tasks to secondary split: " + e);
+        // Set launchtile first so that any stack created after
+        // getAllStackInfos and before reparent (even if unlikely) are placed
+        // correctly.
+        TaskOrganizer.setLaunchRoot(DEFAULT_DISPLAY, tiles.mSecondary.token);
+        List<ActivityManager.RunningTaskInfo> rootTasks =
+                TaskOrganizer.getRootTasks(DEFAULT_DISPLAY, null /* activityTypes */);
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (rootTasks.isEmpty()) {
+            return false;
         }
-        return false;
+        tiles.mHomeAndRecentsSurfaces.clear();
+        for (int i = rootTasks.size() - 1; i >= 0; --i) {
+            final ActivityManager.RunningTaskInfo rootTask = rootTasks.get(i);
+            if (isHomeOrRecentTask(rootTask)) {
+                tiles.mHomeAndRecentsSurfaces.add(rootTask.token.getLeash());
+            }
+            if (rootTask.configuration.windowConfiguration.getWindowingMode()
+                    != WINDOWING_MODE_FULLSCREEN) {
+                continue;
+            }
+            wct.reparent(rootTask.token, tiles.mSecondary.token, true /* onTop */);
+        }
+        boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
+        WindowOrganizer.applyTransaction(wct);
+        return isHomeResizable;
     }
 
     private static boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) {
@@ -214,82 +203,70 @@
      *                          fullscreen. {@code false} resolves the other way.
      */
     static void applyDismissSplit(SplitScreenTaskOrganizer tiles, boolean dismissOrMaximize) {
-        try {
-            // Set launch root first so that any task created after getChildContainers and
-            // before reparent (pretty unlikely) are put into fullscreen.
-            TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
-            tiles.mHomeAndRecentsSurfaces.clear();
-            // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
-            //                 plus specific APIs to clean this up.
-            List<ActivityManager.RunningTaskInfo> primaryChildren =
-                    TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
-            List<ActivityManager.RunningTaskInfo> secondaryChildren =
-                    TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
-            // In some cases (eg. non-resizable is launched), system-server will leave split-screen.
-            // as a result, the above will not capture any tasks; yet, we need to clean-up the
-            // home task bounds.
-            List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
-                    TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
-            if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
-                    && freeHomeAndRecents.isEmpty()) {
-                return;
+        // Set launch root first so that any task created after getChildContainers and
+        // before reparent (pretty unlikely) are put into fullscreen.
+        TaskOrganizer.setLaunchRoot(Display.DEFAULT_DISPLAY, null);
+        tiles.mHomeAndRecentsSurfaces.clear();
+        // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
+        //                 plus specific APIs to clean this up.
+        List<ActivityManager.RunningTaskInfo> primaryChildren =
+                TaskOrganizer.getChildTasks(tiles.mPrimary.token, null /* activityTypes */);
+        List<ActivityManager.RunningTaskInfo> secondaryChildren =
+                TaskOrganizer.getChildTasks(tiles.mSecondary.token, null /* activityTypes */);
+        // In some cases (eg. non-resizable is launched), system-server will leave split-screen.
+        // as a result, the above will not capture any tasks; yet, we need to clean-up the
+        // home task bounds.
+        List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
+                TaskOrganizer.getRootTasks(Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
+        if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
+                && freeHomeAndRecents.isEmpty()) {
+            return;
+        }
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        if (dismissOrMaximize) {
+            // Dismissing, so move all primary split tasks first
+            for (int i = primaryChildren.size() - 1; i >= 0; --i) {
+                wct.reparent(primaryChildren.get(i).token, null /* parent */,
+                        true /* onTop */);
             }
-            WindowContainerTransaction wct = new WindowContainerTransaction();
-            if (dismissOrMaximize) {
-                // Dismissing, so move all primary split tasks first
-                for (int i = primaryChildren.size() - 1; i >= 0; --i) {
-                    wct.reparent(primaryChildren.get(i).token, null /* parent */,
-                            true /* onTop */);
+            // Don't need to worry about home tasks because they are already in the "proper"
+            // order within the secondary split.
+            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+                wct.reparent(ti.token, null /* parent */, true /* onTop */);
+                if (isHomeOrRecentTask(ti)) {
+                    wct.setBounds(ti.token, null);
                 }
-                // Don't need to worry about home tasks because they are already in the "proper"
-                // order within the secondary split.
-                for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
-                    final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+            }
+        } else {
+            // Maximize, so move non-home secondary split first
+            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                if (isHomeOrRecentTask(secondaryChildren.get(i))) {
+                    continue;
+                }
+                wct.reparent(secondaryChildren.get(i).token, null /* parent */,
+                        true /* onTop */);
+            }
+            // Find and place home tasks in-between. This simulates the fact that there was
+            // nothing behind the primary split's tasks.
+            for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+                if (isHomeOrRecentTask(ti)) {
                     wct.reparent(ti.token, null /* parent */, true /* onTop */);
-                    if (isHomeOrRecentTask(ti)) {
-                        wct.setBounds(ti.token, null);
-                    }
-                }
-            } else {
-                // Maximize, so move non-home secondary split first
-                for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
-                    if (isHomeOrRecentTask(secondaryChildren.get(i))) {
-                        continue;
-                    }
-                    wct.reparent(secondaryChildren.get(i).token, null /* parent */,
-                            true /* onTop */);
-                }
-                // Find and place home tasks in-between. This simulates the fact that there was
-                // nothing behind the primary split's tasks.
-                for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
-                    final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
-                    if (isHomeOrRecentTask(ti)) {
-                        wct.reparent(ti.token, null /* parent */, true /* onTop */);
-                        // reset bounds too
-                        wct.setBounds(ti.token, null);
-                    }
-                }
-                for (int i = primaryChildren.size() - 1; i >= 0; --i) {
-                    wct.reparent(primaryChildren.get(i).token, null /* parent */,
-                            true /* onTop */);
+                    // reset bounds too
+                    wct.setBounds(ti.token, null);
                 }
             }
-            for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
-                wct.setBounds(freeHomeAndRecents.get(i).token, null);
+            for (int i = primaryChildren.size() - 1; i >= 0; --i) {
+                wct.reparent(primaryChildren.get(i).token, null /* parent */,
+                        true /* onTop */);
             }
-            // Reset focusable to true
-            wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to remove stack: " + e);
         }
-    }
-
-    static void applyContainerTransaction(WindowContainerTransaction wct) {
-        try {
-            WindowOrganizer.applyTransaction(wct);
-        } catch (RemoteException e) {
-            Log.w(TAG, "Error setting focusability: " + e);
+        for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
+            wct.setBounds(freeHomeAndRecents.get(i).token, null);
         }
+        // Reset focusable to true
+        wct.setFocusable(tiles.mPrimary.token, true /* focusable */);
+        WindowOrganizer.applyTransaction(wct);
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 4fff860..f5c5174 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2784,7 +2784,8 @@
                     false /* includingParents */);
         }
         WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.reparent(task.getStack().mRemoteToken, primarySplitTask.mRemoteToken, toTop);
+        wct.reparent(task.getStack().mRemoteToken.toWindowContainerToken(),
+                primarySplitTask.mRemoteToken.toWindowContainerToken(), toTop);
         mWindowOrganizerController.applyTransaction(wct);
     }
 
@@ -4273,7 +4274,7 @@
                         tempDockedTaskInsetBounds != null ? tempDockedTaskInsetBounds
                             : (tempDockedTaskBounds != null ? tempDockedTaskBounds
                                     : dockedBounds);
-                wct.setBounds(primary.mRemoteToken, primaryRect);
+                wct.setBounds(primary.mRemoteToken.toWindowContainerToken(), primaryRect);
                 Rect otherRect = tempOtherTaskInsetBounds != null ? tempOtherTaskInsetBounds
                         : tempOtherTaskBounds;
                 if (otherRect == null) {
@@ -4285,7 +4286,7 @@
                         otherRect.top = primaryRect.bottom + 6;
                     }
                 }
-                wct.setBounds(secondary.mRemoteToken, otherRect);
+                wct.setBounds(secondary.mRemoteToken.toWindowContainerToken(), otherRect);
                 mWindowOrganizerController.applyTransaction(wct);
             }
         } finally {
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 5b20023..efcb558 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -16,10 +16,6 @@
 
 package com.android.server.wm;
 
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-import android.window.ITaskOrganizer;
 import android.view.SurfaceControl;
 
 import java.util.HashMap;
@@ -50,7 +46,7 @@
     private static final String TAG = "BLASTSyncEngine";
 
     interface TransactionReadyListener {
-        void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction);
+        void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction);
     };
 
     // Holds state associated with a single synchronous set of operations.
@@ -63,12 +59,12 @@
 
         private void tryFinish() {
             if (mRemainingTransactions == 0 && mReady) {
-                mListener.transactionReady(mSyncId, mMergedTransaction);
+                mListener.onTransactionReady(mSyncId, mMergedTransaction);
                 mPendingSyncs.remove(mSyncId);
             }
         }
 
-        public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
+        public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
             mRemainingTransactions--;
             mMergedTransaction.merge(mergedTransaction);
             tryFinish();
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index fd70971..90fdf19 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -21,9 +21,9 @@
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
 import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER;
-import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_ROOT;
-import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_UNDEFINED;
-import static android.window.WindowOrganizer.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
+import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
+import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
+import static android.window.DisplayAreaOrganizer.FEATURE_WINDOW_TOKENS;
 
 import static com.android.internal.util.Preconditions.checkState;
 import static com.android.server.wm.DisplayAreaProto.NAME;
diff --git a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
index 464b127..f05783b 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java
@@ -94,7 +94,7 @@
 
     void onDisplayAreaAppeared(IDisplayAreaOrganizer organizer, DisplayArea da) {
         try {
-            organizer.onDisplayAreaAppeared(da.mRemoteToken);
+            organizer.onDisplayAreaAppeared(da.mRemoteToken.toWindowContainerToken());
         } catch (RemoteException e) {
             // Oh well...
         }
@@ -102,7 +102,7 @@
 
     void onDisplayAreaVanished(IDisplayAreaOrganizer organizer, DisplayArea da) {
         try {
-            organizer.onDisplayAreaVanished(da.mRemoteToken);
+            organizer.onDisplayAreaVanished(da.mRemoteToken.toWindowContainerToken());
         } catch (RemoteException e) {
             // Oh well...
         }
diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
index 950df6f..682a142 100644
--- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
+++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java
@@ -87,8 +87,8 @@
          *
          * Must be unique among the features added to a {@link DisplayAreaPolicyBuilder}.
          *
-         * @see android.window.WindowOrganizer.DisplayAreaOrganizer#FEATURE_SYSTEM_FIRST
-         * @see android.window.WindowOrganizer.DisplayAreaOrganizer#FEATURE_VENDOR_FIRST
+         * @see android.window.DisplayAreaOrganizer#FEATURE_SYSTEM_FIRST
+         * @see android.window.DisplayAreaOrganizer#FEATURE_VENDOR_FIRST
          */
         public int getId() {
             return mId;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index af783c5..2764b12 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2346,7 +2346,7 @@
         stack.getBounds(info.bounds);
         info.displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId() : INVALID_DISPLAY;
         info.stackId = stack.mTaskId;
-        info.stackToken = stack.mRemoteToken;
+        info.stackToken = stack.mRemoteToken.toWindowContainerToken();
         info.userId = stack.mCurrentUser;
         info.visible = stack.shouldBeVisible(null);
         // A stack might be not attached to a display.
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9f5126e..0151b82 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -478,7 +478,7 @@
 
     /**
      * The TaskOrganizer which is delegated presentation of this task. If set the Task will
-     * emit an IWindowContainer (allowing access to it's SurfaceControl leash) to the organizers
+     * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
      * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
      */
     ITaskOrganizer mTaskOrganizer;
@@ -3435,7 +3435,7 @@
         info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
         info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
         info.configuration.setTo(getConfiguration());
-        info.token = mRemoteToken;
+        info.token = mRemoteToken.toWindowContainerToken();
 
         //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
         //                    order changes.
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index a5ae721..9356ec2 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -31,7 +31,7 @@
 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 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;
@@ -1183,7 +1183,8 @@
         for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
             final Task root = mTmpTasks.get(i);
             for (int j = 0; j < root.getChildCount(); j++) {
-                wct.reparent(root.getChildAt(j).mRemoteToken, null, true /* toTop */);
+                wct.reparent(root.getChildAt(j).mRemoteToken.toWindowContainerToken(),
+                        null, true /* toTop */);
             }
         }
         mAtmService.mWindowOrganizerController.applyTransaction(wct);
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 2dec655..872f254 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -36,7 +36,7 @@
 import android.util.SparseArray;
 import android.window.ITaskOrganizer;
 import android.window.ITaskOrganizerController;
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 
 import com.android.internal.util.ArrayUtils;
 
@@ -290,7 +290,7 @@
     }
 
     @Override
-    public boolean deleteRootTask(IWindowContainer token) {
+    public boolean deleteRootTask(WindowContainerToken token) {
         enforceStackPermission("deleteRootTask()");
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -367,7 +367,7 @@
     }
 
     @Override
-    public IWindowContainer getImeTarget(int displayId) {
+    public WindowContainerToken getImeTarget(int displayId) {
         enforceStackPermission("getImeTarget()");
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -382,7 +382,7 @@
                 if (task == null) {
                     return null;
                 }
-                return task.getRootTask().mRemoteToken;
+                return task.getRootTask().mRemoteToken.toWindowContainerToken();
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -390,7 +390,7 @@
     }
 
     @Override
-    public void setLaunchRoot(int displayId, @Nullable IWindowContainer token) {
+    public void setLaunchRoot(int displayId, @Nullable WindowContainerToken token) {
         enforceStackPermission("setLaunchRoot()");
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -422,7 +422,7 @@
     }
 
     @Override
-    public List<RunningTaskInfo> getChildTasks(IWindowContainer parent,
+    public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent,
             @Nullable int[] activityTypes) {
         enforceStackPermission("getChildTasks()");
         final long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 98585a9..58119c2 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -76,7 +76,8 @@
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.animation.Animation;
-import android.window.IWindowContainer;
+import android.window.IWindowContainerToken;
+import android.window.WindowContainerToken;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ToBooleanFunction;
@@ -2449,8 +2450,10 @@
         return RemoteToken.fromBinder(binder).getContainer();
     }
 
-    static class RemoteToken extends IWindowContainer.Stub {
+    static class RemoteToken extends IWindowContainerToken.Stub {
+
         final WeakReference<WindowContainer> mWeakRef;
+        private WindowContainerToken mWindowContainerToken;
 
         RemoteToken(WindowContainer container) {
             mWeakRef = new WeakReference<>(container);
@@ -2476,6 +2479,13 @@
             return sc;
         }
 
+        WindowContainerToken toWindowContainerToken() {
+            if (mWindowContainerToken == null) {
+                mWindowContainerToken = new WindowContainerToken(this);
+            }
+            return mWindowContainerToken;
+        }
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder(128);
@@ -2489,11 +2499,11 @@
     }
 
     @Override
-    public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
+    public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
         mergedTransaction.merge(mBLASTSyncTransaction);
         mUsingBLASTSyncTransaction = false;
 
-        mWaitingListener.transactionReady(mWaitingSyncId, mergedTransaction);
+        mWaitingListener.onTransactionReady(mWaitingSyncId, mergedTransaction);
 
         mWaitingListener = null;
         mWaitingSyncId = -1;
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 14c9429..a332b69 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -340,12 +340,12 @@
     }
 
     @Override
-    public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
+    public void onTransactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
         final IWindowContainerTransactionCallback callback =
                 mTransactionCallbacksByPendingSyncId.get(mSyncId);
 
         try {
-            callback.transactionReady(mSyncId, mergedTransaction);
+            callback.onTransactionReady(mSyncId, mergedTransaction);
         } catch (RemoteException e) {
         }
 
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 8013a6c..6b93e4b 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5752,7 +5752,7 @@
         if (mLocalSyncId >= 0) {
             mBLASTSyncEngine.setReady(mLocalSyncId);
         } else {
-            mWaitingListener.transactionReady(mWaitingSyncId, mBLASTSyncTransaction);
+            mWaitingListener.onTransactionReady(mWaitingSyncId, mBLASTSyncTransaction);
         }
 
         mUsingBLASTSyncTransaction = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 319e9ac..1d952bf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -83,7 +83,7 @@
 import android.service.voice.IVoiceInteractionSession;
 import android.view.Gravity;
 import android.window.ITaskOrganizer;
-import android.window.IWindowContainer;
+import android.window.WindowContainerToken;
 
 import androidx.test.filters.SmallTest;
 
@@ -1014,10 +1014,10 @@
                     WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
             mService.mTaskOrganizerController.registerTaskOrganizer(this,
                     WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-            IWindowContainer primary = mService.mTaskOrganizerController.createRootTask(
+            WindowContainerToken primary = mService.mTaskOrganizerController.createRootTask(
                     displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token;
             mPrimary = WindowContainer.fromBinder(primary.asBinder()).asTask();
-            IWindowContainer secondary = mService.mTaskOrganizerController.createRootTask(
+            WindowContainerToken secondary = mService.mTaskOrganizerController.createRootTask(
                     displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token;
             mSecondary = WindowContainer.fromBinder(secondary.asBinder()).asTask();
         }
@@ -1037,7 +1037,7 @@
                         == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                     mInSplit = true;
                     mService.mTaskOrganizerController.setLaunchRoot(mDisplayId,
-                            mSecondary.mRemoteToken);
+                            mSecondary.mRemoteToken.toWindowContainerToken());
                     // move everything to secondary because test expects this but usually sysui
                     // does it.
                     DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index f05acce..6ef714e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -26,6 +26,8 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
+import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -282,7 +284,7 @@
         final Task task = stack.getTopMostTask();
         WindowContainerTransaction t = new WindowContainerTransaction();
         Rect newBounds = new Rect(10, 10, 100, 100);
-        t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
+        t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertEquals(newBounds, task.getBounds());
     }
@@ -295,7 +297,7 @@
         StackInfo info =
                 mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
         WindowContainerTransaction t = new WindowContainerTransaction();
-        assertEquals(stack.mRemoteToken, info.stackToken);
+        assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.stackToken);
         Rect newBounds = new Rect(10, 10, 100, 100);
         t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
@@ -308,7 +310,7 @@
             .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
         final WindowContainerTransaction t = new WindowContainerTransaction();
 
-        t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
+        t.setWindowingMode(stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode());
@@ -320,8 +322,9 @@
         final ActivityStack stack = record.getStack();
         final WindowContainerTransaction t = new WindowContainerTransaction();
 
-        t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED);
-        t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
+        t.setWindowingMode(stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_PINNED);
+        t.setActivityWindowingMode(
+                stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
 
         assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
@@ -336,10 +339,10 @@
         final Task task = stack.getTopMostTask();
         WindowContainerTransaction t = new WindowContainerTransaction();
         assertTrue(task.isFocusable());
-        t.setFocusable(stack.mRemoteToken, false);
+        t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), false);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertFalse(task.isFocusable());
-        t.setFocusable(stack.mRemoteToken, true);
+        t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), true);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertTrue(task.isFocusable());
     }
@@ -351,10 +354,10 @@
                 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
         WindowContainerTransaction t = new WindowContainerTransaction();
         assertTrue(stack.shouldBeVisible(null));
-        t.setHidden(stack.mRemoteToken, true);
+        t.setHidden(stack.mRemoteToken.toWindowContainerToken(), true);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertFalse(stack.shouldBeVisible(null));
-        t.setHidden(stack.mRemoteToken, false);
+        t.setHidden(stack.mRemoteToken.toWindowContainerToken(), false);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertTrue(stack.shouldBeVisible(null));
     }
@@ -366,19 +369,19 @@
                 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
         final Task task = stack.getTopMostTask();
         WindowContainerTransaction t = new WindowContainerTransaction();
-        t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
+        t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         final int origScreenWDp = task.getConfiguration().screenHeightDp;
         final int origScreenHDp = task.getConfiguration().screenHeightDp;
         t = new WindowContainerTransaction();
         // verify that setting config overrides on parent restricts children.
-        t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp);
-        t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200));
+        t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), origScreenWDp, origScreenHDp);
+        t.setBounds(task.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 150, 200));
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
         t = new WindowContainerTransaction();
-        t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED,
-                Configuration.SCREEN_HEIGHT_DP_UNDEFINED);
+        t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED,
+                SCREEN_HEIGHT_DP_UNDEFINED);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
         assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
     }
@@ -435,7 +438,7 @@
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
         assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
         WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
+        wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertEquals(info1.configuration.windowConfiguration.getWindowingMode(),
                 stack.getWindowingMode());
@@ -455,7 +458,7 @@
         assertEquals(newSize, stack.getBounds());
 
         wct = new WindowContainerTransaction();
-        wct.reparent(stack.mRemoteToken, null, true /* onTop */);
+        wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
         infos = getTasksCreatedByOrganizer(mDisplayContent);
@@ -495,7 +498,7 @@
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
         Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
         WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
+        wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertTrue(called[0]);
         assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
@@ -505,7 +508,7 @@
         final ActivityStack stack2 = createTaskStackOnDisplay(
                 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
         wct = new WindowContainerTransaction();
-        wct.reparent(stack2.mRemoteToken, info1.token, true /* onTop */);
+        wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertTrue(called[0]);
         assertEquals(ACTIVITY_TYPE_HOME, lastReportedTiles.get(0).topActivityType);
@@ -519,8 +522,8 @@
         lastReportedTiles.clear();
         called[0] = false;
         wct = new WindowContainerTransaction();
-        wct.reparent(stack.mRemoteToken, null, true /* onTop */);
-        wct.reparent(stack2.mRemoteToken, null, true /* onTop */);
+        wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
+        wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertTrue(called[0]);
         assertEquals(ACTIVITY_TYPE_UNDEFINED, lastReportedTiles.get(0).topActivityType);
@@ -569,8 +572,8 @@
 
         lastReportedTiles.clear();
         WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
-        wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */);
+        wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
+        wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info2.token, true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertFalse(lastReportedTiles.isEmpty());
         assertEquals(ACTIVITY_TYPE_STANDARD,
@@ -580,7 +583,7 @@
 
         lastReportedTiles.clear();
         wct = new WindowContainerTransaction();
-        wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */);
+        wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, false /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         assertFalse(lastReportedTiles.isEmpty());
         // Standard should still be on top of tile 1, so no change there
@@ -605,7 +608,7 @@
 
         lastReportedTiles.clear();
         wct = new WindowContainerTransaction();
-        wct.reorder(stack2.mRemoteToken, true /* onTop */);
+        wct.reorder(stack2.mRemoteToken.toWindowContainerToken(), true /* onTop */);
         mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
         // Home should now be on top. No change occurs in second tile, so not reported
         assertEquals(1, lastReportedTiles.size());
@@ -641,7 +644,7 @@
         bse.setReady(id);
         // Since this task has no windows the sync is trivial and completes immediately.
         verify(transactionListener)
-            .transactionReady(anyInt(), any());
+            .onTransactionReady(anyInt(), any());
     }
 
     @Test
@@ -691,10 +694,10 @@
         bse.setReady(id);
         // Since we have a window we have to wait for it to draw to finish sync.
         verify(transactionListener, never())
-            .transactionReady(anyInt(), any());
+            .onTransactionReady(anyInt(), any());
         w.finishDrawing(null);
         verify(transactionListener)
-            .transactionReady(anyInt(), any());
+            .onTransactionReady(anyInt(), any());
     }
 
     @Test
@@ -716,7 +719,7 @@
         // Since the window was invisible, the Task had no visible leaves and the sync should
         // complete as soon as we call setReady.
         verify(transactionListener)
-            .transactionReady(anyInt(), any());
+            .onTransactionReady(anyInt(), any());
     }
 
     @Test
@@ -742,13 +745,13 @@
 
         // Since we have a child window we still shouldn't be done.
         verify(transactionListener, never())
-            .transactionReady(anyInt(), any());
+            .onTransactionReady(anyInt(), any());
         reset(transactionListener);
 
         child.finishDrawing(null);
         // Ah finally! Done
         verify(transactionListener)
-                .transactionReady(anyInt(), any());
+                .onTransactionReady(anyInt(), any());
     }
 
     class StubOrganizer extends ITaskOrganizer.Stub {
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
index d468076..b40d022 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerMultiWindowTest.java
@@ -17,10 +17,9 @@
 package com.android.test.taskembed;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
-import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.Activity;
 import android.app.ActivityOptions;
 import android.content.Context;
 import android.content.Intent;
@@ -35,10 +34,12 @@
 import android.view.SurfaceHolder;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.LinearLayout;
 import android.window.ITaskOrganizer;
 import android.window.IWindowContainerTransactionCallback;
+import android.window.TaskOrganizer;
 import android.window.WindowContainerTransaction;
+import android.widget.LinearLayout;
+import android.window.WindowContainerTransactionCallback;
 import android.window.WindowOrganizer;
 
 public class TaskOrganizerMultiWindowTest extends Activity {
@@ -97,7 +98,7 @@
     class ResizingTaskView extends TaskView {
         final Intent mIntent;
         boolean launched = false;
-        ResizingTaskView(Context c, ITaskOrganizer o, int windowingMode, Intent i) {
+        ResizingTaskView(Context c, TaskOrganizer o, int windowingMode, Intent i) {
             super(c, o, windowingMode);
             mIntent = i;
         }
@@ -116,7 +117,7 @@
             final WindowContainerTransaction wct = new WindowContainerTransaction();
             wct.setBounds(mWc, new Rect(0, 0, width, height));
             try {
-                WindowOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
+                mOrganizer.applySyncTransaction(wct, mOrganizer.mTransactionCallback);
             } catch (Exception e) {
                 // Oh well
             }
@@ -127,14 +128,13 @@
     TaskView mTaskView2;
     boolean gotFirstTask = false;
 
-    class Organizer extends ITaskOrganizer.Stub {
+    class Organizer extends TaskOrganizer {
         private int receivedTransactions = 0;
         SurfaceControl.Transaction mergedTransaction = new SurfaceControl.Transaction();
-        IWindowContainerTransactionCallback mTransactionCallback =
-                new IWindowContainerTransactionCallback() {
+        WindowContainerTransactionCallback mTransactionCallback =
+                new WindowContainerTransactionCallback() {
             @Override
-            public void transactionReady(int id, SurfaceControl.Transaction t)
-                    throws RemoteException {
+            public void onTransactionReady(int id, SurfaceControl.Transaction t) {
                 mergedTransaction.merge(t);
                 receivedTransactions++;
                 if (receivedTransactions == 2) {
@@ -142,11 +142,6 @@
                     receivedTransactions = 0;
                 }
             }
-
-            @Override
-            public IBinder asBinder() {
-                return null;
-            }
         };
 
         @Override
@@ -158,14 +153,6 @@
                 mTaskView2.reparentTask(ti.token);
             }
         }
-        public void onTaskVanished(ActivityManager.RunningTaskInfo ti) {
-        }
-        @Override
-        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
-        }
-        @Override
-        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
-        }
     }
 
     Organizer mOrganizer = new Organizer();
@@ -174,10 +161,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        try {
-            TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_MULTI_WINDOW);
-        } catch (Exception e) {
-        }
+        mOrganizer.registerOrganizer(WINDOWING_MODE_MULTI_WINDOW);
 
         mTaskView1 = new ResizingTaskView(this, mOrganizer, WINDOWING_MODE_MULTI_WINDOW,
                 makeSettingsIntent());
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
index a589d95..2a1aa2e 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskOrganizerPipTest.java
@@ -17,7 +17,6 @@
 package com.android.test.taskembed;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-import static android.window.WindowOrganizer.TaskOrganizer;
 
 import android.app.ActivityManager;
 import android.app.Service;
@@ -25,11 +24,10 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.view.ViewGroup;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerTransaction;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
-import android.window.ITaskOrganizer;
-import android.window.WindowContainerTransaction;
-import android.window.WindowOrganizer;
 
 public class TaskOrganizerPipTest extends Service {
     static final int PIP_WIDTH  = 640;
@@ -37,23 +35,13 @@
 
     TaskView mTaskView;
 
-    class Organizer extends ITaskOrganizer.Stub {
+    class Organizer extends TaskOrganizer {
         public void onTaskAppeared(ActivityManager.RunningTaskInfo ti) {
             mTaskView.reparentTask(ti.token);
 
             final WindowContainerTransaction wct = new WindowContainerTransaction();
             wct.scheduleFinishEnterPip(ti.token, new Rect(0, 0, PIP_WIDTH, PIP_HEIGHT));
-            try {
-                WindowOrganizer.applyTransaction(wct);
-            } catch (Exception e) {
-            }
-        }
-        public void onTaskVanished(ActivityManager.RunningTaskInfo ti) {
-        }
-        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
-        }
-        @Override
-        public void onBackPressedOnTaskRoot(ActivityManager.RunningTaskInfo taskInfo) {
+            applyTransaction(wct);
         }
     }
 
@@ -68,10 +56,7 @@
     public void onCreate() {
         super.onCreate();
 
-        try {
-            TaskOrganizer.registerOrganizer(mOrganizer, WINDOWING_MODE_PINNED);
-        } catch (Exception e) {
-        }
+        mOrganizer.registerOrganizer(WINDOWING_MODE_PINNED);
 
         final WindowManager.LayoutParams wlp = new WindowManager.LayoutParams();
         wlp.setTitle("TaskOrganizerPipTest");
diff --git a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
index 438a062..03615f3 100644
--- a/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
+++ b/tests/TaskOrganizerTest/src/com/android/test/taskembed/TaskView.java
@@ -18,7 +18,8 @@
 
 import android.app.ActivityTaskManager;
 import android.content.Context;
-import android.window.IWindowContainer;
+import android.window.TaskOrganizer;
+import android.window.WindowContainerToken;
 import android.view.SurfaceControl;
 import android.view.SurfaceHolder;
 import android.view.SurfaceView;
@@ -29,14 +30,14 @@
  * after it's Surface is ready.
  */
 class TaskView extends SurfaceView implements SurfaceHolder.Callback {
-    final ITaskOrganizer mTaskOrganizer;
+    final TaskOrganizer mTaskOrganizer;
     final int mWindowingMode;
-    IWindowContainer mWc;
+    WindowContainerToken mWc;
 
     boolean mSurfaceCreated = false;
     boolean mNeedsReparent;
 
-    TaskView(Context c, ITaskOrganizer o, int windowingMode) {
+    TaskView(Context c, TaskOrganizer o, int windowingMode) {
         super(c);
         getHolder().addCallback(this);
         setZOrderOnTop(true);
@@ -62,7 +63,7 @@
     public void surfaceDestroyed(SurfaceHolder holder) {
     }
 
-    void reparentTask(IWindowContainer wc) {
+    void reparentTask(WindowContainerToken wc) {
         mWc = wc;
         if (mSurfaceCreated == false) {
             mNeedsReparent = true;