Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -8049,6 +8049,7 @@ package android.app.admin { field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED"; field public static final String ACTION_CHECK_POLICY_COMPLIANCE = "android.app.action.CHECK_POLICY_COMPLIANCE"; field public static final String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE"; field public static final String ACTION_DEVICE_FINANCING_STATE_CHANGED = "android.app.admin.action.DEVICE_FINANCING_STATE_CHANGED"; field public static final String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED"; field public static final String ACTION_DEVICE_POLICY_RESOURCE_UPDATED = "android.app.action.DEVICE_POLICY_RESOURCE_UPDATED"; field public static final String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE"; core/java/android/app/admin/DevicePolicyManager.java +22 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.Manifest.permission; import android.accounts.Account; import android.annotation.BroadcastBehavior; import android.annotation.CallbackExecutor; import android.annotation.ColorInt; import android.annotation.IntDef; Loading Loading @@ -3998,6 +3999,27 @@ public class DevicePolicyManager { public static final String EXTRA_RESOURCE_IDS = "android.app.extra.RESOURCE_IDS"; /** * Broadcast Action: Broadcast sent to indicate that the device financing state has changed. * * <p>This occurs when, for example, a financing kiosk app has been added or removed. * * <p>To query the current device financing state see {@link #isDeviceFinanced}. * * <p>This will be delivered to the following apps if they include a receiver for this action * in their manifest: * <ul> * <li>Device owner admins. * <li>Organization-owned profile owner admins * <li>The supervision app * <li>The device management role holder * </ul> */ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true, includeBackground = true) public static final String ACTION_DEVICE_FINANCING_STATE_CHANGED = "android.app.admin.action.DEVICE_FINANCING_STATE_CHANGED"; /** Allow the user to choose whether to enable MTE on the device. */ public static final int MTE_NOT_CONTROLLED_BY_POLICY = 0; Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +99 −42 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDG import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE; import static android.app.admin.DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY; import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_FINANCING_STATE_CHANGED; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED; import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; Loading Loading @@ -15440,7 +15441,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Slogf.i(LOG_TAG, "Sending %s broadcast to manifest receivers.", intent.getAction()); broadcastIntentToCrossProfileManifestReceivers( intent, parentHandle, requiresPermission); broadcastIntentToDevicePolicyManagerRoleHolder(intent, parentHandle); broadcastExplicitIntentToRoleHolder( intent, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, parentHandle); } @Override Loading Loading @@ -15481,36 +15483,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } private void broadcastIntentToDevicePolicyManagerRoleHolder( Intent intent, UserHandle userHandle) { final int userId = userHandle.getIdentifier(); final String packageName = getDevicePolicyManagementRoleHolderPackageName(mContext); if (packageName == null) { return; } try { final Intent packageIntent = new Intent(intent) .setPackage(packageName); final List<ResolveInfo> receivers = mIPackageManager.queryIntentReceivers( packageIntent, /* resolvedType= */ null, STOCK_PM_FLAGS, userId).getList(); if (receivers.isEmpty()) { return; } for (ResolveInfo receiver : receivers) { final Intent componentIntent = new Intent(packageIntent) .setComponent(receiver.getComponentInfo().getComponentName()) .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendBroadcastAsUser(componentIntent, userHandle); } } catch (RemoteException ex) { Slogf.w(LOG_TAG, "Cannot get list of broadcast receivers for %s because: %s.", intent.getAction(), ex); } } /** * Checks whether the package {@code packageName} has the {@code MODIFY_QUIET_MODE} * permission granted for the user {@code userId}. Loading Loading @@ -20718,7 +20690,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void maybeInstallDevicePolicyManagementRoleHolderInUser(int targetUserId) { String devicePolicyManagerRoleHolderPackageName = getDevicePolicyManagementRoleHolderPackageName(mContext); getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT); if (devicePolicyManagerRoleHolderPackageName == null) { Slogf.d(LOG_TAG, "No device policy management role holder specified."); return; Loading @@ -20744,14 +20716,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } /** * If multiple packages hold the role, returns the first package in the list. */ @Nullable private String getRoleHolderPackageName(Context context, String role) { return getRoleHolderPackageNameOnUser(context, role, Process.myUserHandle()); } private String getDevicePolicyManagementRoleHolderPackageName(Context context) { /** * If multiple packages hold the role, returns the first package in the list. */ @Nullable private String getRoleHolderPackageNameOnUser(Context context, String role, UserHandle user) { RoleManager roleManager = context.getSystemService(RoleManager.class); // Calling identity needs to be cleared as this method is used in the permissions checks. return mInjector.binderWithCleanCallingIdentity(() -> { List<String> roleHolders = roleManager.getRoleHolders(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT); List<String> roleHolders = roleManager.getRoleHoldersAsUser(role, user); if (roleHolders.isEmpty()) { return null; } Loading @@ -20762,7 +20744,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private boolean isCallerDevicePolicyManagementRoleHolder(CallerIdentity caller) { int callerUid = caller.getUid(); String devicePolicyManagementRoleHolderPackageName = getDevicePolicyManagementRoleHolderPackageName(mContext); getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT); int roleHolderUid = mInjector.getPackageManagerInternal().getPackageUid( devicePolicyManagementRoleHolderPackageName, 0, caller.getUserId()); Loading Loading @@ -21830,15 +21812,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } public void register() { mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.SYSTEM); mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL); } @Override public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { if (!RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) { if (RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) { handleDevicePolicyManagementRoleChange(user); return; } if (RoleManager.ROLE_FINANCED_DEVICE_KIOSK.equals(roleName)) { handleFinancedDeviceKioskRoleChange(); return; } String newRoleHolder = getRoleHolder(); } private void handleDevicePolicyManagementRoleChange(UserHandle user) { String newRoleHolder = getDeviceManagementRoleHolder(user); if (isDefaultRoleHolder(newRoleHolder)) { Slogf.i(LOG_TAG, "onRoleHoldersChanged: Default role holder is set, returning early"); Loading Loading @@ -21873,9 +21863,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } private String getRoleHolder() { return DevicePolicyManagerService.this.getDevicePolicyManagementRoleHolderPackageName( mContext); private void handleFinancedDeviceKioskRoleChange() { if (!isDevicePolicyEngineEnabled()) { return; } Slog.i(LOG_TAG, "Handling action " + ACTION_DEVICE_FINANCING_STATE_CHANGED); Intent intent = new Intent(ACTION_DEVICE_FINANCING_STATE_CHANGED); mInjector.binderWithCleanCallingIdentity(() -> { for (UserInfo userInfo : mUserManager.getUsers()) { UserHandle user = userInfo.getUserHandle(); broadcastExplicitIntentToRoleHolder( intent, RoleManager.ROLE_SYSTEM_SUPERVISION, user); broadcastExplicitIntentToRoleHolder( intent, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user); ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(user.getIdentifier()); if (admin == null) { continue; } if (!isProfileOwnerOfOrganizationOwnedDevice( admin.info.getComponent(), user.getIdentifier()) && !isDeviceOwner(admin)) { continue; } // Don't send the broadcast twice if the DPC is the same package as the // DMRH if (admin.info.getPackageName().equals(getDeviceManagementRoleHolder(user))) { continue; } broadcastExplicitIntentToPackage( intent, admin.info.getPackageName(), admin.getUserHandle()); } }); } private String getDeviceManagementRoleHolder(UserHandle user) { return DevicePolicyManagerService.this.getRoleHolderPackageNameOnUser( mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user); } private boolean isDefaultRoleHolder(String packageName) { Loading Loading @@ -21935,6 +21958,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } private void broadcastExplicitIntentToRoleHolder( Intent intent, String role, UserHandle userHandle) { String packageName = getRoleHolderPackageNameOnUser(mContext, role, userHandle); if (packageName == null) { return; } broadcastExplicitIntentToPackage(intent, packageName, userHandle); } private void broadcastExplicitIntentToPackage( Intent intent, String packageName, UserHandle userHandle) { int userId = userHandle.getIdentifier(); if (packageName == null) { return; } Intent packageIntent = new Intent(intent) .setPackage(packageName); List<ResolveInfo> receivers = mContext.getPackageManager().queryBroadcastReceiversAsUser( packageIntent, PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS), userId); if (receivers.isEmpty()) { Slog.i(LOG_TAG, "Found no receivers to handle intent " + intent + " in package " + packageName); return; } for (ResolveInfo receiver : receivers) { Intent componentIntent = new Intent(packageIntent) .setComponent(receiver.getComponentInfo().getComponentName()) .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendBroadcastAsUser(componentIntent, userHandle); } } @Override public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) { Preconditions.checkCallAuthorization(hasCallingOrSelfPermission( Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -8049,6 +8049,7 @@ package android.app.admin { field public static final String ACTION_APPLICATION_DELEGATION_SCOPES_CHANGED = "android.app.action.APPLICATION_DELEGATION_SCOPES_CHANGED"; field public static final String ACTION_CHECK_POLICY_COMPLIANCE = "android.app.action.CHECK_POLICY_COMPLIANCE"; field public static final String ACTION_DEVICE_ADMIN_SERVICE = "android.app.action.DEVICE_ADMIN_SERVICE"; field public static final String ACTION_DEVICE_FINANCING_STATE_CHANGED = "android.app.admin.action.DEVICE_FINANCING_STATE_CHANGED"; field public static final String ACTION_DEVICE_OWNER_CHANGED = "android.app.action.DEVICE_OWNER_CHANGED"; field public static final String ACTION_DEVICE_POLICY_RESOURCE_UPDATED = "android.app.action.DEVICE_POLICY_RESOURCE_UPDATED"; field public static final String ACTION_GET_PROVISIONING_MODE = "android.app.action.GET_PROVISIONING_MODE";
core/java/android/app/admin/DevicePolicyManager.java +22 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainMessa import android.Manifest.permission; import android.accounts.Account; import android.annotation.BroadcastBehavior; import android.annotation.CallbackExecutor; import android.annotation.ColorInt; import android.annotation.IntDef; Loading Loading @@ -3998,6 +3999,27 @@ public class DevicePolicyManager { public static final String EXTRA_RESOURCE_IDS = "android.app.extra.RESOURCE_IDS"; /** * Broadcast Action: Broadcast sent to indicate that the device financing state has changed. * * <p>This occurs when, for example, a financing kiosk app has been added or removed. * * <p>To query the current device financing state see {@link #isDeviceFinanced}. * * <p>This will be delivered to the following apps if they include a receiver for this action * in their manifest: * <ul> * <li>Device owner admins. * <li>Organization-owned profile owner admins * <li>The supervision app * <li>The device management role holder * </ul> */ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) @BroadcastBehavior(explicitOnly = true, includeBackground = true) public static final String ACTION_DEVICE_FINANCING_STATE_CHANGED = "android.app.admin.action.DEVICE_FINANCING_STATE_CHANGED"; /** Allow the user to choose whether to enable MTE on the device. */ public static final int MTE_NOT_CONTROLLED_BY_POLICY = 0; Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +99 −42 Original line number Diff line number Diff line Loading @@ -95,6 +95,7 @@ import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDG import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE; import static android.app.admin.DevicePolicyIdentifiers.AUTO_TIMEZONE_POLICY; import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_FINANCING_STATE_CHANGED; import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED; import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; Loading Loading @@ -15440,7 +15441,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Slogf.i(LOG_TAG, "Sending %s broadcast to manifest receivers.", intent.getAction()); broadcastIntentToCrossProfileManifestReceivers( intent, parentHandle, requiresPermission); broadcastIntentToDevicePolicyManagerRoleHolder(intent, parentHandle); broadcastExplicitIntentToRoleHolder( intent, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, parentHandle); } @Override Loading Loading @@ -15481,36 +15483,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } private void broadcastIntentToDevicePolicyManagerRoleHolder( Intent intent, UserHandle userHandle) { final int userId = userHandle.getIdentifier(); final String packageName = getDevicePolicyManagementRoleHolderPackageName(mContext); if (packageName == null) { return; } try { final Intent packageIntent = new Intent(intent) .setPackage(packageName); final List<ResolveInfo> receivers = mIPackageManager.queryIntentReceivers( packageIntent, /* resolvedType= */ null, STOCK_PM_FLAGS, userId).getList(); if (receivers.isEmpty()) { return; } for (ResolveInfo receiver : receivers) { final Intent componentIntent = new Intent(packageIntent) .setComponent(receiver.getComponentInfo().getComponentName()) .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendBroadcastAsUser(componentIntent, userHandle); } } catch (RemoteException ex) { Slogf.w(LOG_TAG, "Cannot get list of broadcast receivers for %s because: %s.", intent.getAction(), ex); } } /** * Checks whether the package {@code packageName} has the {@code MODIFY_QUIET_MODE} * permission granted for the user {@code userId}. Loading Loading @@ -20718,7 +20690,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private void maybeInstallDevicePolicyManagementRoleHolderInUser(int targetUserId) { String devicePolicyManagerRoleHolderPackageName = getDevicePolicyManagementRoleHolderPackageName(mContext); getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT); if (devicePolicyManagerRoleHolderPackageName == null) { Slogf.d(LOG_TAG, "No device policy management role holder specified."); return; Loading @@ -20744,14 +20716,24 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } /** * If multiple packages hold the role, returns the first package in the list. */ @Nullable private String getRoleHolderPackageName(Context context, String role) { return getRoleHolderPackageNameOnUser(context, role, Process.myUserHandle()); } private String getDevicePolicyManagementRoleHolderPackageName(Context context) { /** * If multiple packages hold the role, returns the first package in the list. */ @Nullable private String getRoleHolderPackageNameOnUser(Context context, String role, UserHandle user) { RoleManager roleManager = context.getSystemService(RoleManager.class); // Calling identity needs to be cleared as this method is used in the permissions checks. return mInjector.binderWithCleanCallingIdentity(() -> { List<String> roleHolders = roleManager.getRoleHolders(RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT); List<String> roleHolders = roleManager.getRoleHoldersAsUser(role, user); if (roleHolders.isEmpty()) { return null; } Loading @@ -20762,7 +20744,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { private boolean isCallerDevicePolicyManagementRoleHolder(CallerIdentity caller) { int callerUid = caller.getUid(); String devicePolicyManagementRoleHolderPackageName = getDevicePolicyManagementRoleHolderPackageName(mContext); getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT); int roleHolderUid = mInjector.getPackageManagerInternal().getPackageUid( devicePolicyManagementRoleHolderPackageName, 0, caller.getUserId()); Loading Loading @@ -21830,15 +21812,23 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } public void register() { mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.SYSTEM); mRm.addOnRoleHoldersChangedListenerAsUser(mExecutor, this, UserHandle.ALL); } @Override public void onRoleHoldersChanged(@NonNull String roleName, @NonNull UserHandle user) { if (!RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) { if (RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT.equals(roleName)) { handleDevicePolicyManagementRoleChange(user); return; } if (RoleManager.ROLE_FINANCED_DEVICE_KIOSK.equals(roleName)) { handleFinancedDeviceKioskRoleChange(); return; } String newRoleHolder = getRoleHolder(); } private void handleDevicePolicyManagementRoleChange(UserHandle user) { String newRoleHolder = getDeviceManagementRoleHolder(user); if (isDefaultRoleHolder(newRoleHolder)) { Slogf.i(LOG_TAG, "onRoleHoldersChanged: Default role holder is set, returning early"); Loading Loading @@ -21873,9 +21863,42 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } private String getRoleHolder() { return DevicePolicyManagerService.this.getDevicePolicyManagementRoleHolderPackageName( mContext); private void handleFinancedDeviceKioskRoleChange() { if (!isDevicePolicyEngineEnabled()) { return; } Slog.i(LOG_TAG, "Handling action " + ACTION_DEVICE_FINANCING_STATE_CHANGED); Intent intent = new Intent(ACTION_DEVICE_FINANCING_STATE_CHANGED); mInjector.binderWithCleanCallingIdentity(() -> { for (UserInfo userInfo : mUserManager.getUsers()) { UserHandle user = userInfo.getUserHandle(); broadcastExplicitIntentToRoleHolder( intent, RoleManager.ROLE_SYSTEM_SUPERVISION, user); broadcastExplicitIntentToRoleHolder( intent, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user); ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(user.getIdentifier()); if (admin == null) { continue; } if (!isProfileOwnerOfOrganizationOwnedDevice( admin.info.getComponent(), user.getIdentifier()) && !isDeviceOwner(admin)) { continue; } // Don't send the broadcast twice if the DPC is the same package as the // DMRH if (admin.info.getPackageName().equals(getDeviceManagementRoleHolder(user))) { continue; } broadcastExplicitIntentToPackage( intent, admin.info.getPackageName(), admin.getUserHandle()); } }); } private String getDeviceManagementRoleHolder(UserHandle user) { return DevicePolicyManagerService.this.getRoleHolderPackageNameOnUser( mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT, user); } private boolean isDefaultRoleHolder(String packageName) { Loading Loading @@ -21935,6 +21958,40 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } private void broadcastExplicitIntentToRoleHolder( Intent intent, String role, UserHandle userHandle) { String packageName = getRoleHolderPackageNameOnUser(mContext, role, userHandle); if (packageName == null) { return; } broadcastExplicitIntentToPackage(intent, packageName, userHandle); } private void broadcastExplicitIntentToPackage( Intent intent, String packageName, UserHandle userHandle) { int userId = userHandle.getIdentifier(); if (packageName == null) { return; } Intent packageIntent = new Intent(intent) .setPackage(packageName); List<ResolveInfo> receivers = mContext.getPackageManager().queryBroadcastReceiversAsUser( packageIntent, PackageManager.ResolveInfoFlags.of(PackageManager.GET_RECEIVERS), userId); if (receivers.isEmpty()) { Slog.i(LOG_TAG, "Found no receivers to handle intent " + intent + " in package " + packageName); return; } for (ResolveInfo receiver : receivers) { Intent componentIntent = new Intent(packageIntent) .setComponent(receiver.getComponentInfo().getComponentName()) .addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); mContext.sendBroadcastAsUser(componentIntent, userHandle); } } @Override public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) { Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(