summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt1
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java22
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java141
3 files changed, 122 insertions, 42 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 02de1cd9a137..ae4dcfaf13e2 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -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";
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 024141777604..6bbbfe1ef4b0 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -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;
@@ -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;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a1789b2b125d..720533f6a389 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -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;
@@ -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
@@ -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}.
@@ -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;
@@ -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;
}
@@ -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());
@@ -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");
@@ -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) {
@@ -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(