Loading core/java/android/app/admin/DevicePolicyManager.java +21 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.security.keystore.StrongBoxUnavailableException; import android.service.restrictions.RestrictionsReceiver; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.text.TextUtils; Loading Loading @@ -11285,6 +11286,26 @@ public class DevicePolicyManager { } } /** * Checks whether the given subscription is enterprise-managed. * * @param info The subscription to check. * @param packageName The package to check against the subscription's group owner. * @return whether the subscription is enterprise-managed. * @hide */ public boolean isSubscriptionEnterpriseManaged( @NonNull SubscriptionInfo info, @NonNull String packageName) { if (mService != null) { try { return mService.isSubscriptionEnterpriseManaged(info, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return false; } /** * Start Quick Contact on the managed profile for the user, if the policy allows. * @hide core/java/android/app/admin/IDevicePolicyManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.os.RemoteCallback; import android.os.UserHandle; import android.security.keymaster.KeymasterCertificateChain; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.telephony.SubscriptionInfo; import android.telephony.data.ApnSetting; import com.android.internal.infra.AndroidFuture; import android.app.admin.DevicePolicyState; Loading Loading @@ -624,6 +625,8 @@ interface IDevicePolicyManager { void setManagedSubscriptionsPolicy(in ManagedSubscriptionsPolicy policy); ManagedSubscriptionsPolicy getManagedSubscriptionsPolicy(); boolean isSubscriptionEnterpriseManaged(in SubscriptionInfo info, String packageName); DevicePolicyState getDevicePolicyState(); boolean triggerDevicePolicyEngineMigration(boolean forceMigration); Loading core/java/android/app/admin/flags/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -442,3 +442,10 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "enterprise_esim_using_carrier_privileges" namespace: "enterprise" description: "Check for enterprise management indicator in carrier privileges of an eSIM profile" bug: "373466339" } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +45 −14 Original line number Diff line number Diff line Loading @@ -490,6 +490,7 @@ import android.telecom.TelecomManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.UiccAccessRule; import android.telephony.data.ApnSetting; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; Loading Loading @@ -1040,6 +1041,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final boolean ENABLE_LOCK_GUARD = true; /** * Pair of magic hash and package name strings used as an enterprise management marker in the * access rules of a subscription. The hash is a SHA-256 hash of the package name. */ private static final String ENTERPRISE_SIM_MAGIC_PACKAGE_NAME = "com.android.notanapp.enterprise_sim"; private static final String ENTERPRISE_SIM_MAGIC_HASH = "5715E84E9FEFDD8CEB019F3CE2DC5B73A24D155363D3731D40CA1852F41A5059"; /** * Profile off deadline is not set or more than MANAGED_PROFILE_OFF_WARNING_PERIOD away, or the * user is running unlocked, no need for notification. Loading Loading @@ -24104,6 +24115,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } @Override public boolean isSubscriptionEnterpriseManaged( @NonNull SubscriptionInfo info, @NonNull String packageName) { boolean result = info.getGroupOwner().equals(packageName); if (Flags.enterpriseEsimUsingCarrierPrivileges()) { result |= enterpriseMarkerExistsInAccessRules(info); } return result; } private static boolean enterpriseMarkerExistsInAccessRules(@NonNull SubscriptionInfo info) { if (info.getAccessRules() == null) { return false; } return info.getAccessRules().stream().anyMatch((UiccAccessRule accessRule) -> accessRule.hasMatchingCertificateHashAndPackageName( ENTERPRISE_SIM_MAGIC_HASH, ENTERPRISE_SIM_MAGIC_PACKAGE_NAME) ); } private void installOemDefaultDialerAndSmsApp(int targetUserId) { try { String defaultDialerPackageName = getOemDefaultDialerPackage(); Loading Loading @@ -24830,20 +24861,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private IntArray getSubscriptionIdsInternal(String callerPackageName) { SubscriptionManager subscriptionManager = mContext.getSystemService(SubscriptionManager.class); return mInjector.binderWithCleanCallingIdentity(() -> { return mInjector.binderWithCleanCallingIdentity( () -> { IntArray adminOwnedSubscriptions = new IntArray(); List<SubscriptionInfo> subs = subscriptionManager.getAvailableSubscriptionInfoList(); List<SubscriptionInfo> subs = subscriptionManager.getAvailableSubscriptionInfoList(); int subCount = (subs != null) ? subs.size() : 0; for (int i = 0; i < subCount; i++) { SubscriptionInfo sub = subs.get(i); if (sub.getGroupOwner() .equals(callerPackageName)) { if (isSubscriptionEnterpriseManaged(sub, callerPackageName)) { adminOwnedSubscriptions.add(sub.getSubscriptionId()); } } return adminOwnedSubscriptions; }); } @Override services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +53 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.hamcrest.MockitoHamcrest.argThat; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertThrows; import static org.testng.Assert.assertTrue; import static java.util.Collections.emptyList; Loading Loading @@ -145,6 +148,7 @@ import android.security.KeyChain; import android.security.keystore.AttestationUtils; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.UiccAccessRule; import android.telephony.data.ApnSetting; import android.test.MoreAsserts; import android.util.ArraySet; Loading Loading @@ -4840,7 +4844,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { int flags) throws Exception { mContext.binder.callingUid = uid; dpm.setLockTaskPackages(who, packages); MoreAsserts.assertEquals(packages, dpm.getLockTaskPackages(who)); assertEquals(packages, dpm.getLockTaskPackages(who)); for (String p : packages) { assertThat(dpm.isLockTaskPermitted(p)).isTrue(); } Loading Loading @@ -8808,6 +8812,54 @@ public class DevicePolicyManagerTest extends DpmTestBase { verifyNoMoreInteractions(getServices().euiccManager); } @Test public void isSubscriptionEnterpriseManaged_packageNameIsGroupOwner_returnsTrue() { SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId(1).setId( 42).setGroupOwner("package-name").build(); assertTrue(dpm.isSubscriptionEnterpriseManaged(subscription, "package-name")); } @Test public void isSubscriptionEnterpriseManaged_packageNameIsNotGroupOwner_returnsFalse() { SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId(1).setId( 42).setGroupOwner("another-package-name").build(); assertFalse(dpm.isSubscriptionEnterpriseManaged(subscription, "package-name")); } @RequiresFlagsEnabled(Flags.FLAG_ENTERPRISE_ESIM_USING_CARRIER_PRIVILEGES) @Test public void isSubscriptionEnterpriseManaged_hasEnterpriseMarkerInAccessRules_returnsTrue() { String enterpriseCarrierConfig = "5715E84E9FEFDD8CEB019F3CE2DC5B73A24D155363D3731D40CA1852F41A5059:com.android" + ".notanapp.enterprise_sim"; SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId( 1).setCarrierConfigAccessRules( UiccAccessRule.decodeRulesFromCarrierConfig( new String[]{enterpriseCarrierConfig})).setId( 42).build(); assertTrue(dpm.isSubscriptionEnterpriseManaged(subscription, "does-not-matter")); } @RequiresFlagsDisabled(Flags.FLAG_ENTERPRISE_ESIM_USING_CARRIER_PRIVILEGES) @Test public void isSubscriptionEnterpriseManaged_hasEnterpriseMarkerInAccessRules_returnsFalse() { String enterpriseCarrierConfig = "5715E84E9FEFDD8CEB019F3CE2DC5B73A24D155363D3731D40CA1852F41A5059:com.android" + ".notanapp.enterprise_sim"; SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId( 1).setCarrierConfigAccessRules( UiccAccessRule.decodeRulesFromCarrierConfig( new String[]{enterpriseCarrierConfig})).setId( 42).build(); assertFalse(dpm.isSubscriptionEnterpriseManaged(subscription, "does-not-matter")); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( Loading Loading
core/java/android/app/admin/DevicePolicyManager.java +21 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.security.keystore.StrongBoxUnavailableException; import android.service.restrictions.RestrictionsReceiver; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.text.TextUtils; Loading Loading @@ -11285,6 +11286,26 @@ public class DevicePolicyManager { } } /** * Checks whether the given subscription is enterprise-managed. * * @param info The subscription to check. * @param packageName The package to check against the subscription's group owner. * @return whether the subscription is enterprise-managed. * @hide */ public boolean isSubscriptionEnterpriseManaged( @NonNull SubscriptionInfo info, @NonNull String packageName) { if (mService != null) { try { return mService.isSubscriptionEnterpriseManaged(info, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return false; } /** * Start Quick Contact on the managed profile for the user, if the policy allows. * @hide
core/java/android/app/admin/IDevicePolicyManager.aidl +3 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.os.RemoteCallback; import android.os.UserHandle; import android.security.keymaster.KeymasterCertificateChain; import android.security.keystore.ParcelableKeyGenParameterSpec; import android.telephony.SubscriptionInfo; import android.telephony.data.ApnSetting; import com.android.internal.infra.AndroidFuture; import android.app.admin.DevicePolicyState; Loading Loading @@ -624,6 +625,8 @@ interface IDevicePolicyManager { void setManagedSubscriptionsPolicy(in ManagedSubscriptionsPolicy policy); ManagedSubscriptionsPolicy getManagedSubscriptionsPolicy(); boolean isSubscriptionEnterpriseManaged(in SubscriptionInfo info, String packageName); DevicePolicyState getDevicePolicyState(); boolean triggerDevicePolicyEngineMigration(boolean forceMigration); Loading
core/java/android/app/admin/flags/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -442,3 +442,10 @@ flag { purpose: PURPOSE_BUGFIX } } flag { name: "enterprise_esim_using_carrier_privileges" namespace: "enterprise" description: "Check for enterprise management indicator in carrier privileges of an eSIM profile" bug: "373466339" }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +45 −14 Original line number Diff line number Diff line Loading @@ -490,6 +490,7 @@ import android.telecom.TelecomManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.UiccAccessRule; import android.telephony.data.ApnSetting; import android.telephony.euicc.EuiccManager; import android.text.TextUtils; Loading Loading @@ -1040,6 +1041,16 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private static final boolean ENABLE_LOCK_GUARD = true; /** * Pair of magic hash and package name strings used as an enterprise management marker in the * access rules of a subscription. The hash is a SHA-256 hash of the package name. */ private static final String ENTERPRISE_SIM_MAGIC_PACKAGE_NAME = "com.android.notanapp.enterprise_sim"; private static final String ENTERPRISE_SIM_MAGIC_HASH = "5715E84E9FEFDD8CEB019F3CE2DC5B73A24D155363D3731D40CA1852F41A5059"; /** * Profile off deadline is not set or more than MANAGED_PROFILE_OFF_WARNING_PERIOD away, or the * user is running unlocked, no need for notification. Loading Loading @@ -24104,6 +24115,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } @Override public boolean isSubscriptionEnterpriseManaged( @NonNull SubscriptionInfo info, @NonNull String packageName) { boolean result = info.getGroupOwner().equals(packageName); if (Flags.enterpriseEsimUsingCarrierPrivileges()) { result |= enterpriseMarkerExistsInAccessRules(info); } return result; } private static boolean enterpriseMarkerExistsInAccessRules(@NonNull SubscriptionInfo info) { if (info.getAccessRules() == null) { return false; } return info.getAccessRules().stream().anyMatch((UiccAccessRule accessRule) -> accessRule.hasMatchingCertificateHashAndPackageName( ENTERPRISE_SIM_MAGIC_HASH, ENTERPRISE_SIM_MAGIC_PACKAGE_NAME) ); } private void installOemDefaultDialerAndSmsApp(int targetUserId) { try { String defaultDialerPackageName = getOemDefaultDialerPackage(); Loading Loading @@ -24830,20 +24861,20 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private IntArray getSubscriptionIdsInternal(String callerPackageName) { SubscriptionManager subscriptionManager = mContext.getSystemService(SubscriptionManager.class); return mInjector.binderWithCleanCallingIdentity(() -> { return mInjector.binderWithCleanCallingIdentity( () -> { IntArray adminOwnedSubscriptions = new IntArray(); List<SubscriptionInfo> subs = subscriptionManager.getAvailableSubscriptionInfoList(); List<SubscriptionInfo> subs = subscriptionManager.getAvailableSubscriptionInfoList(); int subCount = (subs != null) ? subs.size() : 0; for (int i = 0; i < subCount; i++) { SubscriptionInfo sub = subs.get(i); if (sub.getGroupOwner() .equals(callerPackageName)) { if (isSubscriptionEnterpriseManaged(sub, callerPackageName)) { adminOwnedSubscriptions.add(sub.getSubscriptionId()); } } return adminOwnedSubscriptions; }); } @Override
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java +53 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import static org.mockito.hamcrest.MockitoHamcrest.argThat; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertThrows; import static org.testng.Assert.assertTrue; import static java.util.Collections.emptyList; Loading Loading @@ -145,6 +148,7 @@ import android.security.KeyChain; import android.security.keystore.AttestationUtils; import android.telephony.SubscriptionInfo; import android.telephony.TelephonyManager; import android.telephony.UiccAccessRule; import android.telephony.data.ApnSetting; import android.test.MoreAsserts; import android.util.ArraySet; Loading Loading @@ -4840,7 +4844,7 @@ public class DevicePolicyManagerTest extends DpmTestBase { int flags) throws Exception { mContext.binder.callingUid = uid; dpm.setLockTaskPackages(who, packages); MoreAsserts.assertEquals(packages, dpm.getLockTaskPackages(who)); assertEquals(packages, dpm.getLockTaskPackages(who)); for (String p : packages) { assertThat(dpm.isLockTaskPermitted(p)).isTrue(); } Loading Loading @@ -8808,6 +8812,54 @@ public class DevicePolicyManagerTest extends DpmTestBase { verifyNoMoreInteractions(getServices().euiccManager); } @Test public void isSubscriptionEnterpriseManaged_packageNameIsGroupOwner_returnsTrue() { SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId(1).setId( 42).setGroupOwner("package-name").build(); assertTrue(dpm.isSubscriptionEnterpriseManaged(subscription, "package-name")); } @Test public void isSubscriptionEnterpriseManaged_packageNameIsNotGroupOwner_returnsFalse() { SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId(1).setId( 42).setGroupOwner("another-package-name").build(); assertFalse(dpm.isSubscriptionEnterpriseManaged(subscription, "package-name")); } @RequiresFlagsEnabled(Flags.FLAG_ENTERPRISE_ESIM_USING_CARRIER_PRIVILEGES) @Test public void isSubscriptionEnterpriseManaged_hasEnterpriseMarkerInAccessRules_returnsTrue() { String enterpriseCarrierConfig = "5715E84E9FEFDD8CEB019F3CE2DC5B73A24D155363D3731D40CA1852F41A5059:com.android" + ".notanapp.enterprise_sim"; SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId( 1).setCarrierConfigAccessRules( UiccAccessRule.decodeRulesFromCarrierConfig( new String[]{enterpriseCarrierConfig})).setId( 42).build(); assertTrue(dpm.isSubscriptionEnterpriseManaged(subscription, "does-not-matter")); } @RequiresFlagsDisabled(Flags.FLAG_ENTERPRISE_ESIM_USING_CARRIER_PRIVILEGES) @Test public void isSubscriptionEnterpriseManaged_hasEnterpriseMarkerInAccessRules_returnsFalse() { String enterpriseCarrierConfig = "5715E84E9FEFDD8CEB019F3CE2DC5B73A24D155363D3731D40CA1852F41A5059:com.android" + ".notanapp.enterprise_sim"; SubscriptionInfo subscription = new SubscriptionInfo.Builder().setCardId( 1).setCarrierConfigAccessRules( UiccAccessRule.decodeRulesFromCarrierConfig( new String[]{enterpriseCarrierConfig})).setId( 42).build(); assertFalse(dpm.isSubscriptionEnterpriseManaged(subscription, "does-not-matter")); } private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) { final AppOpsManager.PackageOps vpnOp = new AppOpsManager.PackageOps(userVpnPackage, userVpnUid, List.of(new AppOpsManager.OpEntry( Loading