diff options
20 files changed, 185 insertions, 152 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index 0c10551a9b23..e27b2beb3d5a 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -1156,7 +1156,7 @@ class ActivityClientController extends IActivityClientController.Stub { } if (rootTask.inFreeformWindowingMode()) { - rootTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_FULLSCREEN); rootTask.setBounds(null); } else if (!r.supportsFreeform()) { throw new IllegalStateException( @@ -1165,9 +1165,9 @@ class ActivityClientController extends IActivityClientController.Stub { // If the window is on a freeform display, set it to undefined. It will be // resolved to freeform and it can adjust windowing mode when the display mode // changes in runtime. - rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); } else { - rootTask.setWindowingMode(WINDOWING_MODE_FREEFORM); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_FREEFORM); } } } finally { @@ -1278,7 +1278,7 @@ class ActivityClientController extends IActivityClientController.Stub { if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_ENTER) { final int restoreWindowingMode = requester.getRequestedOverrideWindowingMode(); targetWindowingMode = WINDOWING_MODE_FULLSCREEN; - requester.setWindowingMode(targetWindowingMode); + requester.setRootTaskWindowingMode(targetWindowingMode); // The restore windowing mode must be set after the windowing mode is set since // Task#setWindowingMode resets the restore windowing mode to WINDOWING_MODE_INVALID. requester.mMultiWindowRestoreWindowingMode = restoreWindowingMode; @@ -1297,9 +1297,8 @@ class ActivityClientController extends IActivityClientController.Stub { public void startLockTaskModeByToken(IBinder token) { synchronized (mGlobalLock) { final ActivityRecord r = ActivityRecord.forTokenLocked(token); - if (r != null) { - mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */); - } + if (r == null) return; + mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index a76f1b62fe02..d982925268b1 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -2016,7 +2016,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mIsUserAlwaysVisible = properties != null && properties.getAlwaysVisible(); mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 || mIsUserAlwaysVisible; - setOrientation(info.screenOrientation); + setOverrideOrientation(info.screenOrientation); mRotationAnimationHint = info.rotationAnimation; mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0; @@ -3626,10 +3626,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final WindowContainer<?> trigger = endTask ? task : this; final Transition newTransition = mTransitionController.requestCloseTransitionIfNeeded(trigger); - if (newTransition != null) { - newTransition.collectClose(trigger); - } else if (mTransitionController.isCollecting()) { - mTransitionController.getCollectingTransition().collectClose(trigger); + final Transition transition = newTransition != null + ? newTransition : mTransitionController.getCollectingTransition(); + if (transition != null) { + transition.collectClose(trigger); } if (isState(RESUMED)) { if (endTask) { @@ -4302,9 +4302,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // closing the task. final WindowContainer trigger = remove && task != null && task.getChildCount() == 1 ? task : this; - final Transition newTransit = mTransitionController.requestCloseTransitionIfNeeded(trigger); - if (newTransit != null) { - newTransit.collectClose(trigger); + final Transition tr = mTransitionController.requestCloseTransitionIfNeeded(trigger); + if (tr != null) { + tr.collectClose(trigger); } else if (mTransitionController.isCollecting()) { mTransitionController.getCollectingTransition().collectClose(trigger); } @@ -5320,12 +5320,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A task.lastDescription = description; } - void setDeferHidingClient(boolean deferHidingClient) { - if (mDeferHidingClient == deferHidingClient) { - return; - } - mDeferHidingClient = deferHidingClient; - if (!mDeferHidingClient && !mVisibleRequested) { + void setDeferHidingClient() { + mDeferHidingClient = true; + } + + void clearDeferHidingClient() { + if (!mDeferHidingClient) return; + mDeferHidingClient = false; + if (!mVisibleRequested) { // Hiding the client is no longer deferred and the app isn't visible still, go ahead and // update the visibility. setVisibility(false); @@ -5449,8 +5451,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean isCollecting = false; boolean inFinishingTransition = false; if (mTransitionController.isShellTransitionsEnabled()) { - isCollecting = mTransitionController.isCollecting(); - if (isCollecting) { + if (mTransitionController.isCollecting()) { + isCollecting = true; mTransitionController.collect(this); } else { // Failsafe to make sure that we show any activities that were incorrectly hidden @@ -6195,7 +6197,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // stopped or stopping. This gives it a chance to enter Pip in onPause(). final boolean deferHidingClient = canEnterPictureInPicture && !isState(STARTED, STOPPING, STOPPED, PAUSED); - setDeferHidingClient(deferHidingClient); + if (deferHidingClient) { + setDeferHidingClient(); + } else { + clearDeferHidingClient(); + } setVisibility(false); switch (getState()) { @@ -6234,7 +6240,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Slog.v(TAG_VISIBILITY, "Resume visible activity, " + this); } return getRootTask().resumeTopActivityUncheckedLocked(activeActivity /* prev */, - null /* options */); + null /* options */, false /* skipPause */); } else if (shouldPauseActivity(activeActivity)) { if (DEBUG_VISIBILITY) { Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this); @@ -6524,9 +6530,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A void stopIfPossible() { if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this); if (finishing) { - Slog.e(TAG, "Request to stop a finishing activity: " + this); - destroyIfPossible("stopIfPossible-finishing"); - return; + throw new IllegalStateException("Request to stop a finishing activity: " + this); } if (isNoHistory()) { if (!task.shouldSleepActivities()) { diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index a0ef03095010..1660ca913e59 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -612,11 +612,10 @@ public class ActivityStartController { final Task task = r.getTask(); mService.deferWindowLayout(); try { - final TransitionController controller = r.mTransitionController; - final Transition transition = controller.getCollectingTransition(); + final Transition transition = r.mTransitionController.getCollectingTransition(); if (transition != null) { transition.setRemoteAnimationApp(r.app.getThread()); - controller.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask)); + transition.setTransientLaunch(r, TaskDisplayArea.getRootTaskAbove(rootTask)); } task.moveToFront("startExistingRecents"); task.mInResumeTopActivity = true; diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 18aa9a026675..64791112a129 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -1355,9 +1355,21 @@ class ActivityStarter { mService.resumeAppSwitches(); } + // Only do the create here since startActivityInner can abort. If it doesn't abort, + // the requestStart will be sent in handleStartRequest. + final Transition newTransition = r.mTransitionController.isShellTransitionsEnabled() + ? r.mTransitionController.createAndStartCollecting(TRANSIT_OPEN) : null; + // Because startActivity must run immediately, it can get combined with another + // transition meaning it is no-longer independent. This is NOT desirable, but is the + // only option for the time being. + final boolean isIndependent = newTransition != null; + final Transition transition = isIndependent ? newTransition + : mService.getTransitionController().getCollectingTransition(); + mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, checkedOptions, - inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid); + inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid, transition, + isIndependent); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; @@ -1509,33 +1521,27 @@ class ActivityStarter { int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, BalVerdict balVerdict, - NeededUriGrants intentGrants, int realCallingUid) { + NeededUriGrants intentGrants, int realCallingUid, Transition transition, + boolean isIndependentLaunch) { int result = START_CANCELED; final Task startedActivityRootTask; - // Create a transition now to record the original intent of actions taken within - // startActivityInner. Otherwise, logic in startActivityInner could start a different - // transition based on a sub-action. - // Only do the create here (and defer requestStart) since startActivityInner might abort. - final TransitionController transitionController = r.mTransitionController; - Transition newTransition = transitionController.isShellTransitionsEnabled() - ? transitionController.createAndStartCollecting(TRANSIT_OPEN) : null; RemoteTransition remoteTransition = r.takeRemoteTransition(); // Create a display snapshot as soon as possible. - if (newTransition != null && mRequest.freezeScreen) { + if (isIndependentLaunch && mRequest.freezeScreen) { final TaskDisplayArea tda = mLaunchParams.hasPreferredTaskDisplayArea() ? mLaunchParams.mPreferredTaskDisplayArea : mRootWindowContainer.getDefaultTaskDisplayArea(); final DisplayContent dc = mRootWindowContainer.getDisplayContentOrCreate( tda.getDisplayId()); if (dc != null) { - transitionController.collect(dc); - transitionController.collectVisibleChange(dc); + transition.collect(dc); + transition.collectVisibleChange(dc); } } try { mService.deferWindowLayout(); - transitionController.collect(r); + r.mTransitionController.collect(r); try { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, @@ -1545,8 +1551,8 @@ class ActivityStarter { Slog.e(TAG, "Exception on startActivityInner", ex); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); - startedActivityRootTask = handleStartResult(r, options, result, newTransition, - remoteTransition); + startedActivityRootTask = handleStartResult(r, options, result, isIndependentLaunch, + remoteTransition, transition); } } finally { mService.continueWindowLayout(); @@ -1571,8 +1577,8 @@ class ActivityStarter { * @return the root task where the successful started activity resides. */ private @Nullable Task handleStartResult(@NonNull ActivityRecord started, - ActivityOptions options, int result, Transition newTransition, - RemoteTransition remoteTransition) { + ActivityOptions options, int result, boolean isIndependentLaunch, + RemoteTransition remoteTransition, @NonNull Transition transition) { final boolean userLeaving = mSupervisor.mUserLeaving; mSupervisor.mUserLeaving = false; final Task currentRootTask = started.getRootTask(); @@ -1596,8 +1602,9 @@ class ActivityStarter { && !startedActivityRootTask.mCreatedByOrganizer) { startedActivityRootTask.removeIfPossible("handleStartResult"); } - if (newTransition != null) { - newTransition.abort(); + if (isIndependentLaunch + && mService.getTransitionController().isShellTransitionsEnabled()) { + transition.abort(); } return null; } @@ -1649,44 +1656,46 @@ class ActivityStarter { // The activity is started new rather than just brought forward, so record it as an // existence change. transitionController.collectExistenceChange(started); - } else if (result == START_DELIVERED_TO_TOP && newTransition != null + } else if (result == START_DELIVERED_TO_TOP && isIndependentLaunch // An activity has changed order/visibility or the task is occluded by a transient // activity, so this isn't just deliver-to-top && mMovedToTopActivity == null && !transitionController.hasOrderChanges() && !transitionController.isTransientHide(startedActivityRootTask) - && !newTransition.hasChanged(mLastStartActivityRecord)) { + && !transition.hasChanged(mLastStartActivityRecord)) { // We just delivered to top, so there isn't an actual transition here. if (!forceTransientTransition) { - newTransition.abort(); - newTransition = null; + transition.abort(); + transition = null; } } - if (forceTransientTransition) { - transitionController.collect(mLastStartActivityRecord); - transitionController.collect(mPriorAboveTask); + if (forceTransientTransition && transition != null) { + transition.collect(mLastStartActivityRecord); + transition.collect(mPriorAboveTask); // If keyguard is active and occluded, the transient target won't be moved to front // to be collected, so set transient again after it is collected. - transitionController.setTransientLaunch(mLastStartActivityRecord, mPriorAboveTask); + transition.setTransientLaunch(mLastStartActivityRecord, mPriorAboveTask); final DisplayContent dc = mLastStartActivityRecord.getDisplayContent(); // update wallpaper target to TransientHide dc.mWallpaperController.adjustWallpaperWindows(); // execute transition because there is no change - transitionController.setReady(dc, true /* ready */); + transition.setReady(dc, true /* ready */); } - if (!userLeaving) { + if (!userLeaving && transition != null) { // no-user-leaving implies not entering PiP. - transitionController.setCanPipOnFinish(false /* canPipOnFinish */); + transition.setCanPipOnFinish(false /* canPipOnFinish */); } - if (newTransition != null) { - transitionController.requestStartTransition(newTransition, + if (isIndependentLaunch && transition != null) { + transitionController.requestStartTransition(transition, mTargetTask == null ? started.getTask() : mTargetTask, remoteTransition, null /* displayChange */); } else if (result == START_SUCCESS && mStartActivity.isState(RESUMED)) { // Do nothing if the activity is started and is resumed directly. } else if (isStarted) { // Make the collecting transition wait until this request is ready. - transitionController.setReady(started, false); + if (transition != null) { + transition.setReady(started, false); + } } return startedActivityRootTask; } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f23211b98b85..5bb4a8adbd82 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -2116,12 +2116,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { Slog.w(TAG, "removeTask: No task remove with id=" + taskId); return false; } - - if (task.isLeafTask()) { - mTaskSupervisor.removeTask(task, true, REMOVE_FROM_RECENTS, "remove-task"); - } else { - mTaskSupervisor.removeRootTask(task); - } + removeTask(task); return true; } finally { Binder.restoreCallingIdentity(ident); @@ -2129,6 +2124,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + void removeTask(@NonNull Task task) { + if (task.isLeafTask()) { + mTaskSupervisor.removeTask(task, true, REMOVE_FROM_RECENTS, "remove-task"); + } else { + mTaskSupervisor.removeRootTask(task); + } + } + @Override public void removeAllVisibleRecentTasks() { mAmInternal.enforceCallingPermission(REMOVE_TASKS, "removeAllVisibleRecentTasks()"); @@ -2938,7 +2941,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } getTransitionController().requestStartTransition(transition, task, null /* remoteTransition */, null /* displayChange */); - getTransitionController().collect(task); + transition.collect(task); task.resize(bounds, resizeMode, preserveWindow); transition.setReady(task, true); }); diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 8ef2693ec327..1446c353d9d4 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -1528,9 +1528,12 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } mService.deferWindowLayout(); - final Transition newTransition = task.mTransitionController.isShellTransitionsEnabled() - ? task.mTransitionController.isCollecting() ? null - : task.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null; + boolean newTransition = false; + Transition transition = task.mTransitionController.getCollectingTransition(); + if (transition == null && task.mTransitionController.isShellTransitionsEnabled()) { + transition = task.mTransitionController.createTransition(TRANSIT_TO_FRONT); + newTransition = true; + } task.mTransitionController.collect(task); reason = reason + " findTaskToMoveToFront"; boolean reparented = false; @@ -1574,8 +1577,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // transition to avoid delaying the starting window. r.showStartingWindow(true /* taskSwitch */); } - if (newTransition != null) { - task.mTransitionController.requestStartTransition(newTransition, task, + if (newTransition) { + task.mTransitionController.requestStartTransition(transition, task, options != null ? options.getRemoteTransition() : null, null /* displayChange */); } @@ -1644,7 +1647,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { mService.deferWindowLayout(); try { - rootTask.setWindowingMode(WINDOWING_MODE_UNDEFINED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); if (rootTask.getWindowingMode() != WINDOWING_MODE_FREEFORM) { rootTask.setBounds(null); } @@ -1705,7 +1708,10 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // Prevent recursion. return; } - final Transition transit = task.mTransitionController.requestCloseTransitionIfNeeded(task); + Transition transit = task.mTransitionController.requestCloseTransitionIfNeeded(task); + if (transit == null) { + transit = task.mTransitionController.getCollectingTransition(); + } if (transit != null) { transit.collectClose(task); if (!task.mTransitionController.useFullReadyTracking()) { @@ -1717,8 +1723,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // before anything that may need it to wait (setReady(false)). transit.setReady(task, true); } - } else if (task.mTransitionController.isCollecting()) { - task.mTransitionController.getCollectingTransition().collectClose(task); } // Consume the stopping activities immediately so activity manager won't skip killing // the process because it is still foreground state, i.e. RESUMED -> PAUSING set from diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 89e10d36caed..767effd0ef12 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -367,7 +367,7 @@ class BackNavigationController { // client process to prevent the unexpected relayout when handling the back // animation. for (int i = prevActivities.size() - 1; i >= 0; --i) { - prevActivities.get(i).setDeferHidingClient(true); + prevActivities.get(i).setDeferHidingClient(); } } else { scheduleAnimation(builder); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index bded98c6c07f..6427c3229b50 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1633,7 +1633,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // Only resume home activity if isn't finishing. if (r != null && !r.finishing) { r.moveFocusableActivityToTop(myReason); - return resumeFocusedTasksTopActivities(r.getRootTask(), prev, null); + return resumeFocusedTasksTopActivities(r.getRootTask(), prev); } int userId = mWmService.getUserAssignedToDisplay(taskDisplayArea.getDisplayId()); return startHomeOnTaskDisplayArea(userId, myReason, taskDisplayArea, @@ -2202,7 +2202,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // During recents animations, the original task is "occluded" by launcher but // it wasn't paused (due to transient-launch). If we reparent to the (top) task // now, it will take focus briefly which confuses the RecentTasks tracker. - rootTask.setWindowingMode(WINDOWING_MODE_PINNED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED); } // Temporarily disable focus when reparenting to avoid intermediate focus change // (because the task is on top and the activity is resumed), which could cause the @@ -2235,7 +2235,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // TODO(remove-legacy-transit): Move this to the `singleActivity` case when removing // legacy transit. - rootTask.setWindowingMode(WINDOWING_MODE_PINNED); + rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED); if (isPip2ExperimentEnabled() && bounds != null) { // set the final pip bounds in advance if pip2 is enabled rootTask.setBounds(bounds); @@ -2470,12 +2470,12 @@ class RootWindowContainer extends WindowContainer<DisplayContent> } boolean resumeFocusedTasksTopActivities() { - return resumeFocusedTasksTopActivities(null, null, null); + return resumeFocusedTasksTopActivities(null, null, null, false /* deferPause */); } boolean resumeFocusedTasksTopActivities( - Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) { - return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions, + Task targetRootTask, ActivityRecord target) { + return resumeFocusedTasksTopActivities(targetRootTask, target, null /* targetOptions */, false /* deferPause */); } @@ -2527,7 +2527,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // activity is started and resumed, and no recursion occurs. final Task focusedRoot = display.getFocusedRootTask(); if (focusedRoot != null) { - result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions); + result |= focusedRoot.resumeTopActivityUncheckedLocked( + target, targetOptions, false /* skipPause */); } else if (targetRootTask == null) { result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea()); @@ -2632,7 +2633,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> // process the keyguard going away, which can happen before the sleep // token is released. As a result, it is important we resume the // activity here. - rootTask.resumeTopActivityUncheckedLocked(null, null); + rootTask.resumeTopActivityUncheckedLocked(); } // The visibility update must not be called before resuming the top, so the // display orientation can be updated first if needed. Otherwise there may diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 12e91adef9c5..da00d7347eff 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4540,7 +4540,8 @@ class Task extends TaskFragment { reparent(parent, MAX_VALUE); } - setWindowingMode(mMultiWindowRestoreWindowingMode); + // mMultiWindowRestoreWindowingMode is INVALID for non-root tasks + setRootTaskWindowingMode(mMultiWindowRestoreWindowingMode); } @Override @@ -4553,18 +4554,30 @@ class Task extends TaskFragment { return; } - setWindowingMode(windowingMode, false /* creating */); + setWindowingModeInner(windowingMode, false /* creating */); } /** - * Specialization of {@link #setWindowingMode(int)} for this subclass. + * Version of {@link #setWindowingMode(int)} for root tasks. * * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the * previous non-transient mode if this root task is currently in a transient mode. + */ + public void setRootTaskWindowingMode(int preferredWindowingMode) { + if (!isRootTask()) { + Slog.wtf(TAG, "Trying to set root-task windowing-mode on a non-root-task: " + this, + new Throwable()); + super.setWindowingMode(preferredWindowingMode); + return; + } + setWindowingModeInner(preferredWindowingMode, false /* creating */); + } + + /** * @param creating {@code true} if this is being run during task construction. */ - void setWindowingMode(int preferredWindowingMode, boolean creating) { + private void setWindowingModeInner(int preferredWindowingMode, boolean creating) { final TaskDisplayArea taskDisplayArea = getDisplayArea(); if (taskDisplayArea == null) { Slog.d(TAG, "taskDisplayArea is null, bail early"); @@ -4740,7 +4753,7 @@ class Task extends TaskFragment { } } if (isAttached()) { - setWindowingMode(WINDOWING_MODE_UNDEFINED); + setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); moveTaskToBackInner(this, null /* transition */); } if (top.isAttached()) { @@ -5086,10 +5099,10 @@ class Task extends TaskFragment { return someActivityResumed; } - /** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */ @GuardedBy("mService") - boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { - return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */); + boolean resumeTopActivityUncheckedLocked() { + return resumeTopActivityUncheckedLocked(null /* prev */, null /* options */, + false /* skipPause */); } @GuardedBy("mService") @@ -5138,8 +5151,7 @@ class Task extends TaskFragment { // Try to move focus to the next visible root task with a running activity if this // root task is not covering the entire screen or is on a secondary display with // no home root task. - return mRootWindowContainer.resumeFocusedTasksTopActivities(nextFocusedTask, - prev, null /* targetOptions */); + return mRootWindowContainer.resumeFocusedTasksTopActivities(nextFocusedTask, prev); } } @@ -5661,8 +5673,10 @@ class Task extends TaskFragment { if (noAnimation) { mDisplayContent.prepareAppTransition(TRANSIT_NONE); mTaskSupervisor.mNoAnimActivities.add(top); - mTransitionController.collect(top); - mTransitionController.setNoAnimation(top); + if (mTransitionController.isShellTransitionsEnabled()) { + mTransitionController.collect(top); + mTransitionController.setNoAnimation(top); + } ActivityOptions.abort(options); } else { updateTransitLocked(TRANSIT_TO_FRONT, options); @@ -6002,7 +6016,7 @@ class Task extends TaskFragment { } final Task task = getBottomMostTask(); - setWindowingMode(WINDOWING_MODE_UNDEFINED); + setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); // Task could have been removed from the hierarchy due to windowing mode change // where its only child is reparented back to their original parent task. @@ -6674,7 +6688,7 @@ class Task extends TaskFragment { // Set windowing mode after attached to display area or it abort silently. if (mWindowingMode != WINDOWING_MODE_UNDEFINED) { - task.setWindowingMode(mWindowingMode, true /* creating */); + task.setWindowingModeInner(mWindowingMode, true /* creating */); } return task; } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index dba1c364b89b..d9e88e1e460a 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -923,7 +923,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { if (windowingMode != WINDOWING_MODE_UNDEFINED && candidateTask.isRootTask() && candidateTask.getWindowingMode() != windowingMode) { candidateTask.mTransitionController.collect(candidateTask); - candidateTask.setWindowingMode(windowingMode); + candidateTask.setRootTaskWindowingMode(windowingMode); } return candidateTask.getRootTask(); } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 2ee157f42615..329d11bfcb95 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -1927,7 +1927,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { prev.setState(STOPPING, "completePausedLocked"); } else if (!prev.isVisibleRequested() || shouldSleepOrShutDownActivities()) { // Clear out any deferred client hide we might currently have. - prev.setDeferHidingClient(false); + prev.clearDeferHidingClient(); // If we were visible then resumeTopActivities will release resources before // stopping. prev.addToStopping(true /* scheduleIdle */, false /* idleDelayed */, @@ -1948,8 +1948,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (resumeNext) { final Task topRootTask = mRootWindowContainer.getTopDisplayFocusedRootTask(); if (topRootTask != null && !topRootTask.shouldSleepOrShutDownActivities()) { - mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev, - null /* targetOptions */); + mRootWindowContainer.resumeFocusedTasksTopActivities(topRootTask, prev); } else { // checkReadyForSleep(); final ActivityRecord top = diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java index 9ee1fbe91d83..de2e4f5474c4 100644 --- a/services/core/java/com/android/server/wm/TaskOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java @@ -390,7 +390,7 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub { t.mTaskAppearedSent = false; } if (removeFromSystem) { - mService.removeTask(t.mTaskId); + mService.removeTask(t); } return taskAppearedSent; } diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 836ac5f6c1fc..b768bb155563 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -420,6 +420,18 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { updateTransientFlags(mChanges.valueAt(i)); } } + + // TODO(b/188669821): Remove once legacy recents behavior is moved to shell. + // Also interpret HOME transient launch as recents + if (activity.isActivityTypeHomeOrRecents()) { + addFlag(TRANSIT_FLAG_IS_RECENTS); + // When starting recents animation, we assume the recents activity is behind the app + // task and should not affect system bar appearance, + // until WMS#setRecentsAppBehindSystemBars be called from launcher when passing + // the gesture threshold. + activity.getTask().setCanAffectSystemUiFlags(false); + } + ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Transition %d: Set %s as " + "transient-launch", mSyncId, activity); } @@ -1721,6 +1733,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { transaction.addTransactionCompletedListener(Runnable::run, (stats) -> listener.run()); } + mTransactionCompletedListeners = null; } // Fall-back to the default display if there isn't one participating. @@ -1763,6 +1776,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { if (mPriorVisibilityMightBeDirty) { updatePriorVisibility(); } + // Resolve the animating targets from the participants. mTargets = calculateTargets(mParticipants, mChanges); diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 67d7b37396c0..ef25eda1d876 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -19,7 +19,6 @@ package com.android.server.wm; import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS; import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; -import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS; import static android.view.WindowManager.TRANSIT_NONE; import static com.android.server.wm.ActivityTaskManagerService.POWER_MODE_REASON_CHANGE_DISPLAY; @@ -53,8 +52,8 @@ import android.window.WindowContainerTransaction; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.protolog.ProtoLogGroup; import com.android.internal.protolog.ProtoLog; +import com.android.internal.protolog.ProtoLogGroup; import com.android.server.FgThread; import com.android.window.flags.Flags; @@ -1311,23 +1310,6 @@ class TransitionController { void setTransientLaunch(@NonNull ActivityRecord activity, @Nullable Task restoreBelowTask) { if (mCollectingTransition == null) return; mCollectingTransition.setTransientLaunch(activity, restoreBelowTask); - - // TODO(b/188669821): Remove once legacy recents behavior is moved to shell. - // Also interpret HOME transient launch as recents - if (activity.isActivityTypeHomeOrRecents()) { - mCollectingTransition.addFlag(TRANSIT_FLAG_IS_RECENTS); - // When starting recents animation, we assume the recents activity is behind the app - // task and should not affect system bar appearance, - // until WMS#setRecentsAppBehindSystemBars be called from launcher when passing - // the gesture threshold. - activity.getTask().setCanAffectSystemUiFlags(false); - } - } - - /** @see Transition#setCanPipOnFinish */ - void setCanPipOnFinish(boolean canPipOnFinish) { - if (mCollectingTransition == null) return; - mCollectingTransition.setCanPipOnFinish(canPipOnFinish); } void legacyDetachNavigationBarFromApp(@NonNull IBinder token) { @@ -1459,7 +1441,7 @@ class TransitionController { * * WARNING: ONLY use this if the transition absolutely cannot be deferred! */ - @NonNull + @Nullable Transition createAndStartCollecting(int type) { if (mTransitionPlayers.isEmpty()) { return null; diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 64f9c012ea28..15d67eb61a43 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -1611,8 +1611,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< * * @param orientation the specified orientation. */ - void setOrientation(@ScreenOrientation int orientation) { - setOrientation(orientation, null /* requestingContainer */); + protected void setOrientation(@ScreenOrientation int orientation) { + setOrientation(orientation, null /* requesting */); } /** diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index c6d0b729cd5a..9d40b16c37ae 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -322,11 +322,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub // This is a direct call from shell, so the entire transition lifecycle is // contained in the provided transaction if provided. Thus, we can setReady // immediately after apply. - final Transition.ReadyCondition wctApplied = - new Transition.ReadyCondition("start WCT applied"); final boolean needsSetReady = t != null; final Transition nextTransition = new Transition(type, 0 /* flags */, mTransitionController, mService.mWindowManager.mSyncEngine); + final Transition.ReadyCondition wctApplied = + new Transition.ReadyCondition("start WCT applied"); nextTransition.mReadyTracker.add(wctApplied); nextTransition.calcParallelCollectType(wct); mTransitionController.startCollectOrQueue(nextTransition, @@ -342,15 +342,6 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub }); return nextTransition.getToken(); } - // Currently, application of wct can span multiple looper loops (ie. - // waitAsyncStart), so add a condition to ensure that it finishes applying. - final Transition.ReadyCondition wctApplied; - if (t != null) { - wctApplied = new Transition.ReadyCondition("start WCT applied"); - transition.mReadyTracker.add(wctApplied); - } else { - wctApplied = null; - } // The transition already started collecting before sending a request to shell, // so just start here. if (!transition.isCollecting() && !transition.isForcePlaying()) { @@ -358,11 +349,17 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub + " means Shell took too long to respond to a request. WM State may be" + " incorrect now, please file a bug"); applyTransaction(wct, -1 /*syncId*/, null /*transition*/, caller); - if (wctApplied != null) { - wctApplied.meet(); - } return transition.getToken(); } + // Currently, application of wct can span multiple looper loops (ie. + // waitAsyncStart), so add a condition to ensure that it finishes applying. + final Transition.ReadyCondition wctApplied; + if (t != null) { + wctApplied = new Transition.ReadyCondition("start WCT applied"); + transition.mReadyTracker.add(wctApplied); + } else { + wctApplied = null; + } transition.mLogger.mStartWCT = wct; if (transition.shouldApplyOnDisplayThread()) { mService.mH.post(() -> { @@ -851,7 +848,11 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub } final int prevMode = container.getRequestedOverrideWindowingMode(); - container.setWindowingMode(windowingMode); + if (container.asTask() != null && container.asTask().isRootTask()) { + container.asTask().setRootTaskWindowingMode(windowingMode); + } else { + container.setWindowingMode(windowingMode); + } if (prevMode != container.getWindowingMode()) { // The activity in the container may become focusable or non-focusable due to // windowing modes changes (such as entering or leaving pinned windowing mode), diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index ab0c8d4ed60a..ec5e51e7b842 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -2656,6 +2656,7 @@ public class DisplayContentTests extends WindowTestsBase { * display. */ @Test + @SuppressWarnings("GuardedBy") public void testNotResumeHomeRootTaskOnRemovingDisplay() { // Create a display which supports system decoration and allows reparenting root tasks to // another display when the display is removed. @@ -2678,7 +2679,8 @@ public class DisplayContentTests extends WindowTestsBase { // The removed display should have no focused root task and its home root task should never // resume. assertNull(display.getFocusedRootTask()); - verify(homeRootTask, never()).resumeTopActivityUncheckedLocked(any(), any()); + verify(homeRootTask, never()).resumeTopActivityUncheckedLocked( + any(), any(), anyBoolean()); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index d29505f02fe8..84c2c32054d8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -54,6 +54,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.contains; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.refEq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.mock; @@ -598,7 +599,7 @@ public class RootWindowContainerTests extends WindowTestsBase { mRootWindowContainer.applySleepTokens(true); verify(task, times(expectWakeFromSleep ? 1 : 0)).awakeFromSleeping(); verify(task, times(expectResumeTopActivity ? 1 : 0)).resumeTopActivityUncheckedLocked( - null /* target */, null /* targetOptions */); + isNull() /* target */, isNull() /* targetOptions */, eq(false) /* deferPause */); } @Test @@ -790,8 +791,7 @@ public class RootWindowContainerTests extends WindowTestsBase { doReturn(rootTask).when(mRootWindowContainer).getTopDisplayFocusedRootTask(); // Use the task as target to resume. - mRootWindowContainer.resumeFocusedTasksTopActivities(rootTask, activity, - null /* targetOptions */); + mRootWindowContainer.resumeFocusedTasksTopActivities(rootTask, activity); // Verify the target task should resume its activity. verify(rootTask, times(1)).resumeTopActivityUncheckedLocked( diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 36696a16fa39..65e3baad87d1 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -3017,6 +3017,7 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + @SuppressWarnings("GuardedBy") public void testDisplayIgnoreOrientationRequest_pausedAppNotLostSizeCompat() { // Set up a display in landscape and ignoring orientation request. setUpDisplaySizeWithApp(2800, 1400); @@ -3043,7 +3044,8 @@ public class SizeCompatTests extends WindowTestsBase { assertActivityMaxBoundsSandboxed(); final Rect activityBounds = new Rect(mActivity.getBounds()); - mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */); + mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */, + false /* deferPause */); // App still in size compat, and the bounds don't change. verify(mActivity, never()).clearSizeCompatMode(); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java index 18255b8d82f8..f56825faab73 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java @@ -265,7 +265,7 @@ public class WindowOrganizerTests extends WindowTestsBase { rootTask.setTaskOrganizer(null); mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); - verify(mWm.mAtmService).removeTask(eq(rootTask.mTaskId)); + verify(mWm.mAtmService).removeTask(eq(rootTask)); } @Test @@ -283,7 +283,7 @@ public class WindowOrganizerTests extends WindowTestsBase { rootTask.setTaskOrganizer(null); mWm.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); - verify(mWm.mAtmService, never()).removeTask(eq(rootTask.mTaskId)); + verify(mWm.mAtmService, never()).removeTask(eq(rootTask)); } @Test |