Send task description changed though task org taskInfoChanged
- This removes the need for a separate task stack listener and aligns
with other task info change properties
- Also implement equals/hashCode for the token so we can use it in
containers
Bug: 148977538
Test: atest TaskOrganizerTests
Signed-off-by: Winson Chung <winsonc@google.com>
Change-Id: Ie035e6389fdbdc374c1a4b4a684758efa0cb7a9e
diff --git a/api/test-current.txt b/api/test-current.txt
index 641767c..0dff41b 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5232,14 +5232,14 @@
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getChildTasks(@NonNull android.window.WindowContainerToken, @NonNull int[]);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static android.window.WindowContainerToken getImeTarget(int);
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static java.util.List<android.app.ActivityManager.RunningTaskInfo> getRootTasks(int, @NonNull int[]);
- method public void onBackPressedOnTaskRoot(@NonNull android.app.ActivityManager.RunningTaskInfo);
- method public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo);
- method public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
- method public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void registerOrganizer(int);
+ method @BinderThread public void onBackPressedOnTaskRoot(@NonNull android.app.ActivityManager.RunningTaskInfo);
+ method @BinderThread public void onTaskAppeared(@NonNull android.app.ActivityManager.RunningTaskInfo);
+ method @BinderThread public void onTaskInfoChanged(@NonNull android.app.ActivityManager.RunningTaskInfo);
+ method @BinderThread public void onTaskVanished(@NonNull android.app.ActivityManager.RunningTaskInfo);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void registerOrganizer(int);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void setInterceptBackPressedOnTaskRoot(boolean);
method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public static void setLaunchRoot(int, @NonNull android.window.WindowContainerToken);
- method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void unregisterOrganizer();
+ method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public final void unregisterOrganizer();
}
public final class WindowContainerToken implements android.os.Parcelable {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index b6d519a..fd73632 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -69,6 +69,7 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.DisplayMetrics;
import android.util.Singleton;
@@ -1597,6 +1598,39 @@
+ " resizeMode: " + ActivityInfo.resizeModeToString(mResizeMode)
+ " minWidth: " + mMinWidth + " minHeight: " + mMinHeight;
}
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof TaskDescription)) {
+ return false;
+ }
+
+ TaskDescription other = (TaskDescription) obj;
+ return TextUtils.equals(mLabel, other.mLabel)
+ && TextUtils.equals(mIconFilename, other.mIconFilename)
+ && mIcon == other.mIcon
+ && mColorPrimary == other.mColorPrimary
+ && mColorBackground == other.mColorBackground
+ && mStatusBarColor == other.mStatusBarColor
+ && mNavigationBarColor == other.mNavigationBarColor
+ && mEnsureStatusBarContrastWhenTransparent
+ == other.mEnsureStatusBarContrastWhenTransparent
+ && mEnsureNavigationBarContrastWhenTransparent
+ == other.mEnsureNavigationBarContrastWhenTransparent
+ && mResizeMode == other.mResizeMode
+ && mMinWidth == other.mMinWidth
+ && mMinHeight == other.mMinHeight;
+ }
+
+ /** @hide */
+ public static boolean equals(TaskDescription td1, TaskDescription td2) {
+ if (td1 == null && td2 == null) {
+ return true;
+ } else if (td1 != null && td2 != null) {
+ return td1.equals(td2);
+ }
+ return false;
+ }
}
/**
diff --git a/core/java/android/window/TaskEmbedder.java b/core/java/android/window/TaskEmbedder.java
index 45ab310..2ead37a 100644
--- a/core/java/android/window/TaskEmbedder.java
+++ b/core/java/android/window/TaskEmbedder.java
@@ -26,7 +26,6 @@
import android.app.ActivityView;
import android.app.IActivityTaskManager;
import android.app.PendingIntent;
-import android.app.TaskStackListener;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -129,7 +128,6 @@
protected SurfaceControl.Transaction mTransaction;
protected SurfaceControl mSurfaceControl;
- protected TaskStackListener mTaskStackListener;
protected Listener mListener;
protected boolean mOpened; // Protected by mGuard.
@@ -170,13 +168,6 @@
if (!onInitialize()) {
return false;
}
-
- mTaskStackListener = createTaskStackListener();
- try {
- mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to register task stack listener", e);
- }
if (mListener != null && isInitialized()) {
mListener.onInitialized();
}
@@ -187,11 +178,6 @@
}
/**
- * @return the task stack listener for this embedder
- */
- public abstract TaskStackListener createTaskStackListener();
-
- /**
* Whether this container has been initialized.
*
* @return true if initialized
@@ -420,16 +406,6 @@
mSurfaceControl.release();
boolean reportReleased = onRelease();
-
- if (mTaskStackListener != null) {
- try {
- mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to unregister task stack listener", e);
- }
- mTaskStackListener = null;
- }
-
if (mListener != null && reportReleased) {
mListener.onReleased();
}
diff --git a/core/java/android/window/TaskOrganizer.java b/core/java/android/window/TaskOrganizer.java
index 5098b44..f661d9a 100644
--- a/core/java/android/window/TaskOrganizer.java
+++ b/core/java/android/window/TaskOrganizer.java
@@ -16,6 +16,7 @@
package android.window;
+import android.annotation.BinderThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -39,7 +40,7 @@
* and receive taskVanished callbacks in the process.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
- public void registerOrganizer(int windowingMode) {
+ public final void registerOrganizer(int windowingMode) {
try {
getController().registerTaskOrganizer(mInterface, windowingMode);
} catch (RemoteException e) {
@@ -49,7 +50,7 @@
/** Unregisters a previously registered task organizer. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
- public void unregisterOrganizer() {
+ public final void unregisterOrganizer() {
try {
getController().unregisterTaskOrganizer(mInterface);
} catch (RemoteException e) {
@@ -57,13 +58,17 @@
}
}
+ @BinderThread
public void onTaskAppeared(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
+ @BinderThread
public void onTaskVanished(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
- public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo info) {}
+ @BinderThread
+ public void onTaskInfoChanged(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
- public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo info) {}
+ @BinderThread
+ public void onBackPressedOnTaskRoot(@NonNull ActivityManager.RunningTaskInfo taskInfo) {}
/** Creates a persistent root task in WM for a particular windowing-mode. */
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS)
diff --git a/core/java/android/window/TaskOrganizerTaskEmbedder.java b/core/java/android/window/TaskOrganizerTaskEmbedder.java
index 39a0101..b63741e 100644
--- a/core/java/android/window/TaskOrganizerTaskEmbedder.java
+++ b/core/java/android/window/TaskOrganizerTaskEmbedder.java
@@ -21,7 +21,6 @@
import android.app.ActivityManager;
import android.app.ActivityOptions;
-import android.app.ActivityView;
import android.app.TaskStackListener;
import android.content.Context;
import android.graphics.Rect;
@@ -55,11 +54,6 @@
super(context, host);
}
- @Override
- public TaskStackListener createTaskStackListener() {
- return new TaskStackListenerImpl();
- }
-
/**
* Whether this container has been initialized.
*
@@ -219,29 +213,6 @@
Log.d(TAG, "[" + System.identityHashCode(this) + "] " + msg);
}
- /**
- * A task change listener that detects background color change of the topmost stack on our
- * virtual display and updates the background of the surface view. This background will be shown
- * when surface view is resized, but the app hasn't drawn its content in new size yet.
- * It also calls StateCallback.onTaskMovedToFront to notify interested parties that the stack
- * associated with the {@link ActivityView} has had a Task moved to the front. This is useful
- * when needing to also bring the host Activity to the foreground at the same time.
- */
- private class TaskStackListenerImpl extends TaskStackListener {
-
- @Override
- public void onTaskDescriptionChanged(ActivityManager.RunningTaskInfo taskInfo) {
- if (!isInitialized()) {
- return;
- }
- if (taskInfo.taskId == mTaskInfo.taskId) {
- mTaskInfo.taskDescription = taskInfo.taskDescription;
- mHost.onTaskBackgroundColorChanged(TaskOrganizerTaskEmbedder.this,
- taskInfo.taskDescription.getBackgroundColor());
- }
- }
- }
-
private class TaskOrganizerImpl extends TaskOrganizer {
@Override
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo) {
@@ -249,7 +220,6 @@
log("taskAppeared: " + taskInfo.taskId);
}
- // TODO: Ensure visibility/alpha of the leash in its initial state?
mTaskInfo = taskInfo;
mTaskToken = taskInfo.token;
mTaskLeash = mTaskToken.getLeash();
@@ -270,6 +240,13 @@
}
@Override
+ public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
+ mTaskInfo.taskDescription = taskInfo.taskDescription;
+ mHost.post(() -> mHost.onTaskBackgroundColorChanged(TaskOrganizerTaskEmbedder.this,
+ taskInfo.taskDescription.getBackgroundColor()));
+ }
+
+ @Override
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
if (DEBUG) {
log("taskVanished: " + taskInfo.taskId);
diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java
index 0f26d5d..7016469 100644
--- a/core/java/android/window/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -67,6 +67,7 @@
private VirtualDisplay mVirtualDisplay;
private Insets mForwardedInsets;
private DisplayMetrics mTmpDisplayMetrics;
+ private TaskStackListener mTaskStackListener;
/**
* Constructs a new TaskEmbedder.
@@ -82,11 +83,6 @@
mSingleTaskInstance = singleTaskInstance;
}
- @Override
- public TaskStackListener createTaskStackListener() {
- return new TaskStackListenerImpl();
- }
-
/**
* Whether this container has been initialized.
*
@@ -124,6 +120,9 @@
.setDisplayToSingleTaskInstance(displayId);
}
setForwardedInsets(mForwardedInsets);
+
+ mTaskStackListener = new TaskStackListenerImpl();
+ mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
} catch (RemoteException e) {
e.rethrowAsRuntimeException();
}
@@ -142,6 +141,15 @@
// Clear tap-exclude region (if any) for this window.
clearTapExcludeRegion();
+ if (mTaskStackListener != null) {
+ try {
+ mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister task stack listener", e);
+ }
+ mTaskStackListener = null;
+ }
+
if (isInitialized()) {
mVirtualDisplay.release();
mVirtualDisplay = null;
diff --git a/core/java/android/window/WindowContainerToken.java b/core/java/android/window/WindowContainerToken.java
index dde98da..3316d0e 100644
--- a/core/java/android/window/WindowContainerToken.java
+++ b/core/java/android/window/WindowContainerToken.java
@@ -84,4 +84,17 @@
public int describeContents() {
return 0;
}
+
+ @Override
+ public int hashCode() {
+ return mRealToken.asBinder().hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof WindowContainerToken)) {
+ return false;
+ }
+ return mRealToken.asBinder() == ((WindowContainerToken) obj).asBinder();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
index 91d638e..a4b1310 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -105,10 +105,6 @@
mDivider.getHandler().post(() -> handleTaskInfoChanged(taskInfo));
}
- @Override
- public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
- }
-
/**
* This is effectively a finite state machine which moves between the various split-screen
* presentations based on the contents of the split regions.
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 856fbc7..ac13492 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5592,6 +5592,7 @@
_taskDescription.setIconFilename(iconFilePath);
}
taskDescription = _taskDescription;
+ getTask().updateTaskDescription();
}
void setVoiceSessionLocked(IVoiceInteractionSession session) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index c253cd2..f4eb0d2 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3061,8 +3061,6 @@
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
r.setTaskDescription(td);
- final Task task = r.getTask();
- task.updateTaskDescription();
}
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1e70573..2742b38 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1767,6 +1767,10 @@
t.updateTaskDescription();
}
}
+
+ if (isOrganized()) {
+ mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
+ }
}
private static boolean setTaskDescriptionFromActivityAboveRoot(
@@ -1962,7 +1966,7 @@
final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
// If the task organizer has changed, then it will already be receiving taskAppeared with
// the latest task-info thus the task-info won't have changed.
- if (!taskOrgChanged && mTaskOrganizer != null) {
+ if (!taskOrgChanged && isOrganized()) {
mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
}
}
@@ -4153,8 +4157,6 @@
// Let the old organizer know it has lost control.
sendTaskVanished();
mTaskOrganizer = organizer;
-
-
sendTaskAppeared();
onTaskOrganizerChanged();
return true;
@@ -4291,8 +4293,9 @@
void setPictureInPictureParams(PictureInPictureParams p) {
mPictureInPictureParams.copyOnlySet(p);
- mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
- this, true /* force */);
+ if (isOrganized()) {
+ mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 9873031..adc50bf 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -27,6 +27,7 @@
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityManager.TaskDescription;
import android.app.WindowConfiguration;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -439,7 +440,8 @@
boolean changed = lastInfo == null
|| mTmpTaskInfo.topActivityType != lastInfo.topActivityType
|| mTmpTaskInfo.isResizable() != lastInfo.isResizable()
- || mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams;
+ || mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams
+ || !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription);
if (!changed) {
int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration);
final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index f275e37..e41d4dc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -50,6 +50,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackInfo;
import android.app.IRequestFinishCallback;
@@ -856,6 +857,30 @@
}
@Test
+ public void testChangeTaskDescription() {
+ class ChangeSavingOrganizer extends StubOrganizer {
+ RunningTaskInfo mChangedInfo;
+ @Override
+ public void onTaskInfoChanged(RunningTaskInfo info) {
+ mChangedInfo = info;
+ }
+ }
+ ChangeSavingOrganizer o = new ChangeSavingOrganizer();
+ mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o,
+ WINDOWING_MODE_MULTI_WINDOW);
+
+ final ActivityStack stack = createStack();
+ final Task task = createTask(stack);
+ final ActivityRecord record = WindowTestUtils.createActivityRecordInTask(
+ stack.mDisplayContent, task);
+
+ stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
+ record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
+ waitUntilHandlersIdle();
+ assertEquals("TestDescription", o.mChangedInfo.taskDescription.getLabel());
+ }
+
+ @Test
public void testPreventDuplicateAppear() throws RemoteException {
final ActivityStack stack = createStack();
final Task task = createTask(stack);