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.am; 18 19 import android.app.ActivityManager.TaskSnapshot; 20 import android.app.ITaskStackListener; 21 import android.app.ActivityManager.TaskDescription; 22 import android.content.ComponentName; 23 import android.os.Binder; 24 import android.os.Handler; 25 import android.os.Looper; 26 import android.os.Message; 27 import android.os.RemoteCallbackList; 28 import android.os.RemoteException; 29 30 import java.util.ArrayList; 31 32 class TaskChangeNotificationController { 33 private static final int LOG_STACK_STATE_MSG = 1; 34 private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2; 35 private static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3; 36 private static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4; 37 private static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5; 38 private static final int NOTIFY_FORCED_RESIZABLE_MSG = 6; 39 private static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7; 40 private static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8; 41 private static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9; 42 private static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10; 43 private static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11; 44 private static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12; 45 private static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13; 46 private static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14; 47 private static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15; 48 private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16; 49 private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17; 50 private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18; 51 52 // Delay in notifying task stack change listeners (in millis) 53 private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100; 54 55 private final ActivityManagerService mService; 56 private final ActivityStackSupervisor mStackSupervisor; 57 private final Handler mHandler; 58 59 // Task stack change listeners in a remote process. 60 private final RemoteCallbackList<ITaskStackListener> mRemoteTaskStackListeners = 61 new RemoteCallbackList<>(); 62 63 /* 64 * Task stack change listeners in a local process. Tracked separately so that they can be 65 * called on the same thread. 66 */ 67 private final ArrayList<ITaskStackListener> mLocalTaskStackListeners = new ArrayList<>(); 68 69 private final TaskStackConsumer mNotifyTaskStackChanged = (l, m) -> { 70 l.onTaskStackChanged(); 71 }; 72 73 private final TaskStackConsumer mNotifyTaskCreated = (l, m) -> { 74 l.onTaskCreated(m.arg1, (ComponentName) m.obj); 75 }; 76 77 private final TaskStackConsumer mNotifyTaskRemoved = (l, m) -> { 78 l.onTaskRemoved(m.arg1); 79 }; 80 81 private final TaskStackConsumer mNotifyTaskMovedToFront = (l, m) -> { 82 l.onTaskMovedToFront(m.arg1); 83 }; 84 85 private final TaskStackConsumer mNotifyTaskDescriptionChanged = (l, m) -> { 86 l.onTaskDescriptionChanged(m.arg1, (TaskDescription) m.obj); 87 }; 88 89 private final TaskStackConsumer mNotifyActivityRequestedOrientationChanged = (l, m) -> { 90 l.onActivityRequestedOrientationChanged(m.arg1, m.arg2); 91 }; 92 93 private final TaskStackConsumer mNotifyTaskRemovalStarted = (l, m) -> { 94 l.onTaskRemovalStarted(m.arg1); 95 }; 96 97 private final TaskStackConsumer mNotifyActivityPinned = (l, m) -> { 98 l.onActivityPinned((String) m.obj /* packageName */, m.sendingUid /* userId */, 99 m.arg1 /* taskId */, m.arg2 /* stackId */); 100 }; 101 102 private final TaskStackConsumer mNotifyActivityUnpinned = (l, m) -> { 103 l.onActivityUnpinned(); 104 }; 105 106 private final TaskStackConsumer mNotifyPinnedActivityRestartAttempt = (l, m) -> { 107 l.onPinnedActivityRestartAttempt(m.arg1 != 0); 108 }; 109 110 private final TaskStackConsumer mNotifyPinnedStackAnimationStarted = (l, m) -> { 111 l.onPinnedStackAnimationStarted(); 112 }; 113 114 private final TaskStackConsumer mNotifyPinnedStackAnimationEnded = (l, m) -> { 115 l.onPinnedStackAnimationEnded(); 116 }; 117 118 private final TaskStackConsumer mNotifyActivityForcedResizable = (l, m) -> { 119 l.onActivityForcedResizable((String) m.obj, m.arg1, m.arg2); 120 }; 121 122 private final TaskStackConsumer mNotifyActivityDismissingDockedStack = (l, m) -> { 123 l.onActivityDismissingDockedStack(); 124 }; 125 126 private final TaskStackConsumer mNotifyActivityLaunchOnSecondaryDisplayFailed = (l, m) -> { 127 l.onActivityLaunchOnSecondaryDisplayFailed(); 128 }; 129 130 private final TaskStackConsumer mNotifyTaskProfileLocked = (l, m) -> { 131 l.onTaskProfileLocked(m.arg1, m.arg2); 132 }; 133 134 private final TaskStackConsumer mNotifyTaskSnapshotChanged = (l, m) -> { 135 l.onTaskSnapshotChanged(m.arg1, (TaskSnapshot) m.obj); 136 }; 137 138 @FunctionalInterface 139 public interface TaskStackConsumer { accept(ITaskStackListener t, Message m)140 void accept(ITaskStackListener t, Message m) throws RemoteException; 141 } 142 143 private class MainHandler extends Handler { MainHandler(Looper looper)144 public MainHandler(Looper looper) { 145 super(looper); 146 } 147 148 @Override handleMessage(Message msg)149 public void handleMessage(Message msg) { 150 switch (msg.what) { 151 case LOG_STACK_STATE_MSG: { 152 synchronized (mService) { 153 mStackSupervisor.logStackState(); 154 } 155 break; 156 } 157 case NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG: 158 forAllRemoteListeners(mNotifyTaskStackChanged, msg); 159 break; 160 case NOTIFY_TASK_ADDED_LISTENERS_MSG: 161 forAllRemoteListeners(mNotifyTaskCreated, msg); 162 break; 163 case NOTIFY_TASK_REMOVED_LISTENERS_MSG: 164 forAllRemoteListeners(mNotifyTaskRemoved, msg); 165 break; 166 case NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG: 167 forAllRemoteListeners(mNotifyTaskMovedToFront, msg); 168 break; 169 case NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG: 170 forAllRemoteListeners(mNotifyTaskDescriptionChanged, msg); 171 break; 172 case NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS: 173 forAllRemoteListeners(mNotifyActivityRequestedOrientationChanged, msg); 174 break; 175 case NOTIFY_TASK_REMOVAL_STARTED_LISTENERS: 176 forAllRemoteListeners(mNotifyTaskRemovalStarted, msg); 177 break; 178 case NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG: 179 forAllRemoteListeners(mNotifyActivityPinned, msg); 180 break; 181 case NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG: 182 forAllRemoteListeners(mNotifyActivityUnpinned, msg); 183 break; 184 case NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG: 185 forAllRemoteListeners(mNotifyPinnedActivityRestartAttempt, msg); 186 break; 187 case NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG: 188 forAllRemoteListeners(mNotifyPinnedStackAnimationStarted, msg); 189 break; 190 case NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG: 191 forAllRemoteListeners(mNotifyPinnedStackAnimationEnded, msg); 192 break; 193 case NOTIFY_FORCED_RESIZABLE_MSG: 194 forAllRemoteListeners(mNotifyActivityForcedResizable, msg); 195 break; 196 case NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG: 197 forAllRemoteListeners(mNotifyActivityDismissingDockedStack, msg); 198 break; 199 case NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG: 200 forAllRemoteListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg); 201 break; 202 case NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG: 203 forAllRemoteListeners(mNotifyTaskProfileLocked, msg); 204 break; 205 case NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG: 206 forAllRemoteListeners(mNotifyTaskSnapshotChanged, msg); 207 break; 208 } 209 } 210 } 211 TaskChangeNotificationController(ActivityManagerService service, ActivityStackSupervisor stackSupervisor, Handler handler)212 public TaskChangeNotificationController(ActivityManagerService service, 213 ActivityStackSupervisor stackSupervisor, Handler handler) { 214 mService = service; 215 mStackSupervisor = stackSupervisor; 216 mHandler = new MainHandler(handler.getLooper()); 217 } 218 registerTaskStackListener(ITaskStackListener listener)219 public void registerTaskStackListener(ITaskStackListener listener) { 220 synchronized (mService) { 221 if (listener != null) { 222 if (Binder.getCallingPid() == android.os.Process.myPid()) { 223 if (!mLocalTaskStackListeners.contains(listener)) { 224 mLocalTaskStackListeners.add(listener); 225 } 226 } else { 227 mRemoteTaskStackListeners.register(listener); 228 } 229 } 230 } 231 } 232 unregisterTaskStackListener(ITaskStackListener listener)233 public void unregisterTaskStackListener(ITaskStackListener listener) { 234 synchronized (mService) { 235 if (listener != null) { 236 if (Binder.getCallingPid() == android.os.Process.myPid()) { 237 mLocalTaskStackListeners.remove(listener); 238 } else { 239 mRemoteTaskStackListeners.unregister(listener); 240 } 241 } 242 } 243 } 244 forAllRemoteListeners(TaskStackConsumer callback, Message message)245 private void forAllRemoteListeners(TaskStackConsumer callback, Message message) { 246 synchronized (mService) { 247 for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) { 248 try { 249 // Make a one-way callback to the listener 250 callback.accept(mRemoteTaskStackListeners.getBroadcastItem(i), message); 251 } catch (RemoteException e) { 252 // Handled by the RemoteCallbackList. 253 } 254 } 255 mRemoteTaskStackListeners.finishBroadcast(); 256 } 257 } 258 forAllLocalListeners(TaskStackConsumer callback, Message message)259 private void forAllLocalListeners(TaskStackConsumer callback, Message message) { 260 synchronized (mService) { 261 for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) { 262 try { 263 callback.accept(mLocalTaskStackListeners.get(i), message); 264 } catch (RemoteException e) { 265 // Never thrown since this is called locally. 266 } 267 } 268 } 269 } 270 271 /** Notifies all listeners when the task stack has changed. */ notifyTaskStackChanged()272 void notifyTaskStackChanged() { 273 mHandler.sendEmptyMessage(LOG_STACK_STATE_MSG); 274 mHandler.removeMessages(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG); 275 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG); 276 forAllLocalListeners(mNotifyTaskStackChanged, msg); 277 // Only the main task stack change notification requires a delay. 278 mHandler.sendMessageDelayed(msg, NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY); 279 } 280 281 /** Notifies all listeners when an Activity is pinned. */ notifyActivityPinned(ActivityRecord r)282 void notifyActivityPinned(ActivityRecord r) { 283 mHandler.removeMessages(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG); 284 final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG, 285 r.getTask().taskId, r.getStackId(), r.packageName); 286 msg.sendingUid = r.userId; 287 forAllLocalListeners(mNotifyActivityPinned, msg); 288 msg.sendToTarget(); 289 } 290 291 /** Notifies all listeners when an Activity is unpinned. */ notifyActivityUnpinned()292 void notifyActivityUnpinned() { 293 mHandler.removeMessages(NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG); 294 final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG); 295 forAllLocalListeners(mNotifyActivityUnpinned, msg); 296 msg.sendToTarget(); 297 } 298 299 /** 300 * Notifies all listeners when an attempt was made to start an an activity that is already 301 * running in the pinned stack and the activity was not actually started, but the task is 302 * either brought to the front or a new Intent is delivered to it. 303 */ notifyPinnedActivityRestartAttempt(boolean clearedTask)304 void notifyPinnedActivityRestartAttempt(boolean clearedTask) { 305 mHandler.removeMessages(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG); 306 final Message msg = 307 mHandler.obtainMessage(NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG, 308 clearedTask ? 1 : 0, 0); 309 forAllLocalListeners(mNotifyPinnedActivityRestartAttempt, msg); 310 msg.sendToTarget(); 311 } 312 313 /** Notifies all listeners when the pinned stack animation starts. */ notifyPinnedStackAnimationStarted()314 void notifyPinnedStackAnimationStarted() { 315 mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG); 316 final Message msg = 317 mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG); 318 forAllLocalListeners(mNotifyPinnedStackAnimationStarted, msg); 319 msg.sendToTarget(); 320 } 321 322 /** Notifies all listeners when the pinned stack animation ends. */ notifyPinnedStackAnimationEnded()323 void notifyPinnedStackAnimationEnded() { 324 mHandler.removeMessages(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG); 325 final Message msg = 326 mHandler.obtainMessage(NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG); 327 forAllLocalListeners(mNotifyPinnedStackAnimationEnded, msg); 328 msg.sendToTarget(); 329 } 330 notifyActivityDismissingDockedStack()331 void notifyActivityDismissingDockedStack() { 332 mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG); 333 final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG); 334 forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg); 335 msg.sendToTarget(); 336 } 337 notifyActivityForcedResizable(int taskId, int reason, String packageName)338 void notifyActivityForcedResizable(int taskId, int reason, String packageName) { 339 mHandler.removeMessages(NOTIFY_FORCED_RESIZABLE_MSG); 340 final Message msg = mHandler.obtainMessage(NOTIFY_FORCED_RESIZABLE_MSG, taskId, reason, 341 packageName); 342 forAllLocalListeners(mNotifyActivityForcedResizable, msg); 343 msg.sendToTarget(); 344 } 345 notifyActivityLaunchOnSecondaryDisplayFailed()346 void notifyActivityLaunchOnSecondaryDisplayFailed() { 347 mHandler.removeMessages(NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG); 348 final Message msg = mHandler.obtainMessage( 349 NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG); 350 forAllLocalListeners(mNotifyActivityLaunchOnSecondaryDisplayFailed, msg); 351 msg.sendToTarget(); 352 } 353 notifyTaskCreated(int taskId, ComponentName componentName)354 void notifyTaskCreated(int taskId, ComponentName componentName) { 355 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_ADDED_LISTENERS_MSG, 356 taskId, 0 /* unused */, componentName); 357 forAllLocalListeners(mNotifyTaskCreated, msg); 358 msg.sendToTarget(); 359 } 360 notifyTaskRemoved(int taskId)361 void notifyTaskRemoved(int taskId) { 362 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVED_LISTENERS_MSG, 363 taskId, 0 /* unused */); 364 forAllLocalListeners(mNotifyTaskRemoved, msg); 365 msg.sendToTarget(); 366 } 367 notifyTaskMovedToFront(int taskId)368 void notifyTaskMovedToFront(int taskId) { 369 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG, 370 taskId, 0 /* unused */); 371 forAllLocalListeners(mNotifyTaskMovedToFront, msg); 372 msg.sendToTarget(); 373 } 374 notifyTaskDescriptionChanged(int taskId, TaskDescription taskDescription)375 void notifyTaskDescriptionChanged(int taskId, TaskDescription taskDescription) { 376 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG, 377 taskId, 0 /* unused */, taskDescription); 378 forAllLocalListeners(mNotifyTaskDescriptionChanged, msg); 379 msg.sendToTarget(); 380 381 } 382 notifyActivityRequestedOrientationChanged(int taskId, int orientation)383 void notifyActivityRequestedOrientationChanged(int taskId, int orientation) { 384 final Message msg = mHandler.obtainMessage( 385 NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS, taskId, orientation); 386 forAllLocalListeners(mNotifyActivityRequestedOrientationChanged, msg); 387 msg.sendToTarget(); 388 } 389 390 /** 391 * Notify listeners that the task is about to be finished before its surfaces are removed from 392 * the window manager. This allows interested parties to perform relevant animations before 393 * the window disappears. 394 */ notifyTaskRemovalStarted(int taskId)395 void notifyTaskRemovalStarted(int taskId) { 396 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_REMOVAL_STARTED_LISTENERS, taskId, 397 0 /* unused */); 398 forAllLocalListeners(mNotifyTaskRemovalStarted, msg); 399 msg.sendToTarget(); 400 401 } 402 403 /** 404 * Notify listeners that the task has been put in a locked state because one or more of the 405 * activities inside it belong to a managed profile user that has been locked. 406 */ notifyTaskProfileLocked(int taskId, int userId)407 void notifyTaskProfileLocked(int taskId, int userId) { 408 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG, taskId, 409 userId); 410 forAllLocalListeners(mNotifyTaskProfileLocked, msg); 411 msg.sendToTarget(); 412 } 413 414 /** 415 * Notify listeners that the snapshot of a task has changed. 416 */ notifyTaskSnapshotChanged(int taskId, TaskSnapshot snapshot)417 void notifyTaskSnapshotChanged(int taskId, TaskSnapshot snapshot) { 418 final Message msg = mHandler.obtainMessage(NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG, 419 taskId, 0, snapshot); 420 forAllLocalListeners(mNotifyTaskSnapshotChanged, msg); 421 msg.sendToTarget(); 422 } 423 } 424