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

Commit 469dd58b authored by Benjamin Franz's avatar Benjamin Franz
Browse files

Align the behaviour of different lock task modes

Currently lock task modes started by the activity flag
android:lockTaskMode behave differently from those started using
startLockTask(). With those changes lock tasks initiated by non-priv
apps cannot finish without calling into stopLockTask. Revoking the
whitelisting on a locked task will also kill that task, independently
of the way the lock task mode was started.

Bug: 21608206
Change-Id: I841abf1103855e2d7218a4a8ca9b43c105630dc9
parent 7d3b8833
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -3976,6 +3976,9 @@ public class DevicePolicyManager {
     * <p>Any packages that shares uid with an allowed package will also be allowed
     * <p>Any packages that shares uid with an allowed package will also be allowed
     * to activate lock task.
     * to activate lock task.
     *
     *
     * From {@link android.os.Build.VERSION_CODES#MNC} removing packages from the lock task
     * package list results in locked tasks belonging to those packages to be finished.
     *
     * This function can only be called by the device owner.
     * This function can only be called by the device owner.
     * @param packages The list of packages allowed to enter lock task mode
     * @param packages The list of packages allowed to enter lock task mode
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+12 −9
Original line number Original line Diff line number Diff line
@@ -1058,18 +1058,20 @@
         lockTask mode is disabled.
         lockTask mode is disabled.
         <p>While in lockTask mode with multiple permitted tasks running, each launched task is
         <p>While in lockTask mode with multiple permitted tasks running, each launched task is
         permitted to finish, transitioning to the previous locked task, until there is only one
         permitted to finish, transitioning to the previous locked task, until there is only one
         task remaining. At that point the last task running is not permitted to finish. -->
         task remaining. At that point the last task running is not permitted to finish, unless it
         uses the value always. -->
    <attr name="lockTaskMode">
    <attr name="lockTaskMode">
        <!-- This is the default value. Tasks will not launch into lockTask mode but can be
        <!-- This is the default value. Tasks will not launch into lockTask mode but can be
             placed there by calling {@link android.app.Activity#startLockTask}. If a task with
             placed there by calling {@link android.app.Activity#startLockTask}. If a task with
             this mode has been whitelisted using {@link
             this mode has been whitelisted using {@link
             android.app.admin.DevicePolicyManager#setLockTaskPackages} then calling startLockTask
             android.app.admin.DevicePolicyManager#setLockTaskPackages} then calling
             will enter lockTask mode immediately, otherwise the user will be presented with a
             {@link android.app.Activity#startLockTask} will enter lockTask mode immediately,
             dialog to approve entering lockTask mode.
             otherwise the user will be presented with a dialog to approve entering pinned mode.
             <p>If the system is already in lockTask mode when a new task rooted at this activity
             <p>If the system is already in lockTask mode when a new task rooted at this activity
             is launched that task will or will not start depending on whether the package of this
             is launched that task will or will not start depending on whether the package of this
             activity has been whitelisted.
             activity has been whitelisted.
             <p>Tasks rooted at this activity can only exit lockTask mode using stopLockTask(). -->
             <p>Tasks rooted at this activity can only exit lockTask mode using
             {@link android.app.Activity#stopLockTask}. -->
        <enum name="normal" value="0"/>
        <enum name="normal" value="0"/>
        <!-- Tasks will not launch into lockTask mode and cannot be placed there using
        <!-- Tasks will not launch into lockTask mode and cannot be placed there using
             {@link android.app.Activity#startLockTask} or be pinned from the Overview screen.
             {@link android.app.Activity#startLockTask} or be pinned from the Overview screen.
@@ -1082,16 +1084,17 @@
        <!-- Tasks rooted at this activity will always launch into lockTask mode. If the system is
        <!-- Tasks rooted at this activity will always launch into lockTask mode. If the system is
             already in lockTask mode when this task is launched then the new task will be launched
             already in lockTask mode when this task is launched then the new task will be launched
             on top of the current task. Tasks launched in this mode are capable of exiting
             on top of the current task. Tasks launched in this mode are capable of exiting
             lockTask mode using finish(), whereas tasks entering lockTask mode using
             lockTask mode using {@link android.app.Activity#finish()}.
             startLockTask() must use stopLockTask() to exit.
             <p>Note: This mode is only available to system and privileged applications.
             <p>Note: This mode is only available to system and privileged applications.
             Non-privileged apps with this value will be treated as normal.
             Non-privileged apps with this value will be treated as normal.
             -->
             -->
        <enum name="always" value="2"/>
        <enum name="always" value="2"/>
        <!-- If the DevicePolicyManager (DPM) authorizes this package ({@link
        <!-- If the DevicePolicyManager (DPM) authorizes this package ({@link
             android.app.admin.DevicePolicyManager#setLockTaskPackages}) then this mode is
             android.app.admin.DevicePolicyManager#setLockTaskPackages}) then this mode is
             identical to always. If the DPM does not authorize this package then this
             identical to always, except that the activity needs to call
             mode is identical to normal. -->
             {@link android.app.Activity#stopLockTask} before being able to finish if it is the last
             locked task.
             If the DPM does not authorize this package then this mode is identical to normal. -->
        <enum name="if_whitelisted" value="3"/>
        <enum name="if_whitelisted" value="3"/>
    </attr>
    </attr>
    <!-- When set installer will extract native libraries. If set to false
    <!-- When set installer will extract native libraries. If set to false
+7 −5
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -4204,9 +4205,9 @@ public final class ActivityManagerService extends ActivityManagerNative
            if (rootR == null) {
            if (rootR == null) {
                Slog.w(TAG, "Finishing task with all activities already finished");
                Slog.w(TAG, "Finishing task with all activities already finished");
            }
            }
            // Do not allow task to finish if last task in lockTask mode. Launchable apps can
            // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
            // finish themselves.
            // finish.
            if (tr.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE && rootR == r &&
            if (tr.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV && rootR == r &&
                    mStackSupervisor.isLastLockedTask(tr)) {
                    mStackSupervisor.isLastLockedTask(tr)) {
                Slog.i(TAG, "Not finishing task in lock task mode");
                Slog.i(TAG, "Not finishing task in lock task mode");
                mStackSupervisor.showLockTaskToast();
                mStackSupervisor.showLockTaskToast();
@@ -4368,9 +4369,10 @@ public final class ActivityManagerService extends ActivityManagerNative
                    return false;
                    return false;
                }
                }
                // Do not allow the last non-launchable task to finish in Lock Task mode.
                // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
                // can finish.
                final TaskRecord task = r.task;
                final TaskRecord task = r.task;
                if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE &&
                if (task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV &&
                        mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
                        mStackSupervisor.isLastLockedTask(task) && task.getRootActivity() == r) {
                    mStackSupervisor.showLockTaskToast();
                    mStackSupervisor.showLockTaskToast();
                    return false;
                    return false;
+11 −6
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityStack.ActivityState.*;
import static com.android.server.am.ActivityStack.ActivityState.*;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;


@@ -1179,7 +1180,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
        mService.updateOomAdjLocked();
        mService.updateOomAdjLocked();


        final TaskRecord task = r.task;
        final TaskRecord task = r.task;
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) {
        if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE ||
                task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV) {
            setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
            setLockTaskModeLocked(task, LOCK_TASK_MODE_LOCKED, "mLockTaskAuth==LAUNCHABLE", false);
        }
        }


@@ -3785,6 +3787,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
        switch (lockTaskAuth) {
        switch (lockTaskAuth) {
            case LOCK_TASK_AUTH_DONT_LOCK:
            case LOCK_TASK_AUTH_DONT_LOCK:
                return !mLockTaskModeTasks.isEmpty();
                return !mLockTaskModeTasks.isEmpty();
            case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
            case LOCK_TASK_AUTH_LAUNCHABLE:
            case LOCK_TASK_AUTH_LAUNCHABLE:
            case LOCK_TASK_AUTH_WHITELISTED:
            case LOCK_TASK_AUTH_WHITELISTED:
                return false;
                return false;
@@ -3801,12 +3804,14 @@ public final class ActivityStackSupervisor implements DisplayListener {
        boolean didSomething = false;
        boolean didSomething = false;
        for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
        for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
            final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
            final TaskRecord lockedTask = mLockTaskModeTasks.get(taskNdx);
            if (lockedTask.mLockTaskMode != LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED) {
            final boolean wasWhitelisted =
                continue;
                    (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) ||
            }
                    (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED);
            final boolean wasLaunchable = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE;
            lockedTask.setLockTaskAuth();
            lockedTask.setLockTaskAuth();
            if (wasLaunchable && lockedTask.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE) {
            final boolean isWhitelisted =
                    (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE) ||
                    (lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED);
            if (wasWhitelisted && !isWhitelisted) {
                // Lost whitelisting authorization. End it now.
                // Lost whitelisting authorization. End it now.
                if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
                if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
                        lockedTask + " mLockTaskAuth=" + lockedTask.lockTaskAuthToString());
                        lockedTask + " mLockTaskAuth=" + lockedTask.lockTaskAuthToString());
+14 −6
Original line number Original line Diff line number Diff line
@@ -134,12 +134,15 @@ final class TaskRecord {


    /** Can't be put in lockTask mode. */
    /** Can't be put in lockTask mode. */
    final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
    final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
    /** Can enter lockTask with user approval. Can never start over existing lockTask task. */
    /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
    final static int LOCK_TASK_AUTH_PINNABLE = 1;
    final static int LOCK_TASK_AUTH_PINNABLE = 1;
    /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
    /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
    final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
    final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
    /** Can enter lockTask with user approval. Can start over existing lockTask task. */
    /** Can enter lockTask without user approval. Can start over existing lockTask task. */
    final static int LOCK_TASK_AUTH_WHITELISTED = 3;
    final static int LOCK_TASK_AUTH_WHITELISTED = 3;
    /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
     * lockTask task. */
    final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
    int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
    int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;


    int mLockTaskUid = -1;  // The uid of the application that called startLockTask().
    int mLockTaskUid = -1;  // The uid of the application that called startLockTask().
@@ -747,11 +750,18 @@ final class TaskRecord {
            case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
            case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
            case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
            case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
            case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
            case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
            case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
            default: return "unknown=" + mLockTaskAuth;
            default: return "unknown=" + mLockTaskAuth;
        }
        }
    }
    }


    void setLockTaskAuth() {
    void setLockTaskAuth() {
        if (!mPrivileged &&
                (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS ||
                        mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
            // Non-priv apps are not allowed to use always or never, fall back to default
            mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
        }
        switch (mLockTaskMode) {
        switch (mLockTaskMode) {
            case LOCK_TASK_LAUNCH_MODE_DEFAULT:
            case LOCK_TASK_LAUNCH_MODE_DEFAULT:
                mLockTaskAuth = isLockTaskWhitelistedLocked() ?
                mLockTaskAuth = isLockTaskWhitelistedLocked() ?
@@ -759,13 +769,11 @@ final class TaskRecord {
                break;
                break;


            case LOCK_TASK_LAUNCH_MODE_NEVER:
            case LOCK_TASK_LAUNCH_MODE_NEVER:
                mLockTaskAuth = mPrivileged ?
                mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
                        LOCK_TASK_AUTH_DONT_LOCK : LOCK_TASK_AUTH_PINNABLE;
                break;
                break;


            case LOCK_TASK_LAUNCH_MODE_ALWAYS:
            case LOCK_TASK_LAUNCH_MODE_ALWAYS:
                mLockTaskAuth = mPrivileged ?
                mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
                        LOCK_TASK_AUTH_LAUNCHABLE: LOCK_TASK_AUTH_PINNABLE;
                break;
                break;


            case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
            case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED: