blob: 241e5839114402f665690e8714216972ca134240 [file] [log] [blame]
Benjamin Franza83859f2017-07-03 16:34:14 +01001/*
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
17package com.android.server.am;
18
19import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
20import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
21import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
22import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
23import static android.app.StatusBarManager.DISABLE_BACK;
24import static android.app.StatusBarManager.DISABLE_HOME;
25import static android.app.StatusBarManager.DISABLE_MASK;
26import static android.app.StatusBarManager.DISABLE_NONE;
27import static android.app.StatusBarManager.DISABLE_RECENT;
28import static android.content.Context.DEVICE_POLICY_SERVICE;
29import static android.content.Context.STATUS_BAR_SERVICE;
30import static android.os.UserHandle.USER_ALL;
Amith Yamasani7cbbf2222017-08-30 14:22:37 -070031import static android.os.UserHandle.USER_CURRENT;
Benjamin Franza83859f2017-07-03 16:34:14 +010032import static android.provider.Settings.Secure.LOCK_TO_APP_EXIT_LOCKED;
33import static android.view.Display.DEFAULT_DISPLAY;
Charles He520b2832017-09-02 15:27:16 +010034
Benjamin Franza83859f2017-07-03 16:34:14 +010035import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
36import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
37import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
38import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
39import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
40import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
41import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
42import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
43import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
44
45import android.annotation.NonNull;
46import android.annotation.Nullable;
47import android.app.Activity;
48import android.app.ActivityManager;
49import android.app.admin.IDevicePolicyManager;
50import android.content.Context;
51import android.os.Binder;
52import android.os.Debug;
53import android.os.Handler;
54import android.os.IBinder;
55import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.provider.Settings;
58import android.util.Slog;
Charles He520b2832017-09-02 15:27:16 +010059import android.util.SparseArray;
Benjamin Franza83859f2017-07-03 16:34:14 +010060
Charles He520b2832017-09-02 15:27:16 +010061import com.android.internal.annotations.GuardedBy;
Benjamin Franza83859f2017-07-03 16:34:14 +010062import com.android.internal.annotations.VisibleForTesting;
63import com.android.internal.statusbar.IStatusBarService;
64import com.android.internal.widget.LockPatternUtils;
65import com.android.server.LocalServices;
66import com.android.server.statusbar.StatusBarManagerInternal;
67import com.android.server.wm.WindowManagerService;
68
69import java.io.PrintWriter;
70import java.util.ArrayList;
Charles He520b2832017-09-02 15:27:16 +010071import java.util.Arrays;
Benjamin Franza83859f2017-07-03 16:34:14 +010072
73/**
74 * Helper class that deals with all things related to task locking. This includes the screen pinning
75 * mode that can be launched via System UI as well as the fully locked mode that can be achieved
76 * on fully managed devices.
77 *
78 * Note: All methods in this class should only be called with the ActivityManagerService lock held.
79 *
80 * @see Activity#startLockTask()
81 * @see Activity#stopLockTask()
82 */
83public class LockTaskController {
84 private static final String TAG = TAG_WITH_CLASS_NAME ? "LockTaskController" : TAG_AM;
85 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
86
87 @VisibleForTesting
88 static final int STATUS_BAR_MASK_LOCKED = DISABLE_MASK
89 & (~DISABLE_BACK);
90 @VisibleForTesting
91 static final int STATUS_BAR_MASK_PINNED = DISABLE_MASK
92 & (~DISABLE_BACK)
93 & (~DISABLE_HOME)
94 & (~DISABLE_RECENT);
95
96 /** Tag used for disabling of keyguard */
97 private static final String LOCK_TASK_TAG = "Lock-to-App";
98
99 private final IBinder mToken = new Binder();
100 private final ActivityStackSupervisor mSupervisor;
101 private final Context mContext;
102
103 // The following system services cannot be final, because they do not exist when this class
104 // is instantiated during device boot
105 @VisibleForTesting
106 IStatusBarService mStatusBarService;
107 @VisibleForTesting
108 IDevicePolicyManager mDevicePolicyManager;
109 @VisibleForTesting
110 WindowManagerService mWindowManager;
111 @VisibleForTesting
112 LockPatternUtils mLockPatternUtils;
113
114 /**
115 * Helper that is responsible for showing the right toast when a disallowed activity operation
116 * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
117 * fully locked mode we only show that unlocking is blocked.
118 */
119 @VisibleForTesting
120 LockTaskNotify mLockTaskNotify;
121
122 /**
123 * The chain of tasks in lockTask mode. The current frontmost task is at the top, and tasks
124 * may be finished until there is only one entry left. If this is empty the system is not
125 * in lockTask mode.
126 */
127 private final ArrayList<TaskRecord> mLockTaskModeTasks = new ArrayList<>();
128
129 /**
Charles He520b2832017-09-02 15:27:16 +0100130 * Packages that are allowed to be launched into the lock task mode for each user.
131 */
132 private final SparseArray<String[]> mLockTaskPackages = new SparseArray<>();
133
134 /**
Benjamin Franza83859f2017-07-03 16:34:14 +0100135 * Store the current lock task mode. Possible values:
136 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
137 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
138 */
139 private int mLockTaskModeState;
140
141 /**
142 * This is ActivityStackSupervisor's Handler.
143 */
144 private final Handler mHandler;
145
146 LockTaskController(Context context, ActivityStackSupervisor supervisor,
147 Handler handler) {
148 mContext = context;
149 mSupervisor = supervisor;
150 mHandler = handler;
151 }
152
153 /**
154 * Set the window manager instance used in this class. This is necessary, because the window
155 * manager does not exist during instantiation of this class.
156 */
157 void setWindowManager(WindowManagerService windowManager) {
158 mWindowManager = windowManager;
159 }
160
161 /**
162 * @return the current lock task state. This can be any of
163 * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
164 * {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
165 */
166 int getLockTaskModeState() {
167 return mLockTaskModeState;
168 }
169
170 /**
Charles He520b2832017-09-02 15:27:16 +0100171 * @return whether the given task is locked at the moment. Locked tasks cannot be moved to the
172 * back of the stack.
Benjamin Franza83859f2017-07-03 16:34:14 +0100173 */
174 boolean checkLockedTask(TaskRecord task) {
175 if (mLockTaskModeTasks.contains(task)) {
176 showLockTaskToast();
177 return true;
178 }
179 return false;
180 }
181
182 /**
183 * @return whether the given activity is blocked from finishing, because it is the root activity
184 * of the last locked task and finishing it would mean that lock task mode is ended illegally.
185 */
186 boolean activityBlockedFromFinish(ActivityRecord activity) {
187 TaskRecord task = activity.getTask();
188 if (activity == task.getRootActivity()
189 && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV
190 && mLockTaskModeTasks.size() == 1
191 && mLockTaskModeTasks.contains(task)) {
192 Slog.i(TAG, "Not finishing task in lock task mode");
193 showLockTaskToast();
194 return true;
195 }
196 return false;
197 }
198
199 /**
200 * @return whether the requested task is allowed to be launched.
201 */
202 boolean isLockTaskModeViolation(TaskRecord task) {
203 return isLockTaskModeViolation(task, false);
204 }
205
206 /**
207 * @param isNewClearTask whether the task would be cleared as part of the operation.
208 * @return whether the requested task is allowed to be launched.
209 */
210 boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
211 if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
212 showLockTaskToast();
213 return true;
214 }
215 return false;
216 }
217
218 private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
219 // TODO: Double check what's going on here. If the task is already in lock task mode, it's
220 // likely whitelisted, so will return false below.
221 if (getLockedTask() == task && !isNewClearTask) {
222 // If the task is already at the top and won't be cleared, then allow the operation
223 return false;
224 }
225 final int lockTaskAuth = task.mLockTaskAuth;
226 switch (lockTaskAuth) {
227 case LOCK_TASK_AUTH_DONT_LOCK:
228 return !mLockTaskModeTasks.isEmpty();
229 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
230 case LOCK_TASK_AUTH_LAUNCHABLE:
231 case LOCK_TASK_AUTH_WHITELISTED:
232 return false;
233 case LOCK_TASK_AUTH_PINNABLE:
234 // Pinnable tasks can't be launched on top of locktask tasks.
235 return !mLockTaskModeTasks.isEmpty();
236 default:
237 Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth);
238 return true;
239 }
240 }
241
242 /**
243 * Stop the current lock task mode.
244 *
245 * @param isSystemInitiated indicates whether this request was initiated by the system via
246 * {@link ActivityManagerService#stopSystemLockTaskMode()}.
247 * @param callingUid the caller that requested the end of lock task mode.
248 * @throws SecurityException if the caller is not authorized to stop the lock task mode, i.e. if
249 * they differ from the one that launched lock task mode.
250 */
251 void stopLockTaskMode(boolean isSystemInitiated, int callingUid) {
252 final TaskRecord lockTask = getLockedTask();
253 if (lockTask == null || mLockTaskModeState == LOCK_TASK_MODE_NONE) {
254 // Our work here is done.
255 return;
256 }
257
258 if (isSystemInitiated && mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
259 // As system can only start app pinning, we also only let it unlock in this mode.
260 showLockTaskToast();
261 return;
262 }
263
264 // Ensure the same caller for startLockTaskMode and stopLockTaskMode.
265 // It is possible lockTaskMode was started by the system process because
266 // android:lockTaskMode is set to a locking value in the application manifest
267 // instead of the app calling startLockTaskMode. In this case
268 // {@link TaskRecord.mLockTaskUid} will be 0, so we compare the callingUid to the
269 // {@link TaskRecord.effectiveUid} instead. Also caller with
270 // {@link MANAGE_ACTIVITY_STACKS} can stop any lock task.
271 if (!isSystemInitiated && callingUid != lockTask.mLockTaskUid
272 && (lockTask.mLockTaskUid != 0 || callingUid != lockTask.effectiveUid)) {
273 throw new SecurityException("Invalid uid, expected " + lockTask.mLockTaskUid
274 + " callingUid=" + callingUid + " effectiveUid=" + lockTask.effectiveUid);
275 }
276
277 clearLockTaskMode("stopLockTask");
278 }
279
280 /**
281 * Remove the given task from the locked task list. If this was the last task in the list,
282 * lock task mode is stopped.
283 */
284 void removeLockedTask(final TaskRecord task) {
285 if (!mLockTaskModeTasks.remove(task)) {
286 return;
287 }
288 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "removeLockedTask: removed " + task);
289 if (mLockTaskModeTasks.isEmpty()) {
290 // Last one.
291 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "removeLockedTask: task=" + task +
292 " last task, reverting locktask mode. Callers=" + Debug.getCallers(3));
293 mHandler.post(() -> performStopLockTask(task.userId));
294 }
295 }
296
297 /**
298 * Remove the topmost task from the locked task list. If this is the last task in the list, it
299 * will result in the end of locked task mode.
300 */
301 void clearLockTaskMode(String reason) {
302 // Take out of lock task mode if necessary
303 final TaskRecord lockedTask = getLockedTask();
304 if (lockedTask != null) {
305 removeLockedTask(lockedTask);
306 if (!mLockTaskModeTasks.isEmpty()) {
307 // There are locked tasks remaining, can only finish this task, not unlock it.
308 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
309 "setLockTaskMode: Tasks remaining, can't unlock");
310 lockedTask.performClearTaskLocked();
311 mSupervisor.resumeFocusedStackTopActivityLocked();
312 return;
313 }
314 }
315 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
316 "setLockTaskMode: No tasks to unlock. Callers=" + Debug.getCallers(4));
317 }
318
319 // This method should only be called on the handler thread
320 private void performStopLockTask(int userId) {
321 // When lock task ends, we enable the status bars.
322 try {
323 if (getStatusBarService() != null) {
324 getStatusBarService().disable(DISABLE_NONE, mToken,
325 mContext.getPackageName());
326 }
327 mWindowManager.reenableKeyguard(mToken);
328 if (getDevicePolicyManager() != null) {
329 getDevicePolicyManager().notifyLockTaskModeChanged(false, null, userId);
330 }
331 getLockTaskNotify().show(false);
332 try {
Amith Yamasani7cbbf2222017-08-30 14:22:37 -0700333 boolean shouldLockKeyguard = Settings.Secure.getIntForUser(
Benjamin Franza83859f2017-07-03 16:34:14 +0100334 mContext.getContentResolver(),
Amith Yamasani7cbbf2222017-08-30 14:22:37 -0700335 LOCK_TO_APP_EXIT_LOCKED,
336 USER_CURRENT) != 0;
Benjamin Franza83859f2017-07-03 16:34:14 +0100337 if (mLockTaskModeState == LOCK_TASK_MODE_PINNED && shouldLockKeyguard) {
338 mWindowManager.lockNow(null);
339 mWindowManager.dismissKeyguard(null /* callback */);
340 getLockPatternUtils().requireCredentialEntry(USER_ALL);
341 }
342 } catch (Settings.SettingNotFoundException e) {
343 // No setting, don't lock.
344 }
345 } catch (RemoteException ex) {
346 throw new RuntimeException(ex);
347 } finally {
348 mLockTaskModeState = LOCK_TASK_MODE_NONE;
349 }
350 }
351
352 /**
353 * Show the lock task violation toast.
354 */
355 void showLockTaskToast() {
356 mHandler.post(() -> getLockTaskNotify().showToast(mLockTaskModeState));
357 }
358
359 // Starting lock task
360
361 /**
362 * Method to start lock task mode on a given task.
363 *
364 * @param task the task that should be locked.
365 * @param isSystemInitiated indicates whether this request was initiated by the system via
366 * {@link ActivityManagerService#startSystemLockTaskMode(int)}.
367 * @param callingUid the caller that requested the launch of lock task mode.
368 */
369 void startLockTaskMode(@NonNull TaskRecord task, boolean isSystemInitiated,
370 int callingUid) {
371 if (!isSystemInitiated) {
372 task.mLockTaskUid = callingUid;
373 if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
374 // startLockTask() called by app, but app is not part of lock task whitelist. Show
375 // app pinning request. We will come back here with isSystemInitiated true.
376 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
377 StatusBarManagerInternal statusBarManager = LocalServices.getService(
378 StatusBarManagerInternal.class);
379 if (statusBarManager != null) {
380 statusBarManager.showScreenPinningRequest(task.taskId);
381 }
382 return;
383 }
384 }
385
386 // System can only initiate screen pinning, not full lock task mode
387 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, isSystemInitiated ? "Locking pinned" : "Locking fully");
388 setLockTaskMode(task, isSystemInitiated ? LOCK_TASK_MODE_PINNED : LOCK_TASK_MODE_LOCKED,
389 "startLockTask", true);
390 }
391
392 /**
393 * Start lock task mode on the given task.
394 * @param lockTaskModeState whether fully locked or pinned mode.
395 * @param andResume whether the task should be brought to foreground as part of the operation.
396 */
397 private void setLockTaskMode(@NonNull TaskRecord task, int lockTaskModeState,
398 String reason, boolean andResume) {
399 // Should have already been checked, but do it again.
400 if (task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
401 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK,
402 "setLockTaskMode: Can't lock due to auth");
403 return;
404 }
405 if (isLockTaskModeViolation(task)) {
406 Slog.e(TAG_LOCKTASK, "setLockTaskMode: Attempt to start an unauthorized lock task.");
407 return;
408 }
409
410 if (mLockTaskModeTasks.isEmpty()) {
411 // Start lock task on the handler thread
412 mHandler.post(() -> performStartLockTask(
413 task.intent.getComponent().getPackageName(),
414 task.userId,
415 lockTaskModeState));
416 }
417
418 // Add it or move it to the top.
419 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "setLockTaskMode: Locking to " + task +
420 " Callers=" + Debug.getCallers(4));
421 mLockTaskModeTasks.remove(task);
422 mLockTaskModeTasks.add(task);
423
424 if (task.mLockTaskUid == -1) {
425 task.mLockTaskUid = task.effectiveUid;
426 }
427
428 if (andResume) {
429 mSupervisor.findTaskToMoveToFrontLocked(task, 0, null, reason,
430 lockTaskModeState != LOCK_TASK_MODE_NONE);
431 mSupervisor.resumeFocusedStackTopActivityLocked();
432 mWindowManager.executeAppTransition();
433 } else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
434 mSupervisor.handleNonResizableTaskIfNeeded(task, INVALID_STACK_ID, DEFAULT_DISPLAY,
435 task.getStackId(), true /* forceNonResizable */);
436 }
437 }
438
439 // This method should only be called on the handler thread
440 private void performStartLockTask(String packageName, int userId, int lockTaskModeState) {
441 // When lock task starts, we disable the status bars.
442 try {
443 getLockTaskNotify().show(true);
444 mLockTaskModeState = lockTaskModeState;
445 if (getStatusBarService() != null) {
446 int flags = 0;
447 if (mLockTaskModeState == LOCK_TASK_MODE_LOCKED) {
448 flags = STATUS_BAR_MASK_LOCKED;
449 } else if (mLockTaskModeState == LOCK_TASK_MODE_PINNED) {
450 flags = STATUS_BAR_MASK_PINNED;
451 }
452 getStatusBarService().disable(flags, mToken, mContext.getPackageName());
453 }
454 mWindowManager.disableKeyguard(mToken, LOCK_TASK_TAG);
455 if (getDevicePolicyManager() != null) {
456 getDevicePolicyManager().notifyLockTaskModeChanged(true, packageName, userId);
457 }
458 } catch (RemoteException ex) {
459 throw new RuntimeException(ex);
460 }
461 }
462
463 /**
Charles He520b2832017-09-02 15:27:16 +0100464 * Update packages that are allowed to be launched in lock task mode.
465 * @param userId Which user this whitelist is associated with
466 * @param packages The whitelist of packages allowed in lock task mode
467 * @see #mLockTaskPackages
Benjamin Franza83859f2017-07-03 16:34:14 +0100468 */
Charles He520b2832017-09-02 15:27:16 +0100469 void updateLockTaskPackages(int userId, String[] packages) {
470 mLockTaskPackages.put(userId, packages);
471
472 boolean taskChanged = false;
Benjamin Franza83859f2017-07-03 16:34:14 +0100473 for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
474 final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
Charles He520b2832017-09-02 15:27:16 +0100475 final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
476 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
Benjamin Franza83859f2017-07-03 16:34:14 +0100477 lockedTask.setLockTaskAuth();
Charles He520b2832017-09-02 15:27:16 +0100478 final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
479 || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
480
481 if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
482 || lockedTask.userId != userId
483 || !wasWhitelisted || isWhitelisted) {
484 continue;
Benjamin Franza83859f2017-07-03 16:34:14 +0100485 }
Charles He520b2832017-09-02 15:27:16 +0100486
487 // Terminate locked tasks that have recently lost whitelist authorization.
488 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
489 lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
490 removeLockedTask(lockedTask);
491 lockedTask.performClearTaskLocked();
492 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100493 }
494
495 for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
496 ArrayList<ActivityStack> stacks = mSupervisor.getChildAt(displayNdx).mStacks;
497 for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
498 final ActivityStack stack = stacks.get(stackNdx);
499 stack.onLockTaskPackagesUpdatedLocked();
500 }
501 }
Charles He520b2832017-09-02 15:27:16 +0100502
Benjamin Franza83859f2017-07-03 16:34:14 +0100503 final ActivityRecord r = mSupervisor.topRunningActivityLocked();
Charles He520b2832017-09-02 15:27:16 +0100504 final TaskRecord task = (r != null) ? r.getTask() : null;
505 if (mLockTaskModeTasks.isEmpty() && task!= null
Benjamin Franza83859f2017-07-03 16:34:14 +0100506 && task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
507 // This task must have just been authorized.
508 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK,
509 "onLockTaskPackagesUpdated: starting new locktask task=" + task);
Charles He520b2832017-09-02 15:27:16 +0100510 setLockTaskMode(task, LOCK_TASK_MODE_LOCKED, "package updated", false);
511 taskChanged = true;
Benjamin Franza83859f2017-07-03 16:34:14 +0100512 }
Charles He520b2832017-09-02 15:27:16 +0100513
514 if (taskChanged) {
Benjamin Franza83859f2017-07-03 16:34:14 +0100515 mSupervisor.resumeFocusedStackTopActivityLocked();
516 }
517 }
518
Charles He520b2832017-09-02 15:27:16 +0100519 boolean isPackageWhitelisted(int userId, String pkg) {
520 if (pkg == null) {
521 return false;
522 }
523 String[] whitelist;
524 whitelist = mLockTaskPackages.get(userId);
525 if (whitelist == null) {
526 return false;
527 }
528 for (String whitelistedPkg : whitelist) {
529 if (pkg.equals(whitelistedPkg)) {
530 return true;
531 }
532 }
533 return false;
534 }
535
Benjamin Franza83859f2017-07-03 16:34:14 +0100536 /**
537 * @return the topmost locked task
538 */
539 private TaskRecord getLockedTask() {
540 final int top = mLockTaskModeTasks.size() - 1;
541 if (top >= 0) {
542 return mLockTaskModeTasks.get(top);
543 }
544 return null;
545 }
546
547 // Should only be called on the handler thread
548 @Nullable
549 private IStatusBarService getStatusBarService() {
550 if (mStatusBarService == null) {
551 mStatusBarService = IStatusBarService.Stub.asInterface(
552 ServiceManager.checkService(STATUS_BAR_SERVICE));
553 if (mStatusBarService == null) {
554 Slog.w("StatusBarManager", "warning: no STATUS_BAR_SERVICE");
555 }
556 }
557 return mStatusBarService;
558 }
559
560 // Should only be called on the handler thread
561 @Nullable
562 private IDevicePolicyManager getDevicePolicyManager() {
563 if (mDevicePolicyManager == null) {
564 mDevicePolicyManager = IDevicePolicyManager.Stub.asInterface(
565 ServiceManager.checkService(DEVICE_POLICY_SERVICE));
566 if (mDevicePolicyManager == null) {
567 Slog.w(TAG, "warning: no DEVICE_POLICY_SERVICE");
568 }
569 }
570 return mDevicePolicyManager;
571 }
572
573 @NonNull
574 private LockPatternUtils getLockPatternUtils() {
575 if (mLockPatternUtils == null) {
576 // We don't preserve the LPU object to save memory
577 return new LockPatternUtils(mContext);
578 }
579 return mLockPatternUtils;
580 }
581
582 // Should only be called on the handler thread
583 @NonNull
584 private LockTaskNotify getLockTaskNotify() {
585 if (mLockTaskNotify == null) {
586 mLockTaskNotify = new LockTaskNotify(mContext);
587 }
588 return mLockTaskNotify;
589 }
590
591 public void dump(PrintWriter pw, String prefix) {
Charles He520b2832017-09-02 15:27:16 +0100592 pw.println(prefix + "LockTaskController");
593 prefix = prefix + " ";
594 pw.println(prefix + "mLockTaskModeState=" + lockTaskModeToString());
595 pw.println(prefix + "mLockTaskModeTasks=");
596 for (int i = 0; i < mLockTaskModeTasks.size(); ++i) {
597 pw.println(prefix + " #" + i + " " + mLockTaskModeTasks.get(i));
598 }
599 pw.println(prefix + "mLockTaskPackages (userId:packages)=");
600 for (int i = 0; i < mLockTaskPackages.size(); ++i) {
601 pw.println(prefix + " u" + mLockTaskPackages.keyAt(i)
602 + ":" + Arrays.toString(mLockTaskPackages.valueAt(i)));
603 }
Benjamin Franza83859f2017-07-03 16:34:14 +0100604 }
605
606 private String lockTaskModeToString() {
607 switch (mLockTaskModeState) {
608 case LOCK_TASK_MODE_LOCKED:
609 return "LOCKED";
610 case LOCK_TASK_MODE_PINNED:
611 return "PINNED";
612 case LOCK_TASK_MODE_NONE:
613 return "NONE";
614 default: return "unknown=" + mLockTaskModeState;
615 }
616 }
617}