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

Commit 750ef177 authored by Felipe Leme's avatar Felipe Leme
Browse files

Changed DPMS and UMS to explicitly start a profile.

Traditionally, when a profile was started as background user, the
profile would be "visible" (i.e., allowed to launch activities), as
long as its parent is also visible (for example, if the parent is the
system user, the profile would initially be visible, but it would
become invisible when the current user is switched).

On Android U, the concet of "background" was explicitly divided into
"background invisible" and "background visible", as the latter can be
used to start full users visible on passenger displayes (on
automotive).

So, to keep the profile behaviour consistent - and to allow profiles
to be started as "background invisible" when needed - they should be
explicitly started with `startProfile()` (instead of
`startUserInBackground()`).

Test: atest UserControllerTest FrameworksServicesTests:UserManagerServiceTest
Test: manual verification with TestDpc (set a managed profile and
      used QS to turn it on / off)
Fixes: 268045186

Change-Id: I268d47940c23db4ef0e04770f70a2b59d86f9d29
parent 2cc5cf36
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -963,4 +963,12 @@ public abstract class ActivityManagerInternal {
     * @hide
     */
    public abstract boolean canHoldWakeLocksInDeepDoze(int uid, int procstate);

    /**
     * Same as {@link android.app.IActivityManager#startProfile(int userId)}, but it would succeed
     * even if the profile is disabled - it should only be called by
     * {@link com.android.server.devicepolicy.DevicePolicyManagerService} when starting a profile
     * while it's being created.
     */
    public abstract boolean startProfileEvenWhenDisabled(@UserIdInt int userId);
}
+11 −1
Original line number Diff line number Diff line
@@ -93,7 +93,7 @@ interface IActivityManager {
    // below block of transactions.

    // Since these transactions are also called from native code, these must be kept in sync with
    // the ones in frameworks/native/libs/binder/include/binder/IActivityManager.h
    // the ones in frameworks/native/libs/binder/include_activitymanager/binder/ActivityManager.h
    // =============== Beginning of transactions used on native side as well ======================
    ParcelFileDescriptor openContentUri(in String uriString);
    void registerUidObserver(in IUidObserver observer, int which, int cutpoint,
@@ -485,8 +485,18 @@ interface IActivityManager {

    // Start of L transactions
    String getTagForIntentSender(in IIntentSender sender, in String prefix);

    /**
      * Starts a user in the background (i.e., while another user is running in the foreground).
      *
      * Notice that a background user is "invisible" and cannot launch activities. Starting on
      * Android U, all users started with this method are invisible, even profiles (prior to Android
      * U, profiles started with this method would be visible if its parent was the current user) -
      * if you want to start a profile visible, you should call {@code startProfile()} instead.
      */
    @UnsupportedAppUsage
    boolean startUserInBackground(int userid);

    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
    boolean isInLockTaskMode();
    @UnsupportedAppUsage
+9 −2
Original line number Diff line number Diff line
@@ -16851,13 +16851,14 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public boolean startProfile(@UserIdInt int userId) {
        return mUserController.startProfile(userId);
        return mUserController.startProfile(userId, /* evenWhenDisabled= */ false,
                /* unlockListener= */ null);
    }
    @Override
    public boolean startProfileWithListener(@UserIdInt int userId,
            @Nullable IProgressListener unlockListener) {
        return mUserController.startProfile(userId, unlockListener);
        return mUserController.startProfile(userId, /* evenWhenDisabled= */ false, unlockListener);
    }
    @Override
@@ -18456,6 +18457,12 @@ public class ActivityManagerService extends IActivityManager.Stub
            // has a SHORT_FGS.
            return mOomAdjuster.hasUidShortForegroundService(uid);
        }
        @Override
        public boolean startProfileEvenWhenDisabled(@UserIdInt int userId) {
            return mUserController.startProfile(userId, /* evenWhenDisabled= */ true,
                    /* unlockListener= */ null);
        }
    }
    long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) {
+20 −13
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ import static com.android.server.pm.UserManagerInternal.userStartModeToString;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
@@ -1463,18 +1464,24 @@ class UserController implements Handler.Callback {
    }

    /**
     * Starts a user only if it's a profile, with a more relaxed permission requirement:
     * {@link android.Manifest.permission#MANAGE_USERS} or
     * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
     * To be called from ActivityManagerService.
     * @param userId the id of the user to start.
     * @return true if the operation was successful.
     * Starts a {@link UserManager#isProfile() profile user}.
     *
     * <p>To be called from {@link com.android.server.am.ActivityManagerService}.
     *
     * @param userId the id of the profile user to start.
     * @param evenWhenDisabled whether the profile should be started if it's not enabled yet
     *        (most callers should pass {@code false}, except when starting the profile while it's
     *        being provisioned).
     * @param unlockListener listener to be informed when the profile has started and unlocked.
     *
     * @return {@code true} if the operation was successful.
     *
     * @throws IllegalArgumentException if the user doesn't exist or is not a profile.
     */
    boolean startProfile(@UserIdInt int userId) {
        return startProfile(userId, /* unlockListener= */ null);
    }

    boolean startProfile(@UserIdInt int userId, @Nullable IProgressListener unlockListener) {
    @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL})
    boolean startProfile(@UserIdInt int userId, boolean evenWhenDisabled,
            @Nullable IProgressListener unlockListener) {
        if (mInjector.checkCallingPermission(android.Manifest.permission.MANAGE_USERS)
                == PackageManager.PERMISSION_DENIED && mInjector.checkCallingPermission(
                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
@@ -1489,8 +1496,8 @@ class UserController implements Handler.Callback {
            throw new IllegalArgumentException("User " + userId + " is not a profile");
        }

        if (!userInfo.isEnabled()) {
            Slogf.w(TAG, "Cannot start disabled profile #" + userId);
        if (!userInfo.isEnabled() && !evenWhenDisabled) {
            Slogf.w(TAG, "Cannot start disabled profile #%d", userId);
            return false;
        }

+2 −3
Original line number Diff line number Diff line
@@ -1362,15 +1362,14 @@ public class UserManagerService extends IUserManager.Stub {
        }
        try {
            if (enableQuietMode) {
                ActivityManager.getService().stopUser(userId, /* force */true, null);
                ActivityManager.getService().stopUser(userId, /* force= */ true, null);
                LocalServices.getService(ActivityManagerInternal.class)
                        .killForegroundAppsForUser(userId);
            } else {
                IProgressListener callback = target != null
                        ? new DisableQuietModeUserUnlockedCallback(target)
                        : null;
                ActivityManager.getService().startUserInBackgroundWithListener(
                        userId, callback);
                ActivityManager.getService().startProfileWithListener(userId, callback);
            }
            logQuietModeEnabled(userId, enableQuietMode, callingPackage);
        } catch (RemoteException e) {
Loading