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