diff options
author | 2024-12-03 15:27:06 +0000 | |
---|---|---|
committer | 2024-12-03 23:17:07 +0000 | |
commit | c68057f7523160b68d28def73e70521c1c25bb07 (patch) | |
tree | 0277b679c10f9cecac815a2a4780a0ab824c7463 | |
parent | 6b2a4aa10e9ddf2ca29f0f6dd53e753d80ecbf5d (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
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, |