• Home
  • 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