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