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

Commit 60ea32be authored by Salud Lemus's avatar Salud Lemus
Browse files

Add API to set device owner type for a managed device

With this API, it will allow to customize Device Owner warning messages
on a financed device.

Bug: 173826319
Bug: 158157476
Bug: 180521289
Test: m -j64
Test: Used a test device that is registered via ZT
Test: atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest
Test: atest FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest

Change-Id: I97a2e9c4626d3cd9d01b19ce1d233be5fbd7377a
parent cd4ec6ac
Loading
Loading
Loading
Loading
+77 −0
Original line number Diff line number Diff line
@@ -2746,6 +2746,32 @@ public class DevicePolicyManager {
    @Retention(RetentionPolicy.SOURCE)
    public @interface PersonalAppsSuspensionReason {}
    /**
     * The default device owner type for a managed device.
     *
     * @hide
     */
    public static final int DEVICE_OWNER_TYPE_DEFAULT = 0;
    /**
     * The device owner type for a financed device.
     *
     * @hide
     */
    public static final int DEVICE_OWNER_TYPE_FINANCED = 1;
    /**
     * Different device owner types for a managed device.
     *
     * @hide
     */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "DEVICE_OWNER_TYPE_" }, value = {
            DEVICE_OWNER_TYPE_DEFAULT,
            DEVICE_OWNER_TYPE_FINANCED
    })
    public @interface DeviceOwnerType {}
    /** @hide */
    @TestApi
    public static final int OPERATION_LOCK_NOW = 1;
@@ -13459,6 +13485,57 @@ public class DevicePolicyManager {
        }
    }
    /**
     * Sets the device owner type for a managed device (e.g. financed device).
     *
     * @param admin The {@link DeviceAdminReceiver} that is the device owner.
     * @param deviceOwnerType The device owner type is set to. Use
     * {@link #DEVICE_OWNER_TYPE_DEFAULT} for the default device owner type. Use
     * {@link #DEVICE_OWNER_TYPE_FINANCED} for the financed device owner type.
     *
     * @throws IllegalStateException When admin is not the device owner, or there is no device
     *     owner, or attempting to set the device owner type again for the same admin.
     * @throws SecurityException If the caller does not have the permission
     *     {@link permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}.
     *
     * @hide
     */
    public void setDeviceOwnerType(@NonNull ComponentName admin,
            @DeviceOwnerType int deviceOwnerType) {
        throwIfParentInstance("setDeviceOwnerType");
        if (mService != null) {
            try {
                mService.setDeviceOwnerType(admin, deviceOwnerType);
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }
        }
    }
    /**
     * Returns the device owner type for the admin used in
     * {@link #setDeviceOwnerType(ComponentName, int)}. {@link #DEVICE_OWNER_TYPE_DEFAULT}
     * would be returned when the device owner type is not set for the device owner admin.
     *
     * @param admin The {@link DeviceAdminReceiver} that is the device owner.
     *
     * @throws IllegalStateException When admin is not the device owner or there is no device owner.
     *
     * @hide
     */
    @DeviceOwnerType
    public int getDeviceOwnerType(@NonNull ComponentName admin) {
        throwIfParentInstance("getDeviceOwnerType");
        if (mService != null) {
            try {
                return mService.getDeviceOwnerType(admin);
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }
        }
        return DEVICE_OWNER_TYPE_DEFAULT;
    }
    /**
     * Called by device owner or profile owner of an organization-owned managed profile to
     * enable or disable USB data signaling for the device. When disabled, USB data connections
+3 −0
Original line number Diff line number Diff line
@@ -503,6 +503,9 @@ interface IDevicePolicyManager {
    UserHandle createAndProvisionManagedProfile(in ManagedProfileProvisioningParams provisioningParams, in String callerPackage);
    void provisionFullyManagedDevice(in FullyManagedDeviceProvisioningParams provisioningParams, in String callerPackage);

    void setDeviceOwnerType(in ComponentName admin, in int deviceOwnerType);
    int getDeviceOwnerType(in ComponentName admin);

    void resetDefaultCrossProfileIntentFilters(int userId);
    boolean canAdminGrantSensorsPermissionsForUser(int userId);

+9 −0
Original line number Diff line number Diff line
@@ -129,6 +129,15 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
            FullyManagedDeviceProvisioningParams provisioningParams, String callerPackage) {
    }

    @Override
    public void setDeviceOwnerType(@NonNull ComponentName admin, int deviceOwnerType) {
    }

    @Override
    public int getDeviceOwnerType(@NonNull ComponentName admin) {
        return 0;
    }

    public void resetDefaultCrossProfileIntentFilters(@UserIdInt int userId) {}

    public boolean canAdminGrantSensorsPermissionsForUser(int userId) {
+32 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager.DeviceOwnerType;
import android.app.admin.DevicePolicyManager.DevicePolicyOperation;
import android.app.admin.DevicePolicyManager.OperationSafetyReason;
import android.app.admin.DevicePolicyManager.PasswordComplexity;
@@ -16720,6 +16721,37 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return mPolicyCache.canAdminGrantSensorsPermissionsForUser(userId);
    }
    @Override
    public void setDeviceOwnerType(@NonNull ComponentName admin,
            @DeviceOwnerType int deviceOwnerType) {
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
                permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
        verifyDeviceOwnerTypePreconditions(admin);
        final String packageName = admin.getPackageName();
        Preconditions.checkState(!mOwners.isDeviceOwnerTypeSetForDeviceOwner(packageName),
                "The device owner type has already been set for " + packageName);
        synchronized (getLockObject()) {
            mOwners.setDeviceOwnerType(packageName, deviceOwnerType);
        }
    }
    @Override
    @DeviceOwnerType
    public int getDeviceOwnerType(@NonNull ComponentName admin) {
        verifyDeviceOwnerTypePreconditions(admin);
        synchronized (getLockObject()) {
            return mOwners.getDeviceOwnerType(admin.getPackageName());
        }
    }
    private void verifyDeviceOwnerTypePreconditions(@NonNull ComponentName admin) {
        Preconditions.checkState(mOwners.hasDeviceOwner(), "there is no device owner");
        Preconditions.checkState(mOwners.getDeviceOwnerComponent().equals(admin),
                "admin is not the device owner");
    }
    @Override
    public void setUsbDataSignalingEnabled(String packageName, boolean enabled) {
        Objects.requireNonNull(packageName, "Admin package name must be provided");
+60 −0
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package com.android.server.devicepolicy;

import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;

import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManagerInternal;
import android.app.admin.DevicePolicyManager.DeviceOwnerType;
import android.app.admin.SystemUpdateInfo;
import android.app.admin.SystemUpdatePolicy;
import android.content.ComponentName;
@@ -93,6 +96,7 @@ class Owners {
    private static final String TAG_PROFILE_OWNER = "profile-owner";
    // Holds "context" for device-owner, this must not be show up before device-owner.
    private static final String TAG_DEVICE_OWNER_CONTEXT = "device-owner-context";
    private static final String TAG_DEVICE_OWNER_TYPE = "device-owner-type";

    private static final String ATTR_NAME = "name";
    private static final String ATTR_PACKAGE = "package";
@@ -109,6 +113,7 @@ class Owners {
    // New attribute for profile owner of organization-owned device.
    private static final String ATTR_PROFILE_OWNER_OF_ORG_OWNED_DEVICE =
            "isPoOrganizationOwnedDevice";
    private static final String ATTR_DEVICE_OWNER_TYPE_VALUE = "value";

    private final UserManager mUserManager;
    private final UserManagerInternal mUserManagerInternal;
@@ -121,6 +126,9 @@ class Owners {
    // Internal state for the device owner package.
    private OwnerInfo mDeviceOwner;

    // Device owner type for a managed device.
    private final ArrayMap<String, Integer> mDeviceOwnerTypes = new ArrayMap<>();

    private int mDeviceOwnerUserId = UserHandle.USER_NULL;

    // Internal state for the profile owner packages.
@@ -334,6 +342,7 @@ class Owners {

    void clearDeviceOwner() {
        synchronized (mLock) {
            mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
            mDeviceOwner = null;
            mDeviceOwnerUserId = UserHandle.USER_NULL;

@@ -384,12 +393,16 @@ class Owners {

    void transferDeviceOwnership(ComponentName target) {
        synchronized (mLock) {
            Integer previousDeviceOwnerType = mDeviceOwnerTypes.remove(mDeviceOwner.packageName);
            // We don't set a name because it's not used anyway.
            // See DevicePolicyManagerService#getDeviceOwnerName
            mDeviceOwner = new OwnerInfo(null, target,
                    mDeviceOwner.userRestrictionsMigrated, mDeviceOwner.remoteBugreportUri,
                    mDeviceOwner.remoteBugreportHash, /* isOrganizationOwnedDevice =*/
                    mDeviceOwner.isOrganizationOwnedDevice);
            if (previousDeviceOwnerType != null) {
                mDeviceOwnerTypes.put(mDeviceOwner.packageName, previousDeviceOwnerType);
            }
            pushToPackageManagerLocked();
            pushToActivityTaskManagerLocked();
            pushToActivityManagerLocked();
@@ -596,6 +609,37 @@ class Owners {
        }
    }

    void setDeviceOwnerType(String packageName, @DeviceOwnerType int deviceOwnerType) {
        synchronized (mLock) {
            if (!hasDeviceOwner()) {
                Slog.e(TAG, "Attempting to set a device owner type when there is no device owner");
                return;
            } else if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) {
                Slog.e(TAG, "Device owner type for " + packageName + " has already been set");
                return;
            }

            mDeviceOwnerTypes.put(packageName, deviceOwnerType);
            writeDeviceOwner();
        }
    }

    @DeviceOwnerType
    int getDeviceOwnerType(String packageName) {
        synchronized (mLock) {
            if (isDeviceOwnerTypeSetForDeviceOwner(packageName)) {
                return mDeviceOwnerTypes.get(packageName);
            }
            return DEVICE_OWNER_TYPE_DEFAULT;
        }
    }

    boolean isDeviceOwnerTypeSetForDeviceOwner(String packageName) {
        synchronized (mLock) {
            return !mDeviceOwnerTypes.isEmpty() && mDeviceOwnerTypes.containsKey(packageName);
        }
    }

    private boolean readLegacyOwnerFileLocked(File file) {
        if (!file.exists()) {
            // Already migrated or the device has no owners.
@@ -880,6 +924,16 @@ class Owners {
                out.startTag(null, TAG_DEVICE_OWNER_CONTEXT);
                out.attributeInt(null, ATTR_USERID, mDeviceOwnerUserId);
                out.endTag(null, TAG_DEVICE_OWNER_CONTEXT);

            }

            if (!mDeviceOwnerTypes.isEmpty()) {
                for (ArrayMap.Entry<String, Integer> entry : mDeviceOwnerTypes.entrySet()) {
                    out.startTag(null, TAG_DEVICE_OWNER_TYPE);
                    out.attribute(null, ATTR_PACKAGE, entry.getKey());
                    out.attributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE, entry.getValue());
                    out.endTag(null, TAG_DEVICE_OWNER_TYPE);
                }
            }

            if (mSystemUpdatePolicy != null) {
@@ -942,6 +996,12 @@ class Owners {
                        }
                    }
                    break;
                case TAG_DEVICE_OWNER_TYPE:
                    String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                    int deviceOwnerType = parser.getAttributeInt(null, ATTR_DEVICE_OWNER_TYPE_VALUE,
                            DEVICE_OWNER_TYPE_DEFAULT);
                    mDeviceOwnerTypes.put(packageName, deviceOwnerType);
                    break;
                default:
                    Slog.e(TAG, "Unexpected tag: " + tag);
                    return false;
Loading