Loading core/java/android/window/DisplayAreaOrganizer.java +57 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,19 @@ public class DisplayAreaOrganizer extends WindowOrganizer { */ public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1; /** * Last possible vendor specific display area id. * @hide */ public static final int FEATURE_VENDOR_LAST = FEATURE_VENDOR_FIRST + 10_000; /** * Task display areas that can be created at runtime start with this value. * @see #createTaskDisplayArea(int, int, String) * @hide */ public static final int FEATURE_RUNTIME_TASK_CONTAINER_FIRST = FEATURE_VENDOR_LAST + 1; /** * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can * not be registered by multiple organizers at the same time. Loading Loading @@ -131,6 +144,50 @@ public class DisplayAreaOrganizer extends WindowOrganizer { } } /** * Creates a persistent task display area. It will be added to be the top most task display area * in the root. * * The new created TDA is organized by the organizer, and will be deleted on calling * {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}. * * @param displayId the display to create the new task display area in. * @param rootFeatureId the root display area to create the new task display area in. Caller can * use {@link #FEATURE_ROOT} as the root of the logical display. * @param name the name for the new task display area. * @return the new created task display area. * @throws IllegalArgumentException if failed to create a new task display area. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @CallSuper @NonNull public DisplayAreaAppearedInfo createTaskDisplayArea(int displayId, int rootFeatureId, @NonNull String name) { try { return getController().createTaskDisplayArea( mInterface, displayId, rootFeatureId, name); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Deletes a persistent task display area. It can only be one that created by an organizer. * * @throws IllegalArgumentException if failed to delete the task display area. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @CallSuper public void deleteTaskDisplayArea(@NonNull WindowContainerToken taskDisplayArea) { try { getController().deleteTaskDisplayArea(taskDisplayArea); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Called when a DisplayArea of the registered window type can be controlled by this organizer. * It will not be called for the DisplayAreas that exist when {@link #registerOrganizer(int)} is Loading core/java/android/window/IDisplayAreaOrganizerController.aidl +25 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.window; import android.content.pm.ParceledListSlice; import android.window.DisplayAreaAppearedInfo; import android.window.IDisplayAreaOrganizer; import android.window.WindowContainerToken; /** @hide */ interface IDisplayAreaOrganizerController { Loading @@ -37,4 +38,28 @@ interface IDisplayAreaOrganizerController { * Unregisters a previously registered display area organizer. */ void unregisterOrganizer(in IDisplayAreaOrganizer organizer); /** * Creates a persistent task display area. It will be added to be the top most task display area * in the root. * * The new created TDA is organized by the organizer, and will be deleted on calling * {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}. * * @param displayId the display to create the new task display area in. * @param rootFeatureId the root display area to create the new task display area in. Caller can * use {@link #FEATURE_ROOT} as the root of the logical display. * @param name the name for the new task display area. * @return the new created task display area. * @throws IllegalArgumentException if failed to create a new task display area. */ DisplayAreaAppearedInfo createTaskDisplayArea(in IDisplayAreaOrganizer organizer, int displayId, int rootFeatureId, in String name); /** * Deletes a persistent task display area. It can only be one that created by an organizer. * * @throws IllegalArgumentException if failed to delete the task display area. */ void deleteTaskDisplayArea(in WindowContainerToken taskDisplayArea); } data/etc/services.core.protolog.json +12 −12 Original line number Diff line number Diff line Loading @@ -961,6 +961,12 @@ "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, "-948446688": { "message": "Create TaskDisplayArea uid=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, "-937498525": { "message": "Executing finish of failed to pause activity: %s", "level": "VERBOSE", Loading Loading @@ -1273,6 +1279,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/Task.java" }, "-597091183": { "message": "Delete TaskDisplayArea uid=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, "-593535526": { "message": "Binding proc %s with config %s", "level": "VERBOSE", Loading Loading @@ -1495,12 +1507,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-371630969": { "message": "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, "-354571697": { "message": "Existence Changed in transition %d: %s", "level": "VERBOSE", Loading Loading @@ -2101,12 +2107,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "355940361": { "message": "Config is destroying non-running %s", "level": "VERBOSE", "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "371173718": { "message": "finishSync cancel=%b for %s", "level": "VERBOSE", Loading services/core/java/com/android/server/wm/DisplayArea.java +7 −0 Original line number Diff line number Diff line Loading @@ -380,6 +380,13 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { return result; } @Nullable @Override <R> R getItemFromDisplayAreas(Function<DisplayArea, R> callback) { final R item = super.getItemFromDisplayAreas(callback); return item != null ? item : callback.apply(this); } @Nullable @Override <R> R getItemFromTaskDisplayAreas(Function<TaskDisplayArea, R> callback, Loading services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java +147 −5 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package com.android.server.wm; import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.server.wm.DisplayArea.Type.ANY; import android.content.pm.ParceledListSlice; import android.os.Binder; Loading @@ -26,6 +29,7 @@ import android.view.SurfaceControl; import android.window.DisplayAreaAppearedInfo; import android.window.IDisplayAreaOrganizer; import android.window.IDisplayAreaOrganizerController; import android.window.WindowContainerToken; import com.android.internal.protolog.common.ProtoLog; Loading @@ -36,6 +40,12 @@ import java.util.List; public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerController.Stub { private static final String TAG = "DisplayAreaOrganizerController"; /** * Next available feature id for a runtime task display area. * @see #createTaskDisplayArea(IDisplayAreaOrganizer organizer, int, int, String) */ private int mNextTaskDisplayAreaFeatureId = FEATURE_RUNTIME_TASK_CONTAINER_FIRST; final ActivityTaskManagerService mService; private final WindowManagerGlobalLock mGlobalLock; private final HashMap<Integer, IDisplayAreaOrganizer> mOrganizersByFeatureIds = new HashMap(); Loading Loading @@ -92,10 +102,8 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>(); mService.mRootWindowContainer.forAllDisplayAreas((da) -> { if (da.mFeatureId != feature) return; da.setOrganizer(organizer, true /* skipDisplayAreaAppeared */); displayAreaInfos.add(new DisplayAreaAppearedInfo(da.getDisplayAreaInfo(), new SurfaceControl(da.getSurfaceControl(), "DisplayAreaOrganizerController.registerOrganizer"))); displayAreaInfos.add(organizeDisplayArea(organizer, da, "DisplayAreaOrganizerController.registerOrganizer")); }); mOrganizersByFeatureIds.put(feature, organizer); Loading Loading @@ -124,6 +132,77 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl } } @Override public DisplayAreaAppearedInfo createTaskDisplayArea(IDisplayAreaOrganizer organizer, int displayId, int rootFeatureId, String name) { enforceTaskPermission("createTaskDisplayArea()"); final long uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Create TaskDisplayArea uid=%d", uid); final DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId); if (display == null) { throw new IllegalArgumentException("createTaskDisplayArea unknown displayId=" + displayId); } final DisplayArea root = display.getItemFromDisplayAreas(da -> da.asRootDisplayArea() != null && da.mFeatureId == rootFeatureId ? da : null); if (root == null) { throw new IllegalArgumentException("Can't find RootDisplayArea with featureId=" + rootFeatureId); } final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++; final DeathRecipient dr = new DeathRecipient(organizer, taskDisplayAreaFeatureId); try { organizer.asBinder().linkToDeath(dr, 0); } catch (RemoteException e) { // Oh well... } final TaskDisplayArea tda = createTaskDisplayArea(root.asRootDisplayArea(), name, taskDisplayAreaFeatureId); return organizeDisplayArea(organizer, tda, "DisplayAreaOrganizerController.createTaskDisplayArea"); } } finally { Binder.restoreCallingIdentity(origId); } } @Override public void deleteTaskDisplayArea(WindowContainerToken token) { enforceTaskPermission("deleteTaskDisplayArea()"); final long uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Delete TaskDisplayArea uid=%d", uid); final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); if (wc == null || wc.asTaskDisplayArea() == null) { throw new IllegalArgumentException("Can't resolve TaskDisplayArea from token"); } final TaskDisplayArea taskDisplayArea = wc.asTaskDisplayArea(); if (!taskDisplayArea.mCreatedByOrganizer) { throw new IllegalArgumentException( "Attempt to delete TaskDisplayArea not created by organizer " + "TaskDisplayArea=" + taskDisplayArea); } deleteTaskDisplayArea(taskDisplayArea); } } finally { Binder.restoreCallingIdentity(origId); } } void onDisplayAreaAppeared(IDisplayAreaOrganizer organizer, DisplayArea da) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "DisplayArea appeared name=%s", da.getName()); try { Loading Loading @@ -157,8 +236,71 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl IBinder organizerBinder = organizer.asBinder(); mService.mRootWindowContainer.forAllDisplayAreas((da) -> { if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) { if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) { // Delete the organizer created TDA when unregister. deleteTaskDisplayArea(da.asTaskDisplayArea()); } else { da.setOrganizer(null); } } }); } private DisplayAreaAppearedInfo organizeDisplayArea(IDisplayAreaOrganizer organizer, DisplayArea displayArea, String callsite) { displayArea.setOrganizer(organizer, true /* skipDisplayAreaAppeared */); return new DisplayAreaAppearedInfo(displayArea.getDisplayAreaInfo(), new SurfaceControl(displayArea.getSurfaceControl(), callsite)); } private TaskDisplayArea createTaskDisplayArea(RootDisplayArea root, String name, int taskDisplayAreaFeatureId) { final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(root.mDisplayContent, root.mWmService, name, taskDisplayAreaFeatureId, true /* createdByOrganizer */); // Find the top most DA that can contain Task (either a TDA or a DisplayAreaGroup). final DisplayArea topTaskContainer = root.getItemFromDisplayAreas(da -> { if (da.mType != ANY) { return null; } final RootDisplayArea rootDA = da.getRootDisplayArea(); if (rootDA == root || rootDA == da) { // Either it is the top TDA below the root or it is a DisplayAreaGroup. return da; } return null; }); if (topTaskContainer == null) { throw new IllegalStateException("Root must either contain TDA or DAG root=" + root); } // Insert the TaskDisplayArea as the top Task container. final WindowContainer parent = topTaskContainer.getParent(); final int index = parent.mChildren.indexOf(topTaskContainer) + 1; parent.addChild(taskDisplayArea, index); return taskDisplayArea; } private void deleteTaskDisplayArea(TaskDisplayArea taskDisplayArea) { taskDisplayArea.setOrganizer(null); mService.mRootWindowContainer.mTaskSupervisor.beginDeferResume(); // TaskDisplayArea#remove() move the stacks to the default TaskDisplayArea. Task lastReparentedStack; try { lastReparentedStack = taskDisplayArea.remove(); } finally { mService.mRootWindowContainer.mTaskSupervisor.endDeferResume(); } taskDisplayArea.removeImmediately(); // Only update focus/visibility for the last one because there may be many stacks are // reparented and the intermediate states are unnecessary. if (lastReparentedStack != null) { lastReparentedStack.postReparent(); } } } Loading
core/java/android/window/DisplayAreaOrganizer.java +57 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,19 @@ public class DisplayAreaOrganizer extends WindowOrganizer { */ public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1; /** * Last possible vendor specific display area id. * @hide */ public static final int FEATURE_VENDOR_LAST = FEATURE_VENDOR_FIRST + 10_000; /** * Task display areas that can be created at runtime start with this value. * @see #createTaskDisplayArea(int, int, String) * @hide */ public static final int FEATURE_RUNTIME_TASK_CONTAINER_FIRST = FEATURE_VENDOR_LAST + 1; /** * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can * not be registered by multiple organizers at the same time. Loading Loading @@ -131,6 +144,50 @@ public class DisplayAreaOrganizer extends WindowOrganizer { } } /** * Creates a persistent task display area. It will be added to be the top most task display area * in the root. * * The new created TDA is organized by the organizer, and will be deleted on calling * {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}. * * @param displayId the display to create the new task display area in. * @param rootFeatureId the root display area to create the new task display area in. Caller can * use {@link #FEATURE_ROOT} as the root of the logical display. * @param name the name for the new task display area. * @return the new created task display area. * @throws IllegalArgumentException if failed to create a new task display area. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @CallSuper @NonNull public DisplayAreaAppearedInfo createTaskDisplayArea(int displayId, int rootFeatureId, @NonNull String name) { try { return getController().createTaskDisplayArea( mInterface, displayId, rootFeatureId, name); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Deletes a persistent task display area. It can only be one that created by an organizer. * * @throws IllegalArgumentException if failed to delete the task display area. * @hide */ @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS) @CallSuper public void deleteTaskDisplayArea(@NonNull WindowContainerToken taskDisplayArea) { try { getController().deleteTaskDisplayArea(taskDisplayArea); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Called when a DisplayArea of the registered window type can be controlled by this organizer. * It will not be called for the DisplayAreas that exist when {@link #registerOrganizer(int)} is Loading
core/java/android/window/IDisplayAreaOrganizerController.aidl +25 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.window; import android.content.pm.ParceledListSlice; import android.window.DisplayAreaAppearedInfo; import android.window.IDisplayAreaOrganizer; import android.window.WindowContainerToken; /** @hide */ interface IDisplayAreaOrganizerController { Loading @@ -37,4 +38,28 @@ interface IDisplayAreaOrganizerController { * Unregisters a previously registered display area organizer. */ void unregisterOrganizer(in IDisplayAreaOrganizer organizer); /** * Creates a persistent task display area. It will be added to be the top most task display area * in the root. * * The new created TDA is organized by the organizer, and will be deleted on calling * {@link #deleteTaskDisplayArea(WindowContainerToken)} or {@link #unregisterOrganizer()}. * * @param displayId the display to create the new task display area in. * @param rootFeatureId the root display area to create the new task display area in. Caller can * use {@link #FEATURE_ROOT} as the root of the logical display. * @param name the name for the new task display area. * @return the new created task display area. * @throws IllegalArgumentException if failed to create a new task display area. */ DisplayAreaAppearedInfo createTaskDisplayArea(in IDisplayAreaOrganizer organizer, int displayId, int rootFeatureId, in String name); /** * Deletes a persistent task display area. It can only be one that created by an organizer. * * @throws IllegalArgumentException if failed to delete the task display area. */ void deleteTaskDisplayArea(in WindowContainerToken taskDisplayArea); }
data/etc/services.core.protolog.json +12 −12 Original line number Diff line number Diff line Loading @@ -961,6 +961,12 @@ "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/TaskOrganizerController.java" }, "-948446688": { "message": "Create TaskDisplayArea uid=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, "-937498525": { "message": "Executing finish of failed to pause activity: %s", "level": "VERBOSE", Loading Loading @@ -1273,6 +1279,12 @@ "group": "WM_DEBUG_STATES", "at": "com\/android\/server\/wm\/Task.java" }, "-597091183": { "message": "Delete TaskDisplayArea uid=%d", "level": "VERBOSE", "group": "WM_DEBUG_WINDOW_ORGANIZER", "at": "com\/android\/server\/wm\/DisplayAreaOrganizerController.java" }, "-593535526": { "message": "Binding proc %s with config %s", "level": "VERBOSE", Loading Loading @@ -1495,12 +1507,6 @@ "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "-371630969": { "message": "New wallpaper target=%s, oldWallpaper=%s, openingApps=%s, closingApps=%s", "level": "VERBOSE", "group": "WM_DEBUG_APP_TRANSITIONS", "at": "com\/android\/server\/wm\/AppTransitionController.java" }, "-354571697": { "message": "Existence Changed in transition %d: %s", "level": "VERBOSE", Loading Loading @@ -2101,12 +2107,6 @@ "group": "WM_DEBUG_ORIENTATION", "at": "com\/android\/server\/wm\/WindowManagerService.java" }, "355940361": { "message": "Config is destroying non-running %s", "level": "VERBOSE", "group": "WM_DEBUG_CONFIGURATION", "at": "com\/android\/server\/wm\/ActivityRecord.java" }, "371173718": { "message": "finishSync cancel=%b for %s", "level": "VERBOSE", Loading
services/core/java/com/android/server/wm/DisplayArea.java +7 −0 Original line number Diff line number Diff line Loading @@ -380,6 +380,13 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { return result; } @Nullable @Override <R> R getItemFromDisplayAreas(Function<DisplayArea, R> callback) { final R item = super.getItemFromDisplayAreas(callback); return item != null ? item : callback.apply(this); } @Nullable @Override <R> R getItemFromTaskDisplayAreas(Function<TaskDisplayArea, R> callback, Loading
services/core/java/com/android/server/wm/DisplayAreaOrganizerController.java +147 −5 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package com.android.server.wm; import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; import static com.android.server.wm.DisplayArea.Type.ANY; import android.content.pm.ParceledListSlice; import android.os.Binder; Loading @@ -26,6 +29,7 @@ import android.view.SurfaceControl; import android.window.DisplayAreaAppearedInfo; import android.window.IDisplayAreaOrganizer; import android.window.IDisplayAreaOrganizerController; import android.window.WindowContainerToken; import com.android.internal.protolog.common.ProtoLog; Loading @@ -36,6 +40,12 @@ import java.util.List; public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerController.Stub { private static final String TAG = "DisplayAreaOrganizerController"; /** * Next available feature id for a runtime task display area. * @see #createTaskDisplayArea(IDisplayAreaOrganizer organizer, int, int, String) */ private int mNextTaskDisplayAreaFeatureId = FEATURE_RUNTIME_TASK_CONTAINER_FIRST; final ActivityTaskManagerService mService; private final WindowManagerGlobalLock mGlobalLock; private final HashMap<Integer, IDisplayAreaOrganizer> mOrganizersByFeatureIds = new HashMap(); Loading Loading @@ -92,10 +102,8 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl final List<DisplayAreaAppearedInfo> displayAreaInfos = new ArrayList<>(); mService.mRootWindowContainer.forAllDisplayAreas((da) -> { if (da.mFeatureId != feature) return; da.setOrganizer(organizer, true /* skipDisplayAreaAppeared */); displayAreaInfos.add(new DisplayAreaAppearedInfo(da.getDisplayAreaInfo(), new SurfaceControl(da.getSurfaceControl(), "DisplayAreaOrganizerController.registerOrganizer"))); displayAreaInfos.add(organizeDisplayArea(organizer, da, "DisplayAreaOrganizerController.registerOrganizer")); }); mOrganizersByFeatureIds.put(feature, organizer); Loading Loading @@ -124,6 +132,77 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl } } @Override public DisplayAreaAppearedInfo createTaskDisplayArea(IDisplayAreaOrganizer organizer, int displayId, int rootFeatureId, String name) { enforceTaskPermission("createTaskDisplayArea()"); final long uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Create TaskDisplayArea uid=%d", uid); final DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId); if (display == null) { throw new IllegalArgumentException("createTaskDisplayArea unknown displayId=" + displayId); } final DisplayArea root = display.getItemFromDisplayAreas(da -> da.asRootDisplayArea() != null && da.mFeatureId == rootFeatureId ? da : null); if (root == null) { throw new IllegalArgumentException("Can't find RootDisplayArea with featureId=" + rootFeatureId); } final int taskDisplayAreaFeatureId = mNextTaskDisplayAreaFeatureId++; final DeathRecipient dr = new DeathRecipient(organizer, taskDisplayAreaFeatureId); try { organizer.asBinder().linkToDeath(dr, 0); } catch (RemoteException e) { // Oh well... } final TaskDisplayArea tda = createTaskDisplayArea(root.asRootDisplayArea(), name, taskDisplayAreaFeatureId); return organizeDisplayArea(organizer, tda, "DisplayAreaOrganizerController.createTaskDisplayArea"); } } finally { Binder.restoreCallingIdentity(origId); } } @Override public void deleteTaskDisplayArea(WindowContainerToken token) { enforceTaskPermission("deleteTaskDisplayArea()"); final long uid = Binder.getCallingUid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Delete TaskDisplayArea uid=%d", uid); final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); if (wc == null || wc.asTaskDisplayArea() == null) { throw new IllegalArgumentException("Can't resolve TaskDisplayArea from token"); } final TaskDisplayArea taskDisplayArea = wc.asTaskDisplayArea(); if (!taskDisplayArea.mCreatedByOrganizer) { throw new IllegalArgumentException( "Attempt to delete TaskDisplayArea not created by organizer " + "TaskDisplayArea=" + taskDisplayArea); } deleteTaskDisplayArea(taskDisplayArea); } } finally { Binder.restoreCallingIdentity(origId); } } void onDisplayAreaAppeared(IDisplayAreaOrganizer organizer, DisplayArea da) { ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "DisplayArea appeared name=%s", da.getName()); try { Loading Loading @@ -157,8 +236,71 @@ public class DisplayAreaOrganizerController extends IDisplayAreaOrganizerControl IBinder organizerBinder = organizer.asBinder(); mService.mRootWindowContainer.forAllDisplayAreas((da) -> { if (da.mOrganizer != null && da.mOrganizer.asBinder().equals(organizerBinder)) { if (da.isTaskDisplayArea() && da.asTaskDisplayArea().mCreatedByOrganizer) { // Delete the organizer created TDA when unregister. deleteTaskDisplayArea(da.asTaskDisplayArea()); } else { da.setOrganizer(null); } } }); } private DisplayAreaAppearedInfo organizeDisplayArea(IDisplayAreaOrganizer organizer, DisplayArea displayArea, String callsite) { displayArea.setOrganizer(organizer, true /* skipDisplayAreaAppeared */); return new DisplayAreaAppearedInfo(displayArea.getDisplayAreaInfo(), new SurfaceControl(displayArea.getSurfaceControl(), callsite)); } private TaskDisplayArea createTaskDisplayArea(RootDisplayArea root, String name, int taskDisplayAreaFeatureId) { final TaskDisplayArea taskDisplayArea = new TaskDisplayArea(root.mDisplayContent, root.mWmService, name, taskDisplayAreaFeatureId, true /* createdByOrganizer */); // Find the top most DA that can contain Task (either a TDA or a DisplayAreaGroup). final DisplayArea topTaskContainer = root.getItemFromDisplayAreas(da -> { if (da.mType != ANY) { return null; } final RootDisplayArea rootDA = da.getRootDisplayArea(); if (rootDA == root || rootDA == da) { // Either it is the top TDA below the root or it is a DisplayAreaGroup. return da; } return null; }); if (topTaskContainer == null) { throw new IllegalStateException("Root must either contain TDA or DAG root=" + root); } // Insert the TaskDisplayArea as the top Task container. final WindowContainer parent = topTaskContainer.getParent(); final int index = parent.mChildren.indexOf(topTaskContainer) + 1; parent.addChild(taskDisplayArea, index); return taskDisplayArea; } private void deleteTaskDisplayArea(TaskDisplayArea taskDisplayArea) { taskDisplayArea.setOrganizer(null); mService.mRootWindowContainer.mTaskSupervisor.beginDeferResume(); // TaskDisplayArea#remove() move the stacks to the default TaskDisplayArea. Task lastReparentedStack; try { lastReparentedStack = taskDisplayArea.remove(); } finally { mService.mRootWindowContainer.mTaskSupervisor.endDeferResume(); } taskDisplayArea.removeImmediately(); // Only update focus/visibility for the last one because there may be many stacks are // reparented and the intermediate states are unnecessary. if (lastReparentedStack != null) { lastReparentedStack.postReparent(); } } }