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