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

Commit daa65215 authored by Makoto Onuki's avatar Makoto Onuki Committed by Android (Google) Code Review
Browse files

Merge "setDeviceOwner() now requires a full component name."

parents ea174f7c a52562ca
Loading
Loading
Loading
Loading
+21 −16
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public final class Dpm extends BaseCommand {

    private IDevicePolicyManager mDevicePolicyManager;
    private int mUserId = UserHandle.USER_SYSTEM;
    private String mName = "";
    private ComponentName mComponent = null;

    @Override
@@ -52,8 +53,8 @@ public final class Dpm extends BaseCommand {
                "usage: dpm [subcommand] [options]\n" +
                "usage: dpm set-active-admin [ --user <USER_ID> ] <COMPONENT>\n" +
                // STOPSHIP Finalize it
                "usage: dpm set-device-owner [ --user <USER_ID> *EXPERIMENTAL* ] <COMPONENT>\n" +
                "usage: dpm set-profile-owner [ --user <USER_ID> ] <COMPONENT>\n" +
                "usage: dpm set-device-owner [ --user <USER_ID> *EXPERIMENTAL* ] [ --name <NAME> ] <COMPONENT>\n" +
                "usage: dpm set-profile-owner [ --user <USER_ID> ] [ --name <NAME> ] <COMPONENT>\n" +
                "\n" +
                "dpm set-active-admin: Sets the given component as active admin" +
                " for an existing user.\n" +
@@ -90,47 +91,51 @@ public final class Dpm extends BaseCommand {
        }
    }

    private void parseArgs(boolean canHaveUser) {
        String nextArg = nextArgRequired();
        if (canHaveUser && "--user".equals(nextArg)) {
    private void parseArgs(boolean canHaveUser, boolean canHaveName) {
        String opt;
        while ((opt = nextOption()) != null) {
            if (canHaveUser && "--user".equals(opt)) {
                mUserId = parseInt(nextArgRequired());
            nextArg = nextArgRequired();
            } else if (canHaveName && "--name".equals(opt)) {
                mName = nextArgRequired();
            } else {
                throw new IllegalArgumentException("Unknown option: " + opt);
            }
        mComponent = parseComponentName(nextArg);
        }
        mComponent = parseComponentName(nextArgRequired());
    }

    private void runSetActiveAdmin() throws RemoteException {
        parseArgs(true);
        parseArgs(/*canHaveUser=*/ true, /*canHaveName=*/ false);
        mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);

        System.out.println("Success: Active admin set to component " + mComponent.toShortString());
    }

    private void runSetDeviceOwner() throws RemoteException {
        parseArgs(true);
        parseArgs(/*canHaveUser=*/ true, /*canHaveName=*/ true);
        mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);

        String packageName = mComponent.getPackageName();
        try {
            if (!mDevicePolicyManager.setDeviceOwner(packageName, null /*ownerName*/, mUserId)) {
            if (!mDevicePolicyManager.setDeviceOwner(mComponent, mName, mUserId)) {
                throw new RuntimeException(
                        "Can't set package " + packageName + " as device owner.");
                        "Can't set package " + mComponent + " as device owner.");
            }
        } catch (Exception e) {
            // Need to remove the admin that we just added.
            mDevicePolicyManager.removeActiveAdmin(mComponent, UserHandle.USER_SYSTEM);
            throw e;
        }
        System.out.println("Success: Device owner set to package " + packageName);
        System.out.println("Success: Device owner set to package " + mComponent);
        System.out.println("Active admin set to component " + mComponent.toShortString());
    }

    private void runSetProfileOwner() throws RemoteException {
        parseArgs(true);
        parseArgs(/*canHaveUser=*/ true, /*canHaveName=*/ true);
        mDevicePolicyManager.setActiveAdmin(mComponent, true /*refreshing*/, mUserId);

        try {
            if (!mDevicePolicyManager.setProfileOwner(mComponent, "" /*ownerName*/, mUserId)) {
            if (!mDevicePolicyManager.setProfileOwner(mComponent, mName, mUserId)) {
                throw new RuntimeException("Can't set component " + mComponent.toShortString() +
                        " as profile owner for user " + mUserId);
            }
+53 −20
Original line number Diff line number Diff line
@@ -2573,28 +2573,28 @@ public class DevicePolicyManager {
    /**
     * @hide
     * Sets the given package as the device owner.
     * Same as {@link #setDeviceOwner(String, String)} but without setting a device owner name.
     * @param packageName the package name of the application to be registered as the device owner.
     * Same as {@link #setDeviceOwner(ComponentName, String)} but without setting a device owner name.
     * @param who the component name to be registered as device owner.
     * @return whether the package was successfully registered as the device owner.
     * @throws IllegalArgumentException if the package name is null or invalid
     * @throws IllegalStateException If the preconditions mentioned are not met.
     */
    public boolean setDeviceOwner(String packageName) {
        return setDeviceOwner(packageName, null);
    public boolean setDeviceOwner(ComponentName who) {
        return setDeviceOwner(who, null);
    }

    /**
     * @hide
     */
    public boolean setDeviceOwner(String packageName, int userId)  {
        return setDeviceOwner(packageName, null, userId);
    public boolean setDeviceOwner(ComponentName who, int userId)  {
        return setDeviceOwner(who, null, userId);
    }

    /**
     * @hide
     */
    public boolean setDeviceOwner(String packageName, String ownerName) {
        return setDeviceOwner(packageName, ownerName, UserHandle.USER_SYSTEM);
    public boolean setDeviceOwner(ComponentName who, String ownerName) {
        return setDeviceOwner(who, ownerName, UserHandle.USER_SYSTEM);
    }

    /**
@@ -2605,18 +2605,18 @@ public class DevicePolicyManager {
     * this method.
     * Calling this after the setup phase of the primary user has completed is allowed only if
     * the caller is the shell uid, and there are no additional users and no accounts.
     * @param packageName the package name of the application to be registered as the device owner.
     * @param who the component name to be registered as device owner.
     * @param ownerName the human readable name of the institution that owns this device.
     * @param userId ID of the user on which the device owner runs.
     * @return whether the package was successfully registered as the device owner.
     * @throws IllegalArgumentException if the package name is null or invalid
     * @throws IllegalStateException If the preconditions mentioned are not met.
     */
    public boolean setDeviceOwner(String packageName, String ownerName, int userId)
    public boolean setDeviceOwner(ComponentName who, String ownerName, int userId)
            throws IllegalArgumentException, IllegalStateException {
        if (mService != null) {
            try {
                return mService.setDeviceOwner(packageName, ownerName, userId);
                return mService.setDeviceOwner(who, ownerName, userId);
            } catch (RemoteException re) {
                Log.w(TAG, "Failed to set device owner");
            }
@@ -2635,14 +2635,15 @@ public class DevicePolicyManager {
     * the setup process.
     * @param packageName the package name of the app, to compare with the registered device owner
     * app, if any.
     * @return whether or not the package is registered as the device owner app.
     * @return whether or not the package is registered as the device owner app.  Note this method
     * does *not* check weather the device owner is actually running on the current user.
     */
    public boolean isDeviceOwnerApp(String packageName) {
        if (mService != null) {
            try {
                return mService.isDeviceOwner(packageName);
            } catch (RemoteException re) {
                Log.w(TAG, "Failed to check device owner");
                return mService.isDeviceOwnerPackage(packageName);
            } catch (RemoteException e) {
                Log.w(TAG, "Failed talking with device policy service", e);
            }
        }
        return false;
@@ -2656,6 +2657,17 @@ public class DevicePolicyManager {
        return isDeviceOwnerApp(packageName);
    }

    /**
     * Check whether a given component is registered as a device owner.
     * Note this method does *not* check weather the device owner is actually running on the current
     * user.
     *
     * @hide
     */
    public boolean isDeviceOwner(ComponentName who) {
        return (who != null) && who.equals(getDeviceOwner());
    }

    /**
     * Clears the current device owner.  The caller must be the device owner.
     *
@@ -2675,12 +2687,28 @@ public class DevicePolicyManager {
        }
    }

    /** @hide */
    /**
     * Returns the device owner package name.  Note this method will still return the device owner
     * package name even if it's running on a different user.
     *
     * @hide
     */
    @SystemApi
    public String getDeviceOwner() {
        final ComponentName componentName = getDeviceOwnerComponent();
        return componentName == null ? null : componentName.getPackageName();
    }

    /**
     * Returns the device owner name.  Note this method will still return the device owner
     * name even if it's running on a different user.
     *
     * @hide
     */
    public String getDeviceOwnerName() {
        if (mService != null) {
            try {
                return mService.getDeviceOwner();
                return mService.getDeviceOwnerName();
            } catch (RemoteException re) {
                Log.w(TAG, "Failed to get device owner");
            }
@@ -2688,11 +2716,16 @@ public class DevicePolicyManager {
        return null;
    }

    /** @hide */
    public String getDeviceOwnerName() {
    /**
     * Returns the device owner component name.  Note this method will still return the device owner
     * component name even if it's running on a different user.
     *
     * @hide
     */
    public ComponentName getDeviceOwnerComponent() {
        if (mService != null) {
            try {
                return mService.getDeviceOwnerName();
                return mService.getDeviceOwner();
            } catch (RemoteException re) {
                Log.w(TAG, "Failed to get device owner");
            }
+3 −3
Original line number Diff line number Diff line
@@ -113,9 +113,9 @@ interface IDevicePolicyManager {
    void reportFailedPasswordAttempt(int userHandle);
    void reportSuccessfulPasswordAttempt(int userHandle);

    boolean setDeviceOwner(String packageName, String ownerName, int userId);
    boolean isDeviceOwner(String packageName);
    String getDeviceOwner();
    boolean setDeviceOwner(in ComponentName who, String ownerName, int userId);
    boolean isDeviceOwnerPackage(String packageName);
    ComponentName getDeviceOwner();
    String getDeviceOwnerName();
    void clearDeviceOwner(String packageName);

+3 −1
Original line number Diff line number Diff line
@@ -12860,9 +12860,11 @@ public class PackageManagerService extends IPackageManager.Stub {
                ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
        try {
            if (dpm != null) {
                if (dpm.isDeviceOwner(packageName)) {
                // Does the package contains the device owner?
                if (dpm.isDeviceOwnerPackage(packageName)) {
                    return true;
                }
                // Does it contain a device admin for any user?
                int[] users;
                if (userId == UserHandle.USER_ALL) {
                    users = sUserManager.getUserIds();
+93 −29
Original line number Diff line number Diff line
@@ -1326,10 +1326,59 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    void loadOwners() {
        synchronized (this) {
            mOwners.load();
            findOwnerComponentIfNecessaryLocked();

            // TODO PO may not have a class name either due to b/17652534.  Address that too.

            updateDeviceOwnerLocked();
        }
    }

    private void findOwnerComponentIfNecessaryLocked() {
        if (!mOwners.hasDeviceOwner()) {
            return;
        }
        final ComponentName doComponentName = mOwners.getDeviceOwnerComponent();

        if (!TextUtils.isEmpty(doComponentName.getClassName())) {
            return; // Already a full component name.
        }

        final ComponentName doComponent = findAdminComponentWithPackageLocked(
                doComponentName.getPackageName(),
                mOwners.getDeviceOwnerUserId());
        if (doComponent == null) {
            Slog.e(LOG_TAG, "Device-owner isn't registered as device-admin");
        } else {
            mOwners.setDeviceOwner(
                    doComponent,
                    mOwners.getDeviceOwnerName(),
                    mOwners.getDeviceOwnerUserId());
            mOwners.writeDeviceOwner();
        }
    }

    private ComponentName findAdminComponentWithPackageLocked(String packageName, int userId) {
        final DevicePolicyData policy = getUserData(userId);
        final int n = policy.mAdminList.size();
        ComponentName found = null;
        int nFound = 0;
        for (int i = 0; i < n; i++) {
            final ActiveAdmin admin = policy.mAdminList.get(i);
            if (packageName.equals(admin.info.getPackageName())) {
                // Found!
                if (nFound == 0) {
                    found = admin.info.getComponent();
                }
                nFound++;
            }
        }
        if (nFound > 0) {
            Slog.w(LOG_TAG, "Multiple DA found; assume the first one is DO.");
        }
        return found;
    }

    /**
     * Set an alarm for an upcoming event - expiration warning, expiration, or post-expiration
     * reminders.  Clears alarm if no expirations are configured.
@@ -1440,9 +1489,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return null;
    }

    private boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy,
    @VisibleForTesting
    boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy,
            int userId) {
        boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
        boolean ownsDevice = isDeviceOwner(admin.info.getComponent());
        boolean ownsProfile = (getProfileOwner(userId) != null
                && getProfileOwner(userId).getPackageName()
                    .equals(admin.info.getPackageName()));
@@ -1880,8 +1930,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    private void updateDeviceOwnerLocked() {
        long ident = mInjector.binderClearCallingIdentity();
        try {
            if (getDeviceOwner() != null) {
                mInjector.getIActivityManager()
                    .updateDeviceOwner(getDeviceOwner());
                        .updateDeviceOwner(getDeviceOwner().getPackageName());
            }
        } catch (RemoteException e) {
            // Not gonna happen.
        } finally {
@@ -1945,7 +1997,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    public void systemReady(int phase) {
    @VisibleForTesting
    void systemReady(int phase) {
        if (!mHasFeature) {
            return;
        }
@@ -2284,7 +2337,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            if (admin.getUid() != mInjector.binderGetCallingUid()) {
                // Active device owners must remain active admins.
                if (isDeviceOwner(adminReceiver.getPackageName())) {
                if (isDeviceOwner(adminReceiver)) {
                    return;
                }
                mContext.enforceCallingOrSelfPermission(
@@ -3544,7 +3597,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            try {
                if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
                    if (userHandle != UserHandle.USER_SYSTEM
                            || !isDeviceOwner(admin.info.getPackageName())) {
                            || !isDeviceOwner(admin.info.getComponent())) {
                        throw new SecurityException(
                               "Only device owner admins can set WIPE_RESET_PROTECTION_DATA");
                    }
@@ -4293,13 +4346,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    }

    @Override
    public boolean setDeviceOwner(String packageName, String ownerName, int userId) {
    public boolean setDeviceOwner(ComponentName admin, String ownerName, int userId) {
        if (!mHasFeature) {
            return false;
        }
        if (packageName == null
                || !isPackageInstalledForUser(packageName, userId)) {
            throw new IllegalArgumentException("Invalid package name " + packageName
        if (admin == null
                || !isPackageInstalledForUser(admin.getPackageName(), userId)) {
            throw new IllegalArgumentException("Invalid component " + admin
                    + " for device owner");
        }
        synchronized (this) {
@@ -4315,7 +4368,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                mInjector.binderRestoreCallingIdentity(ident);
            }

            mOwners.setDeviceOwner(packageName, ownerName, userId);
            mOwners.setDeviceOwner(admin, ownerName, userId);
            mOwners.writeDeviceOwner();
            updateDeviceOwnerLocked();
            Intent intent = new Intent(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
@@ -4331,24 +4384,33 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    public boolean isDeviceOwner(ComponentName who) {
        if (!mHasFeature) {
            return false;
        }
        synchronized (this) {
            return mOwners.hasDeviceOwner() && mOwners.getDeviceOwnerComponent().equals(who);
        }
    }

    @Override
    public boolean isDeviceOwner(String packageName) {
    public boolean isDeviceOwnerPackage(String packageName) {
        if (!mHasFeature) {
            return false;
        }
        synchronized (this) {
            return mOwners.hasDeviceOwner()
                    && mOwners.getDeviceOwnerPackageName().equals(packageName);
                    && mOwners.getDeviceOwnerComponent().getPackageName().equals(packageName);
        }
    }

    @Override
    public String getDeviceOwner() {
    public ComponentName getDeviceOwner() {
        if (!mHasFeature) {
            return null;
        }
        synchronized (this) {
            return mOwners.getDeviceOwnerPackageName();
            return mOwners.getDeviceOwnerComponent();
        }
    }

@@ -4373,16 +4435,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    // Returns the active device owner or null if there is no device owner.
    @VisibleForTesting
    ActiveAdmin getDeviceOwnerAdminLocked() {
        String deviceOwnerPackageName = getDeviceOwner();
        if (deviceOwnerPackageName == null) {
        ComponentName component = getDeviceOwner();
        if (component == null) {
            return null;
        }

        DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
        DevicePolicyData policy = getUserData(mOwners.getDeviceOwnerUserId());
        final int n = policy.mAdminList.size();
        for (int i = 0; i < n; i++) {
            ActiveAdmin admin = policy.mAdminList.get(i);
            if (deviceOwnerPackageName.equals(admin.info.getPackageName())) {
            if (component.equals(admin.info.getComponent())) {
                return admin;
            }
        }
@@ -4392,15 +4454,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    @Override
    public void clearDeviceOwner(String packageName) {
        Preconditions.checkNotNull(packageName, "packageName is null");
        final int callingUid = mInjector.binderGetCallingUid();
        try {
            int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
            if (uid != mInjector.binderGetCallingUid()) {
            if (uid != callingUid) {
                throw new SecurityException("Invalid packageName");
            }
        } catch (NameNotFoundException e) {
            throw new SecurityException(e);
        }
        if (!isDeviceOwner(packageName)) {
        if (!mOwners.hasDeviceOwner() || !getDeviceOwner().getPackageName().equals(packageName)
                || (mOwners.getDeviceOwnerUserId() != UserHandle.getUserId(callingUid))) {
            throw new SecurityException("clearDeviceOwner can only be called by the device owner");
        }
        synchronized (this) {
@@ -5443,7 +5507,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        synchronized (this) {
            ActiveAdmin activeAdmin =
                    getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
            boolean isDeviceOwner = isDeviceOwner(activeAdmin.info.getPackageName());
            boolean isDeviceOwner = isDeviceOwner(who);
            if (!isDeviceOwner && userHandle != UserHandle.USER_SYSTEM
                    && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) {
                throw new SecurityException("Profile owners cannot set user restriction " + key);
@@ -5976,7 +6040,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            Bundle adminExtras = new Bundle();
            adminExtras.putString(DeviceAdminReceiver.EXTRA_LOCK_TASK_PACKAGE, pkg);
            for (ActiveAdmin admin : policy.mAdminList) {
                boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
                boolean ownsDevice = isDeviceOwner(admin.info.getComponent());
                boolean ownsProfile = (getProfileOwner(userHandle) != null
                        && getProfileOwner(userHandle).equals(admin.info.getPackageName()));
                if (ownsDevice || ownsProfile) {
@@ -6034,10 +6098,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        final ContentResolver contentResolver = mContext.getContentResolver();

        synchronized (this) {
            ActiveAdmin activeAdmin =
            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);

            if (isDeviceOwner(activeAdmin.info.getPackageName())) {
            if (isDeviceOwner(who)) {
                if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) {
                    throw new SecurityException(String.format(
                            "Permission denial: Device owners cannot update %1$s", setting));
@@ -6320,7 +6383,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
    private boolean isCallerDeviceOwner(int callerUid) {
        String[] pkgs = mContext.getPackageManager().getPackagesForUid(callerUid);
        for (String pkg : pkgs) {
            if (isDeviceOwner(pkg)) {
            if (isDeviceOwnerPackage(pkg)) {
                return true;
            }
        }
@@ -6342,7 +6405,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                updateReceivedTime);

        synchronized (this) {
            String deviceOwnerPackage = getDeviceOwner();
            final String deviceOwnerPackage = getDeviceOwner() == null ? null :
                    getDeviceOwner().getPackageName();
            if (deviceOwnerPackage == null) {
                return;
            }
Loading