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

Commit 5f09616e authored by Philipp Weiß's avatar Philipp Weiß Committed by Android (Google) Code Review
Browse files

Merge "Add new API function createAndManageUser"

parents 2c6ffba9 343fb33a
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -4124,6 +4124,47 @@ public class DevicePolicyManager {
        return null;
    }

    /**
      * Flag used by {@link createAndManageUser} to skip setup wizard after creating a new user.
      * @hide
      */
    public static final int SKIP_SETUP_WIZARD = 0x0001;

    /**
     * Called by a device owner to create a user with the specified name and the caller as profile
     * owner. The UserHandle returned by this method should not be persisted as user handles are
     * recycled as users are removed and created. If you need to persist an identifier for this
     * user, use {@link UserManager#getSerialNumberForUser}. The new user will not be started in the
     * background.
     *
     * <p> admin is the {@link DeviceAdminReceiver} which is the device owner, and will become the
     * profile owner and will be registered as an active admin on the new user. The profile owner
     * package will be installed on the new user.
     *
     * <p>If the adminExtras are not null, they will be stored on the device until the user is
     * started for the first time. Then the extras will be passed to the admin when
     * onEnable is called.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param name The user's name.
     * @param adminExtras Extras that will be passed to onEnable of the admin receiver on the new
     *      user.
     * @param flags {@link SKIP_SETUP_WIZARD} is supported.
     * @see UserHandle
     * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
     *         user could not be created.
     * @hide
     */
    public UserHandle createAndManageUser(@NonNull ComponentName admin, @NonNull String name,
            @Nullable PersistableBundle adminExtras, int flags) {
        try {
            return mService.createAndManageUser(admin, name, adminExtras, flags);
        } catch (RemoteException re) {
            Log.w(TAG, REMOTE_EXCEPTION_MESSAGE, re);
        }
        return null;
    }

    /**
     * Called by a device owner to remove a user and all associated data. The primary user can
     * not be removed.
+1 −0
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ interface IDevicePolicyManager {

    UserHandle createUser(in ComponentName who, in String name);
    UserHandle createAndInitializeUser(in ComponentName who, in String name, in String profileOwnerName, in ComponentName profileOwnerComponent, in Bundle adminExtras);
    UserHandle createAndManageUser(in ComponentName who, in String name, in PersistableBundle adminExtras, in int flags);
    boolean removeUser(in ComponentName who, in UserHandle userHandle);
    boolean switchUser(in ComponentName who, in UserHandle userHandle);

+116 −10
Original line number Diff line number Diff line
@@ -175,13 +175,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

    private static final String TAG_STATUS_BAR = "statusbar";

    private static final String TAG_AFFILIATION_ID = "affiliation-id";

    private static final String ATTR_DISABLED = "disabled";

    private static final String DO_NOT_ASK_CREDENTIALS_ON_BOOT_XML =
            "do-not-ask-credentials-on-boot";

    private static final String TAG_AFFILIATION_ID = "affiliation-id";

    private static final String TAG_ADMIN_BROADCAST_PENDING = "admin-broadcast-pending";

    private static final String ATTR_VALUE = "value";

    private static final String TAG_INITIALIZATION_BUNDLE = "initialization-bundle";

    private static final int REQUEST_EXPIRE_PASSWORD = 5571;

    private static final long MS_PER_DAY = 86400 * 1000;
@@ -379,6 +385,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {

        Set<String> mAffiliationIds = new ArraySet<>();

        // Used for initialization of users created by createAndManageUsers.
        boolean mAdminBroadcastPending = false;
        PersistableBundle mInitBundle = null;

        public DevicePolicyData(int userHandle) {
            mUserHandle = userHandle;
        }
@@ -427,15 +437,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            if (Intent.ACTION_USER_REMOVED.equals(action)) {
                removeUserData(userHandle);
            } else if (Intent.ACTION_USER_STARTED.equals(action)
                    || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {

                if (Intent.ACTION_USER_STARTED.equals(action)) {
                    // Reset the policy data
            } else if (Intent.ACTION_USER_STARTED.equals(action)) {
                synchronized (DevicePolicyManagerService.this) {
                    // Reset the policy data
                    mUserData.remove(userHandle);
                    sendAdminEnabledBroadcastLocked(userHandle);
                }
                }
                handlePackagesChanged(null /* check all admins */, userHandle);
            } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
                handlePackagesChanged(null /* check all admins */, userHandle);
            } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
                    || (Intent.ACTION_PACKAGE_ADDED.equals(action)
@@ -2085,6 +2094,19 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                out.endTag(null, TAG_AFFILIATION_ID);
            }

            if (policy.mAdminBroadcastPending) {
                out.startTag(null, TAG_ADMIN_BROADCAST_PENDING);
                out.attribute(null, ATTR_VALUE,
                        Boolean.toString(policy.mAdminBroadcastPending));
                out.endTag(null, TAG_ADMIN_BROADCAST_PENDING);
            }

            if (policy.mInitBundle != null) {
                out.startTag(null, TAG_INITIALIZATION_BUNDLE);
                policy.mInitBundle.saveToXml(out);
                out.endTag(null, TAG_INITIALIZATION_BUNDLE);
            }

            out.endTag(null, "policies");

            out.endDocument();
@@ -2093,7 +2115,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            stream.close();
            journal.commit();
            sendChangedNotification(userHandle);
        } catch (IOException e) {
        } catch (XmlPullParserException | IOException e) {
            Slog.w(LOG_TAG, "failed writing file", e);
            try {
                if (stream != null) {
@@ -2219,6 +2241,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    policy.doNotAskCredentialsOnBoot = true;
                } else if (TAG_AFFILIATION_ID.equals(tag)) {
                    policy.mAffiliationIds.add(parser.getAttributeValue(null, "id"));
                } else if (TAG_ADMIN_BROADCAST_PENDING.equals(tag)) {
                    String pending = parser.getAttributeValue(null, ATTR_VALUE);
                    policy.mAdminBroadcastPending = Boolean.toString(true).equals(pending);
                } else if (TAG_INITIALIZATION_BUNDLE.equals(tag)) {
                    policy.mInitBundle = PersistableBundle.restoreFromXml(parser);
                } else {
                    Slog.w(LOG_TAG, "Unknown tag: " + tag);
                    XmlUtils.skipCurrentTag(parser);
@@ -6344,6 +6371,85 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private void sendAdminEnabledBroadcastLocked(int userHandle) {
        DevicePolicyData policyData = getUserData(userHandle);
        if (policyData.mAdminBroadcastPending) {
            // Send the initialization data to profile owner and delete the data
            ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle);
            if (admin != null) {
                PersistableBundle initBundle = policyData.mInitBundle;
                sendAdminCommandLocked(admin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                        initBundle == null ? null : new Bundle(initBundle), null);
            }
            policyData.mInitBundle = null;
            policyData.mAdminBroadcastPending = false;
            saveSettingsLocked(userHandle);
        }
    }

    @Override
    public UserHandle createAndManageUser(ComponentName admin, String name,
            PersistableBundle adminExtras, int flags) {
        // Create user.
        Preconditions.checkNotNull(admin, "ComponentName is null");
        UserHandle user = null;
        synchronized (this) {
            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);

            final long id = mInjector.binderClearCallingIdentity();
            try {
                UserInfo userInfo = mUserManager.createUser(name, 0 /* flags */);
                if (userInfo != null) {
                    user = userInfo.getUserHandle();
                }
            } finally {
                mInjector.binderRestoreCallingIdentity(id);
            }
        }
        if (user == null) {
            return null;
        }
        // Set admin.
        final long id = mInjector.binderClearCallingIdentity();
        try {
            final String adminPkg = admin.getPackageName();

            final int userHandle = user.getIdentifier();
            try {
                // Install the profile owner if not present.
                if (!mIPackageManager.isPackageAvailable(adminPkg, userHandle)) {
                    mIPackageManager.installExistingPackageAsUser(adminPkg, userHandle);
                }
            } catch (RemoteException e) {
                Slog.e(LOG_TAG, "Failed to make remote calls for createAndManageUser, "
                        + "removing created user", e);
                mUserManager.removeUser(user.getIdentifier());
                return null;
            }

            setActiveAdmin(admin, true, userHandle);
            // User is not started yet, the broadcast by setActiveAdmin will not be received.
            // So we store adminExtras for broadcasting when the user starts for first time.
            synchronized(this) {
                DevicePolicyData policyData = getUserData(userHandle);
                policyData.mInitBundle = adminExtras;
                policyData.mAdminBroadcastPending = true;
                saveSettingsLocked(userHandle);
            }
            final String ownerName = getProfileOwnerName(Process.myUserHandle().getIdentifier());
            setProfileOwner(admin, ownerName, userHandle);

            if ((flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0) {
                Settings.Secure.putIntForUser(mContext.getContentResolver(),
                        Settings.Secure.USER_SETUP_COMPLETE, 1, userHandle);
            }

            return user;
        } finally {
            mInjector.binderRestoreCallingIdentity(id);
        }
    }

    @Override
    public boolean removeUser(ComponentName who, UserHandle userHandle) {
        Preconditions.checkNotNull(who, "ComponentName is null");