Android 屏幕固定功能实现依靠的是 LockTaskController.java 中变量 mLockTaskModeTasks,应用可以通过执行 Activity.startLockTask() 实现
public void startLockTask() {
try {
// Android 9 使用下面方式
// ActivityManager.getService().startLockTaskModeByToken(mToken);
// Android 11 使用下面方式
// ActivityTaskManager.getService().startLockTaskModeByToken(mToken);
} catch (RemoteException e) {
}
}
这个接口在 R 上有一点不同,新增了 ActivityTaskManagerService.java 类去执行 startLockTaskModeByToken 动作。在 startLockTaskModeByToken 方法中调用 LockTaskController.startLockTaskMode。
系统通过 LockTaskController.startLockTaskMode() 给 mLockTaskModeTasks.add 屏幕固定的应用。
系统通过 LockTaskController.stopLockTaskMode() 或 clearLockedTask() 清除 mLockTaskModeTasks 关闭屏幕固定。
系统在启动Activity时,走到 ActivityStarter.startActivityInner
中会调用 LockTaskController.isLockTaskModeViolation() 来判断是否有屏幕固定的,然后决定能不能继续启动 Activity
// 判断当前是不是违反屏幕固定规则,可用于activity启动时判断,能不能启动新的activity
private boolean isLockTaskModeViolationInternal(TaskRecord task, boolean isNewClearTask) {
// TODO: Double check what's going on here. If the task is already in lock task mode, it's
// likely whitelisted, so will return false below.
if (isTaskLocked(task) && !isNewClearTask) {
// If the task is already at the top and won't be cleared, then allow the operation
return false;
}
// Allow recents activity if enabled by policy
if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
return false;
}
// Allow emergency calling when the device is protected by a locked keyguard
if (isKeyguardAllowed(task.userId) && isEmergencyCallTask(task)) {
return false;
}
// 如果mLockTaskModeTasks是空的,表示未添加过屏幕固定
// 或者当前启动task符合系统规则,也可以
return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
}