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

Commit 0be33b19 authored by Kholoud Mohamed's avatar Kholoud Mohamed Committed by Automerger Merge Worker
Browse files

Merge "Change bypassRoleQualification persistence logic" into tm-dev am: 747806dd

parents 4e520519 747806dd
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -69,6 +69,7 @@ class DevicePolicyData {
    private static final String TAG_PASSWORD_VALIDITY = "password-validity";
    private static final String TAG_PASSWORD_VALIDITY = "password-validity";
    private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
    private static final String TAG_PASSWORD_TOKEN_HANDLE = "password-token";
    private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
    private static final String TAG_PROTECTED_PACKAGES = "protected-packages";
    private static final String TAG_BYPASS_ROLE_QUALIFICATIONS = "bypass-role-qualifications";
    private static final String ATTR_VALUE = "value";
    private static final String ATTR_VALUE = "value";
    private static final String ATTR_ALIAS = "alias";
    private static final String ATTR_ALIAS = "alias";
    private static final String ATTR_ID = "id";
    private static final String ATTR_ID = "id";
@@ -107,6 +108,8 @@ class DevicePolicyData {
    int mPasswordOwner = -1;
    int mPasswordOwner = -1;
    long mLastMaximumTimeToLock = -1;
    long mLastMaximumTimeToLock = -1;
    boolean mUserSetupComplete = false;
    boolean mUserSetupComplete = false;
    boolean mBypassDevicePolicyManagementRoleQualifications = false;
    String mCurrentRoleHolder;
    boolean mPaired = false;
    boolean mPaired = false;
    int mUserProvisioningState;
    int mUserProvisioningState;
    int mPermissionPolicy;
    int mPermissionPolicy;
@@ -374,6 +377,12 @@ class DevicePolicyData {
                out.endTag(null, TAG_APPS_SUSPENDED);
                out.endTag(null, TAG_APPS_SUSPENDED);
            }
            }


            if (policyData.mBypassDevicePolicyManagementRoleQualifications) {
                out.startTag(null, TAG_BYPASS_ROLE_QUALIFICATIONS);
                out.attribute(null, ATTR_VALUE, policyData.mCurrentRoleHolder);
                out.endTag(null, TAG_BYPASS_ROLE_QUALIFICATIONS);
            }

            out.endTag(null, "policies");
            out.endTag(null, "policies");


            out.endDocument();
            out.endDocument();
@@ -558,6 +567,9 @@ class DevicePolicyData {
                } else if (TAG_APPS_SUSPENDED.equals(tag)) {
                } else if (TAG_APPS_SUSPENDED.equals(tag)) {
                    policy.mAppsSuspended =
                    policy.mAppsSuspended =
                            parser.getAttributeBoolean(null, ATTR_VALUE, false);
                            parser.getAttributeBoolean(null, ATTR_VALUE, false);
                } else if (TAG_BYPASS_ROLE_QUALIFICATIONS.equals(tag)) {
                    policy.mBypassDevicePolicyManagementRoleQualifications = true;
                    policy.mCurrentRoleHolder =  parser.getAttributeValue(null, ATTR_VALUE);
                } else {
                } else {
                    Slogf.w(TAG, "Unknown tag: %s", tag);
                    Slogf.w(TAG, "Unknown tag: %s", tag);
                    XmlUtils.skipCurrentTag(parser);
                    XmlUtils.skipCurrentTag(parser);
+145 −9
Original line number Original line Diff line number Diff line
@@ -138,7 +138,6 @@ import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.provider.Settings.Global.BYPASS_DEVICE_POLICY_MANAGEMENT_ROLE_QUALIFICATIONS;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Settings.Secure.MANAGED_PROVISIONING_DPC_DOWNLOADED;
import static android.provider.Settings.Secure.MANAGED_PROVISIONING_DPC_DOWNLOADED;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
@@ -222,6 +221,7 @@ import android.app.admin.UnsafeStateException;
import android.app.admin.WifiSsidPolicy;
import android.app.admin.WifiSsidPolicy;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManager;
import android.app.compat.CompatChanges;
import android.app.compat.CompatChanges;
import android.app.role.OnRoleHoldersChangedListener;
import android.app.role.RoleManager;
import android.app.role.RoleManager;
import android.app.trust.TrustManager;
import android.app.trust.TrustManager;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal;
@@ -255,6 +255,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.pm.StringParceledListSlice;
import android.content.pm.StringParceledListSlice;
import android.content.pm.UserInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.content.res.Resources;
@@ -409,6 +410,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Predicate;
@@ -756,6 +758,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    private @UserIdInt int mNetworkLoggingNotificationUserId = UserHandle.USER_NULL;
    private @UserIdInt int mNetworkLoggingNotificationUserId = UserHandle.USER_NULL;
    private final DeviceManagementResourcesProvider mDeviceManagementResourcesProvider;
    private final DeviceManagementResourcesProvider mDeviceManagementResourcesProvider;
    private final DevicePolicyManagementRoleObserver mDevicePolicyManagementRoleObserver;
    private static final boolean ENABLE_LOCK_GUARD = true;
    private static final boolean ENABLE_LOCK_GUARD = true;
@@ -1823,6 +1826,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        mBugreportCollectionManager = new RemoteBugreportManager(this, mInjector);
        mBugreportCollectionManager = new RemoteBugreportManager(this, mInjector);
        mDeviceManagementResourcesProvider = mInjector.getDeviceManagementResourcesProvider();
        mDeviceManagementResourcesProvider = mInjector.getDeviceManagementResourcesProvider();
        mDevicePolicyManagementRoleObserver = new DevicePolicyManagementRoleObserver(mContext);
        mDevicePolicyManagementRoleObserver.register();
        // "Lite" interface is available even when the device doesn't have the feature
        // "Lite" interface is available even when the device doesn't have the feature
        LocalServices.addService(DevicePolicyManagerLiteInternal.class, mLocalService);
        LocalServices.addService(DevicePolicyManagerLiteInternal.class, mLocalService);
@@ -18663,16 +18668,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
                android.Manifest.permission.MANAGE_ROLE_HOLDERS));
                android.Manifest.permission.MANAGE_ROLE_HOLDERS));
        return mInjector.binderWithCleanCallingIdentity(() -> {
        return mInjector.binderWithCleanCallingIdentity(() -> {
            if (mInjector.settingsGlobalGetInt(
            if (getUserData(
                    BYPASS_DEVICE_POLICY_MANAGEMENT_ROLE_QUALIFICATIONS, /* def= */ 0) == 1) {
                    UserHandle.USER_SYSTEM).mBypassDevicePolicyManagementRoleQualifications) {
                return true;
                return true;
            }
            }
            if (shouldAllowBypassingDevicePolicyManagementRoleQualificationInternal()) {
            return shouldAllowBypassingDevicePolicyManagementRoleQualificationInternal();
                mInjector.settingsGlobalPutInt(
                        BYPASS_DEVICE_POLICY_MANAGEMENT_ROLE_QUALIFICATIONS, /* value= */ 1);
                return true;
            }
            return false;
        });
        });
    }
    }
@@ -18685,6 +18685,142 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        return accounts.length == 0;
        return accounts.length == 0;
    }
    }
    private void setBypassDevicePolicyManagementRoleQualificationStateInternal(
            String currentRoleHolder, boolean allowBypass) {
        boolean stateChanged = false;
        DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
        if (policy.mBypassDevicePolicyManagementRoleQualifications != allowBypass) {
            policy.mBypassDevicePolicyManagementRoleQualifications = allowBypass;
            stateChanged = true;
        }
        if (!Objects.equals(currentRoleHolder, policy.mCurrentRoleHolder)) {
            policy.mCurrentRoleHolder = currentRoleHolder;
            stateChanged = true;
        }
        if (stateChanged) {
            synchronized (getLockObject()) {
                saveSettingsLocked(UserHandle.USER_SYSTEM);
            }
        }
    }
    private final class DevicePolicyManagementRoleObserver implements OnRoleHoldersChangedListener {
        private RoleManager mRm;
        private final Executor mExecutor;
        private final Context mContext;
        DevicePolicyManagementRoleObserver(@NonNull Context context) {
            mContext = context;
            mExecutor = mContext.getMainExecutor();
            mRm = mContext.getSystemService(RoleManager.class);
        }
        public void register() {
            mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.SYSTEM);
        }
        @Override
        public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) {
            if (!RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) {
                return;
            }
            String newRoleHolder = getRoleHolder();
            if (isDefaultRoleHolder(newRoleHolder)) {
                Slogf.i(LOG_TAG,
                        "onRoleHoldersChanged: Default role holder is set, returning early");
                return;
            }
            if (newRoleHolder == null) {
                Slogf.i(LOG_TAG,
                        "onRoleHoldersChanged: New role holder is null, returning early");
                return;
            }
            if (shouldAllowBypassingDevicePolicyManagementRoleQualificationInternal()) {
                Slogf.w(LOG_TAG,
                        "onRoleHoldersChanged: Updating current role holder to " + newRoleHolder);
                setBypassDevicePolicyManagementRoleQualificationStateInternal(
                        newRoleHolder, /* allowBypass= */ true);
                return;
            }
            DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM);
            if (!newRoleHolder.equals(policy.mCurrentRoleHolder)) {
                Slogf.w(LOG_TAG,
                        "onRoleHoldersChanged: You can't set a different role holder, role "
                                + "is getting revoked from " + newRoleHolder);
                setBypassDevicePolicyManagementRoleQualificationStateInternal(
                        /* currentRoleHolder= */ null, /* allowBypass= */ false);
                mRm.removeRoleHolderAsUser(
                        RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT,
                        newRoleHolder,
                        /* flags= */ 0,
                        user,
                        mExecutor,
                        successful -> {});
            }
        }
        private String getRoleHolder() {
            return DevicePolicyManagerService.this.getDevicePolicyManagementRoleHolderPackageName(
                    mContext);
        }
        private boolean isDefaultRoleHolder(String packageName) {
            String defaultRoleHolder = getDefaultRoleHolderPackageName();
            if (packageName == null || defaultRoleHolder == null) {
                return false;
            }
            if (!defaultRoleHolder.equals(packageName)) {
                return false;
            }
            return hasSigningCertificate(
                    packageName, getDefaultRoleHolderPackageSignature());
        }
        private boolean hasSigningCertificate(String packageName, String  certificateString) {
            if (packageName == null || certificateString == null) {
                return false;
            }
            byte[] certificate;
            try {
                certificate = new Signature(certificateString).toByteArray();
            } catch (IllegalArgumentException e) {
                Slogf.w(LOG_TAG, "Cannot parse signing certificate: " + certificateString, e);
                return false;
            }
            PackageManager pm = mInjector.getPackageManager();
            return pm.hasSigningCertificate(
                    packageName, certificate, PackageManager.CERT_INPUT_SHA256);
        }
        private String getDefaultRoleHolderPackageName() {
            String[] info = getDefaultRoleHolderPackageNameAndSignature();
            if (info == null) {
                return null;
            }
            return info[0];
        }
        private String getDefaultRoleHolderPackageSignature() {
            String[] info = getDefaultRoleHolderPackageNameAndSignature();
            if (info == null || info.length < 2) {
                return null;
            }
            return info[1];
        }
        private String[] getDefaultRoleHolderPackageNameAndSignature() {
            String packageNameAndSignature = mContext.getString(
                    com.android.internal.R.string.config_devicePolicyManagement);
            if (TextUtils.isEmpty(packageNameAndSignature)) {
                return null;
            }
            if (packageNameAndSignature.contains(":")) {
                return packageNameAndSignature.split(":");
            }
            return new String[]{packageNameAndSignature};
        }
    }
    @Override
    @Override
    public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) {
    public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) {
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
        Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
+1 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,7 @@
    <uses-permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY" />
    <uses-permission android:name="android.permission.READ_NEARBY_STREAMING_POLICY" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING" />
    <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
    <uses-permission android:name="android.permission.PACKAGE_VERIFICATION_AGENT" />
    <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />


    <queries>
    <queries>
        <package android:name="com.android.servicestests.apps.suspendtestapp" />
        <package android:name="com.android.servicestests.apps.suspendtestapp" />
+2 −0
Original line number Original line Diff line number Diff line
@@ -237,6 +237,8 @@ public class DpmMockContext extends MockContext {
                return mMockSystemServices.devicePolicyManager;
                return mMockSystemServices.devicePolicyManager;
            case Context.LOCATION_SERVICE:
            case Context.LOCATION_SERVICE:
                return mMockSystemServices.locationManager;
                return mMockSystemServices.locationManager;
            case Context.ROLE_SERVICE:
                return mMockSystemServices.roleManager;
        }
        }
        throw new UnsupportedOperationException();
        throw new UnsupportedOperationException();
    }
    }
+3 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@ import android.app.IActivityTaskManager;
import android.app.NotificationManager;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManager;
import android.app.role.RoleManager;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ComponentName;
@@ -131,6 +132,7 @@ public class MockSystemServices {
    public final VpnManager vpnManager;
    public final VpnManager vpnManager;
    public final DevicePolicyManager devicePolicyManager;
    public final DevicePolicyManager devicePolicyManager;
    public final LocationManager locationManager;
    public final LocationManager locationManager;
    public final RoleManager roleManager;
    /** Note this is a partial mock, not a real mock. */
    /** Note this is a partial mock, not a real mock. */
    public final PackageManager packageManager;
    public final PackageManager packageManager;
    public final BuildMock buildMock = new BuildMock();
    public final BuildMock buildMock = new BuildMock();
@@ -181,6 +183,7 @@ public class MockSystemServices {
        vpnManager = mock(VpnManager.class);
        vpnManager = mock(VpnManager.class);
        devicePolicyManager = mock(DevicePolicyManager.class);
        devicePolicyManager = mock(DevicePolicyManager.class);
        locationManager = mock(LocationManager.class);
        locationManager = mock(LocationManager.class);
        roleManager = realContext.getSystemService(RoleManager.class);


        // Package manager is huge, so we use a partial mock instead.
        // Package manager is huge, so we use a partial mock instead.
        packageManager = spy(realContext.getPackageManager());
        packageManager = spy(realContext.getPackageManager());