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