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

Commit f9d6f9ad authored by Alex Johnston's avatar Alex Johnston
Browse files

Handle permission-based admin policy persistence

Changes:
- Add a permission based admin to DevicePolicyData.
  This admin will not have a ComponentName or admin info.
- Update setCameraDisabled and getCameraDisabled to
  be callable by an app with the
  MANAGE_DEVICE_POLICY_CAMERA permission.

Bug: 234609037
Test: atest CameraPolicyTest
Change-Id: I5031c38f79c91fdccfae4ae3903e12016c6c83e4
parent 96753d9f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -7881,7 +7881,7 @@ package android.app.admin {
    method @RequiresPermission(value=android.Manifest.permission.SET_TIME_ZONE, conditional=true) public void setAutoTimeZoneEnabled(@NonNull android.content.ComponentName, boolean);
    method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
    method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
    method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
    method @RequiresPermission(value=android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA, conditional=true) public void setCameraDisabled(@Nullable android.content.ComponentName, boolean);
    method @Deprecated public void setCertInstallerPackage(@NonNull android.content.ComponentName, @Nullable String) throws java.lang.SecurityException;
    method public void setCommonCriteriaModeEnabled(@NonNull android.content.ComponentName, boolean);
    method public void setConfiguredNetworksLockdownState(@NonNull android.content.ComponentName, boolean);
+7 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.app.admin;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_CAMERA;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.SET_TIME;
@@ -8265,15 +8266,18 @@ public class DevicePolicyManager {
     * legacy device admins targeting SDK version {@link android.os.Build.VERSION_CODES#P} or
     * below will be silently ignored.
     *
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
     * @param admin Which {@link DeviceAdminReceiver} this request is associated with or null if
                     the caller is not a device admin
     * @param disabled Whether or not the camera should be disabled.
     * @throws SecurityException if {@code admin} is not an active administrator or does not use
     *             {@link DeviceAdminInfo#USES_POLICY_DISABLE_CAMERA}.
     */
    public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
    @RequiresPermission(value = MANAGE_DEVICE_POLICY_CAMERA, conditional = true)
    public void setCameraDisabled(@Nullable ComponentName admin, boolean disabled) {
        if (mService != null) {
            try {
                mService.setCameraDisabled(admin, disabled, mParentInstance);
                mService.setCameraDisabled(admin, mContext.getPackageName(), disabled,
                        mParentInstance);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
+1 −1
Original line number Diff line number Diff line
@@ -141,7 +141,7 @@ interface IDevicePolicyManager {

    boolean requestBugreport(in ComponentName who);

    void setCameraDisabled(in ComponentName who, boolean disabled, boolean parent);
    void setCameraDisabled(in ComponentName who, String callerPackageName, boolean disabled, boolean parent);
    boolean getCameraDisabled(in ComponentName who, int userHandle, boolean parent);

    void setScreenCaptureDisabled(in ComponentName who, boolean disabled, boolean parent);
+16 −11
Original line number Diff line number Diff line
@@ -176,7 +176,8 @@ class ActiveAdmin {
    private static final String ATTR_PACKAGE_POLICY_MODE = "package-policy-type";
    private static final String TAG_CREDENTIAL_MANAGER_POLICY = "credential-manager-policy";


    // If the ActiveAdmin is a permission-based admin, then info will be null because the
    // permission-based admin is not mapped to a device administrator component.
    DeviceAdminInfo info;

    static final int DEF_PASSWORD_HISTORY_LENGTH = 0;
@@ -378,9 +379,11 @@ class ActiveAdmin {

    void writeToXml(TypedXmlSerializer out)
            throws IllegalArgumentException, IllegalStateException, IOException {
        if (info != null) {
            out.startTag(null, TAG_POLICIES);
            info.writePoliciesToXml(out);
            out.endTag(null, TAG_POLICIES);
        }
        if (mPasswordPolicy.quality != PASSWORD_QUALITY_UNSPECIFIED) {
            writeAttributeValueToXml(
                    out, TAG_PASSWORD_QUALITY, mPasswordPolicy.quality);
@@ -1188,6 +1191,7 @@ class ActiveAdmin {
        pw.print("testOnlyAdmin=");
        pw.println(testOnlyAdmin);

        if (info != null) {
            pw.println("policies:");
            ArrayList<DeviceAdminInfo.PolicyInfo> pols = info.getUsedPolicies();
            if (pols != null) {
@@ -1197,6 +1201,7 @@ class ActiveAdmin {
                }
                pw.decreaseIndent();
            }
        }

        pw.print("passwordQuality=0x");
        pw.println(Integer.toHexString(mPasswordPolicy.quality));
+28 −0
Original line number Diff line number Diff line
@@ -123,6 +123,23 @@ class DevicePolicyData {
    final ArrayList<ActiveAdmin> mAdminList = new ArrayList<>();
    final ArrayList<ComponentName> mRemovingAdmins = new ArrayList<>();

    // Some DevicePolicyManager APIs can be called by (1) a DPC or (2) an app with permissions that
    // isn't a DPC. For the latter, the caller won't have to provide a ComponentName and won't be
    // mapped to an ActiveAdmin. This permission-based admin should be used to persist policies
    // set by the permission-based caller. This admin should not be added to mAdminMap or mAdminList
    // since a lot of methods in DPMS assume the ActiveAdmins here have a valid ComponentName.
    // Instead, use variants of DPMS active admin getters to include the permission-based admin.
    ActiveAdmin mPermissionBasedAdmin;

    // Create or get the permission-based admin. The permission-based admin will not have a
    // DeviceAdminInfo or ComponentName.
    ActiveAdmin createOrGetPermissionBasedAdmin() {
        if (mPermissionBasedAdmin == null) {
            mPermissionBasedAdmin = new ActiveAdmin(/* info= */ null, /* parent= */ false);
        }
        return mPermissionBasedAdmin;
    }

    // TODO(b/35385311): Keep track of metadata in TrustedCertificateStore instead.
    final ArraySet<String> mAcceptedCaCertificates = new ArraySet<>();

@@ -256,6 +273,12 @@ class DevicePolicyData {
                }
            }

            if (policyData.mPermissionBasedAdmin != null) {
                out.startTag(null, "permission-based-admin");
                policyData.mPermissionBasedAdmin.writeToXml(out);
                out.endTag(null, "permission-based-admin");
            }

            if (policyData.mPasswordOwner >= 0) {
                out.startTag(null, "password-owner");
                out.attributeInt(null, "value", policyData.mPasswordOwner);
@@ -457,6 +480,7 @@ class DevicePolicyData {
            policy.mLockTaskPackages.clear();
            policy.mAdminList.clear();
            policy.mAdminMap.clear();
            policy.mPermissionBasedAdmin = null;
            policy.mAffiliationIds.clear();
            policy.mOwnerInstalledCaCerts.clear();
            policy.mUserControlDisabledPackages = null;
@@ -484,6 +508,10 @@ class DevicePolicyData {
                    } catch (RuntimeException e) {
                        Slogf.w(TAG, e, "Failed loading admin %s", name);
                    }
                } else if ("permission-based-admin".equals(tag)) {
                    ActiveAdmin ap = new ActiveAdmin(/* info= */ null, /* parent= */ false);
                    ap.readFromXml(parser, /* overwritePolicies= */ false);
                    policy.mPermissionBasedAdmin = ap;
                } else if ("delegation".equals(tag)) {
                    // Parse delegation info.
                    final String delegatePackage = parser.getAttributeValue(null,
Loading