Merge "Created new @TestApi (and Shell command) to get policy-exempt apps." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8771e57dd8
@@ -414,6 +414,7 @@ package android.app.admin {
|
||||
method public long getLastNetworkLogRetrievalTime();
|
||||
method public long getLastSecurityLogRetrievalTime();
|
||||
method public java.util.List<java.lang.String> getOwnerInstalledCaCerts(@NonNull android.os.UserHandle);
|
||||
method @NonNull @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public java.util.Set<java.lang.String> getPolicyExemptApps();
|
||||
method public boolean isCurrentInputMethodSetByOwner();
|
||||
method public boolean isFactoryResetProtectionPolicySupported();
|
||||
method @RequiresPermission(anyOf={"android.permission.MARK_DEVICE_ORGANIZATION_OWNED", "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}, conditional=true) public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName);
|
||||
|
||||
@@ -13726,4 +13726,22 @@ public class DevicePolicyManager {
|
||||
throw re.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists apps that are exempt from policies (such as
|
||||
* {@link #setPackagesSuspended(ComponentName, String[], boolean)}).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@RequiresPermission(value = android.Manifest.permission.MANAGE_DEVICE_ADMINS)
|
||||
public @NonNull Set<String> getPolicyExemptApps() {
|
||||
if (mService == null) return Collections.emptySet();
|
||||
|
||||
try {
|
||||
return new HashSet<>(mService.listPolicyExemptApps());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +177,7 @@ interface IDevicePolicyManager {
|
||||
|
||||
String[] setPackagesSuspended(in ComponentName admin, in String callerPackage, in String[] packageNames, boolean suspended);
|
||||
boolean isPackageSuspended(in ComponentName admin, in String callerPackage, String packageName);
|
||||
List<String> listPolicyExemptApps();
|
||||
|
||||
boolean installCaCert(in ComponentName admin, String callerPackage, in byte[] certBuffer);
|
||||
void uninstallCaCerts(in ComponentName admin, String callerPackage, in String[] aliases);
|
||||
|
||||
@@ -1588,7 +1588,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
CryptoTestHelper.runAndLogSelfTest();
|
||||
}
|
||||
|
||||
public String[] getPersonalAppsForSuspension(int userId) {
|
||||
public String[] getPersonalAppsForSuspension(@UserIdInt int userId) {
|
||||
return PersonalAppsSuspensionHelper.forUser(mContext, userId)
|
||||
.getPersonalAppsForSuspension();
|
||||
}
|
||||
@@ -10619,6 +10619,30 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listPolicyExemptApps() {
|
||||
Preconditions.checkCallAuthorization(
|
||||
hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS));
|
||||
|
||||
// TODO(b/181238156): decide whether it should only list the apps set by the resources,
|
||||
// or also the "critical" apps defined by PersonalAppsSuspensionHelper (like SMS app).
|
||||
// If it's the latter, refactor PersonalAppsSuspensionHelper so it (or a superclass) takes
|
||||
// the resources on constructor.
|
||||
String[] core = mContext.getResources().getStringArray(R.array.policy_exempt_apps);
|
||||
String[] vendor = mContext.getResources().getStringArray(R.array.vendor_policy_exempt_apps);
|
||||
|
||||
int size = core.length + vendor.length;
|
||||
Set<String> apps = new ArraySet<>(size);
|
||||
for (String app : core) {
|
||||
apps.add(app);
|
||||
}
|
||||
for (String app : vendor) {
|
||||
apps.add(app);
|
||||
}
|
||||
|
||||
return new ArrayList<>(apps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserRestriction(ComponentName who, String key, boolean enabledFromThisOwner,
|
||||
boolean parent) {
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.os.ShellCommand;
|
||||
import com.android.server.devicepolicy.Owners.OwnerDto;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -30,6 +31,7 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
private static final String CMD_IS_SAFE_OPERATION_BY_REASON = "is-operation-safe-by-reason";
|
||||
private static final String CMD_SET_SAFE_OPERATION = "set-operation-safe";
|
||||
private static final String CMD_LIST_OWNERS = "list-owners";
|
||||
private static final String CMD_LIST_POLICY_EXEMPT_APPS = "list-policy-exempt-apps";
|
||||
|
||||
private final DevicePolicyManagerService mService;
|
||||
|
||||
@@ -60,6 +62,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
return runSetSafeOperation(pw);
|
||||
case CMD_LIST_OWNERS:
|
||||
return runListOwners(pw);
|
||||
case CMD_LIST_POLICY_EXEMPT_APPS:
|
||||
return runListPolicyExemptApps(pw);
|
||||
default:
|
||||
return onInvalidCommand(pw, cmd);
|
||||
}
|
||||
@@ -88,6 +92,8 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
+ " \n\n");
|
||||
pw.printf(" %s\n", CMD_LIST_OWNERS);
|
||||
pw.printf(" Lists the device / profile owners per user \n\n");
|
||||
pw.printf(" %s\n", CMD_LIST_POLICY_EXEMPT_APPS);
|
||||
pw.printf(" Lists the apps that are exempt from policies\n\n");
|
||||
}
|
||||
|
||||
private int runIsSafeOperation(PrintWriter pw) {
|
||||
@@ -119,18 +125,20 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int runListOwners(PrintWriter pw) {
|
||||
List<OwnerDto> owners = mService.listAllOwners();
|
||||
if (owners.isEmpty()) {
|
||||
pw.println("none");
|
||||
private int printAndGetSize(PrintWriter pw, Collection<?> collection, String nameOnSingular) {
|
||||
if (collection.isEmpty()) {
|
||||
pw.printf("no %ss\n", nameOnSingular);
|
||||
return 0;
|
||||
}
|
||||
int size = owners.size();
|
||||
if (size == 1) {
|
||||
pw.println("1 owner:");
|
||||
} else {
|
||||
pw.printf("%d owners:\n", size);
|
||||
}
|
||||
int size = collection.size();
|
||||
pw.printf("%d %s%s:\n", size, nameOnSingular, (size == 1 ? "" : "s"));
|
||||
return size;
|
||||
}
|
||||
|
||||
private int runListOwners(PrintWriter pw) {
|
||||
List<OwnerDto> owners = mService.listAllOwners();
|
||||
int size = printAndGetSize(pw, owners, "owner");
|
||||
if (size == 0) return 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
OwnerDto owner = owners.get(i);
|
||||
@@ -150,4 +158,17 @@ final class DevicePolicyManagerServiceShellCommand extends ShellCommand {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private int runListPolicyExemptApps(PrintWriter pw) {
|
||||
List<String> apps = mService.listPolicyExemptApps();
|
||||
int size = printAndGetSize(pw, apps, "policy exempt app");
|
||||
|
||||
if (size == 0) return 0;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
String app = apps.get(i);
|
||||
pw.printf(" %d: %s\n", i, app);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,7 @@ import android.telephony.TelephonyManager;
|
||||
import android.telephony.data.ApnSetting;
|
||||
import android.test.MoreAsserts; // TODO(b/171932723): replace by Truth
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -154,6 +155,9 @@ import java.util.concurrent.TimeUnit;
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
|
||||
private static final String TAG = DevicePolicyManagerTest.class.getSimpleName();
|
||||
|
||||
private static final List<String> OWNER_SETUP_PERMISSIONS = Arrays.asList(
|
||||
permission.MANAGE_DEVICE_ADMINS, permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
|
||||
permission.MANAGE_USERS, permission.INTERACT_ACROSS_USERS_FULL);
|
||||
@@ -7187,6 +7191,47 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
assertThat(dpm.isUsbDataSignalingEnabled()).isEqualTo(enabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPolicyExemptApps_noPermission() {
|
||||
assertThrows(SecurityException.class, () -> dpm.getPolicyExemptApps());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPolicyExemptApps_empty() {
|
||||
grantManageDeviceAdmins();
|
||||
mockPolicyExemptApps();
|
||||
mockVendorPolicyExemptApps();
|
||||
|
||||
assertThat(dpm.getPolicyExemptApps()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPolicyExemptApps_baseOnly() {
|
||||
grantManageDeviceAdmins();
|
||||
mockPolicyExemptApps("foo");
|
||||
mockVendorPolicyExemptApps();
|
||||
|
||||
assertThat(dpm.getPolicyExemptApps()).containsExactly("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPolicyExemptApps_vendorOnly() {
|
||||
grantManageDeviceAdmins();
|
||||
mockPolicyExemptApps();
|
||||
mockVendorPolicyExemptApps("bar");
|
||||
|
||||
assertThat(dpm.getPolicyExemptApps()).containsExactly("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetPolicyExemptApps_baseAndVendor() {
|
||||
grantManageDeviceAdmins();
|
||||
mockPolicyExemptApps("4", "23", "15", "42", "8");
|
||||
mockVendorPolicyExemptApps("16", "15", "4");
|
||||
|
||||
assertThat(dpm.getPolicyExemptApps()).containsExactly("4", "8", "15", "16", "23", "42");
|
||||
}
|
||||
|
||||
private void setUserUnlocked(int userHandle, boolean unlocked) {
|
||||
when(getServices().userManager.isUserUnlocked(eq(userHandle))).thenReturn(unlocked);
|
||||
}
|
||||
@@ -7408,4 +7453,18 @@ public class DevicePolicyManagerTest extends DpmTestBase {
|
||||
return new StringParceledListSlice(Arrays.asList(s));
|
||||
}
|
||||
|
||||
private void grantManageDeviceAdmins() {
|
||||
Log.d(TAG, "Granting " + permission.MANAGE_DEVICE_ADMINS);
|
||||
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
|
||||
}
|
||||
|
||||
private void mockPolicyExemptApps(String... apps) {
|
||||
Log.d(TAG, "Mocking R.array.policy_exempt_apps to return " + Arrays.toString(apps));
|
||||
when(mContext.resources.getStringArray(R.array.policy_exempt_apps)).thenReturn(apps);
|
||||
}
|
||||
|
||||
private void mockVendorPolicyExemptApps(String... apps) {
|
||||
Log.d(TAG, "Mocking R.array.vendor_policy_exempt_apps to return " + Arrays.toString(apps));
|
||||
when(mContext.resources.getStringArray(R.array.vendor_policy_exempt_apps)).thenReturn(apps);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user