Add APIs to check whether a device is financed.

Bug: 272483242

Test: btest a.d.c.CheckFinancedTest
Change-Id: I542b02e9e8a0e35a5e98ddc7bfa3652ad16a6089
This commit is contained in:
Elis Elliott
2023-03-09 14:13:08 +00:00
committed by Jonathan Scott
parent 27c67a2c3b
commit 3806294d45
5 changed files with 162 additions and 31 deletions

View File

@@ -7894,6 +7894,7 @@ package android.app.admin {
method @Deprecated public boolean isCallerApplicationRestrictionsManagingPackage();
method public boolean isCommonCriteriaModeEnabled(@Nullable android.content.ComponentName);
method public boolean isComplianceAcknowledgementRequired();
method public boolean isDeviceFinanced();
method public boolean isDeviceIdAttestationSupported();
method public boolean isDeviceOwnerApp(String);
method public boolean isEphemeralUser(@NonNull android.content.ComponentName);

View File

@@ -1261,6 +1261,7 @@ package android.app.admin {
method @Nullable public CharSequence getDeviceOwnerOrganizationName();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public android.app.admin.DevicePolicyState getDevicePolicyState();
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public String getFinancedDeviceKioskRoleHolder();
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.QUERY_ADMIN_POLICY}) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public java.util.List<android.os.UserHandle> getPolicyManagedProfiles(@NonNull android.os.UserHandle);

View File

@@ -16902,4 +16902,55 @@ public class DevicePolicyManager {
}
return false;
}
/**
* Returns {@code true} if this device is marked as a financed device.
*
* <p>A financed device can be entered into lock task mode (see {@link #setLockTaskPackages})
* by the holder of the role {@link android.app.role.RoleManager#ROLE_FINANCED_DEVICE_KIOSK}.
* If this occurs, Device Owners and Profile Owners that have set lock task packages or
* features, or that attempt to set lock task packages or features, will receive a callback
* indicating that it could not be set. See {@link PolicyUpdateReceiver#onPolicyChanged} and
* {@link PolicyUpdateReceiver#onPolicySetResult}.
*
* <p>To be informed of changes to this status you can subscribe to the broadcast
* {@link ACTION_DEVICE_FINANCING_STATE_CHANGED}.
*
* @throws SecurityException if the caller is not a device owner, profile owner of an
* organization-owned managed profile, profile owner on the primary user or holder of one of the
* following roles: {@link android.app.role.RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT},
* android.app.role.RoleManager.ROLE_SYSTEM_SUPERVISION.
*/
public boolean isDeviceFinanced() {
if (mService != null) {
try {
return mService.isDeviceFinanced(mContext.getPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return false;
}
/**
* Returns the package name of the application holding the role:
* {@link android.app.role.RoleManager#ROLE_FINANCED_DEVICE_KIOSK}.
*
* @return the package name of the application holding the role or {@code null} if the role is
* not held by any applications.
* @hide
*/
@SystemApi
@RequiresPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
@Nullable
public String getFinancedDeviceKioskRoleHolder() {
if (mService != null) {
try {
return mService.getFinancedDeviceKioskRoleHolder(mContext.getPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return null;
}
}

View File

@@ -605,4 +605,7 @@ interface IDevicePolicyManager {
void setOverrideKeepProfilesRunning(boolean enabled);
boolean triggerDevicePolicyEngineMigration(boolean forceMigration);
boolean isDeviceFinanced(String callerPackageName);
String getFinancedDeviceKioskRoleHolder(String callerPackageName);
}

View File

@@ -77,6 +77,7 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WALLPAPER;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WINDOWS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
@@ -3965,7 +3966,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
Objects.requireNonNull(adminReceiver, "ComponentName is null");
Preconditions.checkCallAuthorization(isAdb(getCallerIdentity())
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS),
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS),
"Caller must be shell or hold MANAGE_PROFILE_AND_DEVICE_OWNERS to call "
+ "forceRemoveActiveAdmin");
mInjector.binderWithCleanCallingIdentity(() -> {
@@ -9479,7 +9480,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Preconditions.checkCallAuthorization(
isDefaultDeviceOwner(caller) || canManageUsers(caller) || isFinancedDeviceOwner(
caller) || hasCallingOrSelfPermission(
permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mOwners.hasDeviceOwner();
}
@@ -9648,7 +9649,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
if (!callingUserOnly) {
Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
}
synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
@@ -9698,7 +9699,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
synchronized (getLockObject()) {
if (!mOwners.hasDeviceOwner()) {
@@ -10102,7 +10103,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(canManageUsers(caller)
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
if (userHandle != caller.getUserId()) {
Preconditions.checkCallAuthorization(canManageUsers(caller)
@@ -10120,7 +10121,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
final CallerIdentity caller = getCallerIdentity();
final long id = mInjector.binderClearCallingIdentity();
@@ -10433,7 +10434,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
return getProfileOwnerNameUnchecked(userHandle);
}
@@ -10640,7 +10641,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return;
}
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
if ((mIsWatch || hasUserSetupCompleted(userHandle))) {
Preconditions.checkState(isSystemUid(caller),
@@ -10664,7 +10665,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean hasIncompatibleAccountsOrNonAdb) {
if (!isAdb(caller)) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
}
final int code = checkDeviceOwnerProvisioningPreConditionLocked(owner,
@@ -15921,7 +15922,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private boolean canWriteCredentialManagerPolicy(CallerIdentity caller) {
return (isProfileOwner(caller) && isManagedProfile(caller.getUserId()))
|| isDefaultDeviceOwner(caller)
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS);
}
@Override
@@ -16424,7 +16425,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Objects.requireNonNull(packageName, "packageName is null");
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
long originalId = mInjector.binderClearCallingIdentity();
try {
@@ -17157,7 +17158,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Only adb or system apps with the right permission can mark a profile owner on
// organization-owned device.
if (!(isAdb(caller) || hasCallingPermission(permission.MARK_DEVICE_ORGANIZATION_OWNED)
|| hasCallingPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS))) {
|| hasCallingPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS))) {
throw new SecurityException(
"Only the system can mark a profile owner of organization-owned device.");
}
@@ -17758,7 +17759,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void forceUpdateUserSetupComplete(@UserIdInt int userId) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
boolean isUserCompleted = mInjector.settingsSecureGetIntForUser(
Settings.Secure.USER_SETUP_COMPLETE, 0, userId) != 0;
@@ -18696,7 +18697,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public List<String> getDisallowedSystemApps(ComponentName admin, int userId,
String provisioningAction) throws RemoteException {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
return new ArrayList<>(
mOverlayPackagesProvider.getNonRequiredApps(admin, userId, provisioningAction));
@@ -19513,7 +19514,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
long id = mInjector.binderClearCallingIdentity();
try {
@@ -19540,7 +19541,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
|| hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mInjector.binderWithCleanCallingIdentity(() -> isUnattendedManagedKioskUnchecked());
}
@@ -20520,7 +20521,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void clearOrganizationIdForUser(int userHandle) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
synchronized (getLockObject()) {
final ActiveAdmin owner = getDeviceOrProfileOwnerAdminLocked(userHandle);
@@ -20542,7 +20543,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final CallerIdentity caller = getCallerIdentity(callerPackage);
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
provisioningParams.logParams(callerPackage);
@@ -20640,7 +20641,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public void finalizeWorkProfileProvisioning(UserHandle managedProfileUser,
Account migratedAccount) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
if (!isManagedProfile(managedProfileUser.getIdentifier())) {
throw new IllegalStateException("Given user is not a managed profile");
@@ -20742,15 +20743,65 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private boolean isCallerDevicePolicyManagementRoleHolder(CallerIdentity caller) {
return doesCallerHoldRole(caller, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT);
}
private boolean isCallerSystemSupervisionRoleHolder(CallerIdentity caller) {
return doesCallerHoldRole(caller, RoleManager.ROLE_SYSTEM_SUPERVISION);
}
/**
* Check if the caller is holding the given role on the calling user.
*
* @param caller the caller you wish to check
* @param role the name of the role to check for.
* @return {@code true} if the caller holds the role, {@code false} otherwise.
*/
private boolean doesCallerHoldRole(CallerIdentity caller, String role) {
int callerUid = caller.getUid();
String devicePolicyManagementRoleHolderPackageName =
getRoleHolderPackageName(mContext, RoleManager.ROLE_DEVICE_POLICY_MANAGEMENT);
String roleHolderPackageName =
getRoleHolderPackageNameOnUser(role, caller.getUserId());
int roleHolderUid = mInjector.getPackageManagerInternal().getPackageUid(
devicePolicyManagementRoleHolderPackageName, 0, caller.getUserId());
roleHolderPackageName, 0, caller.getUserId());
return callerUid == roleHolderUid;
}
/**
* Return the package name of the role holder on the given user.
*
* <p>If the userId passed in is {@link UserHandle.USER_ALL} then every user will be checked and
* the package name of the role holder on the first user where there is a role holder is
* returned.
*
* @param role the name of the role to check for.
* @param userId the userId to check for the role holder on.
* @return the package name of the role holder
*/
@Nullable
private String getRoleHolderPackageNameOnUser(String role, int userId) {
RoleManager roleManager = mContext.getSystemService(RoleManager.class);
// Clear calling identity as the RoleManager APIs require privileged permissions.
return mInjector.binderWithCleanCallingIdentity(() -> {
List<UserInfo> users;
// Interpret USER_ALL as meaning "any" user.
if (userId == UserHandle.USER_ALL) {
users = mInjector.getUserManagerInternal().getUsers(/*excludeDying=*/ true);
} else {
users = List.of(new UserInfo(userId, /*name=*/ null, /*flags=*/ 0));
}
for (UserInfo user : users) {
List<String> roleHolders =
roleManager.getRoleHoldersAsUser(role, user.getUserHandle());
if (!roleHolders.isEmpty()) {
return roleHolders.get(0);
}
}
return null;
});
}
private void resetInteractAcrossProfilesAppOps(@UserIdInt int userId) {
mInjector.getCrossProfileApps(userId).clearInteractAcrossProfilesAppOps();
pregrantDefaultInteractAcrossProfilesAppOps(userId);
@@ -20977,7 +21028,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
|| (hasCallingOrSelfPermission(permission.PROVISION_DEMO_DEVICE)
&& provisioningParams.isDemoDevice()));
@@ -21165,7 +21216,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void resetDefaultCrossProfileIntentFilters(@UserIdInt int userId) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
mInjector.binderWithCleanCallingIdentity(() -> {
try {
@@ -21304,7 +21355,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public void setDeviceOwnerType(@NonNull ComponentName admin,
@DeviceOwnerType int deviceOwnerType) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
MANAGE_PROFILE_AND_DEVICE_OWNERS));
synchronized (getLockObject()) {
setDeviceOwnerTypeLocked(admin, deviceOwnerType);
@@ -21692,7 +21743,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public boolean isDpcDownloaded() {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
MANAGE_PROFILE_AND_DEVICE_OWNERS));
ContentResolver cr = mContext.getContentResolver();
@@ -21704,7 +21755,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public void setDpcDownloaded(boolean downloaded) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
MANAGE_PROFILE_AND_DEVICE_OWNERS));
int setTo = downloaded ? 1 : 0;
@@ -21995,7 +22046,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public List<UserHandle> getPolicyManagedProfiles(@NonNull UserHandle user) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
MANAGE_PROFILE_AND_DEVICE_OWNERS));
int userId = user.getIdentifier();
return mInjector.binderWithCleanCallingIdentity(() -> {
List<UserInfo> userProfiles = mUserManager.getProfiles(userId);
@@ -22657,7 +22708,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void setOverrideKeepProfilesRunning(boolean enabled) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
mKeepProfilesRunning = enabled;
Slog.i(LOG_TAG, "Keep profiles running overridden to: " + enabled);
}
@@ -22924,14 +22975,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public DevicePolicyState getDevicePolicyState() {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mInjector.binderWithCleanCallingIdentity(mDevicePolicyEngine::getDevicePolicyState);
}
@Override
public boolean triggerDevicePolicyEngineMigration(boolean forceMigration) {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mInjector.binderWithCleanCallingIdentity(() -> {
boolean canForceMigration = forceMigration && !hasNonTestOnlyActiveAdmins();
if (!canForceMigration && !shouldMigrateToDevicePolicyEngine()) {
@@ -23290,4 +23341,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// if the policy engine was ever used?
return !mDevicePolicyEngine.hasActivePolicies();
}
@Override
public boolean isDeviceFinanced(String callerPackageName) {
CallerIdentity caller = getCallerIdentity(callerPackageName);
Preconditions.checkCallAuthorization(isDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isProfileOwnerOnUser0(caller)
|| isCallerDevicePolicyManagementRoleHolder(caller)
|| isCallerSystemSupervisionRoleHolder(caller));
return getFinancedDeviceKioskRoleHolderOnAnyUser() != null;
};
@Override
public String getFinancedDeviceKioskRoleHolder(String callerPackageName) {
CallerIdentity caller = getCallerIdentity(callerPackageName);
enforcePermission(MANAGE_PROFILE_AND_DEVICE_OWNERS, caller.getPackageName(),
caller.getUserId());
return getFinancedDeviceKioskRoleHolderOnAnyUser();
}
private String getFinancedDeviceKioskRoleHolderOnAnyUser() {
return getRoleHolderPackageNameOnUser(
RoleManager.ROLE_FINANCED_DEVICE_KIOSK, UserHandle.USER_ALL);
}
}