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/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);