• 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 package com.android.systemui.shade.data.repository
17 
18 import android.annotation.SuppressLint
19 import com.android.systemui.dagger.SysUISingleton
20 import com.android.systemui.dagger.qualifiers.Background
21 import javax.inject.Inject
22 import kotlinx.coroutines.CoroutineScope
23 import kotlinx.coroutines.channels.BufferOverflow
24 import kotlinx.coroutines.flow.MutableSharedFlow
25 import kotlinx.coroutines.flow.MutableStateFlow
26 import kotlinx.coroutines.flow.SharedFlow
27 import kotlinx.coroutines.flow.StateFlow
28 import kotlinx.coroutines.flow.asStateFlow
29 import kotlinx.coroutines.launch
30 
31 /** Data for the shade, mostly related to expansion of the shade and quick settings. */
32 interface ShadeRepository {
33     /**
34      * Amount qs has expanded, [0-1]. 0 means fully collapsed, 1 means fully expanded. Quick
35      * Settings can be expanded without the full shade expansion.
36      */
37     @Deprecated("Use ShadeInteractor.qsExpansion instead") val qsExpansion: StateFlow<Float>
38 
39     /** Amount shade has expanded with regard to the UDFPS location */
40     val udfpsTransitionToFullShadeProgress: StateFlow<Float>
41 
42     /**
43      * Information about the currently running fling animation, or null if no fling animation is
44      * running.
45      */
46     val currentFling: SharedFlow<FlingInfo?>
47 
48     /**
49      * The amount the lockscreen shade has dragged down by the user, [0-1]. 0 means fully collapsed,
50      * 1 means fully expanded. Value resets to 0 when the user finishes dragging.
51      */
52     val lockscreenShadeExpansion: StateFlow<Float>
53 
54     /**
55      * NotificationPanelViewController.mExpandedFraction as a StateFlow. This nominally represents
56      * the amount the shade has expanded 0-1 like many other flows in this repo, but there are cases
57      * where its value will be 1 and no shade will be rendered, e.g. whenever the keyguard is
58      * visible and when quick settings is expanded. The confusing nature and impending deletion of
59      * this makes it unsuitable for future development, so usage is discouraged.
60      */
61     @Deprecated("Use ShadeInteractor.shadeExpansion instead")
62     val legacyShadeExpansion: StateFlow<Float>
63 
64     /**
65      * NotificationPanelViewController.mTracking as a flow. "Tracking" means that the user is moving
66      * the shade up or down with a pointer. Going forward, this concept will be replaced by checks
67      * for whether a transition was driven by user input instead of whether a pointer is currently
68      * touching the screen, i.e. after the user has lifted their finger to fling the shade, these
69      * values would be different.
70      */
71     @Deprecated("Use ShadeInteractor instead") val legacyShadeTracking: StateFlow<Boolean>
72 
73     /** Specifically tracks the user expanding the shade on the lockscreen only */
74     @Deprecated("Use ShadeInteractor.isUserInteractingWithShade instead")
75     val legacyLockscreenShadeTracking: MutableStateFlow<Boolean>
76 
77     /**
78      * QuickSettingsController.mTracking as a flow. "Tracking" means that the user is moving quick
79      * settings up or down with a pointer. Going forward, this concept will be replaced by checks
80      * for whether a transition was driven by user input instead of whether a pointer is currently
81      * touching the screen, i.e. after the user has lifted their finger to fling the QS, these
82      * values would be different.
83      */
84     @Deprecated("Use ShadeInteractor instead") val legacyQsTracking: StateFlow<Boolean>
85 
86     /**
87      * NotificationPanelViewController.mPanelExpanded as a flow. This value is true whenever the
88      * expansion fraction is greater than zero or NPVC is about to accept an input transfer from the
89      * status bar, home screen, or trackpad.
90      */
91     @Deprecated("Use ShadeInteractor instead")
92     val legacyExpandedOrAwaitingInputTransfer: StateFlow<Boolean>
93 
94     /**
95      * QuickSettingsController.mExpanded as a flow. Indicates that QS is in expanded state:
96      * - single pane shade: expanding shade and then expanding QS
97      * - split shade: just expanding shade (QS are expanded automatically)
98      */
99     @Deprecated("Use ShadeInteractor instead") val legacyIsQsExpanded: StateFlow<Boolean>
100 
101     /**
102      * QuickSettingsController.mExpandImmediate as a flow. Indicates that Quick Settings is being
103      * expanded without first expanding the Shade or Quick Settings is being collapsed without first
104      * collapsing to shade, i.e. expanding with 2-finger swipe or collapsing by flinging from the
105      * bottom of the screen. Replaced by ShadeInteractor.isQsBypassingShade.
106      */
107     @Deprecated("Use ShadeInteractor.isQsBypassingShade instead")
108     val legacyExpandImmediate: StateFlow<Boolean>
109 
110     /**
111      * Whether the shade layout should be wide (true) or narrow (false).
112      *
113      * In a wide layout, notifications and quick settings each take up only half the screen width
114      * (whether they are shown at the same time or not). In a narrow layout, they can each be as
115      * wide as the entire screen.
116      */
117     val isShadeLayoutWide: StateFlow<Boolean>
118 
119     /** True when QS is taking up the entire screen, i.e. fully expanded on a non-unfolded phone. */
120     @Deprecated("Use ShadeInteractor instead") val legacyQsFullscreen: StateFlow<Boolean>
121 
122     /** NPVC.mClosing as a flow. */
123     @Deprecated("Use ShadeAnimationInteractor instead") val legacyIsClosing: StateFlow<Boolean>
124 
125     /** Sets whether the shade layout should be wide (true) or narrow (false). */
setShadeLayoutWidenull126     fun setShadeLayoutWide(isShadeLayoutWide: Boolean)
127 
128     /** Sets whether a closing animation is happening. */
129     @Deprecated("Use ShadeAnimationInteractor instead") fun setLegacyIsClosing(isClosing: Boolean)
130 
131     /**  */
132     @Deprecated("Use ShadeInteractor instead")
133     fun setLegacyQsFullscreen(legacyQsFullscreen: Boolean)
134 
135     /**
136      * Sets whether Quick Settings is being expanded without first expanding the Shade or Quick
137      * Settings is being collapsed without first collapsing to shade.
138      */
139     @Deprecated("Use ShadeInteractor instead")
140     fun setLegacyExpandImmediate(legacyExpandImmediate: Boolean)
141 
142     /** Sets whether QS is expanded. */
143     @Deprecated("Use ShadeInteractor instead")
144     fun setLegacyIsQsExpanded(legacyIsQsExpanded: Boolean)
145 
146     /**
147      * Sets whether the expansion fraction is greater than zero or NPVC is about to accept an input
148      * transfer from the status bar, home screen, or trackpad.
149      */
150     @Deprecated("Use ShadeInteractor instead")
151     fun setLegacyExpandedOrAwaitingInputTransfer(legacyExpandedOrAwaitingInputTransfer: Boolean)
152 
153     /** Sets whether the user is moving Quick Settings with a pointer */
154     @Deprecated("Use ShadeInteractor instead") fun setLegacyQsTracking(legacyQsTracking: Boolean)
155 
156     /** Sets whether the user is moving the shade with a pointer */
157     @Deprecated("Use ShadeInteractor instead") fun setLegacyShadeTracking(tracking: Boolean)
158 
159     /** Sets whether the user is moving the shade with a pointer, on lockscreen only */
160     @Deprecated("Use ShadeInteractor instead")
161     fun setLegacyLockscreenShadeTracking(tracking: Boolean)
162 
163     /** The amount QS has expanded without notifications */
164     fun setQsExpansion(qsExpansion: Float)
165 
166     fun setUdfpsTransitionToFullShadeProgress(progress: Float)
167 
168     /**
169      * Sets the [FlingInfo] of the currently animating fling. If [info] is null, no fling is
170      * animating.
171      */
172     fun setCurrentFling(info: FlingInfo?)
173 
174     /**
175      * Set the amount the shade has dragged down by the user, [0-1]. 0 means fully collapsed, 1
176      * means fully expanded.
177      */
178     fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float)
179 
180     /**
181      * Set the legacy expansion value. This should only be called whenever the value of
182      * NotificationPanelViewController.mExpandedFraction changes or in tests.
183      */
184     @Deprecated("Should only be called by NPVC and tests")
185     fun setLegacyShadeExpansion(expandedFraction: Float)
186 }
187 
188 /** Business logic for shade interactions */
189 @SysUISingleton
190 class ShadeRepositoryImpl @Inject constructor(@Background val backgroundScope: CoroutineScope) :
191     ShadeRepository {
192     private val _qsExpansion = MutableStateFlow(0f)
193     @Deprecated("Use ShadeInteractor.qsExpansion instead")
194     override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
195 
196     private val _lockscreenShadeExpansion = MutableStateFlow(0f)
197     override val lockscreenShadeExpansion: StateFlow<Float> =
198         _lockscreenShadeExpansion.asStateFlow()
199 
200     private var _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
201     override val udfpsTransitionToFullShadeProgress: StateFlow<Float> =
202         _udfpsTransitionToFullShadeProgress.asStateFlow()
203 
204     /**
205      * Must be a SharedFlow, since the fling is by definition an event and dropping it has extreme
206      * consequences in some cases (for example, keyguard uses this to decide when to unlock).
207      */
208     @SuppressLint("SharedFlowCreation")
209     override val currentFling: MutableSharedFlow<FlingInfo?> =
210         MutableSharedFlow(replay = 2, onBufferOverflow = BufferOverflow.DROP_OLDEST)
211 
212     private val _legacyShadeExpansion = MutableStateFlow(0f)
213     @Deprecated("Use ShadeInteractor.shadeExpansion instead")
214     override val legacyShadeExpansion: StateFlow<Float> = _legacyShadeExpansion.asStateFlow()
215 
216     private val _legacyShadeTracking = MutableStateFlow(false)
217     @Deprecated("Use ShadeInteractor instead")
218     override val legacyShadeTracking: StateFlow<Boolean> = _legacyShadeTracking.asStateFlow()
219 
220     @Deprecated("Use ShadeInteractor.isUserInteractingWithShade instead")
221     override val legacyLockscreenShadeTracking = MutableStateFlow(false)
222 
223     private val _legacyQsTracking = MutableStateFlow(false)
224     @Deprecated("Use ShadeInteractor instead")
225     override val legacyQsTracking: StateFlow<Boolean> = _legacyQsTracking.asStateFlow()
226 
227     private val _legacyExpandedOrAwaitingInputTransfer = MutableStateFlow(false)
228     @Deprecated("Use ShadeInteractor instead")
229     override val legacyExpandedOrAwaitingInputTransfer: StateFlow<Boolean> =
230         _legacyExpandedOrAwaitingInputTransfer.asStateFlow()
231 
232     private val _legacyIsQsExpanded = MutableStateFlow(false)
233     @Deprecated("Use ShadeInteractor instead")
234     override val legacyIsQsExpanded: StateFlow<Boolean> = _legacyIsQsExpanded.asStateFlow()
235 
236     private val _legacyExpandImmediate = MutableStateFlow(false)
237     @Deprecated("Use ShadeInteractor instead")
238     override val legacyExpandImmediate: StateFlow<Boolean> = _legacyExpandImmediate.asStateFlow()
239 
240     private val _legacyQsFullscreen = MutableStateFlow(false)
241     @Deprecated("Use ShadeInteractor instead")
242     override val legacyQsFullscreen: StateFlow<Boolean> = _legacyQsFullscreen.asStateFlow()
243 
244     private val _isShadeLayoutWide = MutableStateFlow(false)
245     override val isShadeLayoutWide: StateFlow<Boolean> = _isShadeLayoutWide.asStateFlow()
246 
247     override fun setShadeLayoutWide(isShadeLayoutWide: Boolean) {
248         _isShadeLayoutWide.value = isShadeLayoutWide
249     }
250 
251     @Deprecated("Use ShadeInteractor instead")
252     override fun setLegacyQsFullscreen(legacyQsFullscreen: Boolean) {
253         _legacyQsFullscreen.value = legacyQsFullscreen
254     }
255 
256     @Deprecated("Use ShadeInteractor instead")
257     override fun setLegacyExpandImmediate(legacyExpandImmediate: Boolean) {
258         _legacyExpandImmediate.value = legacyExpandImmediate
259     }
260 
261     @Deprecated("Use ShadeInteractor instead")
262     override fun setLegacyIsQsExpanded(legacyIsQsExpanded: Boolean) {
263         _legacyIsQsExpanded.value = legacyIsQsExpanded
264     }
265 
266     @Deprecated("Use ShadeInteractor instead")
267     override fun setLegacyExpandedOrAwaitingInputTransfer(
268         legacyExpandedOrAwaitingInputTransfer: Boolean
269     ) {
270         _legacyExpandedOrAwaitingInputTransfer.value = legacyExpandedOrAwaitingInputTransfer
271     }
272 
273     @Deprecated("Should only be called by NPVC and tests")
274     override fun setLegacyQsTracking(legacyQsTracking: Boolean) {
275         _legacyQsTracking.value = legacyQsTracking
276     }
277 
278     @Deprecated("Should only be called by NPVC and tests")
279     override fun setLegacyShadeTracking(tracking: Boolean) {
280         _legacyShadeTracking.value = tracking
281     }
282 
283     private val _legacyIsClosing = MutableStateFlow(false)
284     @Deprecated("Use ShadeInteractor instead")
285     override val legacyIsClosing: StateFlow<Boolean> = _legacyIsClosing.asStateFlow()
286 
287     @Deprecated("Use ShadeInteractor instead")
288     override fun setLegacyIsClosing(isClosing: Boolean) {
289         _legacyIsClosing.value = isClosing
290     }
291 
292     @Deprecated("Should only be called by NPVC and tests")
293     override fun setLegacyLockscreenShadeTracking(tracking: Boolean) {
294         legacyLockscreenShadeTracking.value = tracking
295     }
296 
297     override fun setQsExpansion(qsExpansion: Float) {
298         _qsExpansion.value = qsExpansion
299     }
300 
301     override fun setLockscreenShadeExpansion(lockscreenShadeExpansion: Float) {
302         _lockscreenShadeExpansion.value = lockscreenShadeExpansion
303     }
304 
305     override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
306         _udfpsTransitionToFullShadeProgress.value = progress
307     }
308 
309     override fun setCurrentFling(info: FlingInfo?) {
310         backgroundScope.launch { currentFling.emit(info) }
311     }
312 
313     @Deprecated("Should only be called by NPVC and tests")
314     override fun setLegacyShadeExpansion(expandedFraction: Float) {
315         _legacyShadeExpansion.value = expandedFraction
316     }
317 
318     companion object {
319         private const val TAG = "ShadeRepository"
320     }
321 }
322