• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.common
18 
19 import android.app.ActivityManager
20 import android.content.Context
21 import android.content.pm.UserInfo
22 import android.os.UserHandle
23 import android.os.UserManager
24 import android.util.SparseArray
25 import com.android.wm.shell.sysui.ShellController
26 import com.android.wm.shell.sysui.ShellInit
27 import com.android.wm.shell.sysui.UserChangeListener
28 import androidx.core.util.size
29 
30 /** Creates and manages contexts for all the profiles of the current user. */
31 class UserProfileContexts(
32     private val baseContext: Context,
33     private val shellController: ShellController,
34     shellInit: ShellInit,
35 ) {
36     // Contexts for all the profiles of the current user.
37     private val currentProfilesContext = SparseArray<Context>()
38 
39     private val shellUserId = baseContext.userId
40 
41     lateinit var userContext: Context
42         private set
43 
<lambda>null44     init {
45         shellInit.addInitCallback(this::onInit, this)
46     }
47 
onInitnull48     private fun onInit() {
49         shellController.addUserChangeListener(
50             object : UserChangeListener {
51                 override fun onUserChanged(newUserId: Int, userContext: Context) {
52                     currentProfilesContext.clear()
53                     this@UserProfileContexts.userContext = userContext
54                     currentProfilesContext.put(newUserId, userContext)
55                     if (newUserId != shellUserId) {
56                         currentProfilesContext.put(shellUserId, baseContext)
57                     }
58                 }
59 
60                 override fun onUserProfilesChanged(profiles: List<UserInfo>) {
61                     updateProfilesContexts(profiles)
62                 }
63             }
64         )
65         val defaultUserId = ActivityManager.getCurrentUser()
66         val userManager = baseContext.getSystemService(UserManager::class.java)
67         userContext = baseContext.createContextAsUser(UserHandle.of(defaultUserId), /* flags= */ 0)
68         updateProfilesContexts(userManager.getProfiles(defaultUserId))
69     }
70 
updateProfilesContextsnull71     private fun updateProfilesContexts(profiles: List<UserInfo>) {
72         for (profile in profiles) {
73             if (profile.id in currentProfilesContext) continue
74             val profileContext = baseContext.createContextAsUser(profile.userHandle, /* flags= */ 0)
75             currentProfilesContext.put(profile.id, profileContext)
76         }
77         val profilesToRemove = buildList<Int> {
78             for (i in 0..<currentProfilesContext.size) {
79                 val userId = currentProfilesContext.keyAt(i)
80                 if (userId != shellUserId && profiles.none { it.id == userId }) {
81                     add(userId)
82                 }
83             }
84         }
85         profilesToRemove.forEach { currentProfilesContext.remove(it) }
86     }
87 
getnull88     operator fun get(userId: Int): Context? = currentProfilesContext.get(userId)
89 
90     fun getOrCreate(userId: Int): Context {
91         val context = currentProfilesContext[userId]
92         if (context != null) return context
93         return baseContext.createContextAsUser(UserHandle.of(userId), /* flags= */ 0).also {
94             currentProfilesContext[userId] = it
95         }
96     }
97 }
98