Unify ActivityStack extend Task (84/n)
Step towards merging stacks into tasks.
Test: Existing tests pass.
Bug: 80414790
Change-Id: Ifb167129c89a3aba11796daa21a9dee7200913ca
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b596d2a..f911f2e 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -745,7 +745,8 @@
synchronized (mAtmService.mGlobalLock) {
Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
if (isInHistory()) {
- activityStopped(null /*icicle*/, null /*persistentState*/, null /*description*/);
+ activityStopped(
+ null /*icicle*/, null /*persistentState*/, null /*description*/);
}
}
}
@@ -1286,17 +1287,11 @@
updateColorTransform();
- final ActivityStack oldStack = (oldTask != null) ? oldTask.getStack() : null;
- final ActivityStack newStack = (newTask != null) ? newTask.getStack() : null;
- // Inform old stack (if present) of activity removal and new stack (if set) of activity
- // addition.
- if (oldStack != newStack) {
- if (oldStack != null) {
- oldStack.onActivityRemovedFromStack(this);
- }
- if (newStack != null) {
- newStack.onActivityAddedToStack(this);
- }
+ if (oldTask != null) {
+ oldTask.cleanUpActivityReferences(this);
+ }
+ if (newTask != null && isState(RESUMED)) {
+ newTask.setResumedActivity(this, "onParentChanged");
}
}
@@ -2904,8 +2899,7 @@
* Note: Call before {@link #removeFromHistory(String)}.
*/
void cleanUp(boolean cleanServices, boolean setState) {
- final ActivityStack stack = getActivityStack();
- stack.onActivityRemovedFromStack(this);
+ task.cleanUpActivityReferences(this);
deferRelaunchUntilPaused = false;
frozenBeforeDestroy = false;
@@ -5832,7 +5826,7 @@
@Override
boolean isWaitingForTransitionStart() {
final DisplayContent dc = getDisplayContent();
- return dc.mAppTransition.isTransitionSet()
+ return dc != null && dc.mAppTransition.isTransitionSet()
&& (dc.mOpeningApps.contains(this)
|| dc.mClosingApps.contains(this)
|| dc.mChangingApps.contains(this));
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index f5fba8e..60e0f51e 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -80,7 +80,6 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
@@ -119,7 +118,6 @@
import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static java.lang.Integer.MAX_VALUE;
@@ -153,6 +151,7 @@
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.UserHandle;
import android.service.voice.IVoiceInteractionSession;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -162,7 +161,6 @@
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.ITaskOrganizer;
-import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import com.android.internal.annotations.GuardedBy;
@@ -190,7 +188,7 @@
/**
* State and management of a single stack of activities.
*/
-class ActivityStack extends WindowContainer<WindowContainer> implements BoundsAnimationTarget {
+class ActivityStack extends Task implements BoundsAnimationTarget {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM;
static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
private static final String TAG_APP = TAG + POSTFIX_APP;
@@ -251,33 +249,6 @@
RESTARTING_PROCESS
}
- final ActivityTaskManagerService mAtmService;
-
- /**
- * When we are in the process of pausing an activity, before starting the
- * next one, this variable holds the activity that is currently being paused.
- */
- ActivityRecord mPausingActivity = null;
-
- /**
- * This is the last activity that we put into the paused state. This is
- * used to determine if we need to do an activity transition while sleeping,
- * when we normally hold the top activity paused.
- */
- ActivityRecord mLastPausedActivity = null;
-
- /**
- * Activities that specify No History must be removed once the user navigates away from them.
- * If the device goes to sleep with such an activity in the paused state then we save it here
- * and finish it later if another activity replaces it on wakeup.
- */
- ActivityRecord mLastNoHistoryActivity = null;
-
- /**
- * Current activity that is resumed, or null if there is none.
- */
- ActivityRecord mResumedActivity = null;
-
// The topmost Activity passed to convertToTranslucent(). When non-null it means we are
// waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
// are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
@@ -294,11 +265,6 @@
boolean mConfigWillChange;
/**
- * When set, will force the stack to report as invisible.
- */
- boolean mForceHidden = false;
-
- /**
* Used to keep resumeTopActivityUncheckedLocked() from being entered recursively
*/
boolean mInResumeTopActivity = false;
@@ -311,18 +277,12 @@
int mCurrentUser;
- /** The attached Display's unique identifier, or -1 if detached */
- private int mDisplayId;
- // Id of the previous display the stack was on.
- int mPrevDisplayId = INVALID_DISPLAY;
-
/** Unique identifier */
final int mStackId;
/** For comparison with DisplayContent bounds. */
private Rect mTmpRect = new Rect();
private Rect mTmpRect2 = new Rect();
- private Rect mTmpRect3 = new Rect();
/** For Pinned stack controlling. */
private Rect mTmpToBounds = new Rect();
@@ -336,9 +296,6 @@
*/
private final Rect mFullyAdjustedImeBounds = new Rect();
- /** ActivityRecords that are exiting, but still on screen for animations. */
- final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
-
/** Detach this stack from its display when animation completes. */
// TODO: maybe tie this to WindowContainer#removeChild some how...
private boolean mDeferRemoval;
@@ -367,8 +324,6 @@
Rect mPreAnimationBounds = new Rect();
- private Dimmer mDimmer = new Dimmer(this);
-
/**
* For {@link #prepareSurfaces}.
*/
@@ -384,10 +339,6 @@
/** List for processing through a set of activities */
private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>();
- /** Run all ActivityStacks through this */
- protected final ActivityStackSupervisor mStackSupervisor;
- protected final RootWindowContainer mRootWindowContainer;
-
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
@@ -638,52 +589,68 @@
}
}
- ActivityStack(DisplayContent display, int stackId, ActivityStackSupervisor supervisor,
- int activityType) {
- super(supervisor.mService.mWindowManager);
- mStackId = stackId;
- mDockedStackMinimizeThickness =
- supervisor.mService.mWindowManager.mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.docked_stack_minimize_thickness);
- EventLogTags.writeWmStackCreated(stackId);
- mStackSupervisor = supervisor;
- mAtmService = supervisor.mService;
- mRootWindowContainer = mAtmService.mRootWindowContainer;
- mHandler = new ActivityStackHandler(supervisor.mLooper);
- mRemoteToken = new RemoteToken(this);
- mCurrentUser = mAtmService.mAmInternal.getCurrentUserId();
- // Set display id before setting activity and window type to make sure it won't affect
- // stacks on a wrong display.
- mDisplayId = display.mDisplayId;
+ ActivityStack(DisplayContent display, int id, ActivityStackSupervisor supervisor,
+ int activityType, ActivityInfo info, Intent intent) {
+ this(supervisor.mService, id, info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
+ null /*taskDescription*/, null /*stack*/);
+
setActivityType(activityType);
}
- /**
- * This should be called when an activity in a child task changes state. This should only
- * be called from
- * {@link Task#onActivityStateChanged(ActivityRecord, ActivityState, String)}.
- * @param record The {@link ActivityRecord} whose state has changed.
- * @param state The new state.
- * @param reason The reason for the change.
- */
- void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
- if (record == mResumedActivity && state != RESUMED) {
- setResumedActivity(null, reason + " - onActivityStateChanged");
- }
+ ActivityStack(ActivityTaskManagerService atmService, int id, ActivityInfo info, Intent _intent,
+ IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+ ActivityManager.TaskDescription _taskDescription, ActivityStack stack) {
+ this(atmService, id, _intent, null /*_affinityIntent*/, null /*_affinity*/,
+ null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
+ false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
+ UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
+ null /*_lastDescription*/, System.currentTimeMillis(),
+ true /*neverRelinquishIdentity*/,
+ _taskDescription != null ? _taskDescription : new ActivityManager.TaskDescription(),
+ id, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
+ info.applicationInfo.uid, info.packageName, info.resizeMode,
+ info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
+ false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
+ _voiceSession, _voiceInteractor, stack);
+ }
- if (state == RESUMED) {
- if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:"
- + reason);
- setResumedActivity(record, reason + " - onActivityStateChanged");
- if (record == mRootWindowContainer.getTopResumedActivity()) {
- mAtmService.setResumedActivityUncheckLocked(record, reason);
- }
- mStackSupervisor.mRecentTasks.add(record.getTask());
- }
+ ActivityStack(ActivityTaskManagerService atmService, int id, Intent _intent,
+ Intent _affinityIntent, String _affinity, String _rootAffinity,
+ ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
+ boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid,
+ String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity,
+ ActivityManager.TaskDescription _lastTaskDescription, int taskAffiliation,
+ int prevTaskId, int nextTaskId, int taskAffiliationColor, int callingUid,
+ String callingPackage, int resizeMode, boolean supportsPictureInPicture,
+ boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight,
+ ActivityInfo info, IVoiceInteractionSession _voiceSession,
+ IVoiceInteractor _voiceInteractor, ActivityStack stack) {
+ super(atmService, id, _intent, _affinityIntent, _affinity, _rootAffinity,
+ _realActivity, _origActivity, _rootWasReset, _autoRemoveRecents, _askedCompatMode,
+ _userId, _effectiveUid, _lastDescription, lastTimeMoved, neverRelinquishIdentity,
+ _lastTaskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
+ callingUid, callingPackage, resizeMode, supportsPictureInPicture,
+ _realActivitySuspended, userSetupComplete, minWidth, minHeight, info, _voiceSession,
+ _voiceInteractor, stack);
+
+ mStackId = mTaskId;
+ mDockedStackMinimizeThickness = mWmService.mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.docked_stack_minimize_thickness);
+ EventLogTags.writeWmStackCreated(id);
+ mHandler = new ActivityStackHandler(mStackSupervisor.mLooper);
+ mCurrentUser = mAtmService.mAmInternal.getCurrentUserId();
}
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
+ // Calling Task#onConfigurationChanged() for leaf task since the ops in this method are
+ // particularly for ActivityStack, like preventing bounds changes when inheriting certain
+ // windowing mode.
+ if (!isRootTask()) {
+ super.onConfigurationChanged(newParentConfig);
+ return;
+ }
+
final int prevWindowingMode = getWindowingMode();
final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
final int prevRotation = getWindowConfiguration().getRotation();
@@ -801,10 +768,16 @@
@Override
public void setWindowingMode(int windowingMode) {
+ // Calling Task#setWindowingMode() for leaf task since this is the a specialization of
+ // {@link #setWindowingMode(int)} for ActivityStack.
+ if (!isRootTask()) {
+ super.setWindowingMode(windowingMode);
+ return;
+ }
+
setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
false /* creating */);
-
windowingMode = getWindowingMode();
/*
* Different windowing modes may be managed by different task organizers. If
@@ -893,7 +866,8 @@
// Looks like we can't launch in split screen mode or the stack we are launching
// doesn't support split-screen mode, go ahead an dismiss split-screen and display a
// warning toast about it.
- mAtmService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack();
+ mAtmService.getTaskChangeNotificationController()
+ .notifyActivityDismissingDockedStack();
final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack();
primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED,
false /* animate */, false /* showRecents */,
@@ -972,7 +946,7 @@
false /* preserveWindows */, true /* deferResume */);
}
} finally {
- if (showRecents && !alreadyInSplitScreenMode && mDisplayId == DEFAULT_DISPLAY
+ if (showRecents && !alreadyInSplitScreenMode && isOnHomeDisplay()
&& windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
// Make sure recents stack exist when creating a dock stack as it normally needs to
// be on the other side of the docked stack and we make visibility decisions based
@@ -1029,10 +1003,6 @@
return getDisplayContent();
}
- int getDisplayId() {
- return mDisplayId;
- }
-
/**
* Defers updating the bounds of the stack. If the stack was resized/repositioned while
* deferring, the bounds will update in {@link #continueUpdateBounds()}.
@@ -1138,10 +1108,6 @@
return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
}
- ActivityRecord getTopNonFinishingActivity() {
- return getTopActivity(false /*includeFinishing*/, true /*includeOverlays*/);
- }
-
ActivityRecord isInStackLocked(IBinder token) {
final ActivityRecord r = ActivityRecord.forTokenLocked(token);
return isInStackLocked(r);
@@ -1172,11 +1138,7 @@
}
final boolean isOnHomeDisplay() {
- return mDisplayId == DEFAULT_DISPLAY;
- }
-
- private boolean returnsToHomeStack() {
- return !inMultiWindowMode() && hasChild() && getBottomMostTask().returnsToHomeStack();
+ return getDisplayId() == DEFAULT_DISPLAY;
}
void moveToFront(String reason) {
@@ -1280,11 +1242,11 @@
super.switchUser(userId);
forAllTasks((t) -> {
- if (t.mWmService.isCurrentProfile(t.mUserId) || t.showForAllUsers()) {
+ if (t.showToCurrentUser()) {
mChildren.remove(t);
mChildren.add(t);
}
- });
+ }, true /* traverseTopToBottom */, this);
}
void minimalResumeActivityLocked(ActivityRecord r) {
@@ -1609,45 +1571,6 @@
mRootWindowContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS);
}
- /**
- * Returns true if the stack is translucent and can have other contents visible behind it if
- * needed. A stack is considered translucent if it don't contain a visible or
- * starting (about to be visible) activity that is fullscreen (opaque).
- * @param starting The currently starting activity or null if there is none.
- */
- @VisibleForTesting
- boolean isStackTranslucent(ActivityRecord starting) {
- if (!isAttached() || mForceHidden) {
- return true;
- }
- final PooledPredicate p = PooledLambda.obtainPredicate(ActivityStack::isOpaqueActivity,
- PooledLambda.__(ActivityRecord.class), starting);
- final ActivityRecord opaque = getActivity(p);
- p.recycle();
- return opaque == null;
- }
-
- private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
- if (r.finishing) {
- // We don't factor in finishing activities when determining translucency since
- // they will be gone soon.
- return false;
- }
-
- if (!r.visibleIgnoringKeyguard && r != starting) {
- // Also ignore invisible activities that are not the currently starting
- // activity (about to be visible).
- return false;
- }
-
- if (r.occludesParent() || r.hasWallpaper) {
- // Stack isn't translucent if it has at least one fullscreen activity
- // that is visible.
- return true;
- }
- return false;
- }
-
boolean isTopStackOnDisplay() {
final DisplayContent display = getDisplay();
return display != null && display.isTopStack(this);
@@ -1667,15 +1590,6 @@
return topActivity != null && topActivity.mVisibleRequested;
}
- /**
- * Indicate whether the first task in this stack is controlled by a TaskOrganizer. We aren't
- * expecting to use the TaskOrganizer in multiple task per stack scenarios so checking
- * the first one is ok.
- */
- boolean isControlledByTaskOrganizer() {
- return getChildCount() > 0 && getTopMostTask().mTaskOrganizer != null;
- }
-
private static void transferSingleTaskToOrganizer(Task tr, ITaskOrganizer organizer) {
tr.setTaskOrganizer(organizer);
}
@@ -1690,7 +1604,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStack::transferSingleTaskToOrganizer,
PooledLambda.__(Task.class), organizer);
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
}
@@ -1699,6 +1613,7 @@
*
* @param starting The currently starting activity or null if there is none.
*/
+ @Override
boolean shouldBeVisible(ActivityRecord starting) {
return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
}
@@ -1756,7 +1671,7 @@
break;
}
}
- if (other.isStackTranslucent(starting)) {
+ if (other.isTranslucent(starting)) {
// Can be visible behind a translucent fullscreen stack.
gotTranslucentFullscreen = true;
continue;
@@ -1765,7 +1680,7 @@
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& !gotOpaqueSplitScreenPrimary) {
gotSplitScreenStack = true;
- gotTranslucentSplitScreenPrimary = other.isStackTranslucent(starting);
+ gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
&& gotOpaqueSplitScreenPrimary) {
@@ -1775,7 +1690,7 @@
} else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& !gotOpaqueSplitScreenSecondary) {
gotSplitScreenStack = true;
- gotTranslucentSplitScreenSecondary = other.isStackTranslucent(starting);
+ gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
&& gotOpaqueSplitScreenSecondary) {
@@ -1876,13 +1791,7 @@
return inPinnedWindowingMode();
}
- @Override
- public boolean supportsSplitScreenWindowingMode() {
- final Task topTask = getTopMostTask();
- return super.supportsSplitScreenWindowingMode()
- && (topTask == null || topTask.supportsSplitScreenWindowingMode());
- }
-
+ // TODO(NOW!)
/**
* Returns {@code true} if this is the top-most split-screen-primary or
* split-screen-secondary stack, {@code false} otherwise.
@@ -1918,7 +1827,9 @@
* @return true if {@param r} is visible taken Keyguard state into account, false otherwise
*/
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) {
- final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
+ int displayId = getDisplayId();
+ if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
+
final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked();
@@ -2084,24 +1995,6 @@
return result;
}
- /**
- * Returns the currently resumed activity.
- */
- protected ActivityRecord getResumedActivity() {
- return mResumedActivity;
- }
-
- private void setResumedActivity(ActivityRecord r, String reason) {
- if (mResumedActivity == r) {
- return;
- }
-
- if (DEBUG_STACK) Slog.d(TAG_STACK, "setResumedActivity stack:" + this + " + from: "
- + mResumedActivity + " to:" + r + " reason:" + reason);
- mResumedActivity = r;
- mStackSupervisor.updateTopResumedActivityIfNeeded();
- }
-
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
@@ -2412,7 +2305,7 @@
// result of invisible window resize.
// TODO: Remove this once visibilities are set correctly immediately when
// starting an activity.
- notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, mDisplayId,
+ notUpdated = !mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
true /* markFrozenIfConfigChanged */, false /* deferResume */);
}
@@ -2553,7 +2446,7 @@
ActivityOptions.abort(options);
if (DEBUG_STATES) Slog.d(TAG_STATES,
"resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home");
- return mRootWindowContainer.resumeHomeActivity(prev, reason, mDisplayId);
+ return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayId());
}
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
@@ -2827,7 +2720,7 @@
void finishVoiceTask(IVoiceInteractionSession session) {
final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::finishIfVoiceTask,
PooledLambda.__(Task.class), session.asBinder());
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
}
@@ -3020,29 +2913,6 @@
return foundParentInTask;
}
- /**
- * Remove any state associated with the {@link ActivityRecord}. This should be called whenever
- * an activity moves away from the stack.
- */
- void onActivityRemovedFromStack(ActivityRecord r) {
- r.removeTimeouts();
-
- mExitingActivities.remove(r);
-
- if (mResumedActivity != null && mResumedActivity == r) {
- setResumedActivity(null, "onActivityRemovedFromStack");
- }
- if (mPausingActivity != null && mPausingActivity == r) {
- mPausingActivity = null;
- }
- }
-
- void onActivityAddedToStack(ActivityRecord r) {
- if (r.isState(RESUMED)) {
- setResumedActivity(r, "onActivityAddedToStack");
- }
- }
-
void removeLaunchTickMessages() {
forAllActivities(ActivityRecord::removeLaunchTickRunnable);
}
@@ -3141,7 +3011,8 @@
mRootWindowContainer.resumeFocusedStacksTopActivities();
}
EventLogTags.writeWmTaskToFront(tr.mUserId, tr.mTaskId);
- mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo());
+ mAtmService.getTaskChangeNotificationController()
+ .notifyTaskMovedToFront(tr.getTaskInfo());
} finally {
getDisplay().continueUpdateImeTarget();
}
@@ -3239,7 +3110,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStack::processTaskResizeBounds, PooledLambda.__(Task.class),
taskBounds, tempTaskInsetBounds);
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
setBounds(bounds);
@@ -3276,7 +3147,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::setTaskBounds,
PooledLambda.__(Task.class), bounds);
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
}
@@ -3292,7 +3163,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::setTaskDisplayedBounds,
PooledLambda.__(Task.class), bounds);
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
}
@@ -3384,7 +3255,6 @@
private boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
boolean dumpClient, String dumpPackage, boolean needSep) {
-
if (!hasChild()) {
return false;
}
@@ -3403,11 +3273,11 @@
final ArrayList<ActivityRecord> activities = new ArrayList<>();
// Add activities by traversing the hierarchy from bottom to top, since activities
// are dumped in reverse order in {@link ActivityStackSupervisor#dumpHistoryList()}.
- forAllActivities((Consumer<ActivityRecord>) activities::add,
+ task.forAllActivities((Consumer<ActivityRecord>) activities::add,
false /* traverseTopToBottom */);
dumpHistoryList(fd, pw, activities, prefix, "Hist", true, !dumpAll, dumpClient,
dumpPackage, false, null, task);
- });
+ }, true /* traverseTopToBottom */, this);
return true;
}
@@ -3458,49 +3328,9 @@
}
}
- /**
- * Removes the input task from this stack.
- *
- * @param child to remove.
- * @param reason for removal.
- */
- void removeChild(WindowContainer child, String reason) {
- if (!mChildren.contains(child)) {
- // Not really in this stack anymore...
- return;
- }
-
- final DisplayContent display = getDisplay();
- if (DEBUG_TASK_MOVEMENT) {
- Slog.d(TAG_WM, "removeChild: task=" + child + " reason=" + reason);
- }
-
- super.removeChild(child);
-
- EventLogTags.writeWmRemoveTask(((Task) child).mTaskId, mStackId);
-
- if (display.isSingleTaskInstance()) {
- mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
- }
-
- display.mDisplayContent.setLayoutNeeded();
-
- if (!hasChild()) {
- // Stack is now empty...
- removeIfPossible();
- }
- }
-
- @Override
- void removeChild(WindowContainer child) {
- removeChild(child, "removeChild");
- }
-
- Task createTask(int taskId, ActivityInfo info, Intent intent,
- IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
- boolean toTop) {
- return createTask(taskId, info, intent, voiceSession, voiceInteractor, toTop,
- null /*activity*/, null /*source*/, null /*options*/);
+ Task createTask(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
+ return createTask(taskId, info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
+ toTop, null /*activity*/, null /*source*/, null /*options*/);
}
Task createTask(int taskId, ActivityInfo info, Intent intent,
@@ -3511,7 +3341,8 @@
mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
// add the task to stack first, mTaskPositioner might need the stack association
addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
- final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY;
+ int displayId = getDisplayId();
+ if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
final boolean isLockscreenShown = mAtmService.mStackSupervisor.getKeyguardController()
.isKeyguardOrAodShowing(displayId);
if (!mStackSupervisor.getLaunchParamsController()
@@ -3522,14 +3353,25 @@
return task;
}
- void addChild(final Task task, final boolean toTop, boolean showForAllUsers) {
+ void addChild(WindowContainer child, final boolean toTop, boolean showForAllUsers) {
if (isSingleTaskInstance() && hasChild()) {
throw new IllegalStateException("Can only have one child on stack=" + this);
}
- // We only want to move the parents to the parents if we are creating this task at the
- // top of its stack.
- addChild(task, toTop ? MAX_VALUE : 0, showForAllUsers, toTop /*moveParents*/);
+ Task task = child.asTask();
+ try {
+
+ if (task != null) {
+ task.setForceShowForAllUsers(showForAllUsers);
+ }
+ // We only want to move the parents to the parents if we are creating this task at the
+ // top of its stack.
+ addChild(child, toTop ? MAX_VALUE : 0, toTop /*moveParents*/);
+ } finally {
+ if (task != null) {
+ task.setForceShowForAllUsers(false);
+ }
+ }
}
void positionChildAt(Task task, int position) {
@@ -3747,16 +3589,12 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStackSupervisor::updatePictureInPictureMode, mStackSupervisor,
PooledLambda.__(Task.class), targetStackBounds, forceUpdate);
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
}
- public int getStackId() {
- return mStackId;
- }
-
void prepareFreezingTaskBounds() {
- forAllTasks(Task::prepareFreezingBounds);
+ forAllTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */, this);
}
/**
@@ -3788,7 +3626,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(Task::alignToAdjustedBounds,
PooledLambda.__(Task.class), adjusted ? mAdjustedBounds : getRawBounds(),
insetBounds, alignBottom);
- forAllTasks(c);
+ forAllTasks(c, true /* traverseTopToBottom */, this);
c.recycle();
}
@@ -3798,7 +3636,13 @@
@Override
public int setBounds(Rect bounds) {
- return setBounds(getRequestedOverrideBounds(), bounds);
+ // Calling Task#setBounds() for leaf task since this is the a specialization of
+ // {@link #setBounds(int)} for ActivityStack.
+ if (!isRootTask()) {
+ return super.setBounds(bounds);
+ } else {
+ return setBounds(getRequestedOverrideBounds(), bounds);
+ }
}
private int setBounds(Rect existing, Rect bounds) {
@@ -4038,30 +3882,15 @@
* Put a Task in this stack. Used for adding only.
* When task is added to top of the stack, the entire branch of the hierarchy (including stack
* and display) will be brought to top.
- * @param task The task to add.
+ * @param child The child to add.
* @param position Target position to add the task to.
- * @param showForAllUsers Whether to show the task regardless of the current user.
*/
- private void addChild(Task task, int position, boolean showForAllUsers, boolean moveParents) {
- try {
- // Force show for all user so task can be position correctly based on which user is
- // active. We clear the force show below.
- task.setForceShowForAllUsers(showForAllUsers);
- // Add child task.
- addChild(task, null);
+ private void addChild(WindowContainer child, int position, boolean moveParents) {
+ // Add child task.
+ addChild(child, null);
- // Move child to a proper position, as some restriction for position might apply.
- positionChildAt(position, task, moveParents /* includingParents */);
-
- } finally {
- task.setForceShowForAllUsers(false);
- }
- }
-
- @Override
- void addChild(WindowContainer child, int position) {
- final Task task = (Task) child;
- addChild(task, position, task.showForAllUsers(), false /* includingParents */);
+ // Move child to a proper position, as some restriction for position might apply.
+ positionChildAt(position, child, moveParents /* includingParents */);
}
void positionChildAtTop(Task child) {
@@ -4099,29 +3928,18 @@
}
@Override
- void positionChildAt(int position, WindowContainer child, boolean includingParents) {
- final Task task = (Task) child;
- final int targetPosition = findPositionForTask(task, position);
- super.positionChildAt(targetPosition, child, includingParents);
-
- // Log positioning.
- if (DEBUG_TASK_MOVEMENT) {
- Slog.d(TAG_WM, "positionTask: task=" + this + " position=" + position);
- }
-
- final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
- EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, targetPosition);
- }
-
- @Override
void onChildPositionChanged(WindowContainer child) {
if (!mChildren.contains(child)) {
return;
}
- final Task task = (Task) child;
- final boolean isTop = getTopChild() == task;
- task.updateTaskMovement(isTop);
+ final boolean isTop = getTopChild() == child;
+
+ final Task task = child.asTask();
+ if (task != null) {
+ task.updateTaskMovement(isTop);
+ }
+
if (isTop) {
final DisplayContent displayContent = getDisplayContent();
displayContent.layoutAndAssignWindowLayersIfNeeded();
@@ -4129,34 +3947,17 @@
}
@Override
- protected void onParentChanged(
- ConfigurationContainer newParent, ConfigurationContainer oldParent) {
+ void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
final DisplayContent display = newParent != null
? ((WindowContainer) newParent).getDisplayContent() : null;
final DisplayContent oldDisplay = oldParent != null
? ((WindowContainer) oldParent).getDisplayContent() : null;
- mDisplayId = (display != null) ? display.mDisplayId : INVALID_DISPLAY;
- mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
-
- if (display != null) {
- // Rotations are relative to the display. This means if there are 2 displays rotated
- // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
- // from one to the other could look like a rotation change. To prevent this
- // apparent rotation change (and corresponding bounds rotation), pretend like our
- // current rotation is already the same as the new display.
- // Note, if ActivityStack or related logic ever gets nested, this logic will need
- // to move to onConfigurationChanged.
- getConfiguration().windowConfiguration.setRotation(
- display.getWindowConfiguration().getRotation());
- }
super.onParentChanged(newParent, oldParent);
- if (getParent() == null && mDisplayContent != null) {
- EventLogTags.writeWmStackRemoved(mStackId);
- mDisplayContent = null;
- mWmService.mWindowPlacerLocked.requestTraversal();
- }
- if (display != null && inSplitScreenPrimaryWindowingMode()) {
+
+ if (display != null && inSplitScreenPrimaryWindowingMode()
+ // only do this for the base stack
+ && !newParent.inSplitScreenPrimaryWindowingMode()) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
@@ -4164,7 +3965,6 @@
mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect,
mTmpRect2, null, null, PRESERVE_WINDOWS);
}
- mRootWindowContainer.updateUIDsPresentOnDisplay();
// Resume next focusable stack after reparenting to another display if we aren't removing
// the prevous display.
@@ -4178,68 +3978,6 @@
newParent.moveStackToDisplay(this, onTop);
}
- // TODO: We should really have users as a window container in the hierarchy so that we don't
- // have to do complicated things like we are doing in this method.
- int findPositionForTask(Task task, int targetPosition) {
- final boolean canShowTask = task.showToCurrentUser();
-
- final int stackSize = mChildren.size();
- int minPosition = 0;
- int maxPosition = stackSize - 1;
-
- if (canShowTask) {
- minPosition = computeMinPosition(minPosition, stackSize);
- } else {
- maxPosition = computeMaxPosition(maxPosition);
- }
-
- // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
- if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
- return POSITION_BOTTOM;
- } else if (targetPosition == POSITION_TOP && maxPosition == (stackSize - 1)) {
- return POSITION_TOP;
- }
- // Reset position based on minimum/maximum possible positions.
- return Math.min(Math.max(targetPosition, minPosition), maxPosition);
- }
-
- /** Calculate the minimum possible position for a task that can be shown to the user.
- * The minimum position will be above all other tasks that can't be shown.
- * @param minPosition The minimum position the caller is suggesting.
- * We will start adjusting up from here.
- * @param size The size of the current task list.
- */
- // TODO(task-hierarchy): Move user to their own window container.
- private int computeMinPosition(int minPosition, int size) {
- while (minPosition < size) {
- final Task tmpTask = (Task) mChildren.get(minPosition);
- final boolean canShowTmpTask = tmpTask.showToCurrentUser();
- if (canShowTmpTask) {
- break;
- }
- minPosition++;
- }
- return minPosition;
- }
-
- /** Calculate the maximum possible position for a task that can't be shown to the user.
- * The maximum position will be below all other tasks that can be shown.
- * @param maxPosition The maximum position the caller is suggesting.
- * We will start adjusting down from here.
- */
- // TODO(task-hierarchy): Move user to their own window container.
- private int computeMaxPosition(int maxPosition) {
- while (maxPosition > 0) {
- final Task tmpTask = (Task) mChildren.get(maxPosition);
- final boolean canShowTmpTask = tmpTask.showToCurrentUser();
- if (!canShowTmpTask) {
- break;
- }
- maxPosition--;
- }
- return maxPosition;
- }
-
private void updateSurfaceBounds() {
updateSurfaceSize(getPendingTransaction());
updateSurfacePosition();
@@ -4456,15 +4194,6 @@
false /* deferResume */);
}
- @Override
- void removeIfPossible() {
- if (isAnimating(TRANSITION | CHILDREN)) {
- mDeferRemoval = true;
- return;
- }
- removeImmediately();
- }
-
/**
* Adjusts the stack bounds if the IME is visible.
*
@@ -4568,12 +4297,14 @@
t.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
t.setWaitingForDrawnIfResizingChanged();
}
- });
+ }, true /* traverseTopToBottom */, this);
}
/** Resets the resizing state of all windows. */
void endImeAdjustAnimation() {
- forAllTasks((t) -> { t.setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER); });
+ forAllTasks((t) -> {
+ t.setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
+ }, true /* traverseTopToBottom */, this);
}
private int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
@@ -4751,14 +4482,6 @@
return mMinimizeAmount != 0f;
}
- /**
- * @return {@code true} if we have a {@link Task} that is animating (currently only used for the
- * recents animation); {@code false} otherwise.
- */
- boolean isTaskAnimating() {
- return getTask(Task::isTaskAnimating) != null;
- }
-
@Override
void dump(PrintWriter pw, String prefix, boolean dumpAll) {
pw.println(prefix + "mStackId=" + mStackId);
@@ -4792,11 +4515,6 @@
mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix);
}
- @Override
- boolean fillsParent() {
- return matchParentBounds();
- }
-
String getName() {
return toShortString();
}
@@ -4946,18 +4664,6 @@
}
}
- @Override
- protected void onAnimationFinished() {
- super.onAnimationFinished();
- // TODO(b/142617871): we may need to add animation type parameter on onAnimationFinished to
- // identify if the callback is for launch animation finish and then calling
- // activity#onAnimationFinished.
- final ActivityRecord activity = getTopMostActivity();
- if (activity != null) {
- activity.onAnimationFinished();
- }
- }
-
/**
* Sets the current picture-in-picture aspect ratio.
*/
@@ -5008,7 +4714,7 @@
/** Called immediately prior to resizing the tasks at the end of the pinned stack animation. */
void onPipAnimationEndResize() {
mBoundsAnimating = false;
- forAllTasks(Task::clearPreserveNonFloatingState, false);
+ forAllTasks(Task::clearPreserveNonFloatingState, false /* traverseTopToBottom */, this);
mWmService.requestTraversal();
}
@@ -5108,24 +4814,6 @@
}
@Override
- Dimmer getDimmer() {
- return mDimmer;
- }
-
- @Override
- void prepareSurfaces() {
- mDimmer.resetDimStates();
- super.prepareSurfaces();
- getDimBounds(mTmpDimBoundsRect);
-
- // Bounds need to be relative, as the dim layer is a child.
- mTmpDimBoundsRect.offsetTo(0, 0);
- if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
- scheduleAnimation();
- }
- }
-
- @Override
public boolean setPinnedStackAlpha(float alpha) {
// Hold the lock since this is called from the BoundsAnimator running on the UiThread
synchronized (mWmService.mGlobalLock) {
@@ -5144,49 +4832,10 @@
return mDisplayContent.getDisplayInfo();
}
- void dim(float alpha) {
- mDimmer.dimAbove(getPendingTransaction(), alpha);
- scheduleAnimation();
- }
-
- void stopDimming() {
- mDimmer.stopDim(getPendingTransaction());
- scheduleAnimation();
- }
-
AnimatingActivityRegistry getAnimatingActivityRegistry() {
return mAnimatingActivityRegistry;
}
- @Override
- void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
- Rect outSurfaceInsets) {
- final Task task = getTopMostTask();
- if (task != null) {
- task.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
- } else {
- super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
- }
- }
-
- @Override
- RemoteAnimationTarget createRemoteAnimationTarget(
- RemoteAnimationController.RemoteAnimationRecord record) {
- final Task task = getTopMostTask();
- return task != null ? task.createRemoteAnimationTarget(record) : null;
- }
-
- @Override
- public String toString() {
- return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
- + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType())
- + " mode=" + windowingModeToString(getWindowingMode())
- + " visible=" + shouldBeVisible(null /* starting */)
- + " translucent=" + isStackTranslucent(null /* starting */)
- + ", "
- + getChildCount() + " tasks}";
- }
-
void executeAppTransition(ActivityOptions options) {
getDisplay().mDisplayContent.executeAppTransition();
ActivityOptions.abort(options);
@@ -5209,6 +4858,7 @@
return shouldSleepActivities() || mAtmService.mShuttingDown;
}
+ @Override
public void dumpDebug(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
final long token = proto.start(fieldId);
@@ -5216,12 +4866,12 @@
proto.write(com.android.server.am.ActivityStackProto.ID, mStackId);
forAllTasks((t) -> {
- t.dumpDebug(proto, com.android.server.am.ActivityStackProto.TASKS, logLevel);
- });
+ t.dumpDebugInner(proto, com.android.server.am.ActivityStackProto.TASKS, logLevel);
+ }, true /* traverseTopToBottom */, this);
if (mResumedActivity != null) {
mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
}
- proto.write(DISPLAY_ID, mDisplayId);
+ proto.write(DISPLAY_ID, getDisplayId());
if (!matchParentBounds()) {
final Rect bounds = getRequestedOverrideBounds();
bounds.dumpDebug(proto, com.android.server.am.ActivityStackProto.BOUNDS);
@@ -5242,7 +4892,9 @@
final long token = proto.start(fieldId);
super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
proto.write(StackProto.ID, mStackId);
- forAllTasks((t) -> { t.dumpDebugInnerTaskOnly(proto, StackProto.TASKS, logLevel); });
+ forAllTasks((t) -> {
+ t.dumpDebugInnerTaskOnly(proto, StackProto.TASKS, logLevel);
+ }, true /* traverseTopToBottom */, this);
proto.write(FILLS_PARENT, matchParentBounds());
getRawBounds().dumpDebug(proto, StackProto.BOUNDS);
proto.write(DEFER_REMOVAL, mDeferRemoval);
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 8ef01e3..f2ce7e8 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -419,7 +419,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer(
MoveTaskToFullscreenHelper::processTask, this, PooledLambda.__(Task.class));
- fromStack.forAllTasks(c, false);
+ fromStack.forAllTasks(c, false /* traverseTopToBottom */, fromStack);
c.recycle();
mToDisplay = null;
mTopTask = null;
@@ -1724,7 +1724,7 @@
} else {
final PooledConsumer c = PooledLambda.obtainConsumer(
ActivityStackSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
- stack.forAllTasks(c);
+ stack.forAllTasks(c, true /* traverseTopToBottom */, stack);
c.recycle();
}
}
@@ -1849,14 +1849,14 @@
boolean restoreRecentTaskLocked(Task task, ActivityOptions aOptions, boolean onTop) {
final ActivityStack stack =
mRootWindowContainer.getLaunchStack(null, aOptions, task, onTop);
- final ActivityStack currentStack = task.getStack();
+ final WindowContainer parent = task.getParent();
- if (currentStack == stack) {
+ if (parent == stack) {
// Nothing else to do since it is already restored in the right stack.
return true;
}
- if (currentStack != null) {
+ if (parent != null) {
// Task has already been restored once. Just re-parent it to the new stack.
task.reparent(stack, POSITION_TOP, true /*moveParents*/, "restoreRecentTaskLocked");
return true;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 47e8b87..8491bc2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -306,7 +306,7 @@
*/
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_ATM;
- private static final String TAG_STACK = TAG + POSTFIX_STACK;
+ static final String TAG_STACK = TAG + POSTFIX_STACK;
static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
@@ -2057,8 +2057,9 @@
public int getDisplayId(IBinder activityToken) throws RemoteException {
synchronized (mGlobalLock) {
final ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
- if (stack != null && stack.getDisplayId() != INVALID_DISPLAY) {
- return stack.getDisplayId();
+ if (stack != null) {
+ final int displayId = stack.getDisplayId();
+ return displayId != INVALID_DISPLAY ? displayId : DEFAULT_DISPLAY;
}
return DEFAULT_DISPLAY;
}
@@ -3216,8 +3217,7 @@
final ActivityStack stack = r.getActivityStack();
final Task task = stack.createTask(
- mStackSupervisor.getNextTaskIdForUser(r.mUserId), ainfo, intent,
- null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
+ mStackSupervisor.getNextTaskIdForUser(r.mUserId), ainfo, intent, !ON_TOP);
if (!mRecentTasks.addToBottom(task)) {
// The app has too many tasks already and we can't add any more
stack.removeChild(task, "addAppTask");
@@ -4385,7 +4385,7 @@
if (params.hasSetAspectRatio()
&& !mWindowManager.isValidPictureInPictureAspectRatio(
- r.getDisplayId(), params.getAspectRatio())) {
+ r.getDisplay(), params.getAspectRatio())) {
final float minAspectRatio = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
final float maxAspectRatio = mContext.getResources().getFloat(
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 908c4f1..94c606b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -168,8 +168,10 @@
import android.app.ActivityOptions;
import android.app.WindowConfiguration;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
+import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
@@ -4241,7 +4243,7 @@
ArrayList<Task> getVisibleTasks() {
final ArrayList<Task> visibleTasks = new ArrayList<>();
forAllTasks(task -> {
- if (task.isVisible()) {
+ if (!task.isRootTask() && task.isVisible()) {
visibleTasks.add(task);
}
});
@@ -4260,36 +4262,48 @@
private void addStackReferenceIfNeeded(ActivityStack stack) {
if (stack.isActivityTypeHome()) {
if (mHomeStack != null) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
- + mHomeStack + " already exist on display=" + this + " stack=" + stack);
-
+ if (!stack.isDescendantOf(mHomeStack)) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ + mHomeStack + " already exist on display=" + this
+ + " stack=" + stack);
+ }
+ } else {
+ mHomeStack = stack;
}
- mHomeStack = stack;
} else if (stack.isActivityTypeRecents()) {
if (mRecentsStack != null && mRecentsStack != stack) {
- throw new IllegalArgumentException(
- "addStackReferenceIfNeeded: recents stack=" + mRecentsStack
- + " already exist on display=" + this + " stack=" + stack);
+ if (!stack.isDescendantOf(mRecentsStack)) {
+ throw new IllegalArgumentException(
+ "addStackReferenceIfNeeded: recents stack=" + mRecentsStack
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ } else {
+ mRecentsStack = stack;
}
- mRecentsStack = stack;
}
final int windowingMode = stack.getWindowingMode();
if (windowingMode == WINDOWING_MODE_PINNED) {
if (mPinnedStack != null) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
- + mPinnedStack + " already exist on display=" + this
- + " stack=" + stack);
+ if (!stack.isDescendantOf(mPinnedStack)) {
+ throw new IllegalArgumentException(
+ "addStackReferenceIfNeeded: pinned stack=" + mPinnedStack
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ } else {
+ mPinnedStack = stack;
}
- mPinnedStack = stack;
} else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
if (mSplitScreenPrimaryStack != null) {
- throw new IllegalArgumentException("addStackReferenceIfNeeded:"
- + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
- + " already exist on display=" + this + " stack=" + stack);
+ if (!stack.isDescendantOf(mSplitScreenPrimaryStack)) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded:"
+ + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ } else {
+ mSplitScreenPrimaryStack = stack;
+ mDisplayContent.onSplitScreenModeActivated();
+ mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
- mSplitScreenPrimaryStack = stack;
- mDisplayContent.onSplitScreenModeActivated();
- mDividerControllerLocked.notifyDockedStackExistsChanged(true);
}
}
@@ -5738,6 +5752,10 @@
return mAtmService.mStackSupervisor.getNextTaskIdForUser();
}
+ ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
+ return createStack(windowingMode, activityType, onTop, null /*info*/, null /*intent*/);
+ }
+
/**
* Creates a stack matching the input windowing mode and activity type on this display.
* @param windowingMode The windowing mode the stack should be created in. If
@@ -5749,13 +5767,14 @@
* @param onTop If true the stack will be created at the top of the display, else at the bottom.
* @return The newly created stack.
*/
- ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
+ ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
+ Intent intent) {
if (mSingleTaskInstance && getStackCount() > 0) {
// Create stack on default display instead since this display can only contain 1 stack.
// TODO: Kinda a hack, but better that having the decision at each call point. Hoping
// this goes away once ActivityView is no longer using virtual displays.
return mRootWindowContainer.getDefaultDisplay().createStack(
- windowingMode, activityType, onTop);
+ windowingMode, activityType, onTop, info, intent);
}
if (activityType == ACTIVITY_TYPE_UNDEFINED) {
@@ -5783,18 +5802,23 @@
}
final int stackId = getNextStackId();
- return createStackUnchecked(windowingMode, activityType, stackId, onTop);
+ return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent);
}
@VisibleForTesting
ActivityStack createStackUnchecked(int windowingMode, int activityType,
- int stackId, boolean onTop) {
+ int stackId, boolean onTop, ActivityInfo info, Intent intent) {
if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
+ "activity type.");
}
+ if (info == null) {
+ info = new ActivityInfo();
+ info.applicationInfo = new ApplicationInfo();
+ }
+
final ActivityStack stack = new ActivityStack(this, stackId,
- mRootWindowContainer.mStackSupervisor, activityType);
+ mRootWindowContainer.mStackSupervisor, activityType, info, intent);
addStack(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
stack.setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 5df80fc..e1dfc17 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -32,7 +32,6 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Process.SYSTEM_UID;
-import static android.view.Display.DEFAULT_DISPLAY;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
@@ -1382,7 +1381,7 @@
// Ignore tasks from different displays
// TODO (b/115289124): No Recents on non-default displays.
- if (stack.getDisplayId() != DEFAULT_DISPLAY) {
+ if (!stack.isOnHomeDisplay()) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index b255b5e..6148095 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -374,7 +374,7 @@
final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
{ if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
visibleTasks);
- targetStack.forAllTasks(c);
+ targetStack.forAllTasks(c, true /* traverseTopToBottom */, targetStack);
c.recycle();
}
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index e310fc1..2f61ca0 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -247,8 +247,7 @@
} else {
targetTask = mTargetStack.createTask(
atmService.mStackSupervisor.getNextTaskIdForUser(r.mUserId), r.info,
- null /* intent */, null /* voiceSession */, null /* voiceInteractor */,
- false /* toTop */);
+ null /* intent */, false /* toTop */);
targetTask.affinityIntent = r.intent;
createdTasks.add(targetTask);
if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2f726e9..aa4255f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2132,23 +2132,13 @@
// We will then perform a windowing mode change for both scenarios.
stack = display.createStack(
r.getActivityStack().getRequestedOverrideWindowingMode(),
- r.getActivityType(), ON_TOP);
+ r.getActivityType(), ON_TOP, r.info, r.intent);
// There are multiple activities in the task and moving the top activity should
// reveal/leave the other activities in their original task.
- // Currently, we don't support reparenting activities across tasks in two different
- // stacks, so instead, just create a new task in the same stack, reparent the
- // activity into that task, and then reparent the whole task to the new stack. This
- // ensures that all the necessary work to migrate states in the old and new stacks
- // is also done.
- final Task newTask = task.getStack().createTask(
- mStackSupervisor.getNextTaskIdForUser(r.mUserId), r.info,
- r.intent, null, null, true);
+ Task newTask = stack.createTask(mStackSupervisor.getNextTaskIdForUser(r.mUserId),
+ r.info, r.intent, true);
r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
-
- // Defer resume until below, and do not schedule PiP changes until we animate below
- newTask.reparent(stack, ON_TOP, REPARENT_MOVE_STACK_TO_FRONT, !ANIMATE,
- DEFER_RESUME, false /* schedulePictureInPictureModeChange */, reason);
}
stack.setWindowingMode(WINDOWING_MODE_PINNED);
@@ -2417,17 +2407,17 @@
info.position = display != null ? display.getIndexOf(stack) : 0;
info.configuration.setTo(stack.getConfiguration());
- final int numTasks = stack.getChildCount();
+ final int numTasks = stack.getDescendantTaskCount();
info.taskIds = new int[numTasks];
info.taskNames = new String[numTasks];
info.taskBounds = new Rect[numTasks];
info.taskUserIds = new int[numTasks];
- final int[] currenIndex = {0};
+ final int[] currentIndex = {0};
final PooledConsumer c = PooledLambda.obtainConsumer(
RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
- currenIndex);
- stack.forAllTasks(c, false);
+ currentIndex);
+ stack.forAllTasks(c, false /* traverseTopToBottom */, stack);
c.recycle();
final ActivityRecord top = stack.topRunningActivity();
@@ -2570,7 +2560,7 @@
}
ActivityStack findStackBehind(ActivityStack stack) {
- final DisplayContent display = getDisplayContent(stack.getDisplayId());
+ final DisplayContent display = stack.getDisplayContent();
if (display != null) {
for (int i = display.getStackCount() - 1; i >= 0; i--) {
if (display.getStackAt(i) == stack && i > 0) {
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 98127ab..6ebbf77 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -93,6 +93,9 @@
}
private void processTask(Task task) {
+ if (task.isRootTask()) {
+ return;
+ }
if (task.getTopNonFinishingActivity() == null) {
// Skip if there are no activities in the task
return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5cb7091..9fbef34 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -30,6 +30,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
@@ -69,6 +71,7 @@
import static com.android.server.am.TaskRecordProto.STACK_ID;
import static com.android.server.am.TaskRecordProto.TASK;
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
+import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
@@ -82,6 +85,7 @@
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS;
@@ -93,6 +97,7 @@
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
@@ -121,7 +126,6 @@
import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
-import android.os.Parcel;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -203,9 +207,9 @@
// Current version of the task record we persist. Used to check if we need to run any upgrade
// code.
- private static final int PERSIST_TASK_VERSION = 1;
+ static final int PERSIST_TASK_VERSION = 1;
- private static final int INVALID_MIN_SIZE = -1;
+ static final int INVALID_MIN_SIZE = -1;
/**
* The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
@@ -332,6 +336,8 @@
final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
final ActivityTaskManagerService mAtmService;
+ final ActivityStackSupervisor mStackSupervisor;
+ final RootWindowContainer mRootWindowContainer;
/* Unique identifier for this task. */
final int mTaskId;
@@ -346,8 +352,12 @@
// TODO(b/119687367): This member is temporary.
private final Rect mOverrideDisplayedBounds = new Rect();
+ // Id of the previous display the stack was on.
+ int mPrevDisplayId = INVALID_DISPLAY;
+
/** ID of the display which rotation {@link #mRotation} has. */
private int mLastRotationDisplayId = INVALID_DISPLAY;
+
/**
* Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
* moved to a new display.
@@ -389,8 +399,37 @@
private static Exception sTmpException;
+ /** ActivityRecords that are exiting, but still on screen for animations. */
+ final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
+
+ /**
+ * When we are in the process of pausing an activity, before starting the
+ * next one, this variable holds the activity that is currently being paused.
+ */
+ ActivityRecord mPausingActivity = null;
+
+ /**
+ * This is the last activity that we put into the paused state. This is
+ * used to determine if we need to do an activity transition while sleeping,
+ * when we normally hold the top activity paused.
+ */
+ ActivityRecord mLastPausedActivity = null;
+
+ /**
+ * Activities that specify No History must be removed once the user navigates away from them.
+ * If the device goes to sleep with such an activity in the paused state then we save it here
+ * and finish it later if another activity replaces it on wakeup.
+ */
+ ActivityRecord mLastNoHistoryActivity = null;
+
+ /** Current activity that is resumed, or null if there is none. */
+ ActivityRecord mResumedActivity = null;
+
private boolean mForceShowForAllUsers;
+ /** When set, will force the task to report as invisible. */
+ boolean mForceHidden = false;
+
private final FindRootHelper mFindRootHelper = new FindRootHelper();
private class FindRootHelper {
private ActivityRecord mRoot;
@@ -489,6 +528,8 @@
EventLogTags.writeWmTaskCreated(_taskId, stack != null ? stack.mStackId : INVALID_STACK_ID);
mAtmService = atmService;
+ mStackSupervisor = atmService.mStackSupervisor;
+ mRootWindowContainer = mAtmService.mRootWindowContainer;
mTaskId = _taskId;
mUserId = _userId;
mResizeMode = resizeMode;
@@ -552,7 +593,7 @@
if (autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
- mAtmService.mStackSupervisor.mRecentTasks.remove(this);
+ mStackSupervisor.mRecentTasks.remove(this);
}
removeIfPossible();
@@ -561,13 +602,18 @@
@VisibleForTesting
@Override
void removeIfPossible() {
- mAtmService.getLockTaskController().clearLockedTask(this);
+ final boolean isRootTask = isRootTask();
+ if (!isRootTask) {
+ mAtmService.getLockTaskController().clearLockedTask(this);
+ }
if (shouldDeferRemoval()) {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
return;
}
removeImmediately();
- mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
+ if (!isRootTask) {
+ mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
+ }
}
void setResizeMode(int resizeMode) {
@@ -575,8 +621,8 @@
return;
}
mResizeMode = resizeMode;
- mAtmService.mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
- mAtmService.mRootWindowContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
updateTaskDescription();
}
@@ -593,7 +639,7 @@
setBounds(bounds);
if (!inFreeformWindowingMode()) {
// re-restore the task so it can have the proper stack association.
- mAtmService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
+ mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
}
return true;
}
@@ -629,10 +675,9 @@
// this won't cause tons of irrelevant windows being preserved because only
// activities in this task may experience a bounds change. Configs for other
// activities stay the same.
- mAtmService.mRootWindowContainer.ensureActivitiesVisible(r, 0,
- preserveWindow);
+ mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
if (!kept) {
- mAtmService.mRootWindowContainer.resumeFocusedStacksTopActivities();
+ mRootWindowContainer.resumeFocusedStacksTopActivities();
}
}
}
@@ -696,8 +741,8 @@
boolean reparent(ActivityStack preferredStack, int position,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
- final ActivityStackSupervisor supervisor = mAtmService.mStackSupervisor;
- final RootWindowContainer root = mAtmService.mRootWindowContainer;
+ final ActivityStackSupervisor supervisor = mStackSupervisor;
+ final RootWindowContainer root = mRootWindowContainer;
final WindowManagerService windowManager = mAtmService.mWindowManager;
final ActivityStack sourceStack = getStack();
final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
@@ -766,7 +811,7 @@
wasPaused, reason);
}
if (!animate) {
- mAtmService.mStackSupervisor.mNoAnimActivities.add(topActivity);
+ mStackSupervisor.mNoAnimActivities.add(topActivity);
}
// We might trigger a configuration change. Save the current task bounds for freezing.
@@ -785,7 +830,7 @@
} else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Rect bounds = getLaunchBounds();
if (bounds == null) {
- mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
+ mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
bounds = configBounds;
}
kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
@@ -793,7 +838,7 @@
if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
// Move recents to front so it is not behind home stack when going into docked
// mode
- mAtmService.mStackSupervisor.moveRecentsStackToFront(reason);
+ mStackSupervisor.moveRecentsStackToFront(reason);
}
kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
!mightReplaceWindow, deferResume);
@@ -859,6 +904,14 @@
mCallingPackage = r.launchedFromPackage;
setIntent(r.intent, r.info);
setLockTaskAuth(r);
+
+ final WindowContainer parent = getParent();
+ if (parent != null) {
+ final Task t = parent.asTask();
+ if (t != null) {
+ t.setIntent(r);
+ }
+ }
}
/** Sets the original intent, _without_ updating the calling uid or package. */
@@ -972,8 +1025,13 @@
}
boolean returnsToHomeStack() {
- final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
- return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
+ if (inMultiWindowMode() || !hasChild()) return false;
+ if (intent != null) {
+ final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
+ return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
+ }
+ final Task bottomTask = getBottomMostTask();
+ return bottomTask != this && bottomTask.returnsToHomeStack();
}
void setPrevAffiliate(Task prevAffiliate) {
@@ -988,37 +1046,72 @@
@Override
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
- final ActivityStack oldStack = ((ActivityStack) oldParent);
- final ActivityStack newStack = ((ActivityStack) newParent);
+ final DisplayContent display = newParent != null
+ ? ((WindowContainer) newParent).getDisplayContent() : null;
+ final DisplayContent oldDisplay = oldParent != null
+ ? ((WindowContainer) oldParent).getDisplayContent() : null;
+
+ mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
// Task is going to be removed, clean it up before detaching from hierarchy.
if (oldParent != null && newParent == null) {
cleanUpResourcesForDestroy();
}
+ if (display != null) {
+ // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
+ // Rotations are relative to the display. This means if there are 2 displays rotated
+ // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
+ // from one to the other could look like a rotation change. To prevent this
+ // apparent rotation change (and corresponding bounds rotation), pretend like our
+ // current rotation is already the same as the new display.
+ // Note, if ActivityStack or related logic ever gets nested, this logic will need
+ // to move to onConfigurationChanged.
+ getConfiguration().windowConfiguration.setRotation(
+ display.getWindowConfiguration().getRotation());
+ }
+
super.onParentChanged(newParent, oldParent);
- if (oldStack != null) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- ActivityStack::onActivityRemovedFromStack, oldStack,
- PooledLambda.__(ActivityRecord.class));
- forAllActivities(c);
- c.recycle();
+ // TODO(NOW): The check for null display content and setting it to null doesn't really
+ // make sense here...
- if (oldStack.inPinnedWindowingMode()
- && (newStack == null || !newStack.inPinnedWindowingMode())) {
+ // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
+ // the display, so we should probably consolidate it there instead.
+
+ if (getParent() == null && mDisplayContent != null) {
+ EventLogTags.writeWmStackRemoved(getStackId());
+ mDisplayContent = null;
+ mWmService.mWindowPlacerLocked.requestTraversal();
+ }
+
+ if (oldParent != null) {
+ final Task oldParentTask = ((WindowContainer) oldParent).asTask();
+ if (oldParentTask != null) {
+ final PooledConsumer c = PooledLambda.obtainConsumer(
+ Task::cleanUpActivityReferences, oldParentTask,
+ PooledLambda.__(ActivityRecord.class));
+ forAllActivities(c);
+ c.recycle();
+ }
+
+ if (oldParent.inPinnedWindowingMode()
+ && (newParent == null || !newParent.inPinnedWindowingMode())) {
// Notify if a task from the pinned stack is being removed
// (or moved depending on the mode).
mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
}
}
- if (newStack != null) {
- final PooledConsumer c = PooledLambda.obtainConsumer(
- ActivityStack::onActivityAddedToStack, newStack,
- PooledLambda.__(ActivityRecord.class));
- forAllActivities(c);
- c.recycle();
+ if (newParent != null) {
+ final Task newParentTask = ((WindowContainer) newParent).asTask();
+ if (newParentTask != null) {
+ final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
+ false /* includeOverlays */);
+ if (top != null && top.isState(RESUMED)) {
+ newParentTask.setResumedActivity(top, "addedToTask");
+ }
+ }
// TODO: Ensure that this is actually necessary here
// Notify the voice session if required
@@ -1049,7 +1142,41 @@
forceWindowsScaleable(false /* force */);
}
- mAtmService.mRootWindowContainer.updateUIDsPresentOnDisplay();
+ mRootWindowContainer.updateUIDsPresentOnDisplay();
+ }
+
+ void cleanUpActivityReferences(ActivityRecord r) {
+ final WindowContainer parent = getParent();
+ if (parent != null && parent.asTask() != null) {
+ parent.asTask().cleanUpActivityReferences(r);
+ return;
+ }
+ r.removeTimeouts();
+ mExitingActivities.remove(r);
+
+ if (mResumedActivity != null && mResumedActivity == r) {
+ setResumedActivity(null, "cleanUpActivityReferences");
+ }
+ if (mPausingActivity != null && mPausingActivity == r) {
+ mPausingActivity = null;
+ }
+ }
+
+ /** @return the currently resumed activity. */
+ ActivityRecord getResumedActivity() {
+ return mResumedActivity;
+ }
+
+ void setResumedActivity(ActivityRecord r, String reason) {
+ if (mResumedActivity == r) {
+ return;
+ }
+
+ if (ActivityTaskManagerDebugConfig.DEBUG_STACK) Slog.d(TAG_STACK,
+ "setResumedActivity stack:" + this + " + from: "
+ + mResumedActivity + " to:" + r + " reason:" + reason);
+ mResumedActivity = r;
+ mStackSupervisor.updateTopResumedActivityIfNeeded();
}
void updateTaskMovement(boolean toFront) {
@@ -1062,7 +1189,7 @@
mLastTimeMoved *= -1;
}
}
- mAtmService.mRootWindowContainer.invalidateTaskLayers();
+ mRootWindowContainer.invalidateTaskLayers();
}
// Close up recents linked list.
@@ -1115,7 +1242,11 @@
/** Returns the intent for the root activity for this task */
Intent getBaseIntent() {
- return intent != null ? intent : affinityIntent;
+ if (intent != null) return intent;
+ if (affinityIntent != null) return affinityIntent;
+ // Probably a task that contains other tasks, so return the intent for the top task?
+ final Task topTask = getTopMostTask();
+ return topTask != null ? topTask.getBaseIntent() : null;
}
/** Returns the first non-finishing activity from the bottom. */
@@ -1200,11 +1331,18 @@
// If this task had any child before we added this one.
boolean hadChild = hasChild();
- final ActivityRecord r = (ActivityRecord) child;
- index = getAdjustedAddPosition(r, index);
- super.addChild(r, index);
+ index = getAdjustedChildPosition(child, index);
+ super.addChild(child, index);
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
+
+ // Make sure the list of display UID whitelists is updated
+ // now that this record is in a new task.
+ mRootWindowContainer.updateUIDsPresentOnDisplay();
+
+ final ActivityRecord r = child.asActivityRecord();
+ if (r == null) return;
+
r.inHistory = true;
// Only set this based on the first activity
@@ -1229,10 +1367,6 @@
}
updateEffectiveIntent();
-
- // Make sure the list of display UID whitelists is updated
- // now that this record is in a new task.
- mAtmService.mRootWindowContainer.updateUIDsPresentOnDisplay();
}
void addChild(ActivityRecord r) {
@@ -1240,12 +1374,19 @@
}
@Override
- void removeChild(WindowContainer r) {
+ void removeChild(WindowContainer child) {
+ removeChild(child, "removeChild");
+ }
+
+ void removeChild(WindowContainer r, String reason) {
if (!mChildren.contains(r)) {
Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
return;
}
+ if (DEBUG_TASK_MOVEMENT) {
+ Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
+ }
super.removeChild(r);
if (inPinnedWindowingMode()) {
@@ -1255,7 +1396,15 @@
mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
}
- final String reason = "removeChild";
+ final boolean isRootTask = isRootTask();
+ if (isRootTask) {
+ final DisplayContent display = getDisplayContent();
+ if (display.isSingleTaskInstance()) {
+ mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
+ }
+ display.mDisplayContent.setLayoutNeeded();
+ }
+
if (hasChild()) {
updateEffectiveIntent();
@@ -1270,12 +1419,14 @@
// work.
// TODO: If the callers to removeChild() changes such that we have multiple places
// where we are destroying the task, move this back into removeChild()
- mAtmService.mStackSupervisor.removeTask(this, false /* killProcess */,
+ mStackSupervisor.removeTask(this, false /* killProcess */,
!REMOVE_FROM_RECENTS, reason);
}
} else if (!mReuseTask) {
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
- getStack().removeChild(this, reason);
+ if (!isRootTask) {
+ getStack().removeChild(this, reason);
+ }
EventLogTags.writeWmTaskRemoved(mTaskId,
"removeChild: last r=" + r + " in t=" + this);
removeIfPossible();
@@ -1446,11 +1597,15 @@
@Override
public boolean supportsSplitScreenWindowingMode() {
+ final Task topTask = getTopMostTask();
+ return super.supportsSplitScreenWindowingMode()
+ && (topTask == null || topTask.supportsSplitScreenWindowingModeInner());
+ }
+
+ private boolean supportsSplitScreenWindowingModeInner() {
// A task can not be docked even if it is considered resizeable because it only supports
// picture-in-picture mode but has a non-resizeable resizeMode
return super.supportsSplitScreenWindowingMode()
- // TODO(task-group): Probably makes sense to move this and associated code into
- // WindowContainer so it affects every node.
&& mAtmService.mSupportsSplitScreenMultiWindow
&& (mAtmService.mForceResizableActivities
|| (isResizeable(false /* checkSupportsPip */)
@@ -1465,7 +1620,7 @@
* secondary display.
*/
boolean canBeLaunchedOnDisplay(int displayId) {
- return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
+ return mStackSupervisor.canPlaceEntityOnDisplay(displayId,
-1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
}
@@ -1535,6 +1690,14 @@
}
mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
getTaskInfo());
+
+ final WindowContainer parent = getParent();
+ if (parent != null) {
+ final Task t = parent.asTask();
+ if (t != null) {
+ t.updateTaskDescription();
+ }
+ }
}
private static boolean setTaskDescriptionFromActivityAboveRoot(
@@ -1577,9 +1740,11 @@
@VisibleForTesting
void updateEffectiveIntent() {
final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
- setIntent(root);
- // Update the task description when the activities change
- updateTaskDescription();
+ if (root != null) {
+ setIntent(root);
+ // Update the task description when the activities change
+ updateTaskDescription();
+ }
}
void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
@@ -1593,9 +1758,8 @@
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (!inPinnedWindowingMode() && getDisplayContent() != null) {
- final int defaultMinSizeDp =
- mAtmService.mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
+ if (!inPinnedWindowingMode() && getStack() != null) {
+ final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
final DisplayContent display = getDisplayContent();
final float density =
(float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
@@ -1659,10 +1823,25 @@
* @param reason The reason for the change.
*/
void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
- final ActivityStack parent = getStack();
+ final Task parentTask = getParent().asTask();
+ if (parentTask != null) {
+ parentTask.onActivityStateChanged(record, state, reason);
+ return;
+ }
- if (parent != null) {
- parent.onActivityStateChanged(record, state, reason);
+ if (record == mResumedActivity && state != RESUMED) {
+ setResumedActivity(null, reason + " - onActivityStateChanged");
+ }
+
+ if (state == RESUMED) {
+ if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
+ Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason);
+ }
+ setResumedActivity(record, reason + " - onActivityStateChanged");
+ if (record == mRootWindowContainer.getTopResumedActivity()) {
+ mAtmService.setResumedActivityUncheckLocked(record, reason);
+ }
+ mStackSupervisor.mRecentTasks.add(record.getTask());
}
}
@@ -1684,7 +1863,7 @@
final boolean wasInMultiWindowMode = inMultiWindowMode();
super.onConfigurationChanged(newParentConfig);
if (wasInMultiWindowMode != inMultiWindowMode()) {
- mAtmService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
+ mStackSupervisor.scheduleUpdateMultiWindowMode(this);
}
// If the configuration supports persistent bounds (eg. Freeform), keep track of the
@@ -1725,7 +1904,7 @@
}
// Saves the new state so that we can launch the activity at the same location.
- mAtmService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
+ mStackSupervisor.mLaunchParamsPersister.saveTask(this);
}
/**
@@ -1987,6 +2166,10 @@
@Override
void resolveOverrideConfiguration(Configuration newParentConfig) {
+ if (isRootTask()) {
+ super.resolveOverrideConfiguration(newParentConfig);
+ return;
+ }
mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
super.resolveOverrideConfiguration(newParentConfig);
int windowingMode =
@@ -2011,12 +2194,12 @@
final Rect parentBounds =
new Rect(newParentConfig.windowConfiguration.getBounds());
final DisplayContent display = getDisplayContent();
- if (display != null && display.mDisplayContent != null) {
+ if (display != null) {
// If a freeform window moves below system bar, there is no way to move it again
// by touch. Because its caption is covered by system bar. So we exclude them
// from stack bounds. and then caption will be shown inside stable area.
final Rect stableBounds = new Rect();
- display.mDisplayContent.getStableRect(stableBounds);
+ display.getStableRect(stableBounds);
parentBounds.intersect(stableBounds);
}
@@ -2091,6 +2274,7 @@
* input stack. */
void updateOverrideConfigurationForStack(ActivityStack inStack) {
final ActivityStack stack = getStack();
+
if (stack != null && stack == inStack) {
return;
}
@@ -2106,7 +2290,7 @@
if (mLastNonFullscreenBounds != null) {
setBounds(mLastNonFullscreenBounds);
} else {
- mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
+ mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
}
} else {
setBounds(inStack.getRequestedOverrideBounds());
@@ -2149,7 +2333,10 @@
@Override
DisplayContent getDisplayContent() {
- return getStack() != null ? getStack().getDisplayContent() : null;
+ // TODO: Why aren't we just using our own display content vs. parent's???
+ final ActivityStack stack = getStack();
+ return stack != null && stack != this
+ ? stack.getDisplayContent() : super.getDisplayContent();
}
int getDisplayId() {
@@ -2158,7 +2345,8 @@
}
ActivityStack getStack() {
- return (ActivityStack) getParent();
+ final WindowContainer parent = getParent();
+ return (ActivityStack) (parent instanceof ActivityStack ? parent : this);
}
/**
@@ -2169,27 +2357,99 @@
return stack != null ? stack.mStackId : INVALID_STACK_ID;
}
- // TODO(task-hierarchy): Needs to take a generic WindowManager when task contains other tasks.
- int getAdjustedAddPosition(ActivityRecord r, int suggestedPosition) {
- int maxPosition = mChildren.size();
- if (!r.isTaskOverlay()) {
- // We want to place all non-overlay activities below overlays.
- final ActivityRecord bottomMostOverlay = getActivity((ar) -> ar.isTaskOverlay(), false);
- if (bottomMostOverlay != null) {
- maxPosition = Math.max(mChildren.indexOf(bottomMostOverlay) - 1, 0);
+ int getDescendantTaskCount() {
+ final int[] currentCount = {0};
+ final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
+ PooledLambda.__(Task.class), currentCount);
+ forAllTasks(c, false /* traverseTopToBottom */, this);
+ c.recycle();
+ return currentCount[0];
+ }
+
+ /** Calculate the minimum possible position for a task that can be shown to the user.
+ * The minimum position will be above all other tasks that can't be shown.
+ * @param minPosition The minimum position the caller is suggesting.
+ * We will start adjusting up from here.
+ * @param size The size of the current task list.
+ */
+ // TODO: Move user to their own window container.
+ private int computeMinUserPosition(int minPosition, int size) {
+ while (minPosition < size) {
+ final WindowContainer child = mChildren.get(minPosition);
+ final boolean canShow = child.showToCurrentUser();
+ if (canShow) {
+ break;
+ }
+ minPosition++;
+ }
+ return minPosition;
+ }
+
+ /** Calculate the maximum possible position for a task that can't be shown to the user.
+ * The maximum position will be below all other tasks that can be shown.
+ * @param maxPosition The maximum position the caller is suggesting.
+ * We will start adjusting down from here.
+ */
+ // TODO: Move user to their own window container.
+ private int computeMaxUserPosition(int maxPosition) {
+ while (maxPosition > 0) {
+ final WindowContainer child = mChildren.get(maxPosition);
+ final boolean canShow = child.showToCurrentUser();
+ if (!canShow) {
+ break;
+ }
+ maxPosition--;
+ }
+ return maxPosition;
+ }
+
+ private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
+ final boolean canShowChild = wc.showToCurrentUser();
+
+ final int size = mChildren.size();
+
+ // Figure-out min/max possible position depending on if child can show for current user.
+ int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
+ int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
+
+ // Factor in always-on-top children in max possible position.
+ if (!wc.isAlwaysOnTop()) {
+
+ // We want to place all non-always-on-top containers below always-on-top ones.
+ while (maxPosition > minPosition) {
+ if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
+ --maxPosition;
}
}
- return Math.min(maxPosition, suggestedPosition);
+ // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
+ if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
+ return POSITION_BOTTOM;
+ } else if (suggestedPosition == POSITION_TOP && maxPosition == (size - 1)) {
+ return POSITION_TOP;
+ }
+ // Reset position based on minimum/maximum possible positions.
+ return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
}
@Override
void positionChildAt(int position, WindowContainer child, boolean includingParents) {
- position = getAdjustedAddPosition((ActivityRecord) child, position);
+ position = getAdjustedChildPosition(child, position);
super.positionChildAt(position, child, includingParents);
+
+ // Log positioning.
+ if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
+ + " position=" + position + " parent=" + this);
+
+ final int toTop = position >= (mChildren.size() - 1) ? 1 : 0;
+ final Task task = child.asTask();
+ if (task != null) {
+ EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position);
+ }
}
- private boolean hasWindowsAlive() {
+ @VisibleForTesting
+ boolean hasWindowsAlive() {
return getActivity(ActivityRecord::hasWindowsAlive) != null;
}
@@ -2219,8 +2479,6 @@
+ " from stack=" + getStack());
EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
- position = stack.findPositionForTask(this, position);
-
reparent(stack, position);
stack.positionChildAt(position, this, moveParents);
@@ -2286,11 +2544,16 @@
@Override
void onDisplayChanged(DisplayContent dc) {
- adjustBoundsForDisplayChangeIfNeeded(dc);
+ final boolean isRootTask = isRootTask();
+ if (!isRootTask) {
+ adjustBoundsForDisplayChangeIfNeeded(dc);
+ }
super.onDisplayChanged(dc);
- final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
- mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
- mTaskId, displayId);
+ if (!isRootTask) {
+ final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
+ mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
+ mTaskId, displayId);
+ }
}
/**
@@ -2432,7 +2695,7 @@
}
/** Bounds of the task to be used for dimming, as well as touch related tests. */
- public void getDimBounds(Rect out) {
+ void getDimBounds(Rect out) {
final DisplayContent displayContent = getStack().getDisplayContent();
// It doesn't matter if we in particular are part of the resize, since we couldn't have
// a DimLayer anyway if we weren't visible.
@@ -2565,6 +2828,11 @@
mForceShowForAllUsers = forceShowForAllUsers;
}
+ public boolean isAttached() {
+ final DisplayContent display = getDisplayContent();
+ return display != null && !display.isRemoved();
+ }
+
/**
* When we are in a floating stack (Freeform, Pinned, ...) we calculate
* insets differently. However if we are animating to the fullscreen stack
@@ -2576,6 +2844,45 @@
&& !getStack().isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
}
+ /**
+ * Returns true if the stack is translucent and can have other contents visible behind it if
+ * needed. A stack is considered translucent if it don't contain a visible or
+ * starting (about to be visible) activity that is fullscreen (opaque).
+ * @param starting The currently starting activity or null if there is none.
+ */
+ @VisibleForTesting
+ boolean isTranslucent(ActivityRecord starting) {
+ if (!isAttached() || mForceHidden) {
+ return true;
+ }
+ final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
+ PooledLambda.__(ActivityRecord.class), starting);
+ final ActivityRecord opaque = getActivity(p);
+ p.recycle();
+ return opaque == null;
+ }
+
+ private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
+ if (r.finishing) {
+ // We don't factor in finishing activities when determining translucency since
+ // they will be gone soon.
+ return false;
+ }
+
+ if (!r.visibleIgnoringKeyguard && r != starting) {
+ // Also ignore invisible activities that are not the currently starting
+ // activity (about to be visible).
+ return false;
+ }
+
+ if (r.occludesParent() || r.hasWallpaper) {
+ // Stack isn't translucent if it has at least one fullscreen activity
+ // that is visible.
+ return true;
+ }
+ return false;
+ }
+
@Override
public SurfaceControl getAnimationLeashParent() {
if (WindowManagerService.sHierarchicalAnimations) {
@@ -2639,7 +2946,7 @@
return true;
}
}
- return false;
+ return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
}
/**
@@ -2715,26 +3022,45 @@
return mTaskDescription;
}
+ // TODO(task-merge): Figure out what's the right thing to do for places that used it.
+ boolean isRootTask() {
+ return getParent() == null || getParent().asTask() == null;
+ }
+
@Override
boolean fillsParent() {
- return matchParentBounds() || !getWindowConfiguration().canResizeTask();
+ return matchParentBounds();
+ }
+
+ void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom, Task excludedTask) {
+ if (traverseTopToBottom) {
+ super.forAllTasks(callback, traverseTopToBottom);
+ if (excludedTask != this) {
+ callback.accept(this);
+ }
+ } else {
+ super.forAllTasks(callback, traverseTopToBottom);
+ if (excludedTask != this) {
+ callback.accept(this);
+ }
+ }
}
@Override
void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
- // TODO(task-hierarchy): Change to traverse children when tasks can contain other tasks.
- callback.accept(this);
+ forAllTasks(callback, traverseTopToBottom, null /* excludedTask */);
}
@Override
boolean forAllTasks(Function<Task, Boolean> callback) {
+ if (super.forAllTasks(callback)) return true;
return callback.apply(this);
}
@Override
Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
- // I'm a task!
- // TODO(task-hierarchy): Change to traverse children when tasks can contain other tasks.
+ final Task t = super.getTask(callback, traverseTopToBottom);
+ if (t != null) return t;
return callback.test(this) ? this : null;
}
@@ -2770,6 +3096,16 @@
return mDimmer;
}
+ void dim(float alpha) {
+ mDimmer.dimAbove(getPendingTransaction(), alpha);
+ scheduleAnimation();
+ }
+
+ void stopDimming() {
+ mDimmer.stopDim(getPendingTransaction());
+ scheduleAnimation();
+ }
+
boolean isTaskForUser(int userId) {
return mUserId == userId;
}
@@ -2817,7 +3153,7 @@
}
@Override
- public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
+ void dump(PrintWriter pw, String prefix, boolean dumpAll) {
super.dump(pw, prefix, dumpAll);
final String doublePrefix = prefix + " ";
@@ -2877,6 +3213,17 @@
return mTaskId == taskId;
}
+ @Override
+ Task asTask() {
+ // I'm a task!
+ return this;
+ }
+
+ // TODO(task-merge): Figure-out how this should work with hierarchy tasks.
+ boolean shouldBeVisible(ActivityRecord starting) {
+ return true;
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("userId="); pw.print(mUserId);
pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
@@ -2963,7 +3310,7 @@
if (mRootProcess != null) {
pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
}
- pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
+ pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getStackId());
pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
@@ -2990,6 +3337,10 @@
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(" #");
sb.append(mTaskId);
+ sb.append(" visible=" + shouldBeVisible(null /* starting */));
+ sb.append(" type=" + activityTypeToString(getActivityType()));
+ sb.append(" mode=" + windowingModeToString(getWindowingMode()));
+ sb.append(" translucent=" + isTranslucent(null /* starting */));
if (affinity != null) {
sb.append(" A=");
sb.append(affinity);
@@ -3006,8 +3357,7 @@
return toString();
}
- @Override
- public void dumpDebug(ProtoOutputStream proto, long fieldId,
+ void dumpDebugInner(ProtoOutputStream proto, long fieldId,
@WindowTraceLogLevel int logLevel) {
if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
return;
@@ -3218,13 +3568,13 @@
Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor, ActivityStack stack) {
- return new Task(service, taskId, info, intent, voiceSession, voiceInteractor,
+ return new ActivityStack(service, taskId, info, intent, voiceSession, voiceInteractor,
null /*taskDescription*/, stack);
}
Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Intent intent, TaskDescription taskDescription, ActivityStack stack) {
- return new Task(service, taskId, info, intent, null /*voiceSession*/,
+ return new ActivityStack(service, taskId, info, intent, null /*voiceSession*/,
null /*voiceInteractor*/, taskDescription, stack);
}
@@ -3241,7 +3591,7 @@
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
- return new Task(service, taskId, intent, affinityIntent, affinity,
+ return new ActivityStack(service, taskId, intent, affinityIntent, affinity,
rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
askedCompatMode, userId, effectiveUid, lastDescription,
lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
@@ -3483,7 +3833,9 @@
}
boolean isControlledByTaskOrganizer() {
- return mTaskOrganizer != null;
+ // TODO(b/147849315): Clean-up relationship between task-org and task-hierarchy. Ideally
+ // we only give control of the root task.
+ return getTopMostTask().mTaskOrganizer != null;
}
@Override
@@ -3559,13 +3911,16 @@
public void setWindowingMode(int windowingMode) {
super.setWindowingMode(windowingMode);
windowingMode = getWindowingMode();
- /*
- * Different windowing modes may be managed by different task organizers. If
- * getTaskOrganizer returns null, we still call transferToTaskOrganizer to
- * make sure we clear it.
- */
- final ITaskOrganizer org =
- mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
- setTaskOrganizer(org);
+
+ // TODO(b/147849315): Clean-up relationship between task-org and task-hierarchy. Ideally
+ // we only give control of the root task.
+ // Different windowing modes may be managed by different task organizers. If
+ // getTaskOrganizer returns null, we still call transferToTaskOrganizer to make sure we
+ // clear it.
+ if (!isRootTask()) {
+ final ITaskOrganizer org =
+ mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
+ setTaskOrganizer(org);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 3b2d519..c94b8c9 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -562,6 +562,13 @@
return false;
}
+ /** @return true if this window container is a descendant of the input container. */
+ boolean isDescendantOf(WindowContainer ancestor) {
+ final WindowContainer parent = getParent();
+ if (parent == ancestor) return true;
+ return (parent != null) && parent.isDescendantOf(ancestor);
+ }
+
/**
* Move a child from it's current place in siblings list to the specified position,
* with an option to move all its parents to top.
@@ -2235,4 +2242,14 @@
void setSurfaceControl(SurfaceControl sc) {
mSurfaceControl = sc;
}
+
+ /** Cheap way of doing cast and instanceof. */
+ Task asTask() {
+ return null;
+ }
+
+ /** Cheap way of doing cast and instanceof. */
+ ActivityRecord asActivityRecord() {
+ return null;
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e3b593e9..faad17b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2692,8 +2692,7 @@
displayContent.getDockedDividerController().checkMinimizeChanged(animate);
}
- boolean isValidPictureInPictureAspectRatio(int displayId, float aspectRatio) {
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+ boolean isValidPictureInPictureAspectRatio(DisplayContent displayContent, float aspectRatio) {
return displayContent.getPinnedStackController().isValidPictureInPictureAspectRatio(
aspectRatio);
}
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 2a1e980..70774c8 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -228,12 +228,6 @@
return false;
}
- ActivityRecord asActivityRecord() {
- // TODO: Not sure if this is the best way to handle this vs. using instanceof and casting.
- // I am not an app window token!
- return null;
- }
-
@Override
void removeImmediately() {
if (mDisplayContent != null) {