• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 
18 package com.android.systemui.statusbar.policy
19 
20 import android.content.Context
21 import android.content.Intent
22 import android.view.View
23 import com.android.systemui.dagger.SysUISingleton
24 import com.android.systemui.dagger.qualifiers.Application
25 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
26 import com.android.systemui.plugins.ActivityStarter
27 import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower
28 import com.android.systemui.user.data.source.UserRecord
29 import com.android.systemui.user.domain.interactor.GuestUserInteractor
30 import com.android.systemui.user.domain.interactor.UserInteractor
31 import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper
32 import dagger.Lazy
33 import java.io.PrintWriter
34 import java.lang.ref.WeakReference
35 import javax.inject.Inject
36 
37 /** Access point into multi-user switching logic. */
38 @Deprecated("Use UserInteractor or GuestUserInteractor instead.")
39 @SysUISingleton
40 class UserSwitcherController
41 @Inject
42 constructor(
43     @Application private val applicationContext: Context,
44     private val userInteractorLazy: Lazy<UserInteractor>,
45     private val guestUserInteractorLazy: Lazy<GuestUserInteractor>,
46     private val keyguardInteractorLazy: Lazy<KeyguardInteractor>,
47     private val activityStarter: ActivityStarter,
48 ) {
49 
50     /** Defines interface for classes that can be called back when the user is switched. */
interfacenull51     fun interface UserSwitchCallback {
52         /** Notifies that the user has switched. */
53         fun onUserSwitched()
54     }
55 
<lambda>null56     private val userInteractor: UserInteractor by lazy { userInteractorLazy.get() }
<lambda>null57     private val guestUserInteractor: GuestUserInteractor by lazy { guestUserInteractorLazy.get() }
<lambda>null58     private val keyguardInteractor: KeyguardInteractor by lazy { keyguardInteractorLazy.get() }
59 
60     private val callbackCompatMap = mutableMapOf<UserSwitchCallback, UserInteractor.UserCallback>()
61 
62     /** The current list of [UserRecord]. */
63     val users: ArrayList<UserRecord>
64         get() = userInteractor.userRecords.value
65 
66     /** Whether the user switcher experience should use the simple experience. */
67     val isSimpleUserSwitcher: Boolean
68         get() = userInteractor.isSimpleUserSwitcher
69 
70     /** The [UserRecord] of the current user or `null` when none. */
71     val currentUserRecord: UserRecord?
72         get() = userInteractor.selectedUserRecord.value
73 
74     /** The name of the current user of the device or `null`, when none is selected. */
75     val currentUserName: String?
76         get() =
<lambda>null77             currentUserRecord?.let {
78                 LegacyUserUiHelper.getUserRecordName(
79                     context = applicationContext,
80                     record = it,
81                     isGuestUserAutoCreated = userInteractor.isGuestUserAutoCreated,
82                     isGuestUserResetting = userInteractor.isGuestUserResetting,
83                 )
84             }
85 
86     /**
87      * Notifies that a user has been selected.
88      *
89      * This will trigger the right user journeys to create a guest user, switch users, and/or
90      * navigate to the correct destination.
91      *
92      * If a user with the given ID is not found, this method is a no-op.
93      *
94      * @param userId The ID of the user to switch to.
95      * @param dialogShower An optional [DialogShower] in case we need to show dialogs.
96      */
onUserSelectednull97     fun onUserSelected(userId: Int, dialogShower: DialogShower?) {
98         userInteractor.selectUser(userId, dialogShower)
99     }
100 
101     /** Whether the guest user is configured to always be present on the device. */
102     val isGuestUserAutoCreated: Boolean
103         get() = userInteractor.isGuestUserAutoCreated
104 
105     /** Whether the guest user is currently being reset. */
106     val isGuestUserResetting: Boolean
107         get() = userInteractor.isGuestUserResetting
108 
109     /** Registers an adapter to notify when the users change. */
addAdapternull110     fun addAdapter(adapter: WeakReference<BaseUserSwitcherAdapter>) {
111         userInteractor.addCallback(
112             object : UserInteractor.UserCallback {
113                 override fun isEvictable(): Boolean {
114                     return adapter.get() == null
115                 }
116 
117                 override fun onUserStateChanged() {
118                     adapter.get()?.notifyDataSetChanged()
119                 }
120             }
121         )
122     }
123 
124     /** Notifies the item for a user has been clicked. */
onUserListItemClickednull125     fun onUserListItemClicked(
126         record: UserRecord,
127         dialogShower: DialogShower?,
128     ) {
129         userInteractor.onRecordSelected(record, dialogShower)
130     }
131 
132     /**
133      * Removes guest user and switches to target user. The guest must be the current user and its id
134      * must be `guestUserId`.
135      *
136      * If `targetUserId` is `UserHandle.USER_NULL`, then create a new guest user in the foreground,
137      * and immediately switch to it. This is used for wiping the current guest and replacing it with
138      * a new one.
139      *
140      * If `targetUserId` is specified, then remove the guest in the background while switching to
141      * `targetUserId`.
142      *
143      * If device is configured with `config_guestUserAutoCreated`, then after guest user is removed,
144      * a new one is created in the background. This has no effect if `targetUserId` is
145      * `UserHandle.USER_NULL`.
146      *
147      * @param guestUserId id of the guest user to remove
148      * @param targetUserId id of the user to switch to after guest is removed. If
149      *   `UserHandle.USER_NULL`, then switch immediately to the newly created guest user.
150      */
removeGuestUsernull151     fun removeGuestUser(guestUserId: Int, targetUserId: Int) {
152         userInteractor.removeGuestUser(
153             guestUserId = guestUserId,
154             targetUserId = targetUserId,
155         )
156     }
157 
158     /**
159      * Exits guest user and switches to previous non-guest user. The guest must be the current user.
160      *
161      * @param guestUserId user id of the guest user to exit
162      * @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when
163      *   target user id is not known
164      * @param forceRemoveGuestOnExit true: remove guest before switching user, false: remove guest
165      *   only if its ephemeral, else keep guest
166      */
exitGuestUsernull167     fun exitGuestUser(guestUserId: Int, targetUserId: Int, forceRemoveGuestOnExit: Boolean) {
168         userInteractor.exitGuestUser(guestUserId, targetUserId, forceRemoveGuestOnExit)
169     }
170 
171     /**
172      * Guarantee guest is present only if the device is provisioned. Otherwise, create a content
173      * observer to wait until the device is provisioned, then schedule the guest creation.
174      */
schedulePostBootGuestCreationnull175     fun schedulePostBootGuestCreation() {
176         guestUserInteractor.onDeviceBootCompleted()
177     }
178 
179     /** Whether keyguard is showing. */
180     val isKeyguardShowing: Boolean
181         get() = keyguardInteractor.isKeyguardShowing()
182 
183     /** Starts an activity with the given [Intent]. */
startActivitynull184     fun startActivity(intent: Intent) {
185         activityStarter.startActivity(intent, /* dismissShade= */ true)
186     }
187 
188     /**
189      * Refreshes users from UserManager.
190      *
191      * The pictures are only loaded if they have not been loaded yet.
192      */
refreshUsersnull193     fun refreshUsers() {
194         userInteractor.refreshUsers()
195     }
196 
197     /** Adds a subscriber to when user switches. */
addUserSwitchCallbacknull198     fun addUserSwitchCallback(callback: UserSwitchCallback) {
199         val interactorCallback =
200             object : UserInteractor.UserCallback {
201                 override fun onUserStateChanged() {
202                     callback.onUserSwitched()
203                 }
204             }
205         callbackCompatMap[callback] = interactorCallback
206         userInteractor.addCallback(interactorCallback)
207     }
208 
209     /** Removes a previously-added subscriber. */
removeUserSwitchCallbacknull210     fun removeUserSwitchCallback(callback: UserSwitchCallback) {
211         val interactorCallback = callbackCompatMap.remove(callback)
212         if (interactorCallback != null) {
213             userInteractor.removeCallback(interactorCallback)
214         }
215     }
216 
dumpnull217     fun dump(pw: PrintWriter, args: Array<out String>) {
218         userInteractor.dump(pw)
219     }
220 
221     companion object {
222         /** Alpha value to apply to a user view in the user switcher when it's selectable. */
223         private const val ENABLED_ALPHA =
224             LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA
225 
226         /** Alpha value to apply to a user view in the user switcher when it's not selectable. */
227         private const val DISABLED_ALPHA =
228             LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA
229 
230         @JvmStatic
setSelectableAlphanull231         fun setSelectableAlpha(view: View) {
232             view.alpha =
233                 if (view.isEnabled) {
234                     ENABLED_ALPHA
235                 } else {
236                     DISABLED_ALPHA
237                 }
238         }
239     }
240 }
241