Shadow bindDeviceAdminServiceAsUser
PiperOrigin-RevId: 273978733
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowDevicePolicyManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowDevicePolicyManagerTest.java
index ee2f8d2..d4cf81c 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowDevicePolicyManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowDevicePolicyManagerTest.java
@@ -23,23 +23,28 @@
import static org.junit.Assert.fail;
import static org.robolectric.Shadows.shadowOf;
+import android.app.Application;
import android.app.admin.DevicePolicyManager;
import android.app.admin.SystemUpdatePolicy;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.UserHandle;
import android.os.UserManager;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
@@ -50,6 +55,7 @@
@RunWith(AndroidJUnit4.class)
public final class ShadowDevicePolicyManagerTest {
+ private Application context;
private DevicePolicyManager devicePolicyManager;
private UserManager userManager;
private ComponentName testComponent;
@@ -57,7 +63,7 @@
@Before
public void setUp() {
- Context context = ApplicationProvider.getApplicationContext();
+ context = ApplicationProvider.getApplicationContext();
devicePolicyManager =
(DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
@@ -1501,4 +1507,67 @@
assertThat(devicePolicyManager.getSystemUpdatePolicy()).isEqualTo(policy);
}
+
+ @Test
+ @Config(minSdk = O)
+ public void getBindDeviceAdminTargetUsers_returnsEmptyByDefault() {
+ assertThat(devicePolicyManager.getBindDeviceAdminTargetUsers(null)).isEmpty();
+ }
+
+ @Test
+ @Config(minSdk = O)
+ public void getBindDeviceAdminTargetUsers_returnsSetValue() {
+ List<UserHandle> targetUsers = Collections.singletonList(UserHandle.of(10));
+ shadowOf(devicePolicyManager).setBindDeviceAdminTargetUsers(targetUsers);
+
+ assertThat(devicePolicyManager.getBindDeviceAdminTargetUsers(null))
+ .containsExactlyElementsIn(targetUsers);
+ }
+
+ @Test
+ @Config(minSdk = O)
+ public void bindDeviceAdminServiceAsUser_invalidUserHandle_throwsSecurityException() {
+ UserHandle targetUser = UserHandle.of(10);
+
+ Intent serviceIntent = new Intent().setPackage("dummy.package");
+ ServiceConnection conn = buildServiceConnection();
+ int flags = 0;
+
+ try {
+ devicePolicyManager.bindDeviceAdminServiceAsUser(
+ null, serviceIntent, conn, flags, targetUser);
+ fail("Expected SecurityException");
+ } catch (SecurityException expected) {
+ }
+ assertThat(shadowOf(context).getBoundServiceConnections()).isEmpty();
+ }
+
+ @Test
+ @Config(minSdk = O)
+ public void bindDeviceAdminServiceAsUser_validUserHandle_binds() {
+ UserHandle targetUser = UserHandle.of(10);
+ shadowOf(devicePolicyManager)
+ .setBindDeviceAdminTargetUsers(Collections.singletonList(targetUser));
+
+ Intent serviceIntent = new Intent().setPackage("dummy.package");
+ ServiceConnection conn = buildServiceConnection();
+ int flags = 0;
+
+ assertThat(
+ devicePolicyManager.bindDeviceAdminServiceAsUser(
+ null, serviceIntent, conn, flags, targetUser))
+ .isTrue();
+
+ assertThat(shadowOf(context).getBoundServiceConnections()).hasSize(1);
+ }
+
+ private ServiceConnection buildServiceConnection() {
+ return new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {}
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {}
+ };
+ }
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDevicePolicyManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDevicePolicyManager.java
index 32e373d..1c1f8e3 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDevicePolicyManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowDevicePolicyManager.java
@@ -23,7 +23,9 @@
import android.app.admin.SystemUpdatePolicy;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -32,7 +34,9 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Process;
+import android.os.UserHandle;
import android.text.TextUtils;
+import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -107,6 +111,7 @@
private Context context;
private ApplicationPackageManager applicationPackageManager;
private SystemUpdatePolicy policy;
+ private List<UserHandle> bindDeviceAdminTargetUsers = ImmutableList.of();
private @RealObject DevicePolicyManager realObject;
@@ -1113,4 +1118,48 @@
public void setSystemUpdatePolicy(SystemUpdatePolicy policy) {
setSystemUpdatePolicy(null, policy);
}
+
+ /**
+ * Set the list of target users that the calling device or profile owner can use when calling
+ * {@link #bindDeviceAdminServiceAsUser}.
+ *
+ * @see #getBindDeviceAdminTargetUsers(ComponentName)
+ */
+ public void setBindDeviceAdminTargetUsers(List<UserHandle> bindDeviceAdminTargetUsers) {
+ this.bindDeviceAdminTargetUsers = bindDeviceAdminTargetUsers;
+ }
+
+ /**
+ * Returns the list of target users that the calling device or profile owner can use when calling
+ * {@link #bindDeviceAdminServiceAsUser}.
+ *
+ * @see #setBindDeviceAdminTargetUsers(List)
+ */
+ @Implementation(minSdk = O)
+ protected List<UserHandle> getBindDeviceAdminTargetUsers(ComponentName admin) {
+ return bindDeviceAdminTargetUsers;
+ }
+
+ /**
+ * Bind to the same package in another user.
+ *
+ * <p>This validates that the targetUser is one from {@link
+ * #getBindDeviceAdminTargetUsers(ComponentName)} but does not actually bind to a different user,
+ * instead binding to the same user.
+ *
+ * <p>It also does not validate the service being bound to.
+ */
+ @Implementation(minSdk = O)
+ protected boolean bindDeviceAdminServiceAsUser(
+ ComponentName admin,
+ Intent serviceIntent,
+ ServiceConnection conn,
+ int flags,
+ UserHandle targetUser) {
+ if (!getBindDeviceAdminTargetUsers(admin).contains(targetUser)) {
+ throw new SecurityException("Not allowed to bind to target user id");
+ }
+
+ return context.bindServiceAsUser(serviceIntent, conn, flags, targetUser);
+ }
}