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 Original line 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.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.UserChangeListener
import com.android.wm.shell.sysui.UserChangeListener
import androidx.core.util.size


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


    private val shellUserId = baseContext.userId

    lateinit var userContext: Context
    lateinit var userContext: Context
        private set
        private set


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


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


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


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


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


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