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

Commit be3fd8de authored by Pierre Barbier de Reuille's avatar Pierre Barbier de Reuille
Browse files

Always create missing user contexts in WM Shell

Instead of assuming only the current user or its profiles can run tasks,
always create the needed user context. Also, as it seems the default
user (0) is often used, make sure we have its profile cached always.

Fix: 393054733
Test: atest UserProfileContextsTest
Test: atest WindowDecorTaskResourceLoaderTest
Test: atest DesktopTasksControllerTest
Flag: EXEMPT (bug fix)
Change-Id: I77ef353457924d74de713c0bcb9a98ef4cd7128a
parent 7b8ccec4
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.util.SparseArray
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.UserChangeListener
import androidx.core.util.size

/** Creates and manages contexts for all the profiles of the current user. */
class UserProfileContexts(
@@ -35,6 +36,8 @@ class UserProfileContexts(
    // Contexts for all the profiles of the current user.
    private val currentProfilesContext = SparseArray<Context>()

    private val shellUserId = baseContext.userId

    lateinit var userContext: Context
        private set

@@ -49,6 +52,9 @@ class UserProfileContexts(
                    currentProfilesContext.clear()
                    this@UserProfileContexts.userContext = userContext
                    currentProfilesContext.put(newUserId, userContext)
                    if (newUserId != shellUserId) {
                        currentProfilesContext.put(shellUserId, baseContext)
                    }
                }

                override fun onUserProfilesChanged(profiles: List<UserInfo>) {
@@ -69,9 +75,9 @@ class UserProfileContexts(
            currentProfilesContext.put(profile.id, profileContext)
        }
        val profilesToRemove = buildList<Int> {
            for (i in 0..<currentProfilesContext.size()) {
            for (i in 0..<currentProfilesContext.size) {
                val userId = currentProfilesContext.keyAt(i)
                if (profiles.none { it.id == userId }) {
                if (userId != shellUserId && profiles.none { it.id == userId }) {
                    add(userId)
                }
            }
@@ -80,4 +86,12 @@ class UserProfileContexts(
    }

    operator fun get(userId: Int): Context? = currentProfilesContext.get(userId)

    fun getOrCreate(userId: Int): Context {
        val context = currentProfilesContext[userId]
        if (context != null) return context
        return baseContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0).also {
            currentProfilesContext[userId] = it
        }
    }
}
+4 −3
Original line number Diff line number Diff line
@@ -1862,9 +1862,10 @@ class DesktopTasksController(
        //  need updates in some cases.
        val baseActivity = callingTaskInfo.baseActivity ?: return
        val fillIn: Intent =
            userProfileContexts[callingTaskInfo.userId]
                ?.packageManager
                ?.getLaunchIntentForPackage(baseActivity.packageName) ?: return
            userProfileContexts
                .getOrCreate(callingTaskInfo.userId)
                .packageManager
                .getLaunchIntentForPackage(baseActivity.packageName) ?: return
        fillIn.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
        val launchIntent =
            PendingIntent.getActivity(
+1 −3
Original line number Diff line number Diff line
@@ -153,9 +153,7 @@ class WindowDecorTaskResourceLoader(
    private fun loadAppResources(taskInfo: RunningTaskInfo): AppResources {
        Trace.beginSection("$TAG#loadAppResources")
        try {
            val pm = checkNotNull(userProfilesContexts[taskInfo.userId]?.packageManager) {
                "Could not get context for user ${taskInfo.userId}"
            }
            val pm = userProfilesContexts.getOrCreate(taskInfo.userId).packageManager
            val activityInfo = getActivityInfo(taskInfo, pm)
            val appName = pm.getApplicationLabel(activityInfo.applicationInfo)
            val appIconDrawable = iconProvider.getIcon(activityInfo)
+21 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ class UserProfileContextsTest : ShellTestCase() {
            }
            .whenever(baseContext)
            .createContextAsUser(any<UserHandle>(), anyInt())
        doReturn(DEFAULT_USER).whenever(baseContext).userId
        // Define users and profiles
        val currentUser = ActivityManager.getCurrentUser()
        whenever(userManager.getProfiles(eq(currentUser)))
@@ -136,6 +137,25 @@ class UserProfileContextsTest : ShellTestCase() {
        assertThat(userProfilesContexts[SECOND_PROFILE]?.userId).isEqualTo(SECOND_PROFILE)
    }

    @Test
    fun onUserProfilesChanged_keepDefaultUser() {
        val userChangeListener = retrieveUserChangeListener()
        val newUserContext = createContextForUser(SECOND_USER)

        userChangeListener.onUserChanged(SECOND_USER, newUserContext)
        userChangeListener.onUserProfilesChanged(SECOND_PROFILES)

        assertThat(userProfilesContexts[DEFAULT_USER]).isEqualTo(baseContext)
    }

    @Test
    fun getOrCreate_newUser_shouldCreateTheUser() {
        val newContext = userProfilesContexts.getOrCreate(SECOND_USER)

        assertThat(newContext).isNotNull()
        assertThat(userProfilesContexts[SECOND_USER]).isEqualTo(newContext)
    }

    private fun retrieveUserChangeListener(): UserChangeListener {
        val captor = argumentCaptor<UserChangeListener>()

@@ -155,6 +175,7 @@ class UserProfileContextsTest : ShellTestCase() {
        const val MAIN_PROFILE = 11
        const val SECOND_PROFILE = 15
        const val SECOND_PROFILE_2 = 17
        const val DEFAULT_USER = 25

        val SECOND_PROFILES =
            listOf(
+1 −0
Original line number Diff line number Diff line
@@ -351,6 +351,7 @@ class DesktopTasksControllerTest(flags: FlagsParameterization) : ShellTestCase()
            .thenReturn(ExitResult.NoExit)
        whenever(desktopWallpaperActivityTokenProvider.getToken()).thenReturn(wallpaperToken)
        whenever(userProfileContexts[anyInt()]).thenReturn(context)
        whenever(userProfileContexts.getOrCreate(anyInt())).thenReturn(context)

        controller = createController()
        controller.setSplitScreenController(splitScreenController)
Loading