• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2016 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.android.server.wm;
18  
19  import android.app.ActivityManager;
20  import android.app.ActivityManager.RunningTaskInfo;
21  import android.app.ActivityManager.TaskSnapshot;
22  import android.app.ITaskStackListener;
23  import android.app.TaskInfo;
24  import android.content.ComponentName;
25  import android.os.Binder;
26  import android.os.Handler;
27  import android.os.IBinder;
28  import android.os.Looper;
29  import android.os.Message;
30  import android.os.RemoteCallbackList;
31  import android.os.RemoteException;
32  
33  import java.util.ArrayList;
34  
35  class TaskChangeNotificationController {
36      private static final int LOG_STACK_STATE_MSG = 1;
37      private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
38      private static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
39      private static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
40      private static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
41      private static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
42      private static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
43      private static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
44      private static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
45      private static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
46      private static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
47      private static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
48      private static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
49      private static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
50      private static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
51      private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
52      private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
53      private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
54      private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG = 19;
55      private static final int NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG = 20;
56      private static final int NOTIFY_BACK_PRESSED_ON_TASK_ROOT = 21;
57      private static final int NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG = 22;
58  
59      // Delay in notifying task stack change listeners (in millis)
60      private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
61  
62      // Global lock used by the service the instantiate objects of this class.
63      private final Object mServiceLock;
64      private final ActivityStackSupervisor mStackSupervisor;
65      private final Handler mHandler;
66  
67      // Task stack change listeners in a remote process.
68      private final RemoteCallbackList<ITaskStackListener> mRemoteTaskStackListeners =
69              new RemoteCallbackList<>();
70  
71      /*
72       * Task stack change listeners in a local process. Tracked separately so that they can be
73       * called on the same thread.
74       */
75      private final ArrayList<ITaskStackListener> mLocalTaskStackListeners = new ArrayList<>();
76  
77      private final TaskStackConsumer mNotifyTaskStackChanged = (l, m) -> {
78          l.onTaskStackChanged();
79      };
80  
81      private final TaskStackConsumer mNotifyTaskCreated = (l, m) -> {
82          l.onTaskCreated(m.arg1, (ComponentName) m.obj);
83      };
84  
85      private final TaskStackConsumer mNotifyTaskRemoved = (l, m) -> {
86          l.onTaskRemoved(m.arg1);
87      };
88  
89      private final TaskStackConsumer mNotifyTaskMovedToFront = (l, m) -> {
90          l.onTaskMovedToFront((RunningTaskInfo) m.obj);
91      };
92  
93      private final TaskStackConsumer mNotifyTaskDescriptionChanged = (l, m) -> {
94          l.onTaskDescriptionChanged((RunningTaskInfo) m.obj);
95      };
96  
97      private final TaskStackConsumer mNotifyBackPressedOnTaskRoot = (l, m) -> {
98          l.onBackPressedOnTaskRoot((RunningTaskInfo) m.obj);
99      };
100  
101      private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> {
102          l.onActivityRequestedOrientationChanged(m.arg1, m.arg2);
103      };
104  
105      private final TaskStackConsumer mNotifyTaskRemovalStarted = (l, m) -> {
106          l.onTaskRemovalStarted((RunningTaskInfo) m.obj);
107      };
108  
109      private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> {
110          l.onActivityPinned((String) m.obj /* packageName */, m.sendingUid /* userId */,
111                  m.arg1 /* taskId */, m.arg2 /* stackId */);
112      };
113  
114      private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> {
115          l.onActivityUnpinned();
116      };
117  
118      private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> {
119          l.onPinnedActivityRestartAttempt(m.arg1 != 0);
120      };
121  
122      private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> {
123          l.onPinnedStackAnimationStarted();
124      };
125  
126      private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> {
127          l.onPinnedStackAnimationEnded();
128      };
129  
130      private final TaskStackConsumer mNotifyActivityForcedResizable = (l, m) -> {
131          l.onActivityForcedResizable((String) m.obj, m.arg1, m.arg2);
132      };
133  
134      private final TaskStackConsumer mNotifyActivityDismissingDockedStack = (l, m) -> {
135          l.onActivityDismissingDockedStack();
136      };
137  
138      private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> {
139          l.onActivityLaunchOnSecondaryDisplayFailed((RunningTaskInfo) m.obj, m.arg1);
140      };
141  
142      private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayRerouted = (l, m) -> {
143          l.onActivityLaunchOnSecondaryDisplayRerouted((RunningTaskInfo) m.obj, m.arg1);
144      };
145  
146      private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> {
147          l.onTaskProfileLocked(m.arg1, m.arg2);
148      };
149  
150      private final TaskStackConsumer mNotifyTaskSnapshotChanged = (l, m) -> {
151          l.onTaskSnapshotChanged(m.arg1, (TaskSnapshot) m.obj);
152      };
153  
154      private final TaskStackConsumer mOnSizeCompatModeActivityChanged = (l, m) -> {
155          l.onSizeCompatModeActivityChanged(m.arg1, (IBinder) m.obj);
156      };
157  
158      private final TaskStackConsumer mNotifyTaskDisplayChanged = (l, m) -> {
159          l.onTaskDisplayChanged(m.arg1, m.arg2);
160      };
161  
162      @FunctionalInterface
163      public interface TaskStackConsumer {
accept(ITaskStackListener t, Message m)164          void accept(ITaskStackListener t, Message m) throws RemoteException;
165      }
166  
167      private class MainHandler extends Handler {
MainHandler(Looper looper)168          public MainHandler(Looper looper) {
169              super(looper);
170          }
171  
172          @Override
handleMessage(Message msg)173          public void handleMessage(Message msg) {
174              switch (msg.what) {
175                  case LOG_STACK_STATE_MSG: {
176                      synchronized (mServiceLock) {
177                          mStackSupervisor.logStackState();
178                      }
179                      break;
180                  }
181                  case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG:
182                      forAllRemoteListeners(mNotifyTaskStackChanged, msg);
183                      break;
184                  case NOTIFY_TASK_ADDED_LISTENERS_MSG:
185                      forAllRemoteListeners(mNotifyTaskCreated, msg);
186                      break;
187                  case NOTIFY_TASK_REMOVED_LISTENERS_MSG:
188                      forAllRemoteListeners(mNotifyTaskRemoved, msg);
189                      break;
190                  case NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG:
191                      forAllRemoteListeners(mNotifyTaskMovedToFront, msg);
192                      break;
193                  case NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG:
194                      forAllRemoteListeners(mNotifyTaskDescriptionChanged, msg);
195                      break;
196                  case NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS:
197                      forAllRemoteListeners(mNotifyActivityRequestedOrientationChanged, msg);
198                      break;
199                  case NOTIFY_TASK_REMOVAL_STARTED_LISTENERS:
200                      forAllRemoteListeners(mNotifyTaskRemovalStarted, msg);
201                      break;
202                  case NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG:
203                      forAllRemoteListeners(mNotifyActivityPinned, msg);
204                      break;
205                  case NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG:
206                      forAllRemoteListeners(mNotifyActivityUnpinned, msg);
207                      break;
208                  case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG:
209                      forAllRemoteListeners(mNotifyPinnedActivityRestartAttempt, msg);
210                      break;
211                  case NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG:
212                      forAllRemoteListeners(mNotifyPinnedStackAnimationStarted, msg);
213                      break;
214                  case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG:
215                      forAllRemoteListeners(mNotifyPinnedStackAnimationEnded, msg);
216                      break;
217                  case NOTIFY_FORCED_RESIZABLE_MSG:
218                      forAllRemoteListeners(mNotifyActivityForcedResizable, msg);
219                      break;
220                  case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG:
221                      forAllRemoteListeners(mNotifyActivityDismissingDockedStack, msg);
222                      break;
223                  case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG:
224                      forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
225                      break;
226                  case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG:
227                      forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayRerouted, msg);
228                      break;
229                  case NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG:
230                      forAllRemoteListeners(mNotifyTaskProfileLocked, msg);
231                      break;
232                  case NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG:
233                      forAllRemoteListeners(mNotifyTaskSnapshotChanged, msg);
234                      break;
235                  case NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG:
236                      forAllRemoteListeners(mOnSizeCompatModeActivityChanged, msg);
237                      break;
238                  case NOTIFY_BACK_PRESSED_ON_TASK_ROOT:
239                      forAllRemoteListeners(mNotifyBackPressedOnTaskRoot, msg);
240                      break;
241                  case NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG:
242                      forAllRemoteListeners(mNotifyTaskDisplayChanged, msg);
243                      break;
244              }
245          }
246      }
247  
TaskChangeNotificationController(Object serviceLock, ActivityStackSupervisor stackSupervisor, Handler handler)248      public TaskChangeNotificationController(Object serviceLock,
249              ActivityStackSupervisor stackSupervisor, Handler handler) {
250          mServiceLock = serviceLock;
251          mStackSupervisor = stackSupervisor;
252          mHandler = new MainHandler(handler.getLooper());
253      }
254  
registerTaskStackListener(ITaskStackListener listener)255      public void registerTaskStackListener(ITaskStackListener listener) {
256          synchronized (mServiceLock) {
257              if (listener != null) {
258                  if (Binder.getCallingPid() == android.os.Process.myPid()) {
259                      if (!mLocalTaskStackListeners.contains(listener)) {
260                          mLocalTaskStackListeners.add(listener);
261                      }
262                  } else {
263                      mRemoteTaskStackListeners.register(listener);
264                  }
265              }
266          }
267      }
268  
unregisterTaskStackListener(ITaskStackListener listener)269      public void unregisterTaskStackListener(ITaskStackListener listener) {
270          synchronized (mServiceLock) {
271              if (listener != null) {
272                  if (Binder.getCallingPid() == android.os.Process.myPid()) {
273                      mLocalTaskStackListeners.remove(listener);
274                  } else {
275                      mRemoteTaskStackListeners.unregister(listener);
276                  }
277              }
278          }
279      }
280  
forAllRemoteListeners(TaskStackConsumer callback, Message message)281      private void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
282          synchronized (mServiceLock) {
283              for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
284                  try {
285                      // Make a one-way callback to the listener
286                      callback.accept(mRemoteTaskStackListeners.getBroadcastItem(i), message);
287                  } catch (RemoteException e) {
288                      // Handled by the RemoteCallbackList.
289                  }
290              }
291              mRemoteTaskStackListeners.finishBroadcast();
292          }
293      }
294  
forAllLocalListeners(TaskStackConsumer callback, Message message)295      private void forAllLocalListeners(TaskStackConsumer callback, Message message) {
296          synchronized (mServiceLock) {
297              for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) {
298                  try {
299                      callback.accept(mLocalTaskStackListeners.get(i), message);
300                  } catch (RemoteException e) {
301                      // Never thrown since this is called locally.
302                  }
303              }
304          }
305      }
306  
307      /** Notifies all listeners when the task stack has changed. */
notifyTaskStackChanged()308      void notifyTaskStackChanged() {
309          mHandler.sendEmptyMessage(LOG_STACK_STATE_MSG);
310          mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
311          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG);
312          forAllLocalListeners(mNotifyTaskStackChanged, msg);
313          // Only the main task stack change notification requires a delay.
314          mHandler.sendMessageDelayed(msg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY);
315      }
316  
317      /** Notifies all listeners when an Activity is pinned. */
notifyActivityPinned(ActivityRecord r)318      void notifyActivityPinned(ActivityRecord r) {
319          mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG);
320          final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG,
321                  r.getTaskRecord().taskId, r.getStackId(), r.packageName);
322          msg.sendingUid = r.mUserId;
323          forAllLocalListeners(mNotifyActivityPinned, msg);
324          msg.sendToTarget();
325      }
326  
327      /** Notifies all listeners when an Activity is unpinned. */
notifyActivityUnpinned()328      void notifyActivityUnpinned() {
329          mHandler.removeMessages(NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG);
330          final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG);
331          forAllLocalListeners(mNotifyActivityUnpinned, msg);
332          msg.sendToTarget();
333      }
334  
335      /**
336       * Notifies all listeners when an attempt was made to start an an activity that is already
337       * running in the pinned stack and the activity was not actually started, but the task is
338       * either brought to the front or a new Intent is delivered to it.
339       */
notifyPinnedActivityRestartAttempt(boolean clearedTask)340      void notifyPinnedActivityRestartAttempt(boolean clearedTask) {
341          mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG);
342          final Message msg =
343                  mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG,
344                          clearedTask ? 1 : 0, 0);
345          forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg);
346          msg.sendToTarget();
347      }
348  
349      /** Notifies all listeners when the pinned stack animation starts. */
notifyPinnedStackAnimationStarted()350      void notifyPinnedStackAnimationStarted() {
351          mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
352          final Message msg =
353                  mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG);
354          forAllLocalListeners(mNotifyPinnedStackAnimationStarted, msg);
355          msg.sendToTarget();
356      }
357  
358      /** Notifies all listeners when the pinned stack animation ends. */
notifyPinnedStackAnimationEnded()359      void notifyPinnedStackAnimationEnded() {
360          mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
361          final Message msg =
362                  mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG);
363          forAllLocalListeners(mNotifyPinnedStackAnimationEnded, msg);
364          msg.sendToTarget();
365      }
366  
notifyActivityDismissingDockedStack()367      void notifyActivityDismissingDockedStack() {
368          mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
369          final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
370          forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
371          msg.sendToTarget();
372      }
373  
notifyActivityForcedResizable(int taskId, int reason, String packageName)374      void notifyActivityForcedResizable(int taskId, int reason, String packageName) {
375          mHandler.removeMessages(NOTIFY_FORCED_RESIZABLE_MSG);
376          final Message msg = mHandler.obtainMessage(NOTIFY_FORCED_RESIZABLE_MSG, taskId, reason,
377                  packageName);
378          forAllLocalListeners(mNotifyActivityForcedResizable, msg);
379          msg.sendToTarget();
380      }
381  
notifyActivityLaunchOnSecondaryDisplayFailed(TaskInfo ti, int requestedDisplayId)382      void notifyActivityLaunchOnSecondaryDisplayFailed(TaskInfo ti, int requestedDisplayId) {
383          mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG);
384          final Message msg = mHandler.obtainMessage(
385                  NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG, requestedDisplayId,
386                  0 /* unused */, ti);
387          forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg);
388          msg.sendToTarget();
389      }
390  
notifyActivityLaunchOnSecondaryDisplayRerouted(TaskInfo ti, int requestedDisplayId)391      void notifyActivityLaunchOnSecondaryDisplayRerouted(TaskInfo ti, int requestedDisplayId) {
392          mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG);
393          final Message msg = mHandler.obtainMessage(
394                  NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_REROUTED_MSG, requestedDisplayId,
395                  0 /* unused */, ti);
396          forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayRerouted, msg);
397          msg.sendToTarget();
398      }
399  
notifyTaskCreated(int taskId, ComponentName componentName)400      void notifyTaskCreated(int taskId, ComponentName componentName) {
401          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_ADDED_LISTENERS_MSG,
402                  taskId, 0 /* unused */, componentName);
403          forAllLocalListeners(mNotifyTaskCreated, msg);
404          msg.sendToTarget();
405      }
406  
notifyTaskRemoved(int taskId)407      void notifyTaskRemoved(int taskId) {
408          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVED_LISTENERS_MSG,
409                  taskId, 0 /* unused */);
410          forAllLocalListeners(mNotifyTaskRemoved, msg);
411          msg.sendToTarget();
412      }
413  
notifyTaskMovedToFront(TaskInfo ti)414      void notifyTaskMovedToFront(TaskInfo ti) {
415          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG, ti);
416          forAllLocalListeners(mNotifyTaskMovedToFront, msg);
417          msg.sendToTarget();
418      }
419  
notifyTaskDescriptionChanged(TaskInfo taskInfo)420      void notifyTaskDescriptionChanged(TaskInfo taskInfo) {
421          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG,
422                  taskInfo);
423          forAllLocalListeners(mNotifyTaskDescriptionChanged, msg);
424          msg.sendToTarget();
425  
426      }
427  
notifyActivityRequestedOrientationChanged(int taskId, int orientation)428      void notifyActivityRequestedOrientationChanged(int taskId, int orientation) {
429          final Message msg = mHandler.obtainMessage(
430                  NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS, taskId, orientation);
431          forAllLocalListeners(mNotifyActivityRequestedOrientationChanged, msg);
432          msg.sendToTarget();
433      }
434  
435      /**
436       * Notify listeners that the task is about to be finished before its surfaces are removed from
437       * the window manager. This allows interested parties to perform relevant animations before
438       * the window disappears.
439       */
notifyTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo)440      void notifyTaskRemovalStarted(ActivityManager.RunningTaskInfo taskInfo) {
441          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskInfo);
442          forAllLocalListeners(mNotifyTaskRemovalStarted, msg);
443          msg.sendToTarget();
444      }
445  
446      /**
447       * Notify listeners that the task has been put in a locked state because one or more of the
448       * activities inside it belong to a managed profile user that has been locked.
449       */
notifyTaskProfileLocked(int taskId, int userId)450      void notifyTaskProfileLocked(int taskId, int userId) {
451          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG, taskId,
452                  userId);
453          forAllLocalListeners(mNotifyTaskProfileLocked, msg);
454          msg.sendToTarget();
455      }
456  
457      /**
458       * Notify listeners that the snapshot of a task has changed.
459       */
notifyTaskSnapshotChanged(int taskId, TaskSnapshot snapshot)460      void notifyTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) {
461          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG,
462                  taskId, 0, snapshot);
463          forAllLocalListeners(mNotifyTaskSnapshotChanged, msg);
464          msg.sendToTarget();
465      }
466  
467      /**
468       * Notify listeners that whether a size compatibility mode activity is using the override
469       * bounds which is not fit its parent.
470       */
notifySizeCompatModeActivityChanged(int displayId, IBinder activityToken)471      void notifySizeCompatModeActivityChanged(int displayId, IBinder activityToken) {
472          final Message msg = mHandler.obtainMessage(NOTIFY_SIZE_COMPAT_MODE_ACTIVITY_CHANGED_MSG,
473                  displayId, 0 /* unused */, activityToken);
474          forAllLocalListeners(mOnSizeCompatModeActivityChanged, msg);
475          msg.sendToTarget();
476      }
477  
478      /**
479       * Notify listeners that an activity received a back press when there are no other activities
480       * in the back stack.
481       */
notifyBackPressedOnTaskRoot(TaskInfo taskInfo)482      void notifyBackPressedOnTaskRoot(TaskInfo taskInfo) {
483          final Message msg = mHandler.obtainMessage(NOTIFY_BACK_PRESSED_ON_TASK_ROOT,
484                  taskInfo);
485          forAllLocalListeners(mNotifyBackPressedOnTaskRoot, msg);
486          msg.sendToTarget();
487      }
488  
489      /**
490       * Notify listeners that a task is reparented to another display.
491       */
notifyTaskDisplayChanged(int taskId, int newDisplayId)492      void notifyTaskDisplayChanged(int taskId, int newDisplayId) {
493          final Message msg = mHandler.obtainMessage(NOTIFY_TASK_DISPLAY_CHANGED_LISTENERS_MSG,
494                  taskId, newDisplayId);
495          forAllLocalListeners(mNotifyTaskStackChanged, msg);
496          msg.sendToTarget();
497      }
498  }
499