Added TaskWindowContainerController
For linking TaskRecord in AMS to Task window container in WMS.
Bug: 30060889
Test: bit FrameworksServicesTests:com.android.server.wm.AppWindowContainerControllerTests
Test: bit FrameworksServicesTests:com.android.server.wm.TaskWindowContainerControllerTests
Test: Existing test pass and manual testing.
Change-Id: I16248f3e96e5087ba24198a48a3bd10a12ae76a6
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index a17cf3b..0d8829e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -39,6 +39,7 @@
import android.os.Debug;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
@@ -48,6 +49,7 @@
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.util.XmlUtils;
+import com.android.server.wm.TaskWindowContainerController;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -58,6 +60,7 @@
import java.util.ArrayList;
import java.util.Objects;
+import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
@@ -80,6 +83,7 @@
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
@@ -95,6 +99,7 @@
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
final class TaskRecord extends ConfigurationContainer {
private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
@@ -280,6 +285,8 @@
/** Helper object used for updating override configuration. */
private Configuration mTmpConfig = new Configuration();
+ private TaskWindowContainerController mWindowContainerController;
+
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
mService = service;
@@ -389,6 +396,155 @@
mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
}
+ TaskWindowContainerController getWindowContainerController() {
+ return mWindowContainerController;
+ }
+
+ void createWindowContainer(boolean onTop, boolean showForAllUsers) {
+ if (mWindowContainerController != null) {
+ throw new IllegalArgumentException("Window container=" + mWindowContainerController
+ + " already created for task=" + this);
+ }
+
+ final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
+ final Configuration overrideConfig = getOverrideConfiguration();
+ mWindowContainerController = new TaskWindowContainerController(taskId, getStackId(), userId,
+ bounds, overrideConfig, mResizeMode, isHomeTask(), isOnTopLauncher(), onTop,
+ showForAllUsers);
+ }
+
+ void removeWindowContainer() {
+ mService.mStackSupervisor.removeLockedTaskLocked(this);
+ mWindowContainerController.removeContainer();
+ if (!StackId.persistTaskBounds(getStackId())) {
+ // Reset current bounds for task whose bounds shouldn't be persisted so it uses
+ // default configuration the next time it launches.
+ updateOverrideConfiguration(null);
+ }
+ mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId);
+ mWindowContainerController = null;
+ }
+
+ void setResizeMode(int resizeMode) {
+ if (mResizeMode == resizeMode) {
+ return;
+ }
+ mResizeMode = resizeMode;
+ mWindowContainerController.setResizeable(resizeMode);
+ mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+ }
+
+ void setTaskDockedResizing(boolean resizing) {
+ mWindowContainerController.setTaskDockedResizing(resizing);
+ }
+
+ boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
+ if (!isResizeable()) {
+ Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
+ return true;
+ }
+
+ // If this is a forced resize, let it go through even if the bounds is not changing,
+ // as we might need a relayout due to surface size change (to/from fullscreen).
+ final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
+ if (Objects.equals(mBounds, bounds) && !forced) {
+ // Nothing to do here...
+ return true;
+ }
+ bounds = validateBounds(bounds);
+
+ if (mWindowContainerController == null) {
+ // Task doesn't exist in window manager yet (e.g. was restored from recents).
+ // All we can do for now is update the bounds so it can be used when the task is
+ // added to window manager.
+ updateOverrideConfiguration(bounds);
+ if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ // re-restore the task so it can have the proper stack association.
+ mService.mStackSupervisor.restoreRecentTaskLocked(this,
+ FREEFORM_WORKSPACE_STACK_ID);
+ }
+ return true;
+ }
+
+ if (!canResizeToBounds(bounds)) {
+ throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
+ + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
+ }
+
+ // Do not move the task to another stack here.
+ // This method assumes that the task is already placed in the right stack.
+ // we do not mess with that decision and we only do the resize!
+
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
+
+ final boolean updatedConfig = updateOverrideConfiguration(bounds);
+ // This variable holds information whether the configuration didn't change in a significant
+ // way and the activity was kept the way it was. If it's false, it means the activity had
+ // to be relaunched due to configuration change.
+ boolean kept = true;
+ if (updatedConfig) {
+ final ActivityRecord r = topRunningActivityLocked();
+ if (r != null) {
+ kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow);
+
+ if (!deferResume) {
+ // All other activities must be made visible with their correct configuration.
+ mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
+ if (!kept) {
+ mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
+ }
+ }
+ }
+ }
+ mWindowContainerController.resize(mBounds, getOverrideConfiguration(), kept, forced);
+
+ Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
+ return kept;
+ }
+
+ // TODO: Investigate combining with the resize() method above.
+ void resizeWindowContainer() {
+ mWindowContainerController.resize(mBounds, getOverrideConfiguration(), false /* relayout */,
+ false /* forced */);
+ }
+
+ // TODO: Remove once we have a stack controller.
+ void positionWindowContainerAt(int stackId, int index) {
+ mWindowContainerController.positionAt(stackId, index, mBounds, getOverrideConfiguration());
+ }
+
+ // TODO: Replace with moveChildToTop?
+ void moveWindowContainerToTop(boolean includingParents) {
+ if (mWindowContainerController != null) {
+ mWindowContainerController.moveToTop(includingParents);
+ }
+ }
+
+ // TODO: Replace with moveChildToBottom?
+ void moveWindowContainerToBottom() {
+ if (mWindowContainerController != null) {
+ mWindowContainerController.moveToBottom();
+ }
+ }
+
+ void getWindowContainerBounds(Rect bounds) {
+ mWindowContainerController.getBounds(bounds);
+ }
+
+ // TODO: make this part of adding it to the stack?
+ void reparentWindowContainer(int stackId, int position) {
+ mWindowContainerController.reparent(stackId, position);
+ }
+
+ void cancelWindowTransition() {
+ mWindowContainerController.cancelWindowTransition();
+ }
+
+ void cancelThumbnailTransition() {
+ mWindowContainerController.cancelThumbnailTransition();
+ }
+
void touchActiveTime() {
lastActiveTime = System.currentTimeMillis();
if (firstActiveTime == 0) {
@@ -852,7 +1008,7 @@
// Sync. with window manager
updateOverrideConfigurationFromLaunchBounds();
- r.positionWindowContainerAt(index);
+ mWindowContainerController.positionChildAt(r.getWindowContainerController(), index);
r.onOverrideConfigurationSent();
}