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

Commit 4e81913a authored by Jason Monk's avatar Jason Monk Committed by Android (Google) Code Review
Browse files

Merge "Allow device owner to configure secondary users"

parents 9c68b42d 03978a40
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5199,6 +5199,7 @@ package android.app.admin {
    method public void clearDeviceOwnerApp();
    method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
    method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
    method public android.os.UserHandle createAndInitializeUser(android.content.ComponentName, java.lang.String, java.lang.String, android.content.ComponentName, android.os.Bundle);
    method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
    method public java.lang.String[] getAccountTypesWithManagementDisabled();
    method public java.util.List<android.content.ComponentName> getActiveAdmins();
+6 −0
Original line number Diff line number Diff line
@@ -222,6 +222,12 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
     * Called after the administrator is first enabled, as a result of
     * receiving {@link #ACTION_DEVICE_ADMIN_ENABLED}.  At this point you
     * can use {@link DevicePolicyManager} to set your desired policies.
     *
     * <p> If the admin is activated by a device owner, then the intent
     * may contain private extras that are relevant to user setup.
     * {@see DevicePolicyManager#createAndInitializeUser(ComponentName, String, String,
     *      ComponentName, Intent)}
     *
     * @param context The running context as per {@link #onReceive}.
     * @param intent The received intent as per {@link #onReceive}.
     */
+35 −0
Original line number Diff line number Diff line
@@ -2110,6 +2110,41 @@ public class DevicePolicyManager {
        return null;
    }

    /**
     * Called by a device owner to create a user with the specified name. 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 be started in the background
     * immediately.
     *
     * <p> profileOwnerComponent is the {@link DeviceAdminReceiver} to be the profile owner as well
     * as registered as an active admin on the new user.  The profile owner package will be
     * installed on the new user if it already is installed on the device.
     *
     * <p>If the optionalInitializeData is not null, then the extras will be passed to the
     * profileOwnerComponent when onEnable is called.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param name the user's name
     * @param ownerName the human readable name of the organisation associated with this DPM.
     * @param profileOwnerComponent The {@link DeviceAdminReceiver} that will be an active admin on
     *      the user.
     * @param adminExtras Extras that will be passed to onEnable of the admin receiver
     *      on the new user.
     * @see UserHandle
     * @return the UserHandle object for the created user, or null if the user could not be created.
     */
    public UserHandle createAndInitializeUser(ComponentName admin, String name, String ownerName,
            ComponentName profileOwnerComponent, Bundle adminExtras) {
        try {
            return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent,
                    adminExtras);
        } catch (RemoteException re) {
            Log.w(TAG, "Could not create a user", 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
@@ -136,6 +136,7 @@ interface IDevicePolicyManager {
    boolean isApplicationBlocked(in ComponentName admin, in String packageName);

    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);
    boolean removeUser(in ComponentName who, in UserHandle userHandle);

    void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
+47 −2
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -839,15 +840,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        sendAdminCommandLocked(admin, action, null);
    }

    void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
        sendAdminCommandLocked(admin, action, null, result);
    }

    /**
     * Send an update to one specific admin, get notified when that admin returns a result.
     */
    void sendAdminCommandLocked(ActiveAdmin admin, String action, BroadcastReceiver result) {
    void sendAdminCommandLocked(ActiveAdmin admin, String action, Bundle adminExtras,
            BroadcastReceiver result) {
        Intent intent = new Intent(action);
        intent.setComponent(admin.info.getComponent());
        if (action.equals(DeviceAdminReceiver.ACTION_PASSWORD_EXPIRING)) {
            intent.putExtra("expiration", admin.passwordExpirationDate);
        }
        if (adminExtras != null) {
            intent.putExtras(adminExtras);
        }
        if (result != null) {
            mContext.sendOrderedBroadcastAsUser(intent, admin.getUserHandle(),
                    null, result, mHandler, Activity.RESULT_OK, null, null);
@@ -1375,6 +1384,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (!mHasFeature) {
            return;
        }
        setActiveAdmin(adminReceiver, refreshing, userHandle, null);
    }

    private void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle,
            Bundle onEnableData) {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.MANAGE_DEVICE_ADMINS, null);
        enforceCrossUserPermission(userHandle);
@@ -1411,7 +1425,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    policy.mAdminList.set(replaceIndex, newAdmin);
                }
                saveSettingsLocked(userHandle);
                sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED);
                sendAdminCommandLocked(newAdmin, DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED,
                        onEnableData, null);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
@@ -3497,6 +3512,36 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    @Override
    public UserHandle createAndInitializeUser(ComponentName who, String name,
            String ownerName, ComponentName profileOwnerComponent, Bundle adminExtras) {
        UserHandle user = createUser(who, name);
        long id = Binder.clearCallingIdentity();
        try {
            String profileOwnerPkg = profileOwnerComponent.getPackageName();
            final IPackageManager ipm = AppGlobals.getPackageManager();
            IActivityManager activityManager = ActivityManagerNative.getDefault();

            try {
                // Install the profile owner if not present.
                if (!ipm.isPackageAvailable(profileOwnerPkg, user.getIdentifier())) {
                    ipm.installExistingPackageAsUser(profileOwnerPkg, user.getIdentifier());
                }

                // Start user in background.
                activityManager.startUserInBackground(user.getIdentifier());
            } catch (RemoteException e) {
                Slog.e(LOG_TAG, "Failed to make remote calls for configureUser", e);
            }

            setActiveAdmin(profileOwnerComponent, true, user.getIdentifier(), adminExtras);
            setProfileOwner(profileOwnerPkg, ownerName, user.getIdentifier());
            return user;
        } finally {
            restoreCallingIdentity(id);
        }
    }

    @Override
    public boolean removeUser(ComponentName who, UserHandle userHandle) {
        synchronized (this) {