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