1 /*
2  * Copyright (C) 2023 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 package com.android.systemui.qs.tiles
17 
18 import android.content.Intent
19 import android.os.Handler
20 import android.os.Looper
21 import android.provider.Settings
22 import android.view.View
23 import com.android.internal.jank.InteractionJankMonitor
24 import com.android.internal.logging.MetricsLogger
25 import com.android.systemui.R
26 import com.android.systemui.accessibility.fontscaling.FontScalingDialog
27 import com.android.systemui.animation.DialogCuj
28 import com.android.systemui.animation.DialogLaunchAnimator
29 import com.android.systemui.dagger.qualifiers.Background
30 import com.android.systemui.dagger.qualifiers.Main
31 import com.android.systemui.flags.FeatureFlags
32 import com.android.systemui.flags.Flags
33 import com.android.systemui.plugins.ActivityStarter
34 import com.android.systemui.plugins.FalsingManager
35 import com.android.systemui.plugins.qs.QSTile
36 import com.android.systemui.plugins.statusbar.StatusBarStateController
37 import com.android.systemui.qs.QSHost
38 import com.android.systemui.qs.QsEventLogger
39 import com.android.systemui.qs.logging.QSLogger
40 import com.android.systemui.qs.tileimpl.QSTileImpl
41 import com.android.systemui.settings.UserTracker
42 import com.android.systemui.statusbar.phone.SystemUIDialog
43 import com.android.systemui.statusbar.policy.KeyguardStateController
44 import com.android.systemui.util.concurrency.DelayableExecutor
45 import com.android.systemui.util.settings.SecureSettings
46 import com.android.systemui.util.settings.SystemSettings
47 import com.android.systemui.util.time.SystemClock
48 import javax.inject.Inject
49 
50 class FontScalingTile
51 @Inject
52 constructor(
53     host: QSHost,
54     uiEventLogger: QsEventLogger,
55     @Background backgroundLooper: Looper,
56     @Main private val mainHandler: Handler,
57     falsingManager: FalsingManager,
58     metricsLogger: MetricsLogger,
59     statusBarStateController: StatusBarStateController,
60     activityStarter: ActivityStarter,
61     qsLogger: QSLogger,
62     private val keyguardStateController: KeyguardStateController,
63     private val dialogLaunchAnimator: DialogLaunchAnimator,
64     private val systemSettings: SystemSettings,
65     private val secureSettings: SecureSettings,
66     private val systemClock: SystemClock,
67     private val featureFlags: FeatureFlags,
68     private val userTracker: UserTracker,
69     @Background private val backgroundDelayableExecutor: DelayableExecutor
70 ) :
71     QSTileImpl<QSTile.State?>(
72         host,
73         uiEventLogger,
74         backgroundLooper,
75         mainHandler,
76         falsingManager,
77         metricsLogger,
78         statusBarStateController,
79         activityStarter,
80         qsLogger
81     ) {
82     private val icon = ResourceIcon.get(R.drawable.ic_qs_font_scaling)
83 
84     override fun isAvailable(): Boolean {
85         return featureFlags.isEnabled(Flags.ENABLE_FONT_SCALING_TILE)
86     }
87 
88     override fun newTileState(): QSTile.State {
89         return QSTile.State()
90     }
91 
92     override fun handleClick(view: View?) {
93         // We animate from the touched view only if we are not on the keyguard
94         val animateFromView: Boolean = view != null && !keyguardStateController.isShowing
95 
96         val runnable = Runnable {
97             val dialog: SystemUIDialog =
98                 FontScalingDialog(
99                     mContext,
100                     systemSettings,
101                     secureSettings,
102                     systemClock,
103                     userTracker,
104                     mainHandler,
105                     backgroundDelayableExecutor
106                 )
107             if (animateFromView) {
108                 dialogLaunchAnimator.showFromView(
109                     dialog,
110                     view!!,
111                     DialogCuj(InteractionJankMonitor.CUJ_SHADE_DIALOG_OPEN, INTERACTION_JANK_TAG)
112                 )
113             } else {
114                 dialog.show()
115             }
116         }
117 
118         mainHandler.post {
119             mActivityStarter.executeRunnableDismissingKeyguard(
120                 runnable,
121                 /* cancelAction= */ null,
122                 /* dismissShade= */ true,
123                 /* afterKeyguardGone= */ true,
124                 /* deferred= */ false
125             )
126         }
127     }
128 
129     override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
130         state?.label = mContext.getString(R.string.quick_settings_font_scaling_label)
131         state?.icon = icon
132     }
133 
134     override fun getLongClickIntent(): Intent? {
135         return Intent(Settings.ACTION_TEXT_READING_SETTINGS)
136     }
137 
138     override fun getTileLabel(): CharSequence {
139         return mContext.getString(R.string.quick_settings_font_scaling_label)
140     }
141 
142     companion object {
143         const val TILE_SPEC = "font_scaling"
144         private const val INTERACTION_JANK_TAG = "font_scaling"
145     }
146 }
147