1 /*
<lambda>null2  * 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.user.ui.dialog
19 
20 import android.app.Dialog
21 import android.content.Context
22 import com.android.internal.jank.InteractionJankMonitor
23 import com.android.internal.logging.UiEventLogger
24 import com.android.settingslib.users.UserCreatingDialog
25 import com.android.systemui.CoreStartable
26 import com.android.systemui.animation.DialogCuj
27 import com.android.systemui.animation.DialogTransitionAnimator
28 import com.android.systemui.broadcast.BroadcastSender
29 import com.android.systemui.classifier.FalsingCollector
30 import com.android.systemui.dagger.SysUISingleton
31 import com.android.systemui.dagger.qualifiers.Application
32 import com.android.systemui.plugins.ActivityStarter
33 import com.android.systemui.plugins.FalsingManager
34 import com.android.systemui.qs.tiles.UserDetailView
35 import com.android.systemui.user.UserSwitchFullscreenDialog
36 import com.android.systemui.user.domain.interactor.UserSwitcherInteractor
37 import com.android.systemui.user.domain.model.ShowDialogRequestModel
38 import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel
39 import dagger.Lazy
40 import javax.inject.Inject
41 import javax.inject.Provider
42 import kotlinx.coroutines.CoroutineScope
43 import kotlinx.coroutines.flow.filterNotNull
44 import kotlinx.coroutines.launch
45 
46 /** Coordinates dialogs for user switcher logic. */
47 @SysUISingleton
48 class UserSwitcherDialogCoordinator
49 @Inject
50 constructor(
51     @Application private val context: Lazy<Context>,
52     @Application private val applicationScope: Lazy<CoroutineScope>,
53     private val falsingManager: Lazy<FalsingManager>,
54     private val broadcastSender: Lazy<BroadcastSender>,
55     private val dialogTransitionAnimator: Lazy<DialogTransitionAnimator>,
56     private val interactor: Lazy<UserSwitcherInteractor>,
57     private val userDetailAdapterProvider: Provider<UserDetailView.Adapter>,
58     private val eventLogger: Lazy<UiEventLogger>,
59     private val activityStarter: Lazy<ActivityStarter>,
60     private val falsingCollector: Lazy<FalsingCollector>,
61     private val userSwitcherViewModel: Lazy<UserSwitcherViewModel>,
62 ) : CoreStartable {
63 
64     private var currentDialog: Dialog? = null
65 
66     override fun start() {
67         startHandlingDialogShowRequests()
68         startHandlingDialogDismissRequests()
69     }
70 
71     private fun startHandlingDialogShowRequests() {
72         applicationScope.get().launch {
73             interactor.get().dialogShowRequests.filterNotNull().collect { request ->
74                 val (dialog, dialogCuj) =
75                     when (request) {
76                         is ShowDialogRequestModel.ShowAddUserDialog ->
77                             Pair(
78                                 AddUserDialog(
79                                     context = context.get(),
80                                     userHandle = request.userHandle,
81                                     isKeyguardShowing = request.isKeyguardShowing,
82                                     showEphemeralMessage = request.showEphemeralMessage,
83                                     falsingManager = falsingManager.get(),
84                                     broadcastSender = broadcastSender.get(),
85                                     dialogTransitionAnimator = dialogTransitionAnimator.get(),
86                                 ),
87                                 DialogCuj(
88                                     InteractionJankMonitor.CUJ_USER_DIALOG_OPEN,
89                                     INTERACTION_JANK_ADD_NEW_USER_TAG,
90                                 ),
91                             )
92                         is ShowDialogRequestModel.ShowUserCreationDialog ->
93                             Pair(
94                                 UserCreatingDialog(
95                                     context.get(),
96                                     request.isGuest,
97                                 ),
98                                 null,
99                             )
100                         is ShowDialogRequestModel.ShowExitGuestDialog ->
101                             Pair(
102                                 ExitGuestDialog(
103                                     context = context.get(),
104                                     guestUserId = request.guestUserId,
105                                     isGuestEphemeral = request.isGuestEphemeral,
106                                     targetUserId = request.targetUserId,
107                                     isKeyguardShowing = request.isKeyguardShowing,
108                                     falsingManager = falsingManager.get(),
109                                     dialogTransitionAnimator = dialogTransitionAnimator.get(),
110                                     onExitGuestUserListener = request.onExitGuestUser,
111                                 ),
112                                 DialogCuj(
113                                     InteractionJankMonitor.CUJ_USER_DIALOG_OPEN,
114                                     INTERACTION_JANK_EXIT_GUEST_MODE_TAG,
115                                 ),
116                             )
117                         is ShowDialogRequestModel.ShowUserSwitcherDialog ->
118                             Pair(
119                                 UserSwitchDialog(
120                                     context = context.get(),
121                                     adapter = userDetailAdapterProvider.get(),
122                                     uiEventLogger = eventLogger.get(),
123                                     falsingManager = falsingManager.get(),
124                                     activityStarter = activityStarter.get(),
125                                     dialogTransitionAnimator = dialogTransitionAnimator.get(),
126                                 ),
127                                 DialogCuj(
128                                     InteractionJankMonitor.CUJ_USER_DIALOG_OPEN,
129                                     INTERACTION_JANK_EXIT_GUEST_MODE_TAG,
130                                 ),
131                             )
132                         is ShowDialogRequestModel.ShowUserSwitcherFullscreenDialog ->
133                             Pair(
134                                 UserSwitchFullscreenDialog(
135                                     context = context.get(),
136                                     falsingCollector = falsingCollector.get(),
137                                     userSwitcherViewModel = userSwitcherViewModel.get(),
138                                 ),
139                                 null, /* dialogCuj */
140                             )
141                     }
142                 currentDialog = dialog
143 
144                 val controller = request.expandable?.dialogTransitionController(dialogCuj)
145                 if (controller != null) {
146                     dialogTransitionAnimator.get().show(dialog, controller)
147                 } else if (request.dialogShower != null && dialogCuj != null) {
148                     request.dialogShower?.showDialog(dialog, dialogCuj)
149                 } else {
150                     dialog.show()
151                 }
152 
153                 interactor.get().onDialogShown()
154             }
155         }
156     }
157 
158     private fun startHandlingDialogDismissRequests() {
159         applicationScope.get().launch {
160             interactor.get().dialogDismissRequests.filterNotNull().collect {
161                 currentDialog?.let {
162                     if (it.isShowing) {
163                         it.cancel()
164                     }
165                 }
166 
167                 interactor.get().onDialogDismissed()
168             }
169         }
170     }
171 
172     companion object {
173         private const val INTERACTION_JANK_ADD_NEW_USER_TAG = "add_new_user"
174         private const val INTERACTION_JANK_EXIT_GUEST_MODE_TAG = "exit_guest_mode"
175     }
176 }
177