summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vitor Carvalho <vtrmc@google.com> 2024-12-03 15:27:06 +0000
committer Vitor Carvalho <vtrmc@google.com> 2024-12-03 23:17:07 +0000
commitc68057f7523160b68d28def73e70521c1c25bb07 (patch)
tree0277b679c10f9cecac815a2a4780a0ab824c7463
parent6b2a4aa10e9ddf2ca29f0f6dd53e753d80ecbf5d (diff)
Introduce a method in SupervisionService to check if a caller is the active supervision app.
Bug: 382038274 Flag: android.app.supervision.flags.deprecate_dpm_supervision_apis Test: atest SupervisionServiceTest Change-Id: Ie1889844123240b86ff591cdab42a09c0809079f
-rw-r--r--core/java/android/app/supervision/SupervisionManagerInternal.java31
-rw-r--r--core/java/android/app/supervision/flags.aconfig8
-rw-r--r--services/supervision/java/com/android/server/supervision/SupervisionService.java30
-rw-r--r--services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt35
4 files changed, 86 insertions, 18 deletions
diff --git a/core/java/android/app/supervision/SupervisionManagerInternal.java b/core/java/android/app/supervision/SupervisionManagerInternal.java
index d571e14ff5fa..2cf6ae6f9d01 100644
--- a/core/java/android/app/supervision/SupervisionManagerInternal.java
+++ b/core/java/android/app/supervision/SupervisionManagerInternal.java
@@ -27,32 +27,41 @@ import android.os.PersistableBundle;
*/
public abstract class SupervisionManagerInternal {
/**
- * Returns whether supervision is enabled for the specified user
+ * Returns whether the app with given process uid is the active supervision app.
*
- * @param userId The user to retrieve the supervision state for
- * @return whether the user is supervised
+ * <p>Supervision app is considered active when supervision is enabled for the user running the
+ * given process uid.
+ *
+ * @param uid App process uid.
+ * @return Whether the app is the active supervision app.
*/
- public abstract boolean isSupervisionEnabledForUser(@UserIdInt int userId);
+ public abstract boolean isActiveSupervisionApp(int uid);
/**
- * Returns whether the supervision lock screen needs to be shown.
+ * Returns whether supervision is enabled for the specified user.
+ *
+ * @param userId The user to retrieve the supervision state for.
+ * @return Whether the user is supervised.
*/
+ public abstract boolean isSupervisionEnabledForUser(@UserIdInt int userId);
+
+ /** Returns whether the supervision lock screen needs to be shown. */
public abstract boolean isSupervisionLockscreenEnabledForUser(@UserIdInt int userId);
/**
* Set whether supervision is enabled for the specified user.
*
- * @param userId The user to set the supervision state for
- * @param enabled Whether or not the user should be supervised
+ * @param userId The user to set the supervision state for.
+ * @param enabled Whether or not the user should be supervised.
*/
public abstract void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled);
/**
- * Sets whether the supervision lock screen should be shown for the specified user
+ * Sets whether the supervision lock screen should be shown for the specified user.
*
- * @param userId The user set the superivision state for
- * @param enabled Whether or not the superivision lock screen needs to be shown
- * @param options Optional configuration parameters for the supervision lock screen
+ * @param userId The user set the superivision state for.
+ * @param enabled Whether or not the superivision lock screen needs to be shown.
+ * @param options Optional configuration parameters for the supervision lock screen.
*/
public abstract void setSupervisionLockscreenEnabledForUser(
@UserIdInt int userId, boolean enabled, @Nullable PersistableBundle options);
diff --git a/core/java/android/app/supervision/flags.aconfig b/core/java/android/app/supervision/flags.aconfig
index d4f82f665fd4..1b0353274fb9 100644
--- a/core/java/android/app/supervision/flags.aconfig
+++ b/core/java/android/app/supervision/flags.aconfig
@@ -24,3 +24,11 @@ flag {
description: "Flag that enables supervision when the supervision app is the profile owner"
bug: "377261590"
}
+
+flag {
+ name: "deprecate_dpm_supervision_apis"
+ is_exported: true
+ namespace: "supervision"
+ description: "Flag that deprecates supervision methods in DPM"
+ bug: "382034839"
+}
diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java
index 3093c424e8b2..0ccaa6043f5f 100644
--- a/services/supervision/java/com/android/server/supervision/SupervisionService.java
+++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java
@@ -29,11 +29,13 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.os.UserHandle;
import android.util.SparseArray;
import com.android.internal.R;
@@ -63,11 +65,13 @@ public class SupervisionService extends ISupervisionManager.Stub {
private final SparseArray<SupervisionUserData> mUserData = new SparseArray<>();
private final DevicePolicyManagerInternal mDpmInternal;
+ private final PackageManager mPackageManager;
private final UserManagerInternal mUserManagerInternal;
public SupervisionService(Context context) {
mContext = context.createAttributionContext(LOG_TAG);
mDpmInternal = LocalServices.getService(DevicePolicyManagerInternal.class);
+ mPackageManager = context.getPackageManager();
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener());
}
@@ -148,12 +152,13 @@ public class SupervisionService extends ISupervisionManager.Stub {
/** Returns whether the supervision app has profile owner status. */
private boolean isProfileOwner(@UserIdInt int userId) {
ComponentName profileOwner = mDpmInternal.getProfileOwnerAsUser(userId);
- if (profileOwner == null) {
- return false;
- }
+ return profileOwner != null && isSupervisionAppPackage(profileOwner.getPackageName());
+ }
- String configPackage = mContext.getResources().getString(R.string.config_systemSupervision);
- return profileOwner.getPackageName().equals(configPackage);
+ /** Returns whether the given package name belongs to the supervision role holder. */
+ private boolean isSupervisionAppPackage(String packageName) {
+ return packageName.equals(
+ mContext.getResources().getString(R.string.config_systemSupervision));
}
public static class Lifecycle extends SystemService {
@@ -211,6 +216,21 @@ public class SupervisionService extends ISupervisionManager.Stub {
private final class SupervisionManagerInternalImpl extends SupervisionManagerInternal {
@Override
+ public boolean isActiveSupervisionApp(int uid) {
+ String[] packages = mPackageManager.getPackagesForUid(uid);
+ if (packages == null) {
+ return false;
+ }
+ for (var packageName : packages) {
+ if (SupervisionService.this.isSupervisionAppPackage(packageName)) {
+ int userId = UserHandle.getUserId(uid);
+ return SupervisionService.this.isSupervisionEnabledForUser(userId);
+ }
+ }
+ return false;
+ }
+
+ @Override
public boolean isSupervisionEnabledForUser(@UserIdInt int userId) {
return SupervisionService.this.isSupervisionEnabledForUser(userId);
}
diff --git a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
index a8544f60fb74..5862ac65eba9 100644
--- a/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
+++ b/services/tests/servicestests/src/com/android/server/supervision/SupervisionServiceTest.kt
@@ -26,6 +26,7 @@ import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
+import android.content.pm.PackageManager
import android.content.pm.UserInfo
import android.os.Handler
import android.os.PersistableBundle
@@ -59,6 +60,7 @@ class SupervisionServiceTest {
@get:Rule val mocks: MockitoRule = MockitoJUnit.rule()
@Mock private lateinit var mockDpmInternal: DevicePolicyManagerInternal
+ @Mock private lateinit var mockPackageManager: PackageManager
@Mock private lateinit var mockUserManagerInternal: UserManagerInternal
private lateinit var context: Context
@@ -68,7 +70,7 @@ class SupervisionServiceTest {
@Before
fun setUp() {
context = InstrumentationRegistry.getInstrumentation().context
- context = SupervisionContextWrapper(context)
+ context = SupervisionContextWrapper(context, mockPackageManager)
LocalServices.removeServiceForTest(DevicePolicyManagerInternal::class.java)
LocalServices.addService(DevicePolicyManagerInternal::class.java, mockDpmInternal)
@@ -137,6 +139,31 @@ class SupervisionServiceTest {
}
@Test
+ fun isActiveSupervisionApp_supervisionUid_supervisionEnabled_returnsTrue() {
+ whenever(mockPackageManager.getPackagesForUid(APP_UID))
+ .thenReturn(arrayOf(systemSupervisionPackage))
+ service.setSupervisionEnabledForUser(USER_ID, true)
+
+ assertThat(service.mInternal.isActiveSupervisionApp(APP_UID)).isTrue()
+ }
+
+ @Test
+ fun isActiveSupervisionApp_supervisionUid_supervisionNotEnabled_returnsFalse() {
+ whenever(mockPackageManager.getPackagesForUid(APP_UID))
+ .thenReturn(arrayOf(systemSupervisionPackage))
+ service.setSupervisionEnabledForUser(USER_ID, false)
+
+ assertThat(service.mInternal.isActiveSupervisionApp(APP_UID)).isFalse()
+ }
+
+ @Test
+ fun isActiveSupervisionApp_notSupervisionUid_returnsFalse() {
+ whenever(mockPackageManager.getPackagesForUid(APP_UID)).thenReturn(arrayOf())
+
+ assertThat(service.mInternal.isActiveSupervisionApp(APP_UID)).isFalse()
+ }
+
+ @Test
fun setSupervisionEnabledForUser() {
assertThat(service.isSupervisionEnabledForUser(USER_ID)).isFalse()
@@ -191,6 +218,7 @@ class SupervisionServiceTest {
private companion object {
const val USER_ID = 100
+ val APP_UID = USER_ID * UserHandle.PER_USER_RANGE
}
}
@@ -198,9 +226,12 @@ class SupervisionServiceTest {
* A context wrapper that allows broadcast intents to immediately invoke the receivers without
* performing checks on the sending user.
*/
-private class SupervisionContextWrapper(val context: Context) : ContextWrapper(context) {
+private class SupervisionContextWrapper(val context: Context, val pkgManager: PackageManager) :
+ ContextWrapper(context) {
val interceptors = mutableListOf<Pair<BroadcastReceiver, IntentFilter>>()
+ override fun getPackageManager() = pkgManager
+
override fun registerReceiverForAllUsers(
receiver: BroadcastReceiver?,
filter: IntentFilter,