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