1 /* 2 * Copyright 2017, 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 static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED; 20 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; 21 import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 23 import static android.content.Context.DEVICE_POLICY_SERVICE; 24 import static android.content.Context.STATUS_BAR_SERVICE; 25 import static android.content.Intent.ACTION_CALL_EMERGENCY; 26 import static android.os.UserHandle.USER_ALL; 27 import static android.os.UserHandle.USER_CURRENT; 28 import static android.telecom.TelecomManager.EMERGENCY_DIALER_COMPONENT; 29 import static android.view.Display.DEFAULT_DISPLAY; 30 31 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK; 32 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK; 33 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 34 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 35 import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; 36 import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; 37 import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; 38 import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_PINNABLE; 39 import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; 40 41 import android.annotation.NonNull; 42 import android.annotation.Nullable; 43 import android.app.Activity; 44 import android.app.ActivityManager; 45 import android.app.StatusBarManager; 46 import android.app.admin.DevicePolicyManager; 47 import android.app.admin.IDevicePolicyManager; 48 import android.content.ComponentName; 49 import android.content.Context; 50 import android.content.Intent; 51 import android.os.Binder; 52 import android.os.Debug; 53 import android.os.Handler; 54 import android.os.IBinder; 55 import android.os.RemoteException; 56 import android.os.ServiceManager; 57 import android.os.UserHandle; 58 import android.provider.Settings; 59 import android.telecom.TelecomManager; 60 import android.util.Pair; 61 import android.util.Slog; 62 import android.util.SparseArray; 63 import android.util.SparseIntArray; 64 65 import com.android.internal.annotations.VisibleForTesting; 66 import com.android.internal.policy.IKeyguardDismissCallback; 67 import com.android.internal.statusbar.IStatusBarService; 68 import com.android.internal.widget.LockPatternUtils; 69 import com.android.server.LocalServices; 70 import com.android.server.am.ActivityManagerService; 71 import com.android.server.statusbar.StatusBarManagerInternal; 72 73 import java.io.PrintWriter; 74 import java.util.ArrayList; 75 import java.util.Arrays; 76 77 /** 78 * Helper class that deals with all things related to task locking. This includes the screen pinning 79 * mode that can be launched via System UI as well as the fully locked mode that can be achieved 80 * on fully managed devices. 81 * 82 * Note: All methods in this class should only be called with the ActivityTaskManagerService lock 83 * held. 84 * 85 * @see Activity#startLockTask() 86 * @see Activity#stopLockTask() 87 */ 88 public class LockTaskController { 89 private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_ATM; 90 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK; 91 92 @VisibleForTesting 93 static final int STATUS_BAR_MASK_LOCKED = StatusBarManager.DISABLE_MASK 94 & (~StatusBarManager.DISABLE_EXPAND) 95 & (~StatusBarManager.DISABLE_NOTIFICATION_TICKER) 96 & (~StatusBarManager.DISABLE_SYSTEM_INFO) 97 & (~StatusBarManager.DISABLE_BACK); 98 @VisibleForTesting 99 static final int STATUS_BAR_MASK_PINNED = StatusBarManager.DISABLE_MASK 100 & (~StatusBarManager.DISABLE_BACK) 101 & (~StatusBarManager.DISABLE_HOME) 102 & (~StatusBarManager.DISABLE_RECENT); 103 104 private static final SparseArray<Pair<Integer, Integer>> STATUS_BAR_FLAG_MAP_LOCKED; 105 static { 106 STATUS_BAR_FLAG_MAP_LOCKED = new SparseArray<>(); 107 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO, new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS))108 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO, 109 new Pair<>(StatusBarManager.DISABLE_CLOCK, StatusBarManager.DISABLE2_SYSTEM_ICONS)); 110 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS, new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS | StatusBarManager.DISABLE_NOTIFICATION_ALERTS, StatusBarManager.DISABLE2_NOTIFICATION_SHADE))111 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS, 112 new Pair<>(StatusBarManager.DISABLE_NOTIFICATION_ICONS 113 | StatusBarManager.DISABLE_NOTIFICATION_ALERTS, 114 StatusBarManager.DISABLE2_NOTIFICATION_SHADE)); 115 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME, new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE))116 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_HOME, 117 new Pair<>(StatusBarManager.DISABLE_HOME, StatusBarManager.DISABLE2_NONE)); 118 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW, new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE))119 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW, 120 new Pair<>(StatusBarManager.DISABLE_RECENT, StatusBarManager.DISABLE2_NONE)); 121 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS, new Pair<>(StatusBarManager.DISABLE_NONE, StatusBarManager.DISABLE2_GLOBAL_ACTIONS))122 STATUS_BAR_FLAG_MAP_LOCKED.append(DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS, 123 new Pair<>(StatusBarManager.DISABLE_NONE, 124 StatusBarManager.DISABLE2_GLOBAL_ACTIONS)); 125 } 126 127 /** Tag used for disabling of keyguard */ 128 private static final String LOCK_TASK_TAG = "Lock-to-App"; 129 130 private final IBinder mToken = new LockTaskToken(); 131 private final ActivityStackSupervisor mSupervisor; 132 private final Context mContext; 133 134 // The following system services cannot be final, because they do not exist when this class 135 // is instantiated during device boot 136 @VisibleForTesting 137 IStatusBarService mStatusBarService; 138 @VisibleForTesting 139 IDevicePolicyManager mDevicePolicyManager; 140 @VisibleForTesting 141 WindowManagerService mWindowManager; 142 @VisibleForTesting 143 LockPatternUtils mLockPatternUtils; 144 @VisibleForTesting 145 TelecomManager mTelecomManager; 146 147 /** 148 * The chain of tasks in LockTask mode, in the order of when they first entered LockTask mode. 149 * 150 * The first task in the list, which started the current LockTask session, is called the root 151 * task. It coincides with the Home task in a typical multi-app kiosk deployment. When there are 152 * more than one locked tasks, the root task can't be finished. Nor can it be moved to the back 153 * of the stack by {@link ActivityStack#moveTaskToBackLocked(int)}; 154 * 155 * Calling {@link Activity#stopLockTask()} on the root task will finish all tasks but itself in 156 * this list, and the device will exit LockTask mode. 157 * 158 * The list is empty if LockTask is inactive. 159 */ 160 private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>(); 161 162 /** 163 * Packages that are allowed to be launched into the lock task mode for each user. 164 */ 165 private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>(); 166 167 /** 168 * Features that are allowed by DPC to show during LockTask mode. 169 */ 170 private final SparseIntArray mLockTaskFeatures = new SparseIntArray(); 171 172 /** 173 * Store the current lock task mode. Possible values: 174 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, 175 * {@link ActivityManager#LOCK_TASK_MODE_PINNED} 176 */ 177 private int mLockTaskModeState = LOCK_TASK_MODE_NONE; 178 179 /** 180 * This is ActivityStackSupervisor's Handler. 181 */ 182 private final Handler mHandler; 183 184 /** 185 * Stores the user for which we're trying to dismiss the keyguard and then subsequently 186 * disable it. 187 * 188 * Tracking this ensures we don't mistakenly disable the keyguard if we've stopped trying to 189 * between the dismiss request and when it succeeds. 190 * 191 * Must only be accessed from the Handler thread. 192 */ 193 private int mPendingDisableFromDismiss = UserHandle.USER_NULL; 194 LockTaskController(Context context, ActivityStackSupervisor supervisor, Handler handler)195 LockTaskController(Context context, ActivityStackSupervisor supervisor, 196 Handler handler) { 197 mContext = context; 198 mSupervisor = supervisor; 199 mHandler = handler; 200 } 201 202 /** 203 * Set the window manager instance used in this class. This is necessary, because the window 204 * manager does not exist during instantiation of this class. 205 */ setWindowManager(WindowManagerService windowManager)206 void setWindowManager(WindowManagerService windowManager) { 207 mWindowManager = windowManager; 208 } 209 210 /** 211 * @return the current lock task state. This can be any of 212 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED}, 213 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}. 214 */ getLockTaskModeState()215 int getLockTaskModeState() { 216 return mLockTaskModeState; 217 } 218 219 /** 220 * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the 221 * back of the stack. 222 */ 223 @VisibleForTesting isTaskLocked(TaskRecord task)224 boolean isTaskLocked(TaskRecord task) { 225 return mLockTaskModeTasks.contains(task); 226 } 227 228 /** 229 * @return {@code true} whether this task first started the current LockTask session. 230 */ isRootTask(TaskRecord task)231 private boolean isRootTask(TaskRecord task) { 232 return mLockTaskModeTasks.indexOf(task) == 0; 233 } 234 235 /** 236 * @return whether the given activity is blocked from finishing, because it is the only activity 237 * of the last locked task and finishing it would mean that lock task mode is ended illegally. 238 */ activityBlockedFromFinish(ActivityRecord activity)239 boolean activityBlockedFromFinish(ActivityRecord activity) { 240 final TaskRecord task = activity.getTaskRecord(); 241 if (activity == task.getRootActivity() 242 && activity == task.getTopActivity() 243 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV 244 && isRootTask(task)) { 245 Slog.i(TAG, "Not finishing task in lock task mode"); 246 showLockTaskToast(); 247 return true; 248 } 249 return false; 250 } 251 252 /** 253 * @return whether the given task can be moved to the back of the stack with 254 * {@link ActivityStack#moveTaskToBackLocked(int)} 255 * @see #mLockTaskModeTasks 256 */ canMoveTaskToBack(TaskRecord task)257 boolean canMoveTaskToBack(TaskRecord task) { 258 if (isRootTask(task)) { 259 showLockTaskToast(); 260 return false; 261 } 262 return true; 263 } 264 265 /** 266 * @return whether the requested task is allowed to be locked (either whitelisted, or declares 267 * lockTaskMode="always" in the manifest). 268 */ isTaskWhitelisted(TaskRecord task)269 boolean isTaskWhitelisted(TaskRecord task) { 270 switch(task.mLockTaskAuth) { 271 case LOCK_TASK_AUTH_WHITELISTED: 272 case LOCK_TASK_AUTH_LAUNCHABLE: 273 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: 274 return true; 275 case LOCK_TASK_AUTH_PINNABLE: 276 case LOCK_TASK_AUTH_DONT_LOCK: 277 default: 278 return false; 279 } 280 } 281 282 /** 283 * @return whether the requested task is disallowed to be launched. 284 */ isLockTaskModeViolation(TaskRecord task)285 boolean isLockTaskModeViolation(TaskRecord task) { 286 return isLockTaskModeViolation(task, false); 287 } 288 289 /** 290 * @param isNewClearTask whether the task would be cleared as part of the operation. 291 * @return whether the requested task is disallowed to be launched. 292 */ isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask)293 boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) { 294 if (isLockTaskModeViolationInternal(task, isNewClearTask)) { 295 showLockTaskToast(); 296 return true; 297 } 298 return false; 299 } 300 301 /** 302 * @return the root task of the lock task. 303 */ getRootTask()304 TaskRecord getRootTask() { 305 if (mLockTaskModeTasks.isEmpty()) { 306 return null; 307 } 308 return mLockTaskModeTasks.get(0); 309 } 310 isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask)311 private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) { 312 // TODO: Double check what's going on here. If the task is already in lock task mode, it's 313 // likely whitelisted, so will return false below. 314 if (isTaskLocked(task) && !isNewClearTask) { 315 // If the task is already at the top and won't be cleared, then allow the operation 316 return false; 317 } 318 319 // Allow recents activity if enabled by policy 320 if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) { 321 return false; 322 } 323 324 // Allow emergency calling when the device is protected by a locked keyguard 325 if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) { 326 return false; 327 } 328 329 return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty()); 330 } 331 isRecentsAllowed(int userId)332 private boolean isRecentsAllowed(int userId) { 333 return (getLockTaskFeaturesForUser(userId) 334 & DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW) != 0; 335 } 336 isKeyguardAllowed(int userId)337 private boolean isKeyguardAllowed(int userId) { 338 return (getLockTaskFeaturesForUser(userId) 339 & DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD) != 0; 340 } 341 isEmergencyCallTask(TaskRecord task)342 private boolean isEmergencyCallTask(TaskRecord task) { 343 final Intent intent = task.intent; 344 if (intent == null) { 345 return false; 346 } 347 348 // 1. The emergency keypad activity launched on top of the keyguard 349 if (EMERGENCY_DIALER_COMPONENT.equals(intent.getComponent())) { 350 return true; 351 } 352 353 // 2. The intent sent by the keypad, which is handled by Telephony 354 if (ACTION_CALL_EMERGENCY.equals(intent.getAction())) { 355 return true; 356 } 357 358 // 3. Telephony then starts the default package for making the call 359 final TelecomManager tm = getTelecomManager(); 360 final String dialerPackage = tm != null ? tm.getSystemDialerPackage() : null; 361 if (dialerPackage != null && dialerPackage.equals(intent.getComponent().getPackageName())) { 362 return true; 363 } 364 365 return false; 366 } 367 368 /** 369 * Stop the current lock task mode. 370 * 371 * This is called by {@link ActivityManagerService} and performs various checks before actually 372 * finishing the locked task. 373 * 374 * @param task the task that requested the end of lock task mode ({@code null} for quitting app 375 * pinning mode) 376 * @param isSystemCaller indicates whether this request comes from the system via 377 * {@link ActivityTaskManagerService#stopSystemLockTaskMode()}. If 378 * {@code true}, it means the user intends to stop pinned mode through UI; 379 * otherwise, it's called by an app and we need to stop locked or pinned 380 * mode, subject to checks. 381 * @param callingUid the caller that requested the end of lock task mode. 382 * @throws IllegalArgumentException if the calling task is invalid (e.g., {@code null} or not in 383 * foreground) 384 * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if 385 * they differ from the one that launched lock task mode. 386 */ stopLockTaskMode(@ullable TaskRecord task, boolean isSystemCaller, int callingUid)387 void stopLockTaskMode(@Nullable TaskRecord task, boolean isSystemCaller, int callingUid) { 388 if (mLockTaskModeState == LOCK_TASK_MODE_NONE) { 389 return; 390 } 391 392 if (isSystemCaller) { 393 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { 394 clearLockedTasks("stopAppPinning"); 395 } else { 396 Slog.e(TAG_LOCKTASK, "Attempted to stop LockTask with isSystemCaller=true"); 397 showLockTaskToast(); 398 } 399 400 } else { 401 // Ensure calling activity is not null 402 if (task == null) { 403 throw new IllegalArgumentException("can't stop LockTask for null task"); 404 } 405 406 // Ensure the same caller for startLockTaskMode and stopLockTaskMode. 407 // It is possible lockTaskMode was started by the system process because 408 // android:lockTaskMode is set to a locking value in the application manifest 409 // instead of the app calling startLockTaskMode. In this case 410 // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the 411 // {@link TaskRecord.effectiveUid} instead. Also caller with 412 // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task. 413 if (callingUid != task.mLockTaskUid 414 && (task.mLockTaskUid != 0 || callingUid != task.effectiveUid)) { 415 throw new SecurityException("Invalid uid, expected " + task.mLockTaskUid 416 + " callingUid=" + callingUid + " effectiveUid=" + task.effectiveUid); 417 } 418 419 // We don't care if it's pinned or locked mode; this will stop it anyways. 420 clearLockedTask(task); 421 } 422 } 423 424 /** 425 * Clear all locked tasks and request the end of LockTask mode. 426 * 427 * This method is called by UserController when starting a new foreground user, and, 428 * unlike {@link #stopLockTaskMode(TaskRecord, boolean, int)}, it doesn't perform the checks. 429 */ clearLockedTasks(String reason)430 void clearLockedTasks(String reason) { 431 if (DEBUG_LOCKTASK) Slog.i(TAG_LOCKTASK, "clearLockedTasks: " + reason); 432 if (!mLockTaskModeTasks.isEmpty()) { 433 clearLockedTask(mLockTaskModeTasks.get(0)); 434 } 435 } 436 437 /** 438 * Clear one locked task from LockTask mode. 439 * 440 * If the requested task is the root task (see {@link #mLockTaskModeTasks}), then all locked 441 * tasks are cleared. Otherwise, only the requested task is cleared. LockTask mode is stopped 442 * when the last locked task is cleared. 443 * 444 * @param task the task to be cleared from LockTask mode. 445 */ clearLockedTask(final TaskRecord task)446 void clearLockedTask(final TaskRecord task) { 447 if (task == null || mLockTaskModeTasks.isEmpty()) return; 448 449 if (task == mLockTaskModeTasks.get(0)) { 450 // We're removing the root task while there are other locked tasks. Therefore we should 451 // clear all locked tasks in reverse order. 452 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx > 0; --taskNdx) { 453 clearLockedTask(mLockTaskModeTasks.get(taskNdx)); 454 } 455 } 456 457 removeLockedTask(task); 458 if (mLockTaskModeTasks.isEmpty()) { 459 return; 460 } 461 task.performClearTaskLocked(); 462 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities(); 463 } 464 465 /** 466 * Remove the given task from the locked task list. If this was the last task in the list, 467 * lock task mode is stopped. 468 */ removeLockedTask(final TaskRecord task)469 private void removeLockedTask(final TaskRecord task) { 470 if (!mLockTaskModeTasks.remove(task)) { 471 return; 472 } 473 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: removed " + task); 474 if (mLockTaskModeTasks.isEmpty()) { 475 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task + 476 " last task, reverting locktask mode. Callers=" + Debug.getCallers(3)); 477 mHandler.post(() -> performStopLockTask(task.userId)); 478 } 479 } 480 481 // This method should only be called on the handler thread performStopLockTask(int userId)482 private void performStopLockTask(int userId) { 483 // When lock task ends, we enable the status bars. 484 try { 485 setStatusBarState(LOCK_TASK_MODE_NONE, userId); 486 setKeyguardState(LOCK_TASK_MODE_NONE, userId); 487 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { 488 lockKeyguardIfNeeded(); 489 } 490 if (getDevicePolicyManager() != null) { 491 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId); 492 } 493 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { 494 getStatusBarService().showPinningEnterExitToast(false /* entering */); 495 } 496 mWindowManager.onLockTaskStateChanged(LOCK_TASK_MODE_NONE); 497 } catch (RemoteException ex) { 498 throw new RuntimeException(ex); 499 } finally { 500 mLockTaskModeState = LOCK_TASK_MODE_NONE; 501 } 502 } 503 504 /** 505 * Show the lock task violation toast. Currently we only show toast for screen pinning mode, and 506 * no-op if the device is in locked mode. 507 */ showLockTaskToast()508 void showLockTaskToast() { 509 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) { 510 try { 511 getStatusBarService().showPinningEscapeToast(); 512 } catch (RemoteException e) { 513 Slog.e(TAG, "Failed to send pinning escape toast", e); 514 } 515 } 516 } 517 518 // Starting lock task 519 520 /** 521 * Method to start lock task mode on a given task. 522 * 523 * @param task the task that should be locked. 524 * @param isSystemCaller indicates whether this request was initiated by the system via 525 * {@link ActivityTaskManagerService#startSystemLockTaskMode(int)}. If 526 * {@code true}, this intends to start pinned mode; otherwise, we look 527 * at the calling task's mLockTaskAuth to decide which mode to start. 528 * @param callingUid the caller that requested the launch of lock task mode. 529 */ startLockTaskMode(@onNull TaskRecord task, boolean isSystemCaller, int callingUid)530 void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemCaller, int callingUid) { 531 if (!isSystemCaller) { 532 task.mLockTaskUid = callingUid; 533 if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) { 534 // startLockTask() called by app, but app is not part of lock task whitelist. Show 535 // app pinning request. We will come back here with isSystemCaller true. 536 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user"); 537 StatusBarManagerInternal statusBarManager = LocalServices.getService( 538 StatusBarManagerInternal.class); 539 if (statusBarManager != null) { 540 statusBarManager.showScreenPinningRequest(task.taskId); 541 } 542 return; 543 } 544 } 545 546 // System can only initiate screen pinning, not full lock task mode 547 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 548 isSystemCaller ? "Locking pinned" : "Locking fully"); 549 setLockTaskMode(task, isSystemCaller ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED, 550 "startLockTask", true); 551 } 552 553 /** 554 * Start lock task mode on the given task. 555 * @param lockTaskModeState whether fully locked or pinned mode. 556 * @param andResume whether the task should be brought to foreground as part of the operation. 557 */ setLockTaskMode(@onNull TaskRecord task, int lockTaskModeState, String reason, boolean andResume)558 private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState, 559 String reason, boolean andResume) { 560 // Should have already been checked, but do it again. 561 if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) { 562 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, 563 "setLockTaskMode: Can't lock due to auth"); 564 return; 565 } 566 if (isLockTaskModeViolation(task)) { 567 Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task."); 568 return; 569 } 570 571 final Intent taskIntent = task.intent; 572 if (mLockTaskModeTasks.isEmpty() && taskIntent != null) { 573 mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId); 574 // Start lock task on the handler thread 575 mHandler.post(() -> performStartLockTask( 576 taskIntent.getComponent().getPackageName(), 577 task.userId, 578 lockTaskModeState)); 579 } 580 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task + 581 " Callers=" + Debug.getCallers(4)); 582 583 if (!mLockTaskModeTasks.contains(task)) { 584 mLockTaskModeTasks.add(task); 585 } 586 587 if (task.mLockTaskUid == -1) { 588 task.mLockTaskUid = task.effectiveUid; 589 } 590 591 if (andResume) { 592 mSupervisor.findTaskToMoveToFront(task, 0, null, reason, 593 lockTaskModeState != LOCK_TASK_MODE_NONE); 594 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities(); 595 final ActivityStack stack = task.getStack(); 596 if (stack != null) { 597 stack.getDisplay().mDisplayContent.executeAppTransition(); 598 } 599 } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) { 600 mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, 601 DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */); 602 } 603 } 604 605 // This method should only be called on the handler thread performStartLockTask(String packageName, int userId, int lockTaskModeState)606 private void performStartLockTask(String packageName, int userId, int lockTaskModeState) { 607 // When lock task starts, we disable the status bars. 608 try { 609 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) { 610 getStatusBarService().showPinningEnterExitToast(true /* entering */); 611 } 612 mWindowManager.onLockTaskStateChanged(lockTaskModeState); 613 mLockTaskModeState = lockTaskModeState; 614 setStatusBarState(lockTaskModeState, userId); 615 setKeyguardState(lockTaskModeState, userId); 616 if (getDevicePolicyManager() != null) { 617 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId); 618 } 619 } catch (RemoteException ex) { 620 throw new RuntimeException(ex); 621 } 622 } 623 624 /** 625 * Update packages that are allowed to be launched in lock task mode. 626 * @param userId Which user this whitelist is associated with 627 * @param packages The whitelist of packages allowed in lock task mode 628 * @see #mLockTaskPackages 629 */ updateLockTaskPackages(int userId, String[] packages)630 void updateLockTaskPackages(int userId, String[] packages) { 631 mLockTaskPackages.put(userId, packages); 632 633 boolean taskChanged = false; 634 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) { 635 final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx); 636 final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE 637 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED; 638 lockedTask.setLockTaskAuth(); 639 final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE 640 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED; 641 642 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED 643 || lockedTask.userId != userId 644 || !wasWhitelisted || isWhitelisted) { 645 continue; 646 } 647 648 // Terminate locked tasks that have recently lost whitelist authorization. 649 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " + 650 lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString()); 651 removeLockedTask(lockedTask); 652 lockedTask.performClearTaskLocked(); 653 taskChanged = true; 654 } 655 656 for (int displayNdx = mSupervisor.mRootActivityContainer.getChildCount() - 1; 657 displayNdx >= 0; --displayNdx) { 658 mSupervisor.mRootActivityContainer.getChildAt(displayNdx).onLockTaskPackagesUpdated(); 659 } 660 661 final ActivityRecord r = mSupervisor.mRootActivityContainer.topRunningActivity(); 662 final TaskRecord task = (r != null) ? r.getTaskRecord() : null; 663 if (mLockTaskModeTasks.isEmpty() && task!= null 664 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) { 665 // This task must have just been authorized. 666 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, 667 "onLockTaskPackagesUpdated: starting new locktask task=" + task); 668 setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false); 669 taskChanged = true; 670 } 671 672 if (taskChanged) { 673 mSupervisor.mRootActivityContainer.resumeFocusedStacksTopActivities(); 674 } 675 } 676 isPackageWhitelisted(int userId, String pkg)677 boolean isPackageWhitelisted(int userId, String pkg) { 678 if (pkg == null) { 679 return false; 680 } 681 String[] whitelist; 682 whitelist = mLockTaskPackages.get(userId); 683 if (whitelist == null) { 684 return false; 685 } 686 for (String whitelistedPkg : whitelist) { 687 if (pkg.equals(whitelistedPkg)) { 688 return true; 689 } 690 } 691 return false; 692 } 693 694 /** 695 * Update the UI features that are enabled for LockTask mode. 696 * @param userId Which user these feature flags are associated with 697 * @param flags Bitfield of feature flags 698 * @see DevicePolicyManager#setLockTaskFeatures(ComponentName, int) 699 */ updateLockTaskFeatures(int userId, int flags)700 void updateLockTaskFeatures(int userId, int flags) { 701 int oldFlags = getLockTaskFeaturesForUser(userId); 702 if (flags == oldFlags) { 703 return; 704 } 705 706 mLockTaskFeatures.put(userId, flags); 707 if (!mLockTaskModeTasks.isEmpty() && userId == mLockTaskModeTasks.get(0).userId) { 708 mHandler.post(() -> { 709 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) { 710 setStatusBarState(mLockTaskModeState, userId); 711 setKeyguardState(mLockTaskModeState, userId); 712 } 713 }); 714 } 715 } 716 717 /** 718 * Helper method for configuring the status bar disabled state. 719 * Should only be called on the handler thread to avoid race. 720 */ setStatusBarState(int lockTaskModeState, int userId)721 private void setStatusBarState(int lockTaskModeState, int userId) { 722 IStatusBarService statusBar = getStatusBarService(); 723 if (statusBar == null) { 724 Slog.e(TAG, "Can't find StatusBarService"); 725 return; 726 } 727 728 // Default state, when lockTaskModeState == LOCK_TASK_MODE_NONE 729 int flags1 = StatusBarManager.DISABLE_NONE; 730 int flags2 = StatusBarManager.DISABLE2_NONE; 731 732 if (lockTaskModeState == LOCK_TASK_MODE_PINNED) { 733 flags1 = STATUS_BAR_MASK_PINNED; 734 735 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) { 736 int lockTaskFeatures = getLockTaskFeaturesForUser(userId); 737 Pair<Integer, Integer> statusBarFlags = getStatusBarDisableFlags(lockTaskFeatures); 738 flags1 = statusBarFlags.first; 739 flags2 = statusBarFlags.second; 740 } 741 742 try { 743 statusBar.disable(flags1, mToken, mContext.getPackageName()); 744 statusBar.disable2(flags2, mToken, mContext.getPackageName()); 745 } catch (RemoteException e) { 746 Slog.e(TAG, "Failed to set status bar flags", e); 747 } 748 } 749 750 /** 751 * Helper method for configuring the keyguard disabled state. 752 * Should only be called on the handler thread to avoid race. 753 */ setKeyguardState(int lockTaskModeState, int userId)754 private void setKeyguardState(int lockTaskModeState, int userId) { 755 mPendingDisableFromDismiss = UserHandle.USER_NULL; 756 if (lockTaskModeState == LOCK_TASK_MODE_NONE) { 757 mWindowManager.reenableKeyguard(mToken, userId); 758 759 } else if (lockTaskModeState == LOCK_TASK_MODE_LOCKED) { 760 if (isKeyguardAllowed(userId)) { 761 mWindowManager.reenableKeyguard(mToken, userId); 762 } else { 763 // If keyguard is not secure and it is locked, dismiss the keyguard before 764 // disabling it, which avoids the platform to think the keyguard is still on. 765 if (mWindowManager.isKeyguardLocked() && !mWindowManager.isKeyguardSecure(userId)) { 766 mPendingDisableFromDismiss = userId; 767 mWindowManager.dismissKeyguard(new IKeyguardDismissCallback.Stub() { 768 @Override 769 public void onDismissError() throws RemoteException { 770 Slog.i(TAG, "setKeyguardState: failed to dismiss keyguard"); 771 } 772 773 @Override 774 public void onDismissSucceeded() throws RemoteException { 775 mHandler.post( 776 () -> { 777 if (mPendingDisableFromDismiss == userId) { 778 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, 779 userId); 780 mPendingDisableFromDismiss = UserHandle.USER_NULL; 781 } 782 }); 783 } 784 785 @Override 786 public void onDismissCancelled() throws RemoteException { 787 Slog.i(TAG, "setKeyguardState: dismiss cancelled"); 788 } 789 }, null); 790 } else { 791 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId); 792 } 793 } 794 795 } else { // lockTaskModeState == LOCK_TASK_MODE_PINNED 796 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG, userId); 797 } 798 } 799 800 /** 801 * Helper method for locking the device immediately. This may be necessary when the device 802 * leaves the pinned mode. 803 */ lockKeyguardIfNeeded()804 private void lockKeyguardIfNeeded() { 805 if (shouldLockKeyguard()) { 806 mWindowManager.lockNow(null); 807 mWindowManager.dismissKeyguard(null /* callback */, null /* message */); 808 getLockPatternUtils().requireCredentialEntry(USER_ALL); 809 } 810 } 811 shouldLockKeyguard()812 private boolean shouldLockKeyguard() { 813 // This functionality should be kept consistent with 814 // com.android.settings.security.ScreenPinningSettings (see b/127605586) 815 try { 816 return Settings.Secure.getIntForUser( 817 mContext.getContentResolver(), 818 Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, USER_CURRENT) != 0; 819 } catch (Settings.SettingNotFoundException e) { 820 // Log to SafetyNet for b/127605586 821 android.util.EventLog.writeEvent(0x534e4554, "127605586", -1, ""); 822 return getLockPatternUtils().isSecure(USER_CURRENT); 823 } 824 } 825 826 /** 827 * Translates from LockTask feature flags to StatusBarManager disable and disable2 flags. 828 * @param lockTaskFlags Bitfield of flags as per 829 * {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)} 830 * @return A {@link Pair} of {@link StatusBarManager#disable(int)} and 831 * {@link StatusBarManager#disable2(int)} flags 832 */ 833 @VisibleForTesting getStatusBarDisableFlags(int lockTaskFlags)834 Pair<Integer, Integer> getStatusBarDisableFlags(int lockTaskFlags) { 835 // Everything is disabled by default 836 int flags1 = StatusBarManager.DISABLE_MASK; 837 int flags2 = StatusBarManager.DISABLE2_MASK; 838 for (int i = STATUS_BAR_FLAG_MAP_LOCKED.size() - 1; i >= 0; i--) { 839 Pair<Integer, Integer> statusBarFlags = STATUS_BAR_FLAG_MAP_LOCKED.valueAt(i); 840 if ((STATUS_BAR_FLAG_MAP_LOCKED.keyAt(i) & lockTaskFlags) != 0) { 841 flags1 &= ~statusBarFlags.first; 842 flags2 &= ~statusBarFlags.second; 843 } 844 } 845 // Some flags are not used for LockTask purposes, so we mask them 846 flags1 &= STATUS_BAR_MASK_LOCKED; 847 return new Pair<>(flags1, flags2); 848 } 849 850 /** 851 * Gets the cached value of LockTask feature flags for a specific user. 852 */ getLockTaskFeaturesForUser(int userId)853 private int getLockTaskFeaturesForUser(int userId) { 854 return mLockTaskFeatures.get(userId, DevicePolicyManager.LOCK_TASK_FEATURE_NONE); 855 } 856 857 // Should only be called on the handler thread 858 @Nullable getStatusBarService()859 private IStatusBarService getStatusBarService() { 860 if (mStatusBarService == null) { 861 mStatusBarService = IStatusBarService.Stub.asInterface( 862 ServiceManager.checkService(STATUS_BAR_SERVICE)); 863 if (mStatusBarService == null) { 864 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE"); 865 } 866 } 867 return mStatusBarService; 868 } 869 870 // Should only be called on the handler thread 871 @Nullable getDevicePolicyManager()872 private IDevicePolicyManager getDevicePolicyManager() { 873 if (mDevicePolicyManager == null) { 874 mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface( 875 ServiceManager.checkService(DEVICE_POLICY_SERVICE)); 876 if (mDevicePolicyManager == null) { 877 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE"); 878 } 879 } 880 return mDevicePolicyManager; 881 } 882 883 @NonNull getLockPatternUtils()884 private LockPatternUtils getLockPatternUtils() { 885 if (mLockPatternUtils == null) { 886 // We don't preserve the LPU object to save memory 887 return new LockPatternUtils(mContext); 888 } 889 return mLockPatternUtils; 890 } 891 892 @Nullable getTelecomManager()893 private TelecomManager getTelecomManager() { 894 if (mTelecomManager == null) { 895 // We don't preserve the TelecomManager object to save memory 896 return mContext.getSystemService(TelecomManager.class); 897 } 898 return mTelecomManager; 899 } 900 dump(PrintWriter pw, String prefix)901 public void dump(PrintWriter pw, String prefix) { 902 pw.println(prefix + "LockTaskController"); 903 prefix = prefix + " "; 904 pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString()); 905 pw.println(prefix + "mLockTaskModeTasks="); 906 for (int i = 0; i < mLockTaskModeTasks.size(); ++i) { 907 pw.println(prefix + " #" + i + " " + mLockTaskModeTasks.get(i)); 908 } 909 pw.println(prefix + "mLockTaskPackages (userId:packages)="); 910 for (int i = 0; i < mLockTaskPackages.size(); ++i) { 911 pw.println(prefix + " u" + mLockTaskPackages.keyAt(i) 912 + ":" + Arrays.toString(mLockTaskPackages.valueAt(i))); 913 } 914 } 915 lockTaskModeToString()916 private String lockTaskModeToString() { 917 switch (mLockTaskModeState) { 918 case LOCK_TASK_MODE_LOCKED: 919 return "LOCKED"; 920 case LOCK_TASK_MODE_PINNED: 921 return "PINNED"; 922 case LOCK_TASK_MODE_NONE: 923 return "NONE"; 924 default: return "unknown=" + mLockTaskModeState; 925 } 926 } 927 928 /** Marker class for the token used to disable keyguard. */ 929 static class LockTaskToken extends Binder { LockTaskToken()930 private LockTaskToken() { 931 } 932 } 933 } 934