Don't copy null surface control and remove lingering references to leashes

- If a task that should otherwise be organized but does not yet have a
  surface when the task organizer is registered, then skip trying to
  return that task as we can not leash it.  Existing logic will send the
  task to the organizer once a surface control is set on it.
- In the entry points to the shell where leashes are given from WM core
  (ie. the organizers), ensure that we release them when we are notified
  that they are no longer organized

Bug: 235858985
Test: atest ShellTaskOrganizerTests
Test: atest WindowOrganizerTests
Change-Id: I16d29315b615b9756a78310d6a62fb6f21ba1184
This commit is contained in:
Winson Chung
2022-06-30 05:30:12 +00:00
parent dad802aa6d
commit c40e75b6d3
11 changed files with 63 additions and 9 deletions

View File

@@ -85,6 +85,8 @@ public class RootDisplayAreaOrganizer extends DisplayAreaOrganizer {
}
mDisplayAreasInfo.remove(displayId);
mLeashes.get(displayId).release();
mLeashes.remove(displayId);
}
@Override

View File

@@ -529,7 +529,8 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
}
final int taskId = taskInfo.taskId;
final TaskListener listener = getTaskListener(mTasks.get(taskId).getTaskInfo());
final TaskAppearedInfo appearedInfo = mTasks.get(taskId);
final TaskListener listener = getTaskListener(appearedInfo.getTaskInfo());
mTasks.remove(taskId);
if (listener != null) {
listener.onTaskVanished(taskInfo);
@@ -539,6 +540,10 @@ public class ShellTaskOrganizer extends TaskOrganizer implements
notifyCompatUI(taskInfo, null /* taskListener */);
// Notify the recent tasks that a task has been removed
mRecentTasks.ifPresent(recentTasks -> recentTasks.onTaskRemoved(taskInfo));
if (appearedInfo.getLeash() != null) {
appearedInfo.getLeash().release();
}
}
}

View File

@@ -128,9 +128,10 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer {
final WindowContainerTransaction wct = new WindowContainerTransaction();
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
applyBoundsAndOffsets(
displayAreaInfo.token, mDisplayAreaMap.get(displayAreaInfo.token), wct, t);
final SurfaceControl leash = mDisplayAreaMap.get(displayAreaInfo.token);
applyBoundsAndOffsets(displayAreaInfo.token, leash, wct, t);
applyTransaction(wct, t);
leash.release();
mDisplayAreaMap.remove(displayAreaInfo.token);
}
}

View File

@@ -159,6 +159,10 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
@Override
public void onDisplayAreaVanished(@NonNull DisplayAreaInfo displayAreaInfo) {
final SurfaceControl leash = mDisplayAreaTokenMap.get(displayAreaInfo.token);
if (leash != null) {
leash.release();
}
mDisplayAreaTokenMap.remove(displayAreaInfo.token);
}

View File

@@ -943,6 +943,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mPipBoundsState.setBounds(new Rect());
mPipUiEventLoggerLogger.setTaskInfo(null);
mMainExecutor.executeDelayed(() -> mPipMenuController.detach(), 0);
mLeash = null;
if (info.displayId != Display.DEFAULT_DISPLAY && mOnDisplayIdChangeCallback != null) {
mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);

View File

@@ -434,7 +434,15 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
}
RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
return reparentSplitTasksForAnimation(apps, false /*splitExpectedToBeVisible*/);
try {
return reparentSplitTasksForAnimation(apps, false /*splitExpectedToBeVisible*/);
} finally {
for (RemoteAnimationTarget appTarget : apps) {
if (appTarget.leash != null) {
appTarget.leash.release();
}
}
}
}
private RemoteAnimationTarget[] reparentSplitTasksForAnimation(RemoteAnimationTarget[] apps,

View File

@@ -1022,6 +1022,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
mRootTaskInfo = null;
mRootTaskLeash = null;
}

View File

@@ -242,6 +242,7 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
if (mRootTaskInfo.taskId == taskId) {
mCallbacks.onRootTaskVanished();
mRootTaskInfo = null;
mRootLeash = null;
mSyncQueue.runInSync(t -> {
t.remove(mDimLayer);
mSplitDecorManager.release(t);

View File

@@ -46,6 +46,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.SparseArray;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.ITaskOrganizer;
import android.window.ITaskOrganizerController;
import android.window.TaskAppearedInfo;
@@ -137,12 +138,24 @@ public class ShellTaskOrganizerTests {
}
@Test
public void registerOrganizer_sendRegisterTaskOrganizer() throws RemoteException {
public void testRegisterOrganizer_sendRegisterTaskOrganizer() throws RemoteException {
mOrganizer.registerOrganizer();
verify(mTaskOrganizerController).registerTaskOrganizer(any(ITaskOrganizer.class));
}
@Test
public void testTaskLeashReleasedAfterVanished() throws RemoteException {
RunningTaskInfo taskInfo = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
SurfaceControl taskLeash = new SurfaceControl.Builder(new SurfaceSession())
.setName("task").build();
mOrganizer.registerOrganizer();
mOrganizer.onTaskAppeared(taskInfo, taskLeash);
assertTrue(taskLeash.isValid());
mOrganizer.onTaskVanished(taskInfo);
assertTrue(!taskLeash.isValid());
}
@Test
public void testOneListenerPerType() {
mOrganizer.addListenerForType(new TrackingTaskListener(), TASK_LISTENER_TYPE_MULTI_WINDOW);

View File

@@ -382,11 +382,12 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
mService.mRootWindowContainer.forAllTasks((task) -> {
boolean returnTask = !task.mCreatedByOrganizer;
task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */);
if (returnTask) {
SurfaceControl outSurfaceControl = state.addTaskWithoutCallback(task,
// It is possible for the task to not yet have a surface control, so ensure that
// the update succeeded in setting the organizer for the task before returning
if (task.isOrganized() && returnTask) {
SurfaceControl taskLeash = state.addTaskWithoutCallback(task,
"TaskOrganizerController.registerTaskOrganizer");
taskInfos.add(
new TaskAppearedInfo(task.getTaskInfo(), outSurfaceControl));
taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), taskLeash));
}
});
};

View File

@@ -457,6 +457,23 @@ public class WindowOrganizerTests extends WindowTestsBase {
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
}
@Test
public void testRegisterTaskOrganizerWithExistingTasks_noSurfaceControl()
throws RemoteException {
final Task rootTask = createRootTask();
final Task task = createTask(rootTask);
final Task rootTask2 = createRootTask();
final Task task2 = createTask(rootTask2);
rootTask2.setSurfaceControl(null);
ArrayList<TaskAppearedInfo> existingTasks = new ArrayList<>();
final ITaskOrganizer organizer = registerMockOrganizer(existingTasks);
assertContainsTasks(existingTasks, rootTask);
// Verify we don't get onTaskAppeared if we are returned the tasks
verify(organizer, never())
.onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
}
@Test
public void testTaskTransaction() {
removeGlobalMinSizeRestriction();