Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d62f9650 authored by Charles He's avatar Charles He
Browse files

Enable Recents activity in LockTask mode.

In P, we introduce DevicePolicyManager.setLockTaskFeatures() API, which
lets the DPC enable the SystemUI Recents activity in LockTask mode. To
do this, we

1) Allow recents activity in LockTaskController (otherwise it'll be
blocked from starting as it's not whitelisted)

2) Clear the RecentTasks list, so that only whitelisted tasks remain in
the list (and therefore the recents UI)

Note that 2) is done even when Recents isn't enabled through the
setLockTaskFeatures() API.

Bug: 68238765
Test: runtest systemui
Test: bit FrameworksServicesTests:com.android.server.am.LockTaskControllerTest
Test: CTS verifier > CTS verifier > Managed provisioning > Device owner tests
      > LockTask UI
Change-Id: I63c524c4d9a68b87a63cecf1642ecebd94aa2bb0
parent a604a878
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -68,7 +68,6 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.app.AssistUtils;
import com.android.internal.os.BackgroundThread;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.UiOffloadThread;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsImpl;
@@ -372,7 +371,7 @@ public class SystemServicesProxy {
        if (mIam == null) return false;

        try {
            return mIam.isInLockTaskMode();
            return mIam.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_PINNED;
        } catch (RemoteException e) {
            return false;
        }
+31 −16
Original line number Diff line number Diff line
@@ -250,7 +250,24 @@ public class LockTaskController {
    }

    /**
     * @return whether the requested task is allowed to be launched.
     * @return whether the requested task is allowed to be locked (either whitelisted, or declares
     * lockTaskMode="always" in the manifest).
     */
    boolean isTaskWhitelisted(TaskRecord task) {
        switch(task.mLockTaskAuth) {
            case LOCK_TASK_AUTH_WHITELISTED:
            case LOCK_TASK_AUTH_LAUNCHABLE:
            case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
                return true;
            case LOCK_TASK_AUTH_PINNABLE:
            case LOCK_TASK_AUTH_DONT_LOCK:
            default:
                return false;
        }
    }

    /**
     * @return whether the requested task is disallowed to be launched.
     */
    boolean isLockTaskModeViolation(TaskRecord task) {
        return isLockTaskModeViolation(task, false);
@@ -258,7 +275,7 @@ public class LockTaskController {

    /**
     * @param isNewClearTask whether the task would be cleared as part of the operation.
     * @return whether the requested task is allowed to be launched.
     * @return whether the requested task is disallowed to be launched.
     */
    boolean isLockTaskModeViolation(TaskRecord task, boolean isNewClearTask) {
        if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
@@ -275,21 +292,18 @@ public class LockTaskController {
            // If the task is already at the top and won't be cleared, then allow the operation
            return false;
        }
        final int lockTaskAuth = task.mLockTaskAuth;
        switch (lockTaskAuth) {
            case LOCK_TASK_AUTH_DONT_LOCK:
                return !mLockTaskModeTasks.isEmpty();
            case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
            case LOCK_TASK_AUTH_LAUNCHABLE:
            case LOCK_TASK_AUTH_WHITELISTED:

        // Allow recents activity if enabled by policy
        if (task.isActivityTypeRecents() && isRecentsAllowed(task.userId)) {
            return false;
            case LOCK_TASK_AUTH_PINNABLE:
                // Pinnable tasks can't be launched on top of locktask tasks.
                return !mLockTaskModeTasks.isEmpty();
            default:
                Slog.w(TAG, "isLockTaskModeViolation: invalid lockTaskAuth value=" + lockTaskAuth);
                return true;
        }

        return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
    }

    private boolean isRecentsAllowed(int userId) {
        return (getLockTaskFeaturesForUser(userId)
                & DevicePolicyManager.LOCK_TASK_FEATURE_RECENTS) != 0;
    }

    /**
@@ -491,6 +505,7 @@ public class LockTaskController {
        }

        if (mLockTaskModeTasks.isEmpty()) {
            mSupervisor.mRecentTasks.onLockTaskModeStateChanged(lockTaskModeState, task.userId);
            // Start lock task on the handler thread
            mHandler.post(() -> performStartLockTask(
                    task.intent.getComponent().getPackageName(),
+12 −0
Original line number Diff line number Diff line
@@ -502,6 +502,18 @@ class RecentTasks {
        }
    }

    void onLockTaskModeStateChanged(int lockTaskModeState, int userId) {
        if (lockTaskModeState != ActivityManager.LOCK_TASK_MODE_LOCKED) {
            return;
        }
        for (int i = mTasks.size() - 1; i >= 0; --i) {
            final TaskRecord tr = mTasks.get(i);
            if (tr.userId == userId && !mService.mLockTaskController.isTaskWhitelisted(tr)) {
                remove(tr);
            }
        }
    }

    void removeTasksByPackageName(String packageName, int userId) {
        for (int i = mTasks.size() - 1; i >= 0; --i) {
            final TaskRecord tr = mTasks.get(i);
+5 −1
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ public class LockTaskControllerTest {
    @Mock private LockPatternUtils mLockPatternUtils;
    @Mock private LockTaskNotify mLockTaskNotify;
    @Mock private StatusBarManagerInternal mStatusBarManagerInternal;
    @Mock private RecentTasks mRecentTasks;

    private LockTaskController mLockTaskController;
    private Context mContext;
@@ -110,9 +111,10 @@ public class LockTaskControllerTest {
            Looper.prepare();
        }

        mSupervisor.mRecentTasks = mRecentTasks;

        mLockTaskController = new LockTaskController(mContext, mSupervisor,
                new ImmediatelyExecuteHandler());

        mLockTaskController.setWindowManager(mWindowManager);
        mLockTaskController.mStatusBarService = mStatusBarService;
        mLockTaskController.mDevicePolicyManager = mDevicePolicyManager;
@@ -601,6 +603,8 @@ public class LockTaskControllerTest {
                eq(mContext.getPackageName()));
        verify(mStatusBarService).disable2(eq(statusBarMask2), any(IBinder.class),
                eq(mContext.getPackageName()));
        // THEN recents should have been notified
        verify(mRecentTasks).onLockTaskModeStateChanged(anyInt(), eq(TEST_USER_ID));
        // THEN the DO/PO should be informed about the operation
        verify(mDevicePolicyManager).notifyLockTaskModeChanged(true, TEST_PACKAGE_NAME,
                TEST_USER_ID);