Clean-up ActivityRecord reparenting/adding to Task (57/n)
- Updated Configuration#onParentChanged to take params newParent and oldParent to make logic of reparenting less complex to deal with in classes that extend. - Introduced WindowContainer#reparent to consolidate reparenting logic and also allow us to only set onParentChanged once for the operation. - Simplfied logic flow around adding/remove/reparenting activity to task by using methods like addChild(), onChildAdded(), and such. - Removed Task.mDeferRemoval which no longer makes sense and was leading to task and stack leaks. Bug: 80414790 Test: Existing tests pass Change-Id: I4ffa79a1c731dc137213bdd3d7f04b8f013decc4
This commit is contained in:
@@ -216,7 +216,8 @@ message TaskProto {
|
||||
optional bool fills_parent = 4;
|
||||
optional .android.graphics.RectProto bounds = 5;
|
||||
optional .android.graphics.RectProto displayed_bounds = 6;
|
||||
optional bool defer_removal = 7;
|
||||
// Will be removed soon.
|
||||
optional bool defer_removal = 7 [deprecated=true];
|
||||
optional int32 surface_width = 8;
|
||||
optional int32 surface_height = 9;
|
||||
}
|
||||
|
||||
@@ -817,12 +817,6 @@
|
||||
"group": "WM_DEBUG_ORIENTATION",
|
||||
"at": "com\/android\/server\/wm\/DisplayRotation.java"
|
||||
},
|
||||
"-415912575": {
|
||||
"message": "setTask: %s at top.",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"-415865166": {
|
||||
"message": "findFocusedWindow: Found new focus @ %s",
|
||||
"level": "VERBOSE",
|
||||
@@ -883,6 +877,12 @@
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/WindowState.java"
|
||||
},
|
||||
"-303497363": {
|
||||
"message": "reparent: moving activity=%s to task=%d at %d",
|
||||
"level": "INFO",
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"-253016819": {
|
||||
"message": "applyAnimation: transition animation is disabled or skipped. atoken=%s",
|
||||
"level": "VERBOSE",
|
||||
@@ -1237,12 +1237,6 @@
|
||||
"group": "WM_DEBUG_FOCUS_LIGHT",
|
||||
"at": "com\/android\/server\/wm\/WindowManagerService.java"
|
||||
},
|
||||
"393054329": {
|
||||
"message": "reParentWindowToken: removing window token=%s from task=%s",
|
||||
"level": "INFO",
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"399841913": {
|
||||
"message": "SURFACE RECOVER DESTROY: %s",
|
||||
"level": "INFO",
|
||||
@@ -1351,6 +1345,12 @@
|
||||
"group": "WM_SHOW_TRANSACTIONS",
|
||||
"at": "com\/android\/server\/wm\/Session.java"
|
||||
},
|
||||
"609651209": {
|
||||
"message": "addChild: %s at top.",
|
||||
"level": "VERBOSE",
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/TaskRecord.java"
|
||||
},
|
||||
"620368427": {
|
||||
"message": "******* TELLING SURFACE FLINGER WE ARE BOOTED!",
|
||||
"level": "INFO",
|
||||
@@ -1999,12 +1999,6 @@
|
||||
"group": "WM_SHOW_TRANSACTIONS",
|
||||
"at": "com\/android\/server\/wm\/WindowAnimator.java"
|
||||
},
|
||||
"1995048598": {
|
||||
"message": "reparent: moving app token=%s to task=%d at %d",
|
||||
"level": "INFO",
|
||||
"group": "WM_DEBUG_ADD_REMOVE",
|
||||
"at": "com\/android\/server\/wm\/ActivityRecord.java"
|
||||
},
|
||||
"2016061474": {
|
||||
"message": "Prepare app transition: transit=%s %s alwaysKeepCurrent=%b displayId=%d Callers=%s",
|
||||
"level": "VERBOSE",
|
||||
|
||||
@@ -137,10 +137,8 @@ import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
|
||||
import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
|
||||
import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
|
||||
import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
|
||||
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
|
||||
import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
|
||||
import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
|
||||
import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
|
||||
@@ -299,10 +297,10 @@ import android.view.WindowManager;
|
||||
import android.view.WindowManager.LayoutParams;
|
||||
import android.view.animation.Animation;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.ResolverActivity;
|
||||
import com.android.internal.content.ReferrerIntent;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.ToBooleanFunction;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.AttributeCache;
|
||||
@@ -426,8 +424,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// Last configuration reported to the activity in the client process.
|
||||
private MergedConfiguration mLastReportedConfiguration;
|
||||
private int mLastReportedDisplayId;
|
||||
private boolean mLastReportedMultiWindowMode;
|
||||
private boolean mLastReportedPictureInPictureMode;
|
||||
boolean mLastReportedMultiWindowMode;
|
||||
boolean mLastReportedPictureInPictureMode;
|
||||
CompatibilityInfo compat;// last used compatibility mode
|
||||
ActivityRecord resultTo; // who started this entry, so will get our reply
|
||||
final String resultWho; // additional identifier for use by resultTo.
|
||||
@@ -490,7 +488,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
long lastLaunchTime; // time of last launch of this activity
|
||||
ComponentName requestedVrComponent; // the requested component for handling VR mode.
|
||||
|
||||
private boolean inHistory; // are we in the history stack?
|
||||
boolean inHistory; // are we in the history stack?
|
||||
final ActivityStackSupervisor mStackSupervisor;
|
||||
final RootActivityContainer mRootActivityContainer;
|
||||
|
||||
@@ -530,10 +528,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// True if we are current in the process of removing this app token from the display
|
||||
private boolean mRemovingFromDisplay = false;
|
||||
|
||||
// Flag set while reparenting to prevent actions normally triggered by an individual parent
|
||||
// change.
|
||||
private boolean mReparenting;
|
||||
|
||||
private RemoteAnimationDefinition mRemoteAnimationDefinition;
|
||||
|
||||
private AnimatingActivityRegistry mAnimatingActivityRegistry;
|
||||
@@ -1189,7 +1183,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove once TaskRecord and Task are unified.
|
||||
// TODO(task-unify): Remove once TaskRecord and Task are unified.
|
||||
TaskRecord getTaskRecord() {
|
||||
return task;
|
||||
}
|
||||
@@ -1201,16 +1195,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
* {@link ActivityStack}.
|
||||
* @param task The new parent {@link TaskRecord}.
|
||||
*/
|
||||
// TODO(task-unify): Can be remove after task level unification. Callers can just use addChild
|
||||
void setTask(TaskRecord task) {
|
||||
setTask(task /* task */, false /* reparenting */);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
|
||||
* @param task The new parent task.
|
||||
* @param reparenting Whether we're in the middle of reparenting.
|
||||
*/
|
||||
void setTask(TaskRecord task, boolean reparenting) {
|
||||
// Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
|
||||
if (task != null && task == getTaskRecord()) {
|
||||
return;
|
||||
@@ -1222,7 +1208,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// Inform old stack (if present) of activity removal and new stack (if set) of activity
|
||||
// addition.
|
||||
if (oldStack != newStack) {
|
||||
if (!reparenting && oldStack != null) {
|
||||
if (oldStack != null) {
|
||||
oldStack.onActivityRemovedFromStack(this);
|
||||
}
|
||||
|
||||
@@ -1231,38 +1217,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
}
|
||||
|
||||
final TaskRecord oldTask = this.task;
|
||||
this.task = task;
|
||||
|
||||
// This is attaching the activity to the task which we only want to do once.
|
||||
// TODO: Need to re-work after unifying the task level since it will already have a parent
|
||||
// then. Just need to restructure the re-parent case not to do this. NOTE that the
|
||||
// reparenting flag passed in can't be used directly for this as it isn't set in
|
||||
// TODO(task-unify): Need to re-work after unifying the task level since it will already
|
||||
// have a parent then. Just need to restructure the re-parent case not to do this. NOTE that
|
||||
// the reparenting flag passed in can't be used directly for this as it isn't set in
|
||||
// ActivityRecord#reparent() case that ends up calling this method.
|
||||
if (task != null && getParent() == null) {
|
||||
inHistory = true;
|
||||
final Task container = task.getTask();
|
||||
if (container != null) {
|
||||
onAttachToTask(task.voiceSession != null, container.getDisplayContent(),
|
||||
getInputDispatchingTimeoutLocked(this) * 1000000L);
|
||||
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "setTask: %s at top.", this);
|
||||
container.addChild(this, Integer.MAX_VALUE /* add on top */);
|
||||
}
|
||||
|
||||
// TODO(b/36505427): Maybe this call should be moved inside
|
||||
// updateOverrideConfiguration()
|
||||
task.updateOverrideConfigurationFromLaunchBounds();
|
||||
// Make sure size-compat is up-to-date before using to create window controller.
|
||||
updateSizeCompatMode();
|
||||
|
||||
task.addActivityToTop(this);
|
||||
|
||||
// When an activity is started directly into a split-screen fullscreen stack, we need to
|
||||
// update the initial multi-window modes so that the callbacks are scheduled correctly
|
||||
// when the user leaves that mode.
|
||||
mLastReportedMultiWindowMode = inMultiWindowMode();
|
||||
mLastReportedPictureInPictureMode = inPinnedWindowingMode();
|
||||
} else if (!reparenting) {
|
||||
onParentChanged();
|
||||
task.addChild(this);
|
||||
} else {
|
||||
onParentChanged(task, oldTask);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1288,24 +1254,46 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
super.onParentChanged();
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
final TaskRecord oldTask = (oldParent != null) ? ((Task) oldParent).mTaskRecord : null;
|
||||
final TaskRecord newTask = (newParent != null) ? ((Task) newParent).mTaskRecord : null;
|
||||
this.task = newTask;
|
||||
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
|
||||
final Task task = getTask();
|
||||
|
||||
if (oldParent == null && newParent != null) {
|
||||
// First time we are adding the activity to the system.
|
||||
// TODO(task-unify): See if mVoiceInteraction variable is really needed after task level
|
||||
// unification.
|
||||
mVoiceInteraction = task.mTaskRecord != null && task.mTaskRecord.voiceSession != null;
|
||||
mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
|
||||
onDisplayChanged(task.getDisplayContent());
|
||||
if (task.mTaskRecord != null) {
|
||||
task.mTaskRecord.updateOverrideConfigurationFromLaunchBounds();
|
||||
}
|
||||
// Make sure override configuration is up-to-date before using to create window
|
||||
// controller.
|
||||
updateSizeCompatMode();
|
||||
// When an activity is started directly into a split-screen fullscreen stack, we need to
|
||||
// update the initial multi-window modes so that the callbacks are scheduled correctly
|
||||
// when the user leaves that mode.
|
||||
mLastReportedMultiWindowMode = inMultiWindowMode();
|
||||
mLastReportedPictureInPictureMode = inPinnedWindowingMode();
|
||||
}
|
||||
|
||||
// When the associated task is {@code null}, the {@link ActivityRecord} can no longer
|
||||
// access visual elements like the {@link DisplayContent}. We must remove any associations
|
||||
// such as animations.
|
||||
if (!mReparenting) {
|
||||
if (task == null) {
|
||||
// It is possible we have been marked as a closing app earlier. We must remove ourselves
|
||||
// from this list so we do not participate in any future animations.
|
||||
if (getDisplayContent() != null) {
|
||||
getDisplayContent().mClosingApps.remove(this);
|
||||
}
|
||||
} else if (mLastParent != null && mLastParent.mStack != null) {
|
||||
task.mStack.mExitingActivities.remove(this);
|
||||
if (task == null) {
|
||||
// It is possible we have been marked as a closing app earlier. We must remove ourselves
|
||||
// from this list so we do not participate in any future animations.
|
||||
if (getDisplayContent() != null) {
|
||||
getDisplayContent().mClosingApps.remove(this);
|
||||
}
|
||||
} else if (mLastParent != null && mLastParent.mStack != null) {
|
||||
task.mStack.mExitingActivities.remove(this);
|
||||
}
|
||||
final TaskStack stack = getStack();
|
||||
|
||||
@@ -1320,6 +1308,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
mLastParent = task;
|
||||
|
||||
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) {
|
||||
// TODO(task-unify): Might be better to use onChildAdded and onChildRemoved signal for
|
||||
// this once task level is unified.
|
||||
if (oldStack != null) {
|
||||
oldStack.onActivityRemovedFromStack(this);
|
||||
}
|
||||
if (newStack != null) {
|
||||
newStack.onActivityAddedToStack(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateColorTransform() {
|
||||
@@ -1697,17 +1700,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
return hasProcess() && app.hasThread();
|
||||
}
|
||||
|
||||
void onAttachToTask(boolean voiceInteraction, DisplayContent dc,
|
||||
long inputDispatchingTimeoutNanos) {
|
||||
mInputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
|
||||
mVoiceInteraction = voiceInteraction;
|
||||
onDisplayChanged(dc);
|
||||
|
||||
// Application tokens start out hidden.
|
||||
setHidden(true);
|
||||
hiddenRequested = true;
|
||||
}
|
||||
|
||||
boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
|
||||
CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
|
||||
IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
|
||||
@@ -1967,12 +1959,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
});
|
||||
}
|
||||
|
||||
void removeWindowContainer() {
|
||||
private void removeAppTokenFromDisplay() {
|
||||
if (mWmService.mRoot == null) return;
|
||||
|
||||
final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
|
||||
if (dc == null) {
|
||||
Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
|
||||
Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
|
||||
+ appToken + " from non-existing displayId=" + getDisplayId());
|
||||
return;
|
||||
}
|
||||
@@ -2005,56 +1997,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
+ " r=" + this + " (" + prevTask.getStackId() + ")");
|
||||
}
|
||||
|
||||
final Task task = newTask.getTask();
|
||||
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving app token=%s"
|
||||
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
|
||||
+ " to task=%d at %d", this, task.mTaskId, position);
|
||||
|
||||
if (task == null) {
|
||||
throw new IllegalArgumentException("reparent: could not find task");
|
||||
}
|
||||
final Task currentTask = getTask();
|
||||
if (task == currentTask) {
|
||||
throw new IllegalArgumentException(
|
||||
"window token=" + this + " already child of task=" + currentTask);
|
||||
}
|
||||
reparent(newTask.getTask(), position);
|
||||
}
|
||||
|
||||
if (currentTask.mStack != task.mStack) {
|
||||
throw new IllegalArgumentException(
|
||||
"window token=" + this + " current task=" + currentTask
|
||||
+ " belongs to a different stack than " + task);
|
||||
}
|
||||
|
||||
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reParentWindowToken: removing window token=%s"
|
||||
+ " from task=%s" , this, currentTask);
|
||||
final DisplayContent prevDisplayContent = getDisplayContent();
|
||||
|
||||
mReparenting = true;
|
||||
|
||||
getParent().removeChild(this);
|
||||
task.addChild(this, position);
|
||||
|
||||
mReparenting = false;
|
||||
|
||||
// Relayout display(s).
|
||||
final DisplayContent displayContent = task.getDisplayContent();
|
||||
displayContent.setLayoutNeeded();
|
||||
if (prevDisplayContent != displayContent) {
|
||||
onDisplayChanged(displayContent);
|
||||
prevDisplayContent.setLayoutNeeded();
|
||||
}
|
||||
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
|
||||
|
||||
// Reparenting prevents informing the parent stack of activity removal in the case that
|
||||
// the new stack has the same parent. we must manually signal here if this is not the case.
|
||||
final ActivityStack prevStack = prevTask.getStack();
|
||||
|
||||
if (prevStack != newTask.getStack()) {
|
||||
prevStack.onActivityRemovedFromStack(this);
|
||||
}
|
||||
// Remove the activity from the old task and add it to the new task.
|
||||
prevTask.removeActivity(this, true /* reparenting */);
|
||||
|
||||
newTask.addActivityAtIndex(position, this);
|
||||
// TODO(task-unify): Remove once Task level is unified.
|
||||
void onParentChanged(TaskRecord newParent, TaskRecord oldParent) {
|
||||
onParentChanged(
|
||||
newParent != null ? newParent.mTask : null,
|
||||
oldParent != null ? oldParent.mTask : null);
|
||||
}
|
||||
|
||||
private boolean isHomeIntent(Intent intent) {
|
||||
@@ -2895,6 +2848,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
}
|
||||
|
||||
/** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
|
||||
// TODO(task-unify): Look into consolidating this with TaskRecord.removeChild once we unify
|
||||
// task level.
|
||||
void removeFromHistory(String reason) {
|
||||
finishActivityResults(Activity.RESULT_CANCELED, null /* resultData */);
|
||||
makeFinishingLocked();
|
||||
@@ -2912,41 +2867,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
setState(DESTROYED, "removeFromHistory");
|
||||
if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
|
||||
app = null;
|
||||
removeWindowContainer();
|
||||
final TaskRecord task = getTaskRecord();
|
||||
final boolean lastActivity = task.removeActivity(this);
|
||||
// If we are removing the last activity in the task, not including task overlay activities,
|
||||
// then fall through into the block below to remove the entire task itself
|
||||
final boolean onlyHasTaskOverlays =
|
||||
task.onlyHasTaskOverlayActivities(false /* excludingFinishing */);
|
||||
|
||||
if (lastActivity || onlyHasTaskOverlays) {
|
||||
if (DEBUG_STATES) {
|
||||
Slog.i(TAG, "removeFromHistory: last activity removed from " + this
|
||||
+ " onlyHasTaskOverlays=" + onlyHasTaskOverlays);
|
||||
}
|
||||
|
||||
// The following block can be executed multiple times if there is more than one overlay.
|
||||
// {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
|
||||
// of the task by id and exiting early if not found.
|
||||
if (onlyHasTaskOverlays) {
|
||||
// When destroying a task, tell the supervisor to remove it so that any activity it
|
||||
// has can be cleaned up correctly. This is currently the only place where we remove
|
||||
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
|
||||
// state into removeTask(), we just clear the task here before the other residual
|
||||
// work.
|
||||
// TODO: If the callers to removeTask() changes such that we have multiple places
|
||||
// where we are destroying the task, move this back into removeTask()
|
||||
mStackSupervisor.removeTaskByIdLocked(task.mTaskId, false /* killProcess */,
|
||||
!REMOVE_FROM_RECENTS, reason);
|
||||
}
|
||||
|
||||
// We must keep the task around until all activities are destroyed. The following
|
||||
// statement will only execute once since overlays are also considered activities.
|
||||
if (lastActivity) {
|
||||
stack.removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING);
|
||||
}
|
||||
}
|
||||
removeAppTokenFromDisplay();
|
||||
|
||||
cleanUpActivityServices();
|
||||
removeUriPermissionsLocked();
|
||||
|
||||
@@ -246,12 +246,13 @@ class ActivityStack extends ConfigurationContainer {
|
||||
ActivityDisplay current = getParent();
|
||||
if (current != parent) {
|
||||
mDisplayId = parent.mDisplayId;
|
||||
onParentChanged();
|
||||
onParentChanged(parent, current);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onParentChanged() {
|
||||
protected void onParentChanged(
|
||||
ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
ActivityDisplay display = getParent();
|
||||
if (display != null) {
|
||||
// Rotations are relative to the display. This means if there are 2 displays rotated
|
||||
@@ -264,7 +265,7 @@ class ActivityStack extends ConfigurationContainer {
|
||||
getConfiguration().windowConfiguration.setRotation(
|
||||
display.getWindowConfiguration().getRotation());
|
||||
}
|
||||
super.onParentChanged();
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
if (display != null && inSplitScreenPrimaryWindowingMode()) {
|
||||
// If we created a docked stack we want to resize it so it resizes all other stacks
|
||||
// in the system.
|
||||
@@ -915,12 +916,13 @@ class ActivityStack extends ConfigurationContainer {
|
||||
|
||||
/** Removes the stack completely. Also calls WindowManager to do the same on its side. */
|
||||
void remove() {
|
||||
final ActivityDisplay oldDisplay = getDisplay();
|
||||
removeFromDisplay();
|
||||
if (mTaskStack != null) {
|
||||
mTaskStack.removeIfPossible();
|
||||
mTaskStack = null;
|
||||
}
|
||||
onParentChanged();
|
||||
onParentChanged(null, oldDisplay);
|
||||
}
|
||||
|
||||
ActivityDisplay getDisplay() {
|
||||
@@ -4719,12 +4721,13 @@ class ActivityStack extends ConfigurationContainer {
|
||||
* {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}.
|
||||
*/
|
||||
void removeTask(TaskRecord task, String reason, int mode) {
|
||||
final boolean removed = mTaskHistory.remove(task);
|
||||
|
||||
if (removed) {
|
||||
EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.mTaskId, getStackId());
|
||||
if (!mTaskHistory.remove(task)) {
|
||||
// Not really in this stack anymore...
|
||||
return;
|
||||
}
|
||||
|
||||
EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.mTaskId, getStackId());
|
||||
|
||||
removeActivitiesFromLRUList(task);
|
||||
updateTaskMovement(task, true);
|
||||
|
||||
@@ -4758,7 +4761,7 @@ class ActivityStack extends ConfigurationContainer {
|
||||
if (inPinnedWindowingMode()) {
|
||||
mService.getTaskChangeNotificationController().notifyActivityUnpinned();
|
||||
}
|
||||
if (display.isSingleTaskInstance()) {
|
||||
if (display != null && display.isSingleTaskInstance()) {
|
||||
mService.notifySingleTaskDisplayEmpty(display.mDisplayId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1864,9 +1864,8 @@ class ActivityStarter {
|
||||
mLaunchFlags);
|
||||
|
||||
// The above code can remove {@code reusedActivity} from the task, leading to the
|
||||
// the {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The
|
||||
// task reference is needed in the call below to
|
||||
// {@link setTargetStackAndMoveToFrontIfNeeded}.
|
||||
// {@code ActivityRecord} removing its reference to the {@code TaskRecord}. The task
|
||||
// reference is needed in the call below to {@link setTargetStackAndMoveToFrontIfNeeded}
|
||||
if (targetTaskTop.getTaskRecord() == null) {
|
||||
targetTaskTop.setTask(targetTask);
|
||||
}
|
||||
@@ -2450,7 +2449,7 @@ class ActivityStarter {
|
||||
|
||||
private void addOrReparentStartingActivity(TaskRecord parent, String reason) {
|
||||
if (mStartActivity.getTaskRecord() == null || mStartActivity.getTaskRecord() == parent) {
|
||||
parent.addActivityToTop(mStartActivity);
|
||||
parent.addChild(mStartActivity);
|
||||
} else {
|
||||
mStartActivity.reparent(parent, parent.getChildCount() /* top */, reason);
|
||||
}
|
||||
|
||||
@@ -540,7 +540,7 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
|
||||
return sameWindowingMode;
|
||||
}
|
||||
|
||||
public void registerConfigurationChangeListener(ConfigurationContainerListener listener) {
|
||||
void registerConfigurationChangeListener(ConfigurationContainerListener listener) {
|
||||
if (mChangeListeners.contains(listener)) {
|
||||
return;
|
||||
}
|
||||
@@ -548,7 +548,7 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
|
||||
listener.onRequestedOverrideConfigurationChanged(mResolvedOverrideConfiguration);
|
||||
}
|
||||
|
||||
public void unregisterConfigurationChangeListener(ConfigurationContainerListener listener) {
|
||||
void unregisterConfigurationChangeListener(ConfigurationContainerListener listener) {
|
||||
mChangeListeners.remove(listener);
|
||||
}
|
||||
|
||||
@@ -560,13 +560,12 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> {
|
||||
/**
|
||||
* Must be called when new parent for the container was set.
|
||||
*/
|
||||
void onParentChanged() {
|
||||
final ConfigurationContainer parent = getParent();
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
// Removing parent usually means that we've detached this entity to destroy it or to attach
|
||||
// to another parent. In both cases we don't need to update the configuration now.
|
||||
if (parent != null) {
|
||||
if (newParent != null) {
|
||||
// Update full configuration of this container and all its children.
|
||||
onConfigurationChanged(parent.mFullConfiguration);
|
||||
onConfigurationChanged(newParent.mFullConfiguration);
|
||||
// Update merged override configuration of this container and all its children.
|
||||
onMergedOverrideConfigurationChanged();
|
||||
}
|
||||
|
||||
@@ -4359,9 +4359,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
if (getParent() != null) {
|
||||
super.onParentChanged(() -> {
|
||||
super.onParentChanged(newParent, oldParent, () -> {
|
||||
mAppAnimationLayer = makeChildSurface(null)
|
||||
.setName("animationLayer")
|
||||
.build();
|
||||
@@ -4381,7 +4381,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
.show(mSplitScreenDividerAnchor);
|
||||
});
|
||||
} else {
|
||||
super.onParentChanged();
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
mWmService.mTransactionFactory.get()
|
||||
.remove(mAppAnimationLayer)
|
||||
.remove(mBoostedAppAnimationLayer)
|
||||
@@ -4611,7 +4611,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
// Since we are the top of the SurfaceControl hierarchy here
|
||||
// we create the root surfaces explicitly rather than chaining
|
||||
// up as the default implementation in onParentChanged does. So we
|
||||
|
||||
@@ -67,7 +67,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
final int mTaskId;
|
||||
/* User for which this task was created. */
|
||||
final int mUserId;
|
||||
private boolean mDeferRemoval = false;
|
||||
|
||||
final Rect mPreparedFrozenBounds = new Rect();
|
||||
final Configuration mPreparedFrozenMergedConfig = new Configuration();
|
||||
@@ -176,14 +175,18 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
void addChild(ActivityRecord child, int position) {
|
||||
position = getAdjustedAddPosition(position);
|
||||
super.addChild(child, position);
|
||||
mDeferRemoval = false;
|
||||
|
||||
// Inform the TaskRecord side of the child addition
|
||||
// TODO(task-unify): Will be removed after task unification.
|
||||
if (mTaskRecord != null) {
|
||||
mTaskRecord.onChildAdded(child, position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void positionChildAt(int position, ActivityRecord child, boolean includingParents) {
|
||||
position = getAdjustedAddPosition(position);
|
||||
super.positionChildAt(position, child, includingParents);
|
||||
mDeferRemoval = false;
|
||||
}
|
||||
|
||||
private boolean hasWindowsAlive() {
|
||||
@@ -197,8 +200,10 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
|
||||
@VisibleForTesting
|
||||
boolean shouldDeferRemoval() {
|
||||
// TODO: This should probably return false if mChildren.isEmpty() regardless if the stack
|
||||
// is animating...
|
||||
if (mChildren.isEmpty()) {
|
||||
// No reason to defer removal of a Task that doesn't have any child.
|
||||
return false;
|
||||
}
|
||||
return hasWindowsAlive() && mStack.isSelfOrChildAnimating();
|
||||
}
|
||||
|
||||
@@ -206,7 +211,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
void removeIfPossible() {
|
||||
if (shouldDeferRemoval()) {
|
||||
if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
|
||||
mDeferRemoval = true;
|
||||
return;
|
||||
}
|
||||
removeImmediately();
|
||||
@@ -216,7 +220,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
void removeImmediately() {
|
||||
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
|
||||
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask");
|
||||
mDeferRemoval = false;
|
||||
if (mTaskRecord != null) {
|
||||
mTaskRecord.unregisterConfigurationChangeListener(this);
|
||||
}
|
||||
@@ -266,8 +269,8 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
super.onParentChanged();
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
|
||||
// Update task bounds if needed.
|
||||
adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
|
||||
@@ -290,11 +293,18 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
|
||||
super.removeChild(child);
|
||||
|
||||
// Inform the TaskRecord side of the child removal
|
||||
// TODO(task-unify): Will be removed after task unification.
|
||||
if (mTaskRecord != null) {
|
||||
mTaskRecord.onChildRemoved(child);
|
||||
}
|
||||
|
||||
// TODO(task-unify): Need to make this account for what we are doing in
|
||||
// ActivityRecord.removeFromHistory so that the task isn't removed in some situations when
|
||||
// we unify task level.
|
||||
if (mChildren.isEmpty()) {
|
||||
EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeActivity: last activity");
|
||||
if (mDeferRemoval) {
|
||||
removeIfPossible();
|
||||
}
|
||||
removeIfPossible();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -745,7 +755,7 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}";
|
||||
return "{taskId=" + mTaskId + " appTokens=" + mChildren + "}";
|
||||
}
|
||||
|
||||
String getName() {
|
||||
@@ -792,7 +802,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
proto.write(FILLS_PARENT, matchParentBounds());
|
||||
getBounds().writeToProto(proto, BOUNDS);
|
||||
mOverrideDisplayedBounds.writeToProto(proto, DISPLAYED_BOUNDS);
|
||||
proto.write(DEFER_REMOVAL, mDeferRemoval);
|
||||
proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
|
||||
proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
|
||||
proto.end(token);
|
||||
@@ -805,7 +814,6 @@ class Task extends WindowContainer<ActivityRecord> implements ConfigurationConta
|
||||
|
||||
pw.println(prefix + "taskId=" + mTaskId);
|
||||
pw.println(doublePrefix + "mBounds=" + getBounds().toShortString());
|
||||
pw.println(doublePrefix + "mdr=" + mDeferRemoval);
|
||||
pw.println(doublePrefix + "appTokens=" + mChildren);
|
||||
pw.println(doublePrefix + "mDisplayedBounds=" + mOverrideDisplayedBounds.toShortString());
|
||||
|
||||
|
||||
@@ -68,13 +68,16 @@ import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
|
||||
import static com.android.server.am.TaskRecordProto.STACK_ID;
|
||||
import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
|
||||
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
|
||||
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
|
||||
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
|
||||
import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
|
||||
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;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
|
||||
@@ -82,6 +85,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECEN
|
||||
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.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
|
||||
import static com.android.server.wm.WindowContainer.POSITION_TOP;
|
||||
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
|
||||
@@ -126,6 +130,7 @@ import android.view.DisplayInfo;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.app.IVoiceInteractor;
|
||||
import com.android.internal.util.XmlUtils;
|
||||
import com.android.server.protolog.common.ProtoLog;
|
||||
import com.android.server.wm.ActivityStack.ActivityState;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
@@ -969,6 +974,7 @@ class TaskRecord extends ConfigurationContainer {
|
||||
* Must be used for setting parent stack because it performs configuration updates.
|
||||
* Must be called after adding task as a child to the stack.
|
||||
*/
|
||||
// TODO(task-unify): Remove or rework after task level unification.
|
||||
void setStack(ActivityStack stack) {
|
||||
if (stack != null && !stack.isInStackLocked(this)) {
|
||||
throw new IllegalStateException("Task must be added as a Stack child first.");
|
||||
@@ -993,7 +999,7 @@ class TaskRecord extends ConfigurationContainer {
|
||||
}
|
||||
}
|
||||
|
||||
onParentChanged();
|
||||
onParentChanged(mStack, oldStack);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1019,8 +1025,9 @@ class TaskRecord extends ConfigurationContainer {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onParentChanged() {
|
||||
super.onParentChanged();
|
||||
protected void onParentChanged(
|
||||
ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
|
||||
}
|
||||
|
||||
@@ -1215,10 +1222,6 @@ class TaskRecord extends ConfigurationContainer {
|
||||
updateEffectiveIntent();
|
||||
}
|
||||
|
||||
void addActivityToTop(ActivityRecord r) {
|
||||
addActivityAtIndex(getChildCount(), r);
|
||||
}
|
||||
|
||||
@Override
|
||||
/*@WindowConfiguration.ActivityType*/
|
||||
public int getActivityType() {
|
||||
@@ -1229,18 +1232,11 @@ class TaskRecord extends ConfigurationContainer {
|
||||
return getChildAt(0).getActivityType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
|
||||
* be in the current task or unparented to any task.
|
||||
*/
|
||||
void addActivityAtIndex(int index, ActivityRecord r) {
|
||||
TaskRecord task = r.getTaskRecord();
|
||||
if (task != null && task != this) {
|
||||
throw new IllegalArgumentException("Can not add r=" + " to task=" + this
|
||||
+ " current parent=" + task);
|
||||
}
|
||||
|
||||
r.setTask(this);
|
||||
/** Called when a Task child is added from the Task.java side. */
|
||||
// TODO(task-unify): Just override addChild to do what is needed when someone calls to add a
|
||||
// child.
|
||||
void onChildAdded(ActivityRecord r, int index) {
|
||||
r.inHistory = true;
|
||||
|
||||
// Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
|
||||
if (!mActivities.remove(r) && r.occludesParent()) {
|
||||
@@ -1287,34 +1283,34 @@ class TaskRecord extends ConfigurationContainer {
|
||||
mAtmService.notifyTaskPersisterLocked(this, false);
|
||||
}
|
||||
|
||||
if (r.getParent() != null) {
|
||||
// Only attempt to move in WM if the child has a controller. It is possible we haven't
|
||||
// created controller for the activity we are starting yet.
|
||||
mTask.positionChildAt(r, index);
|
||||
}
|
||||
|
||||
// Make sure the list of display UID whitelists is updated
|
||||
// now that this record is in a new task.
|
||||
mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified activity from this task.
|
||||
* @param r The {@link ActivityRecord} to remove.
|
||||
* @return true if this was the last activity in the task.
|
||||
*/
|
||||
boolean removeActivity(ActivityRecord r) {
|
||||
return removeActivity(r, false /* reparenting */);
|
||||
}
|
||||
|
||||
boolean removeActivity(ActivityRecord r, boolean reparenting) {
|
||||
if (r.getTaskRecord() != this) {
|
||||
throw new IllegalArgumentException(
|
||||
"Activity=" + r + " does not belong to task=" + this);
|
||||
// TODO(task-unify): Merge onChildAdded method below into this since task will be a single
|
||||
// object.
|
||||
void addChild(ActivityRecord r) {
|
||||
if (r.getParent() != null) {
|
||||
// Shouldn't already have a parent since we are just adding to the task...
|
||||
throw new IllegalStateException(
|
||||
"r=" + r + " parent=" + r.getParent() + " task=" + this);
|
||||
}
|
||||
|
||||
r.setTask(null /* task */, reparenting /* reparenting */);
|
||||
ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
|
||||
// This means the activity isn't attached to Task.java yet. Go ahead and do that.
|
||||
// TODO(task-unify): Remove/call super once we unify task level.
|
||||
if (mTask != null) {
|
||||
mTask.addChild(r, Integer.MAX_VALUE /* add on top */);
|
||||
} else {
|
||||
onChildAdded(r, Integer.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a Task child is removed from the Task.java side. */
|
||||
// TODO(task-unify): Just override removeChild to do what is needed when someone calls to remove
|
||||
// a child.
|
||||
void onChildRemoved(ActivityRecord r) {
|
||||
if (mActivities.remove(r) && r.occludesParent()) {
|
||||
// Was previously in list.
|
||||
numFullscreen--;
|
||||
@@ -1330,11 +1326,27 @@ class TaskRecord extends ConfigurationContainer {
|
||||
mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
|
||||
}
|
||||
|
||||
if (!hasChild()) {
|
||||
return !mReuseTask;
|
||||
if (hasChild()) {
|
||||
updateEffectiveIntent();
|
||||
|
||||
// The following block can be executed multiple times if there is more than one overlay.
|
||||
// {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
|
||||
// of the task by id and exiting early if not found.
|
||||
if (onlyHasTaskOverlayActivities(false /* excludingFinishing */)) {
|
||||
// When destroying a task, tell the supervisor to remove it so that any activity it
|
||||
// has can be cleaned up correctly. This is currently the only place where we remove
|
||||
// a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
|
||||
// state into removeTask(), we just clear the task here before the other residual
|
||||
// work.
|
||||
// TODO: If the callers to removeTask() changes such that we have multiple places
|
||||
// where we are destroying the task, move this back into removeTask()
|
||||
mAtmService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false /* killProcess */,
|
||||
!REMOVE_FROM_RECENTS, "onChildRemoved");
|
||||
}
|
||||
} else if (!mReuseTask) {
|
||||
// Remove entire task if it doesn't have any activity left and it isn't marked for reuse
|
||||
mStack.removeTask(this, "onChildRemoved", REMOVE_TASK_MODE_DESTROYING);
|
||||
}
|
||||
updateEffectiveIntent();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -950,8 +950,8 @@ public class TaskStack extends WindowContainer<Task> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
super.onParentChanged();
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
|
||||
if (getParent() != null || mDisplayContent == null) {
|
||||
return;
|
||||
|
||||
@@ -106,6 +106,10 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
*/
|
||||
private WindowContainer<WindowContainer> mParent = null;
|
||||
|
||||
// Set to true when we are performing a reparenting operation so we only send one
|
||||
// onParentChanged() notification.
|
||||
private boolean mReparenting;
|
||||
|
||||
// List of children for this window container. List is in z-order as the children appear on
|
||||
// screen with the top-most window container at the tail of the list.
|
||||
protected final WindowList<E> mChildren = new WindowList<E>();
|
||||
@@ -187,9 +191,45 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
scheduleAnimation();
|
||||
}
|
||||
|
||||
void reparent(WindowContainer newParent, int position) {
|
||||
if (newParent == null) {
|
||||
throw new IllegalArgumentException("reparent: can't reparent to null " + this);
|
||||
}
|
||||
|
||||
final WindowContainer oldParent = mParent;
|
||||
if (mParent == newParent) {
|
||||
throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
|
||||
}
|
||||
|
||||
// The display object before reparenting as that might lead to old parent getting removed
|
||||
// from the display if it no longer has any child.
|
||||
final DisplayContent prevDc = oldParent.getDisplayContent();
|
||||
final DisplayContent dc = newParent.getDisplayContent();
|
||||
|
||||
mReparenting = true;
|
||||
oldParent.removeChild(this);
|
||||
newParent.addChild(this, position);
|
||||
mReparenting = false;
|
||||
|
||||
// Send onParentChanged notification here is we disabled sending it in setParent for
|
||||
// reparenting case.
|
||||
onParentChanged(newParent, oldParent);
|
||||
|
||||
// Relayout display(s)
|
||||
dc.setLayoutNeeded();
|
||||
if (prevDc != dc) {
|
||||
onDisplayChanged(dc);
|
||||
prevDc.setLayoutNeeded();
|
||||
}
|
||||
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
|
||||
}
|
||||
|
||||
final protected void setParent(WindowContainer<WindowContainer> parent) {
|
||||
final WindowContainer oldParent = mParent;
|
||||
mParent = parent;
|
||||
onParentChanged();
|
||||
if (!mReparenting) {
|
||||
onParentChanged(mParent, oldParent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,12 +237,13 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
|
||||
* Supposed to be overridden and contain actions that should be executed after parent was set.
|
||||
*/
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
onParentChanged(null);
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
onParentChanged(newParent, oldParent, null);
|
||||
}
|
||||
|
||||
void onParentChanged(PreAssignChildLayersCallback callback) {
|
||||
super.onParentChanged();
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
|
||||
PreAssignChildLayersCallback callback) {
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
if (mParent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -868,8 +868,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
super.onParentChanged();
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
super.onParentChanged(newParent, oldParent);
|
||||
setDrawnStateEvaluated(false /*evaluated*/);
|
||||
|
||||
getDisplayContent().reapplyMagnificationSpec();
|
||||
|
||||
@@ -130,13 +130,13 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
|
||||
@Test
|
||||
public void testStackCleanupOnClearingTask() {
|
||||
mActivity.setTask(null);
|
||||
mActivity.onParentChanged(null /*newParent*/, mActivity.getTask());
|
||||
verify(mStack, times(1)).onActivityRemovedFromStack(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStackCleanupOnActivityRemoval() {
|
||||
mTask.removeActivity(mActivity);
|
||||
mTask.mTask.removeChild(mActivity);
|
||||
verify(mStack, times(1)).onActivityRemovedFromStack(any());
|
||||
}
|
||||
|
||||
@@ -795,7 +795,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
|
||||
// Remove activity from task
|
||||
mActivity.finishing = false;
|
||||
mActivity.setTask(null);
|
||||
mActivity.onParentChanged(null /*newParent*/, mActivity.getTask());
|
||||
assertEquals("Activity outside of task/stack cannot be finished", FINISH_RESULT_CANCELLED,
|
||||
mActivity.finishIfPossible("test", false /* oomAdj */));
|
||||
assertFalse(mActivity.finishing);
|
||||
|
||||
@@ -710,7 +710,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
|
||||
if (startedActivity != null && startedActivity.getTaskRecord() != null) {
|
||||
// Remove the activity so it doesn't interfere with with subsequent activity launch
|
||||
// tests from this method.
|
||||
startedActivity.getTaskRecord().removeActivity(startedActivity);
|
||||
startedActivity.getTaskRecord().mTask.removeChild(startedActivity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import static android.view.WindowManager.TRANSIT_UNSET;
|
||||
|
||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
|
||||
import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
|
||||
@@ -208,6 +209,9 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testSizeCompatBounds() {
|
||||
// Disable the real configuration resolving because we only simulate partial flow.
|
||||
// TODO: Have test use full flow.
|
||||
doNothing().when(mTask.mTaskRecord).computeConfigResourceOverrides(any(), any());
|
||||
final Rect fixedBounds = mActivity.getRequestedOverrideConfiguration().windowConfiguration
|
||||
.getBounds();
|
||||
fixedBounds.set(0, 0, 1200, 1600);
|
||||
@@ -249,6 +253,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
@Test
|
||||
@Presubmit
|
||||
public void testGetOrientation() {
|
||||
mActivity.setHidden(false);
|
||||
|
||||
mActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
|
||||
|
||||
mActivity.setOccludesParent(false);
|
||||
@@ -309,6 +315,8 @@ public class AppWindowTokenTests extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testSetOrientation() {
|
||||
mActivity.setHidden(false);
|
||||
|
||||
// Assert orientation is unspecified to start.
|
||||
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, mActivity.getOrientation());
|
||||
|
||||
|
||||
@@ -334,8 +334,9 @@ public class ConfigurationContainerTests {
|
||||
private TestConfigurationContainer mParent;
|
||||
|
||||
TestConfigurationContainer addChild(TestConfigurationContainer childContainer) {
|
||||
final ConfigurationContainer oldParent = childContainer.getParent();
|
||||
childContainer.mParent = this;
|
||||
childContainer.onParentChanged();
|
||||
childContainer.onParentChanged(this, oldParent);
|
||||
mChildren.add(childContainer);
|
||||
return childContainer;
|
||||
}
|
||||
@@ -349,8 +350,9 @@ public class ConfigurationContainerTests {
|
||||
}
|
||||
|
||||
void removeChild(TestConfigurationContainer child) {
|
||||
final ConfigurationContainer oldParent = child.getParent();
|
||||
child.mParent = null;
|
||||
child.onParentChanged();
|
||||
child.onParentChanged(null, oldParent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -772,7 +772,7 @@ public class WindowContainerTests extends WindowTestsBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
void onParentChanged() {
|
||||
void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
|
||||
mOnParentChangedCalled = true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user