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