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

Commit a1015c8c authored by Eran Messeri's avatar Eran Messeri
Browse files

DPM: Add method for Organization-owned device detection

Add a method to the DevicePolicyManager for finding out if the device is
an organization-owned device with a work profile (i.e. it has a work
profile but the work profile was created during the provisioning flow).

This method is currently available for privileged callers (system API),
since other methods (e.g. isDeviceManaged) are also restricted.

NOTE: Addition of GTS tests is pending final decision on whether this
will be public API or not.

Bug: 143518237
Bug: 144978467
Bug: 147340575
Test: atest FrameworksServicesTests:DevicePolicyManagerTest#testIsOrganizationOwnedDevice
Test: CTS tests that are on hold for now.

Change-Id: I26ce1de10844dc297924427a6d46df9208931ab0
parent 005c68cf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -799,6 +799,7 @@ package android.app.admin {
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned();
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioningConfigApplied();
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedKiosk();
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isOrganizationOwnedDeviceWithManagedProfile();
    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUnattendedManagedKiosk();
    method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long);
    method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
+30 −3
Original line number Diff line number Diff line
@@ -88,7 +88,6 @@ import android.telephony.data.ApnSetting;
import android.util.ArraySet;
import android.util.Log;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.Preconditions;
@@ -6756,6 +6755,34 @@ public class DevicePolicyManager {
        return null;
    }

    /**
     * @hide
     * Privileged apps can use this method to find out if the device was provisioned as
     * organization-owend device with a managed profile.
     *
     * This, together with checking whether the device has a device owner (by calling
     * {@link #isDeviceManaged()}), could be used to learn whether the device is owned by an
     * organization or an individual:
     * If this method returns true OR {@link #isDeviceManaged()} returns true, then
     * the device is owned by an organization. Otherwise, it's owned by an individual.
     *
     * @return {@code true} if the device was provisioned as organization-owned device,
     * {@code false} otherwise.
     */
    @SystemApi
    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
    public boolean isOrganizationOwnedDeviceWithManagedProfile() {
        throwIfParentInstance("isOrganizationOwnedDeviceWithManagedProfile");
        if (mService != null) {
            try {
                return mService.isOrganizationOwnedDeviceWithManagedProfile();
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }
        }
        return false;
    }

    /**
     * Returns whether the specified package can read the device identifiers.
     *
@@ -11215,12 +11242,12 @@ public class DevicePolicyManager {
     * #setCrossProfilePackages(ComponentName, Set)}.</li>
     * <li>The default package names set by the OEM that are allowed to request user consent for
     * cross-profile communication without being explicitly enabled by the admin, via
     * {@link R.array#cross_profile_apps}</li>
     * {@link com.android.internal.R.array#cross_profile_apps}</li>
     * </ul>
     *
     * @return the combined set of whitelisted package names set via
     * {@link #setCrossProfilePackages(ComponentName, Set)} and
     * {@link R.array#cross_profile_apps}
     * {@link com.android.internal.R.array#cross_profile_apps}
     *
     * @hide
     */
+1 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ interface IDevicePolicyManager {
    void setProfileName(in ComponentName who, String profileName);
    void clearProfileOwner(in ComponentName who);
    boolean hasUserSetupCompleted();
    boolean isOrganizationOwnedDeviceWithManagedProfile();

    boolean checkDeviceIdentifierAccess(in String packageName, int pid, int uid);

+4 −0
Original line number Diff line number Diff line
@@ -64,4 +64,8 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
    }

    public void setLocationEnabled(ComponentName who, boolean locationEnabled) {}

    public boolean isOrganizationOwnedDeviceWithManagedProfile() {
        return false;
    }
}
+18 −0
Original line number Diff line number Diff line
@@ -8606,6 +8606,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return getApplicationLabel(profileOwner.getPackageName(), userHandle);
    }
    @Override
    public boolean isOrganizationOwnedDeviceWithManagedProfile() {
        if (!mHasFeature) {
            return false;
        }
        enforceManageUsers();
        return mInjector.binderWithCleanCallingIdentity(() -> {
            for (UserInfo ui : mUserManager.getUsers()) {
                if (ui.isManagedProfile() && isProfileOwnerOfOrganizationOwnedDevice(ui.id)) {
                    return true;
                }
            }
            return false;
        });
    }
    @Override
    public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
        ensureCallerIdentityMatchesIfNotSystem(packageName, pid, uid);
Loading