Loading core/java/android/app/TaskInfo.java +19 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.window.TaskSnapshot; import android.window.WindowContainerToken; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** Loading Loading @@ -179,6 +178,19 @@ public class TaskInfo { @Nullable public ActivityInfo topActivityInfo; /** * The top activity in this task. * @hide */ @Nullable public IBinder topActivityToken; /** * Whether the direct top activity is in size compat mode on foreground. * @hide */ public boolean topActivityInSizeCompat; /** * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity * supports), this is what the system actually uses for resizability based on other policy and Loading Loading @@ -356,6 +368,8 @@ public class TaskInfo { parentTaskId = source.readInt(); isFocused = source.readBoolean(); isVisible = source.readBoolean(); topActivityToken = source.readStrongBinder(); topActivityInSizeCompat = source.readBoolean(); } /** Loading Loading @@ -391,6 +405,8 @@ public class TaskInfo { dest.writeInt(parentTaskId); dest.writeBoolean(isFocused); dest.writeBoolean(isVisible); dest.writeStrongBinder(topActivityToken); dest.writeBoolean(topActivityInSizeCompat); } @Override Loading @@ -415,6 +431,8 @@ public class TaskInfo { + " parentTaskId=" + parentTaskId + " isFocused=" + isFocused + " isVisible=" + isVisible + " topActivityToken=" + topActivityToken + " topActivityInSizeCompat=" + topActivityInSizeCompat + "}"; } } services/core/java/com/android/server/wm/ActivityRecord.java +7 −0 Original line number Diff line number Diff line Loading @@ -2180,6 +2180,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** @return Root task of this activity, null if there is no task. */ @Nullable Task getRootTask() { return task != null ? task.getRootTask() : null; } Loading @@ -2188,6 +2189,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task != null ? task.getRootTaskId() : INVALID_TASK_ID; } /** @return the first organized parent task. */ @Nullable Task getOrganizedTask() { return task != null ? task.getOrganizedTask() : null; } @Override @Nullable TaskDisplayArea getDisplayArea() { Loading services/core/java/com/android/server/wm/DisplayContent.java +9 −1 Original line number Diff line number Diff line Loading @@ -5485,14 +5485,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Checks whether the given activity is in size compatibility mode and notifies the change. */ void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) { if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { final Task organizedTask = r.getOrganizedTask(); if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN || organizedTask == null) { // The callback is only interested in the foreground changes of fullscreen activity. return; } if (!r.inSizeCompatMode()) { if (mLastCompatModeActivity != null) { // TODO(b/178327644) Remove notifySizeCompatModeActivityChanged mAtmService.getTaskChangeNotificationController() .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */); // This will do nothing until SizeCompatModeActivityController is moved to shell organizedTask.onSizeCompatActivityChanged(); } mLastCompatModeActivity = null; return; Loading @@ -5501,8 +5506,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return; } mLastCompatModeActivity = r; // TODO(b/178327644) Remove notifySizeCompatModeActivityChanged mAtmService.getTaskChangeNotificationController() .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken); // This will do nothing until SizeCompatModeActivityController is moved to shell organizedTask.onSizeCompatActivityChanged(); } boolean isUidPresent(int uid) { Loading services/core/java/com/android/server/wm/Task.java +28 −0 Original line number Diff line number Diff line Loading @@ -3082,6 +3082,20 @@ class Task extends WindowContainer<WindowContainer> { return parentTask == null ? this : parentTask.getRootTask(); } /** @return the first organized task. */ @Nullable Task getOrganizedTask() { if (isOrganized()) { return this; } final WindowContainer parent = getParent(); if (parent == null) { return null; } final Task parentTask = parent.asTask(); return parentTask == null ? null : parentTask.getOrganizedTask(); } // TODO(task-merge): Figure out what's the right thing to do for places that used it. boolean isRootTask() { return getRootTask() == this; Loading Loading @@ -4172,6 +4186,14 @@ class Task extends WindowContainer<WindowContainer> { info.topActivityInfo = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.info : null; info.topActivityToken = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.appToken : null; // Whether the direct top activity is in size compat mode on foreground. info.topActivityInSizeCompat = mReuseActivitiesReport.top != null && mReuseActivitiesReport.top.getOrganizedTask() == this && mReuseActivitiesReport.top.inSizeCompatMode() && mReuseActivitiesReport.top.isState(RESUMED); info.launchCookies.clear(); info.addLaunchCookie(mLaunchCookie); forAllActivities(r -> { Loading Loading @@ -5221,6 +5243,12 @@ class Task extends WindowContainer<WindowContainer> { } } /** Called when the top activity in the Root Task enters or exits size compat mode. */ void onSizeCompatActivityChanged() { // Trigger TaskInfoChanged to update the size compat restart button. dispatchTaskInfoChangedIfNeeded(true /* force */); } /** * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +43 −0 Original line number Diff line number Diff line Loading @@ -480,10 +480,13 @@ public class SizeCompatTests extends WindowTestsBase { /** * Ensures that {@link TaskStackListener} can receive callback about the activity in size * compatibility mode. * * TODO(b/178327644) Remove after update DC#handleActivitySizeCompatModeIfNeeded */ @Test public void testHandleActivitySizeCompatMode() { setUpDisplaySizeWithApp(1000, 2000); doReturn(true).when(mTask).isOrganized(); ActivityRecord activity = mActivity; activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatMode"); prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); Loading Loading @@ -520,6 +523,46 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(null, compatTokens.get(0)); } /** * Ensures that {@link TaskOrganizerController} can receive callback about the activity in size * compatibility mode. */ @Test public void testHandleActivitySizeCompatModeChanged() { setUpDisplaySizeWithApp(1000, 2000); doReturn(true).when(mTask).isOrganized(); ActivityRecord activity = mActivity; activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatModeChanged"); prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); assertFitted(); // Resize the display so that the activity exercises size-compat mode. resizeDisplay(mTask.mDisplayContent, 1000, 2500); // Expect the exact token when the activity is in size compatibility mode. verify(mTask).onSizeCompatActivityChanged(); ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo(); assertEquals(mActivity.appToken, taskInfo.topActivityToken); assertTrue(taskInfo.topActivityInSizeCompat); // Make the activity resizable again by restarting it clearInvocations(mTask); activity.info.resizeMode = RESIZE_MODE_RESIZEABLE; activity.mVisibleRequested = true; activity.restartProcessIfVisible(); // The full lifecycle isn't hooked up so manually set state to resumed activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatModeChanged"); mTask.mDisplayContent.handleActivitySizeCompatModeIfNeeded(activity); // Expect null token when switching to non-size-compat mode activity. verify(mTask).onSizeCompatActivityChanged(); taskInfo = mTask.getTaskInfo(); assertEquals(mActivity.appToken, taskInfo.topActivityToken); assertFalse(taskInfo.topActivityInSizeCompat); } @Test public void testShouldUseSizeCompatModeOnResizableTask() { setUpDisplaySizeWithApp(1000, 2500); Loading Loading
core/java/android/app/TaskInfo.java +19 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,6 @@ import android.window.TaskSnapshot; import android.window.WindowContainerToken; import java.util.ArrayList; import java.util.List; import java.util.Objects; /** Loading Loading @@ -179,6 +178,19 @@ public class TaskInfo { @Nullable public ActivityInfo topActivityInfo; /** * The top activity in this task. * @hide */ @Nullable public IBinder topActivityToken; /** * Whether the direct top activity is in size compat mode on foreground. * @hide */ public boolean topActivityInSizeCompat; /** * Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity * supports), this is what the system actually uses for resizability based on other policy and Loading Loading @@ -356,6 +368,8 @@ public class TaskInfo { parentTaskId = source.readInt(); isFocused = source.readBoolean(); isVisible = source.readBoolean(); topActivityToken = source.readStrongBinder(); topActivityInSizeCompat = source.readBoolean(); } /** Loading Loading @@ -391,6 +405,8 @@ public class TaskInfo { dest.writeInt(parentTaskId); dest.writeBoolean(isFocused); dest.writeBoolean(isVisible); dest.writeStrongBinder(topActivityToken); dest.writeBoolean(topActivityInSizeCompat); } @Override Loading @@ -415,6 +431,8 @@ public class TaskInfo { + " parentTaskId=" + parentTaskId + " isFocused=" + isFocused + " isVisible=" + isVisible + " topActivityToken=" + topActivityToken + " topActivityInSizeCompat=" + topActivityInSizeCompat + "}"; } }
services/core/java/com/android/server/wm/ActivityRecord.java +7 −0 Original line number Diff line number Diff line Loading @@ -2180,6 +2180,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** @return Root task of this activity, null if there is no task. */ @Nullable Task getRootTask() { return task != null ? task.getRootTask() : null; } Loading @@ -2188,6 +2189,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return task != null ? task.getRootTaskId() : INVALID_TASK_ID; } /** @return the first organized parent task. */ @Nullable Task getOrganizedTask() { return task != null ? task.getOrganizedTask() : null; } @Override @Nullable TaskDisplayArea getDisplayArea() { Loading
services/core/java/com/android/server/wm/DisplayContent.java +9 −1 Original line number Diff line number Diff line Loading @@ -5485,14 +5485,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Checks whether the given activity is in size compatibility mode and notifies the change. */ void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) { if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { final Task organizedTask = r.getOrganizedTask(); if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN || organizedTask == null) { // The callback is only interested in the foreground changes of fullscreen activity. return; } if (!r.inSizeCompatMode()) { if (mLastCompatModeActivity != null) { // TODO(b/178327644) Remove notifySizeCompatModeActivityChanged mAtmService.getTaskChangeNotificationController() .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */); // This will do nothing until SizeCompatModeActivityController is moved to shell organizedTask.onSizeCompatActivityChanged(); } mLastCompatModeActivity = null; return; Loading @@ -5501,8 +5506,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return; } mLastCompatModeActivity = r; // TODO(b/178327644) Remove notifySizeCompatModeActivityChanged mAtmService.getTaskChangeNotificationController() .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken); // This will do nothing until SizeCompatModeActivityController is moved to shell organizedTask.onSizeCompatActivityChanged(); } boolean isUidPresent(int uid) { Loading
services/core/java/com/android/server/wm/Task.java +28 −0 Original line number Diff line number Diff line Loading @@ -3082,6 +3082,20 @@ class Task extends WindowContainer<WindowContainer> { return parentTask == null ? this : parentTask.getRootTask(); } /** @return the first organized task. */ @Nullable Task getOrganizedTask() { if (isOrganized()) { return this; } final WindowContainer parent = getParent(); if (parent == null) { return null; } final Task parentTask = parent.asTask(); return parentTask == null ? null : parentTask.getOrganizedTask(); } // TODO(task-merge): Figure out what's the right thing to do for places that used it. boolean isRootTask() { return getRootTask() == this; Loading Loading @@ -4172,6 +4186,14 @@ class Task extends WindowContainer<WindowContainer> { info.topActivityInfo = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.info : null; info.topActivityToken = mReuseActivitiesReport.top != null ? mReuseActivitiesReport.top.appToken : null; // Whether the direct top activity is in size compat mode on foreground. info.topActivityInSizeCompat = mReuseActivitiesReport.top != null && mReuseActivitiesReport.top.getOrganizedTask() == this && mReuseActivitiesReport.top.inSizeCompatMode() && mReuseActivitiesReport.top.isState(RESUMED); info.launchCookies.clear(); info.addLaunchCookie(mLaunchCookie); forAllActivities(r -> { Loading Loading @@ -5221,6 +5243,12 @@ class Task extends WindowContainer<WindowContainer> { } } /** Called when the top activity in the Root Task enters or exits size compat mode. */ void onSizeCompatActivityChanged() { // Trigger TaskInfoChanged to update the size compat restart button. dispatchTaskInfoChangedIfNeeded(true /* force */); } /** * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +43 −0 Original line number Diff line number Diff line Loading @@ -480,10 +480,13 @@ public class SizeCompatTests extends WindowTestsBase { /** * Ensures that {@link TaskStackListener} can receive callback about the activity in size * compatibility mode. * * TODO(b/178327644) Remove after update DC#handleActivitySizeCompatModeIfNeeded */ @Test public void testHandleActivitySizeCompatMode() { setUpDisplaySizeWithApp(1000, 2000); doReturn(true).when(mTask).isOrganized(); ActivityRecord activity = mActivity; activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatMode"); prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); Loading Loading @@ -520,6 +523,46 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(null, compatTokens.get(0)); } /** * Ensures that {@link TaskOrganizerController} can receive callback about the activity in size * compatibility mode. */ @Test public void testHandleActivitySizeCompatModeChanged() { setUpDisplaySizeWithApp(1000, 2000); doReturn(true).when(mTask).isOrganized(); ActivityRecord activity = mActivity; activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatModeChanged"); prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT); assertFitted(); // Resize the display so that the activity exercises size-compat mode. resizeDisplay(mTask.mDisplayContent, 1000, 2500); // Expect the exact token when the activity is in size compatibility mode. verify(mTask).onSizeCompatActivityChanged(); ActivityManager.RunningTaskInfo taskInfo = mTask.getTaskInfo(); assertEquals(mActivity.appToken, taskInfo.topActivityToken); assertTrue(taskInfo.topActivityInSizeCompat); // Make the activity resizable again by restarting it clearInvocations(mTask); activity.info.resizeMode = RESIZE_MODE_RESIZEABLE; activity.mVisibleRequested = true; activity.restartProcessIfVisible(); // The full lifecycle isn't hooked up so manually set state to resumed activity.setState(Task.ActivityState.RESUMED, "testHandleActivitySizeCompatModeChanged"); mTask.mDisplayContent.handleActivitySizeCompatModeIfNeeded(activity); // Expect null token when switching to non-size-compat mode activity. verify(mTask).onSizeCompatActivityChanged(); taskInfo = mTask.getTaskInfo(); assertEquals(mActivity.appToken, taskInfo.topActivityToken); assertFalse(taskInfo.topActivityInSizeCompat); } @Test public void testShouldUseSizeCompatModeOnResizableTask() { setUpDisplaySizeWithApp(1000, 2500); Loading