Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54c51948 authored by Yvonne Jiang's avatar Yvonne Jiang Committed by Android (Google) Code Review
Browse files

Merge "Update createConfirmSupervisionCredentialsIntent to return null if the...

Merge "Update createConfirmSupervisionCredentialsIntent to return null if the supervising user is not present or does not have secure credentials." into main
parents b022da38 ff2ab485
Loading
Loading
Loading
Loading
+10 −3
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.pm;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SpecialUsers.CanBeNULL;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.Context;
import android.content.pm.LauncherUserInfo;
import android.content.pm.LauncherUserInfo;
@@ -620,11 +621,17 @@ public abstract class UserManagerInternal {
     * Returns the user id of the communal profile, or {@link android.os.UserHandle#USER_NULL}
     * Returns the user id of the communal profile, or {@link android.os.UserHandle#USER_NULL}
     * if there is no such user.
     * if there is no such user.
     */
     */
    public abstract @UserIdInt int getCommunalProfileId();
    public abstract @CanBeNULL @UserIdInt int getCommunalProfileId();


    /**
    /**
     * Checks whether to show a notification for sounds (e.g., alarms, timers, etc.) from
     * Returns the user id of the supervising profile, or {@link android.os.UserHandle#USER_NULL} if
     * background users.
     * there is no such user.
     */
    public abstract @CanBeNULL @UserIdInt int getSupervisingProfileId();

    /**
     * Checks whether to show a notification for sounds (e.g., alarms, timers, etc.) from background
     * users.
     */
     */
    public static boolean shouldShowNotificationForBackgroundUserSounds() {
    public static boolean shouldShowNotificationForBackgroundUserSounds() {
        return Flags.addUiForSoundsFromBackgroundUsers() && Resources.getSystem().getBoolean(
        return Flags.addUiForSoundsFromBackgroundUsers() && Resources.getSystem().getBoolean(
+19 −1
Original line number Original line Diff line number Diff line
@@ -1530,6 +1530,20 @@ public class UserManagerService extends IUserManager.Stub {
        return UserHandle.USER_NULL;
        return UserHandle.USER_NULL;
    }
    }


    /** Returns the currently-designated supervising profile, or USER_NULL if not present. */
    private @CanBeNULL @UserIdInt int getSupervisingProfileId() {
        synchronized (mUsersLock) {
            final int userSize = mUsers.size();
            for (int i = 0; i < userSize; i++) {
                final UserInfo user = mUsers.valueAt(i).info;
                if (user.isSupervisingProfile() && !mRemovingUserIds.get(user.id)) {
                    return user.id;
                }
            }
        }
        return UserHandle.USER_NULL;
    }

    public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
    public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
        return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */
        return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */
                true);
                true);
@@ -8348,10 +8362,14 @@ public class UserManagerService extends IUserManager.Stub {
        }
        }


        @Override
        @Override
        public @UserIdInt int getCommunalProfileId() {
        public @CanBeNULL @UserIdInt int getCommunalProfileId() {
            return getCommunalProfileIdUnchecked();
            return getCommunalProfileIdUnchecked();
        }
        }


        @Override
        public @CanBeNULL @UserIdInt int getSupervisingProfileId() {
            return UserManagerService.this.getSupervisingProfileId();
        }
    } // class LocalService
    } // class LocalService




+23 −2
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SuppressLint;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.KeyguardManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.supervision.ISupervisionManager;
import android.app.supervision.ISupervisionManager;
@@ -147,9 +148,21 @@ public class SupervisionService extends ISupervisionManager.Stub {
    @Override
    @Override
    @Nullable
    @Nullable
    public Intent createConfirmSupervisionCredentialsIntent() {
    public Intent createConfirmSupervisionCredentialsIntent() {
        // TODO(b/392961554): (1) Return null if supervision is not enabled.
        // (2) check if PIN exists before return a valid intent.
        enforceAnyPermission(QUERY_USERS, MANAGE_USERS);
        enforceAnyPermission(QUERY_USERS, MANAGE_USERS);
        if (!isSupervisionEnabledForUser(mContext.getUserId())) {
            return null;
        }
        // Verify the supervising user profile exists and has a secure credential set.
        final int supervisingUserId = mInjector.getUserManagerInternal().getSupervisingProfileId();
        final long token = Binder.clearCallingIdentity();
        try {
            if (supervisingUserId == UserHandle.USER_NULL
                    || !mInjector.getKeyguardManager().isDeviceSecure(supervisingUserId)) {
                return null;
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
        final Intent intent = new Intent(ACTION_CONFIRM_SUPERVISION_CREDENTIALS);
        final Intent intent = new Intent(ACTION_CONFIRM_SUPERVISION_CREDENTIALS);
        // explicitly set the package for security
        // explicitly set the package for security
        intent.setPackage("com.android.settings");
        intent.setPackage("com.android.settings");
@@ -277,6 +290,7 @@ public class SupervisionService extends ISupervisionManager.Stub {
    static class Injector {
    static class Injector {
        private final Context mContext;
        private final Context mContext;
        private DevicePolicyManagerInternal mDpmInternal;
        private DevicePolicyManagerInternal mDpmInternal;
        private KeyguardManager mKeyguardManager;
        private PackageManager mPackageManager;
        private PackageManager mPackageManager;
        private UserManagerInternal mUserManagerInternal;
        private UserManagerInternal mUserManagerInternal;


@@ -292,6 +306,13 @@ public class SupervisionService extends ISupervisionManager.Stub {
            return mDpmInternal;
            return mDpmInternal;
        }
        }


        KeyguardManager getKeyguardManager() {
            if (mKeyguardManager == null) {
                mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
            }
            return mKeyguardManager;
        }

        PackageManager getPackageManager() {
        PackageManager getPackageManager() {
            if (mPackageManager == null) {
            if (mPackageManager == null) {
                mPackageManager = mContext.getPackageManager();
                mPackageManager = mContext.getPackageManager();
+47 −3
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.supervision
package com.android.server.supervision


import android.app.Activity
import android.app.Activity
import android.app.KeyguardManager
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManager
import android.app.admin.DevicePolicyManagerInternal
import android.app.admin.DevicePolicyManagerInternal
import android.app.supervision.flags.Flags
import android.app.supervision.flags.Flags
@@ -61,6 +62,9 @@ class SupervisionServiceTest {
    @get:Rule val mocks: MockitoRule = MockitoJUnit.rule()
    @get:Rule val mocks: MockitoRule = MockitoJUnit.rule()


    @Mock private lateinit var mockDpmInternal: DevicePolicyManagerInternal
    @Mock private lateinit var mockDpmInternal: DevicePolicyManagerInternal

    @Mock
    private lateinit var mockKeyguardManager: KeyguardManager
    @Mock private lateinit var mockPackageManager: PackageManager
    @Mock private lateinit var mockPackageManager: PackageManager
    @Mock private lateinit var mockUserManagerInternal: UserManagerInternal
    @Mock private lateinit var mockUserManagerInternal: UserManagerInternal


@@ -71,7 +75,7 @@ class SupervisionServiceTest {
    @Before
    @Before
    fun setUp() {
    fun setUp() {
        context = InstrumentationRegistry.getInstrumentation().context
        context = InstrumentationRegistry.getInstrumentation().context
        context = SupervisionContextWrapper(context, mockPackageManager)
        context = SupervisionContextWrapper(context, mockKeyguardManager, mockPackageManager)


        LocalServices.removeServiceForTest(DevicePolicyManagerInternal::class.java)
        LocalServices.removeServiceForTest(DevicePolicyManagerInternal::class.java)
        LocalServices.addService(DevicePolicyManagerInternal::class.java, mockDpmInternal)
        LocalServices.addService(DevicePolicyManagerInternal::class.java, mockDpmInternal)
@@ -250,11 +254,41 @@ class SupervisionServiceTest {


    @Test
    @Test
    fun createConfirmSupervisionCredentialsIntent() {
    fun createConfirmSupervisionCredentialsIntent() {
        service.mInternal.setSupervisionEnabledForUser(context.getUserId(), true)
        whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(SUPERVISING_USER_ID)
        whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true)

        val intent = checkNotNull(service.createConfirmSupervisionCredentialsIntent())
        val intent = checkNotNull(service.createConfirmSupervisionCredentialsIntent())
        assertThat(intent.action).isEqualTo(ACTION_CONFIRM_SUPERVISION_CREDENTIALS)
        assertThat(intent.action).isEqualTo(ACTION_CONFIRM_SUPERVISION_CREDENTIALS)
        assertThat(intent.getPackage()).isEqualTo("com.android.settings")
        assertThat(intent.getPackage()).isEqualTo("com.android.settings")
    }
    }


    @Test
    fun createConfirmSupervisionCredentialsIntent_supervisionNotEnabled_returnsNull() {
        service.mInternal.setSupervisionEnabledForUser(context.getUserId(), false)
        whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(SUPERVISING_USER_ID)
        whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(true)

        assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull()
    }

    @Test
    fun createConfirmSupervisionCredentialsIntent_noSupervisingUser_returnsNull() {
        service.mInternal.setSupervisionEnabledForUser(context.getUserId(), true)
        whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(UserHandle.USER_NULL)

        assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull()
    }

    @Test
    fun createConfirmSupervisionCredentialsIntent_supervisingUserMissingSecureLock_returnsNull() {
        service.mInternal.setSupervisionEnabledForUser(context.getUserId(), true)
        whenever(mockUserManagerInternal.getSupervisingProfileId()).thenReturn(SUPERVISING_USER_ID)
        whenever(mockKeyguardManager.isDeviceSecure(SUPERVISING_USER_ID)).thenReturn(false)

        assertThat(service.createConfirmSupervisionCredentialsIntent()).isNull()
    }

    private val systemSupervisionPackage: String
    private val systemSupervisionPackage: String
        get() = context.getResources().getString(R.string.config_systemSupervision)
        get() = context.getResources().getString(R.string.config_systemSupervision)


@@ -279,6 +313,7 @@ class SupervisionServiceTest {
    private companion object {
    private companion object {
        const val USER_ID = 100
        const val USER_ID = 100
        const val APP_UID = USER_ID * UserHandle.PER_USER_RANGE
        const val APP_UID = USER_ID * UserHandle.PER_USER_RANGE
        const val SUPERVISING_USER_ID = 10
    }
    }
}
}


@@ -286,10 +321,19 @@ class SupervisionServiceTest {
 * A context wrapper that allows broadcast intents to immediately invoke the receivers without
 * A context wrapper that allows broadcast intents to immediately invoke the receivers without
 * performing checks on the sending user.
 * performing checks on the sending user.
 */
 */
private class SupervisionContextWrapper(val context: Context, val pkgManager: PackageManager) :
private class SupervisionContextWrapper(
    ContextWrapper(context) {
    val context: Context,
    val keyguardManager: KeyguardManager,
    val pkgManager: PackageManager,
) : ContextWrapper(context) {
    val interceptors = mutableListOf<Pair<BroadcastReceiver, IntentFilter>>()
    val interceptors = mutableListOf<Pair<BroadcastReceiver, IntentFilter>>()


    override fun getSystemService(name: String): Any =
        when (name) {
            Context.KEYGUARD_SERVICE -> keyguardManager
            else -> super.getSystemService(name)
        }

    override fun getPackageManager() = pkgManager
    override fun getPackageManager() = pkgManager


    override fun registerReceiverForAllUsers(
    override fun registerReceiverForAllUsers(