1 /*
2  * Copyright (C) 2021 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.systemui.qs.user
18 
19 import android.app.Dialog
20 import android.content.Context
21 import android.content.DialogInterface
22 import android.content.Intent
23 import android.provider.Settings
24 import android.view.LayoutInflater
25 import android.view.View
26 import androidx.annotation.VisibleForTesting
27 import com.android.systemui.R
28 import com.android.systemui.animation.DialogLaunchAnimator
29 import com.android.systemui.dagger.SysUISingleton
30 import com.android.systemui.plugins.ActivityStarter
31 import com.android.systemui.plugins.FalsingManager
32 import com.android.systemui.qs.tiles.UserDetailView
33 import com.android.systemui.statusbar.phone.SystemUIDialog
34 import javax.inject.Inject
35 import javax.inject.Provider
36 
37 /**
38  * Controller for [UserDialog].
39  */
40 @SysUISingleton
41 class UserSwitchDialogController @VisibleForTesting constructor(
42     private val userDetailViewAdapterProvider: Provider<UserDetailView.Adapter>,
43     private val activityStarter: ActivityStarter,
44     private val falsingManager: FalsingManager,
45     private val dialogLaunchAnimator: DialogLaunchAnimator,
46     private val dialogFactory: (Context) -> SystemUIDialog
47 ) {
48 
49     @Inject
50     constructor(
51         userDetailViewAdapterProvider: Provider<UserDetailView.Adapter>,
52         activityStarter: ActivityStarter,
53         falsingManager: FalsingManager,
54         dialogLaunchAnimator: DialogLaunchAnimator
55     ) : this(
56         userDetailViewAdapterProvider,
57         activityStarter,
58         falsingManager,
59         dialogLaunchAnimator,
60         { SystemUIDialog(it) }
61     )
62 
63     companion object {
64         private val USER_SETTINGS_INTENT = Intent(Settings.ACTION_USER_SETTINGS)
65     }
66 
67     /**
68      * Show a [UserDialog].
69      *
70      * Populate the dialog with information from and adapter obtained from
71      * [userDetailViewAdapterProvider] and show it as launched from [view].
72      */
73     fun showDialog(view: View) {
74         with(dialogFactory(view.context)) {
75             setShowForAllUsers(true)
76             setCanceledOnTouchOutside(true)
77 
78             setTitle(R.string.qs_user_switch_dialog_title)
79             setPositiveButton(R.string.quick_settings_done, null)
80             setNeutralButton(R.string.quick_settings_more_user_settings) { _, _ ->
81                 if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
82                     dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations()
83                     activityStarter.postStartActivityDismissingKeyguard(
84                         USER_SETTINGS_INTENT,
85                         0
86                     )
87                 }
88             }
89             val gridFrame = LayoutInflater.from(this.context)
90                 .inflate(R.layout.qs_user_dialog_content, null)
91             setView(gridFrame)
92 
93             val adapter = userDetailViewAdapterProvider.get()
94 
95             adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid))
96 
97             dialogLaunchAnimator.showFromView(this, view)
98             adapter.injectDialogShower(DialogShowerImpl(this, dialogLaunchAnimator))
99         }
100     }
101 
102     private class DialogShowerImpl(
103         private val animateFrom: Dialog,
104         private val dialogLaunchAnimator: DialogLaunchAnimator
105     ) : DialogInterface by animateFrom, DialogShower {
106         override fun showDialog(dialog: Dialog) {
107             dialogLaunchAnimator.showFromDialog(
108                 dialog,
109                 animateFrom = animateFrom
110             )
111         }
112     }
113 
114     interface DialogShower : DialogInterface {
115         fun showDialog(dialog: Dialog)
116     }
117 }