Merge "Change bypassRoleQualification persistence logic" into tm-dev am: 747806ddf8
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17539065 Change-Id: I1582d22f1bef65118bd475e6a62cd95df76ac2c0 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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" />
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
Reference in New Issue
Block a user