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

Commit ec7d92a7 authored by Felipe Leme's avatar Felipe Leme Committed by Automerger Merge Worker
Browse files

Merge "Fixed createAndManageUser() for headless system user mode." into sc-dev am: f2a75766

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13679504

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I84048171bc1acf78920c2a63dea393c7761938ae
parents b00b63b1 f2a75766
Loading
Loading
Loading
Loading
+31 −1
Original line number Diff line number Diff line
@@ -585,6 +585,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * @param intent The received intent as per {@link #onReceive}.
     */
    public void onEnabled(@NonNull Context context, @NonNull Intent intent) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onEnabled() on user " + context.getUserId());
        }
    }

    /**
@@ -600,6 +603,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     */
    public @Nullable CharSequence onDisableRequested(@NonNull Context context,
            @NonNull Intent intent) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onDisableRequested() on user "
                    + context.getUserId());
        }
        return null;
    }

@@ -612,6 +619,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * @param intent The received intent as per {@link #onReceive}.
     */
    public void onDisabled(@NonNull Context context, @NonNull Intent intent) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onDisabled() on user " + context.getUserId());
        }
    }

    /**
@@ -786,6 +796,10 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * @param intent The received intent as per {@link #onReceive}.
     */
    public void onProfileProvisioningComplete(@NonNull Context context, @NonNull Intent intent) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onProfileProvisioningComplete() on user "
                    + context.getUserId());
        }
    }

    /**
@@ -961,6 +975,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     */
    public void onUserAdded(@NonNull Context context, @NonNull Intent intent,
            @NonNull UserHandle addedUser) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onUserAdded() on user " + context.getUserId());
        }
    }

    /**
@@ -974,6 +991,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     */
    public void onUserRemoved(@NonNull Context context, @NonNull Intent intent,
            @NonNull UserHandle removedUser) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onUserRemoved() on user " + context.getUserId());
        }
    }

    /**
@@ -987,6 +1007,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     */
    public void onUserStarted(@NonNull Context context, @NonNull Intent intent,
            @NonNull UserHandle startedUser) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onUserStarted() on user " + context.getUserId());
        }
    }

    /**
@@ -1000,6 +1023,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     */
    public void onUserStopped(@NonNull Context context, @NonNull Intent intent,
            @NonNull UserHandle stoppedUser) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onUserStopped() on user " + context.getUserId());
        }
    }

    /**
@@ -1013,6 +1039,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     */
    public void onUserSwitched(@NonNull Context context, @NonNull Intent intent,
            @NonNull UserHandle switchedUser) {
        if (LOCAL_LOGV) {
            Log.v(TAG, getClass().getName() + ".onUserSwitched() on user " + context.getUserId());
        }
    }

    /**
@@ -1104,7 +1133,8 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
    public void onReceive(@NonNull Context context, @NonNull Intent intent) {
        String action = intent.getAction();
        if (LOCAL_LOGV) {
            Log.v(TAG, "onReceive(): received " + action + " on user " + context.getUserId());
            Log.v(TAG, getClass().getName() + ".onReceive(): received " + action + " on user "
                    + context.getUserId());
        }

        if (ACTION_PASSWORD_CHANGED.equals(action)) {
+11 −4
Original line number Diff line number Diff line
@@ -63,8 +63,13 @@ public abstract class UserManagerInternal {
     */
    public interface UserLifecycleListener {

        /** Called when a new user is created. */
        default void onUserCreated(UserInfo user) {}
        /**
         * Called when a new user is created.
         *
         * @param user new user.
         * @param token token passed to the method that created the user.
         */
        default void onUserCreated(UserInfo user, @Nullable Object token) {}

        /** Called when an existing user is removed. */
        default void onUserRemoved(UserInfo user) {}
@@ -179,10 +184,12 @@ public abstract class UserManagerInternal {
     * {@link UserManager#DISALLOW_ADD_USER} and {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}
     *
     * <p>Called by the {@link com.android.server.devicepolicy.DevicePolicyManagerService} when
     * createAndManageUser is called by the device owner.
     * createAndManageUser is called by the device owner; it uses {@code token} to block until
     * the user is created (as it will be passed back to it through
     * {@link UserLifecycleListener#onUserCreated(UserInfo, Object)});
     */
    public abstract UserInfo createUserEvenWhenDisallowed(String name, String userType,
            int flags, String[] disallowedPackages)
            int flags, String[] disallowedPackages, @Nullable Object token)
            throws UserManager.CheckedUserOperationException;

    /**
+17 −14
Original line number Diff line number Diff line
@@ -3323,7 +3323,7 @@ public class UserManagerService extends IUserManager.Stub {
        checkManageOrCreateUsersPermission(flags);
        try {
            return createUserInternalUnchecked(name, userType, flags, userId,
                    /* preCreate= */ false, disallowedPackages);
                    /* preCreate= */ false, disallowedPackages, /* token= */ null);
        } catch (UserManager.CheckedUserOperationException e) {
            throw e.toServiceSpecificException();
        }
@@ -3356,7 +3356,7 @@ public class UserManagerService extends IUserManager.Stub {
        try {
            return createUserInternalUnchecked(/* name= */ null, userType, flags,
                    /* parentId= */ UserHandle.USER_NULL, /* preCreate= */ true,
                    /* disallowedPackages= */ null);
                    /* disallowedPackages= */ null, /* token= */ null);
        } catch (UserManager.CheckedUserOperationException e) {
            throw e.toServiceSpecificException();
        }
@@ -3372,12 +3372,13 @@ public class UserManagerService extends IUserManager.Stub {
        enforceUserRestriction(restriction, UserHandle.getCallingUserId(),
                "Cannot add user");
        return createUserInternalUnchecked(name, userType, flags, parentId,
                /* preCreate= */ false, disallowedPackages);
                /* preCreate= */ false, disallowedPackages, /* token= */ null);
    }

    private UserInfo createUserInternalUnchecked(@Nullable String name,
            @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId,
            boolean preCreate, @Nullable String[] disallowedPackages)
            boolean preCreate, @Nullable String[] disallowedPackages,
            @Nullable Object token)
            throws UserManager.CheckedUserOperationException {
        final int nextProbableUserId = getNextAvailableId();
        final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
@@ -3386,7 +3387,7 @@ public class UserManagerService extends IUserManager.Stub {
        UserInfo newUser = null;
        try {
            newUser = createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
                        preCreate, disallowedPackages, t);
                        preCreate, disallowedPackages, t, token);
            return newUser;
        } finally {
            logUserCreateJourneyFinish(sessionId, nextProbableUserId, newUser != null);
@@ -3397,7 +3398,8 @@ public class UserManagerService extends IUserManager.Stub {
    private UserInfo createUserInternalUncheckedNoTracing(@Nullable String name,
            @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int parentId,
            boolean preCreate, @Nullable String[] disallowedPackages,
            @NonNull TimingsTraceAndSlog t) throws UserManager.CheckedUserOperationException {
            @NonNull TimingsTraceAndSlog t, @Nullable Object token)
                    throws UserManager.CheckedUserOperationException {
        final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
        if (userTypeDetails == null) {
            Slog.e(LOG_TAG, "Cannot create user of invalid user type: " + userType);
@@ -3423,7 +3425,8 @@ public class UserManagerService extends IUserManager.Stub {

        // Try to use a pre-created user (if available).
        if (!preCreate && parentId < 0 && isUserTypeEligibleForPreCreation(userTypeDetails)) {
            final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name);
            final UserInfo preCreatedUser = convertPreCreatedUserIfPossible(userType, flags, name,
                    token);
            if (preCreatedUser != null) {
                return preCreatedUser;
            }
@@ -3602,7 +3605,7 @@ public class UserManagerService extends IUserManager.Stub {
                    Slog.w(LOG_TAG, "could not start pre-created user " + userId, e);
                }
            } else {
                dispatchUserAdded(userInfo);
                dispatchUserAdded(userInfo, token);
            }

        } finally {
@@ -3702,7 +3705,7 @@ public class UserManagerService extends IUserManager.Stub {
     * @return the converted user, or {@code null} if no pre-created user could be converted.
     */
    private @Nullable UserInfo convertPreCreatedUserIfPossible(String userType,
            @UserInfoFlag int flags, String name) {
            @UserInfoFlag int flags, String name, @Nullable Object token) {
        final UserData preCreatedUserData;
        synchronized (mUsersLock) {
            preCreatedUserData = getPreCreatedUserLU(userType);
@@ -3740,7 +3743,7 @@ public class UserManagerService extends IUserManager.Stub {
        }
        updateUserIds();
        mPm.onNewUserCreated(preCreatedUser.id, /* convertedFromPreCreated= */ true);
        dispatchUserAdded(preCreatedUser);
        dispatchUserAdded(preCreatedUser, token);
        return preCreatedUser;
    }

@@ -3772,11 +3775,11 @@ public class UserManagerService extends IUserManager.Stub {
        return (now > EPOCH_PLUS_30_YEARS) ? now : 0;
    }

    private void dispatchUserAdded(@NonNull UserInfo userInfo) {
    private void dispatchUserAdded(@NonNull UserInfo userInfo, @Nullable Object token) {
        // Notify internal listeners first...
        synchronized (mUserLifecycleListeners) {
            for (int i = 0; i < mUserLifecycleListeners.size(); i++) {
                mUserLifecycleListeners.get(i).onUserCreated(userInfo);
                mUserLifecycleListeners.get(i).onUserCreated(userInfo, token);
            }
        }

@@ -5381,10 +5384,10 @@ public class UserManagerService extends IUserManager.Stub {

        @Override
        public UserInfo createUserEvenWhenDisallowed(String name, @NonNull String userType,
                @UserInfoFlag int flags, String[] disallowedPackages)
                @UserInfoFlag int flags, String[] disallowedPackages, @Nullable Object token)
                throws UserManager.CheckedUserOperationException {
            return createUserInternalUnchecked(name, userType, flags,
                    UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages);
                    UserHandle.USER_NULL, /* preCreated= */ false, disallowedPackages, token);
        }

        @Override
+58 −28
Original line number Diff line number Diff line
@@ -715,6 +715,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    @Nullable
    private DevicePolicySafetyChecker mSafetyChecker;
    @GuardedBy("getLockObject()")
    private final ArrayList<Object> mPendingUserCreatedCallbackTokens = new ArrayList<>();
    public static final class Lifecycle extends SystemService {
        private BaseIDevicePolicyManager mService;
@@ -965,8 +968,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener {
        @Override
        public void onUserCreated(UserInfo user) {
            mHandler.post(() -> handleNewUserCreated(user));
        public void onUserCreated(UserInfo user, Object token) {
            mHandler.post(() -> handleNewUserCreated(user, token));
        }
    }
@@ -3151,11 +3154,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        if (!mHasFeature) {
            return;
        }
        setActiveAdmin(adminReceiver, refreshing, userHandle, null);
    }
    private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
            Bundle onEnableData) {
        Preconditions.checkArgumentNonnegative(userHandle, "Invalid userId");
        final CallerIdentity caller = getCallerIdentity();
@@ -3198,7 +3196,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                }
                saveSettingsLocked(userHandle);
                sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                        onEnableData, null);
                        /* adminExtras= */ null, /* result= */ null);
            });
        }
    }
@@ -9193,6 +9191,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                pw.println("Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
                pw.println();
                if (mPendingUserCreatedCallbackTokens.isEmpty()) {
                    pw.println("no pending user created callback tokens");
                } else {
                    int size = mPendingUserCreatedCallbackTokens.size();
                    pw.printf("%d pending user created callback token%s\n", size,
                            (size == 1 ? "" : "s"));
                }
                pw.println();
                mPolicyCache.dump(pw);
                pw.println();
                mStateCache.dump(pw);
@@ -9949,8 +9957,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                clearInitBundle = sendAdminCommandLocked(admin,
                        DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                        initBundle == null ? null : new Bundle(initBundle),
                        null /* result receiver */,
                        true /* send in foreground */);
                        /* result= */ null ,
                        /* inForeground= */ true);
            }
            if (clearInitBundle) {
                // If there's no admin or we've successfully called the admin, clear the init bundle
@@ -10023,9 +10031,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                            UserHandle.myUserId(), ACTION_PROVISION_MANAGED_USER).toArray(
                            new String[0]);
                }
                Object token = new Object();
                Slog.d(LOG_TAG, "Adding new pending token: " + token);
                mPendingUserCreatedCallbackTokens.add(token);
                try {
                    UserInfo userInfo = mUserManagerInternal.createUserEvenWhenDisallowed(name,
                            userType, userInfoFlags, disallowedPackages);
                            userType, userInfoFlags, disallowedPackages, token);
                    if (userInfo != null) {
                        user = userInfo.getUserHandle();
                    }
@@ -10035,7 +10047,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
            } finally {
                mInjector.binderRestoreCallingIdentity(id);
            }
        }
        } // synchronized
        if (user == null) {
            if (targetSdkVersion >= Build.VERSION_CODES.P) {
                throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN,
@@ -10057,14 +10070,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final long id = mInjector.binderClearCallingIdentity();
        try {
            if (!mInjector.userManagerIsHeadlessSystemUserMode()) {
            manageUserUnchecked(admin, profileOwner, userHandle, adminExtras,
                    /* showDisclaimer= */ true);
            } else if (VERBOSE_LOG) {
                Slog.v(LOG_TAG, "createAndManageUser(): skipping manageUserUnchecked() on user "
                        + userHandle + " on headless system user as it will be called by "
                                + "handleNewUserCreated()");
            }
            if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
                Settings.Secure.putIntForUser(mContext.getContentResolver(),
@@ -10086,7 +10093,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    private void manageUserUnchecked(ComponentName admin, ComponentName profileOwner,
            @UserIdInt int userId, PersistableBundle adminExtras, boolean showDisclaimer) {
            @UserIdInt int userId, @Nullable PersistableBundle adminExtras,
            boolean showDisclaimer) {
        synchronized (getLockObject()) {
            if (VERBOSE_LOG) {
                Slog.v(LOG_TAG, "manageUserUnchecked(): admin=" + admin + ", po=" + profileOwner
                        + ", userId=" + userId + ", hasAdminExtras=" + (adminExtras != null)
                        + ", showDisclaimer=" + showDisclaimer);
            }
        }
        final String adminPkg = admin.getPackageName();
        try {
            // Install the profile owner if not present.
@@ -10116,23 +10131,37 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
                    ? DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED
                    : DevicePolicyData.NEW_USER_DISCLAIMER_NOT_NEEDED;
            saveSettingsLocked(userId);
        }
    }
    private void handleNewUserCreated(UserInfo user) {
        if (VERBOSE_LOG) Slog.v(LOG_TAG, "handleNewUserCreated(): " + user.toFullString());
        if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
    private void handleNewUserCreated(UserInfo user, @Nullable Object token) {
        if (VERBOSE_LOG) {
            Slog.v(LOG_TAG, "handleNewUserCreated(): user=" + user.toFullString()
                    + ", token=" + token);
        }
        final int userId = user.id;
        if (token != null) {
            synchronized (getLockObject()) {
                if (mPendingUserCreatedCallbackTokens.contains(token)) {
                    // Ignore because it was triggered by createAndManageUser()
                    Slog.d(LOG_TAG, "handleNewUserCreated(): ignoring for user " + userId
                            + " due to token" + token);
                    mPendingUserCreatedCallbackTokens.remove(token);
                    return;
                }
            }
        }
        if (!mOwners.hasDeviceOwner() || !user.isFull() || user.isManagedProfile()) return;
        if (mInjector.userManagerIsHeadlessSystemUserMode()) {
            ComponentName admin = mOwners.getDeviceOwnerComponent();
            Slog.i(LOG_TAG, "Automatically setting profile owner (" + admin + ") on new user "
                    + userId);
            manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin,
                    /* managedUser= */ userId, /* adminExtras= */ null,
                    /* showDisclaimer= */ true);
                    /* managedUser= */ userId, /* adminExtras= */ null, /* showDisclaimer= */ true);
        } else {
            Log.i(LOG_TAG, "User " + userId + " added on DO mode; setting ShowNewUserDisclaimer");
            setShowNewUserDisclaimer(userId, DevicePolicyData.NEW_USER_DISCLAIMER_NEEDED);
@@ -10253,11 +10282,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        final long id = mInjector.binderClearCallingIdentity();
        try {
            if (!mInjector.getActivityManagerInternal().canStartMoreUsers()) {
                Log.w(LOG_TAG, "Cannot start more users in background");
                Log.w(LOG_TAG, "Cannot start user " + userId + ", too many users in background");
                return UserManager.USER_OPERATION_ERROR_MAX_RUNNING_USERS;
            }
            if (mInjector.getIActivityManager().startUserInBackground(userId)) {
                Log.i(LOG_TAG, "Started used " + userId + " in background");
                return UserManager.USER_OPERATION_SUCCESS;
            } else {
                return UserManager.USER_OPERATION_ERROR_UNKNOWN;