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 package com.android.systemui.shade
18 
19 import android.view.MotionEvent
20 import com.android.systemui.log.dagger.ShadeLog
21 import com.android.systemui.log.LogBuffer
22 import com.android.systemui.log.core.LogLevel
23 import com.android.systemui.shade.ShadeViewController.Companion.FLING_COLLAPSE
24 import com.android.systemui.shade.ShadeViewController.Companion.FLING_EXPAND
25 import com.android.systemui.shade.ShadeViewController.Companion.FLING_HIDE
26 import com.google.errorprone.annotations.CompileTimeConstant
27 import javax.inject.Inject
28 
29 private const val TAG = "systemui.shade"
30 
31 /** Lightweight logging utility for the Shade. */
32 class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
33     fun v(@CompileTimeConstant msg: String) {
34         buffer.log(TAG, LogLevel.VERBOSE, msg)
35     }
36 
37     fun d(@CompileTimeConstant msg: String) {
38         buffer.log(TAG, LogLevel.DEBUG, msg)
39     }
40 
41     fun onQsInterceptMoveQsTrackingEnabled(h: Float) {
42         buffer.log(
43             TAG,
44             LogLevel.VERBOSE,
45             { double1 = h.toDouble() },
46             { "onQsIntercept: move action, QS tracking enabled. h = $double1" }
47         )
48     }
49 
50     fun logQsTrackingNotStarted(
51         initialTouchY: Float,
52         y: Float,
53         h: Float,
54         touchSlop: Float,
55         qsExpanded: Boolean,
56         keyguardShowing: Boolean,
57         qsExpansionEnabled: Boolean,
58         downTime: Long
59     ) {
60         buffer.log(
61             TAG,
62             LogLevel.VERBOSE,
63             {
64                 int1 = initialTouchY.toInt()
65                 int2 = y.toInt()
66                 long1 = h.toLong()
67                 double1 = touchSlop.toDouble()
68                 bool1 = qsExpanded
69                 bool2 = keyguardShowing
70                 bool3 = qsExpansionEnabled
71                 str1 = downTime.toString()
72             },
73             {
74                 "QsTrackingNotStarted: downTime=$str1,initTouchY=$int1,y=$int2,h=$long1," +
75                         "slop=$double1,qsExpanded=$bool1,keyguardShowing=$bool2,qsExpansion=$bool3"
76             }
77         )
78     }
79 
80     fun logMotionEvent(event: MotionEvent, message: String) {
81         buffer.log(
82                 TAG,
83                 LogLevel.VERBOSE,
84                 {
85                     str1 = message
86                     long1 = event.eventTime
87                     long2 = event.downTime
88                     int1 = event.action
89                     int2 = event.classification
90                 },
91                 {
92                     "$str1: eventTime=$long1,downTime=$long2,action=$int1,class=$int2"
93                 }
94         )
95     }
96 
97     /** Logs motion event dispatch results from NotificationShadeWindowViewController. */
98     fun logShadeWindowDispatch(event: MotionEvent, message: String, result: Boolean?) {
99         buffer.log(
100                 TAG,
101                 LogLevel.VERBOSE,
102                 {
103                     str1 = message
104                     long1 = event.eventTime
105                     long2 = event.downTime
106                 },
107                 {
108                     val prefix = when (result) {
109                         true -> "SHADE TOUCH REROUTED"
110                         false -> "SHADE TOUCH BLOCKED"
111                         null -> "SHADE TOUCH DISPATCHED"
112                     }
113                     "$prefix: eventTime=$long1,downTime=$long2, reason=$str1"
114                 }
115         )
116     }
117 
118     fun logMotionEventStatusBarState(event: MotionEvent, statusBarState: Int, message: String) {
119         buffer.log(
120                 TAG,
121                 LogLevel.VERBOSE,
122                 {
123                     str1 = message
124                     long1 = event.eventTime
125                     long2 = event.downTime
126                     int1 = event.action
127                     int2 = statusBarState
128                     double1 = event.y.toDouble()
129                 },
130                 {
131                     "$str1\neventTime=$long1,downTime=$long2,y=$double1,action=$int1," +
132                             "statusBarState=${when (int2) {
133                                 0 -> "SHADE"
134                                 1 -> "KEYGUARD"
135                                 2 -> "SHADE_LOCKED"
136                                 else -> "UNKNOWN:$int2"
137                             }}"
138                 }
139         )
140     }
141 
142     fun logExpansionChanged(
143             message: String,
144             fraction: Float,
145             expanded: Boolean,
146             tracking: Boolean,
147             dragDownPxAmount: Float,
148     ) {
149         buffer.log(
150             TAG,
151             LogLevel.VERBOSE,
152             {
153                 str1 = message
154                 double1 = fraction.toDouble()
155                 bool1 = expanded
156                 bool2 = tracking
157                 long1 = dragDownPxAmount.toLong()
158             },
159             {
160                 "$str1 fraction=$double1,expanded=$bool1," +
161                     "tracking=$bool2," + "dragDownPxAmount=$dragDownPxAmount"
162             }
163         )
164     }
165 
166     fun logHasVibrated(hasVibratedOnOpen: Boolean, fraction: Float) {
167         buffer.log(
168             TAG,
169             LogLevel.VERBOSE,
170             {
171                 bool1 = hasVibratedOnOpen
172                 double1 = fraction.toDouble()
173             },
174             { "hasVibratedOnOpen=$bool1, expansionFraction=$double1" }
175         )
176     }
177 
178     fun logQsExpandImmediateChanged(newValue: Boolean) {
179         buffer.log(
180             TAG,
181             LogLevel.VERBOSE,
182             {
183                 bool1 = newValue
184             },
185             { "qsExpandImmediate=$bool1" }
186         )
187     }
188 
189     fun logQsExpansionChanged(
190             message: String,
191             qsExpanded: Boolean,
192             qsMinExpansionHeight: Int,
193             qsMaxExpansionHeight: Int,
194             stackScrollerOverscrolling: Boolean,
195             qsAnimatorExpand: Boolean,
196             animatingQs: Boolean
197     ) {
198         buffer.log(
199             TAG,
200             LogLevel.VERBOSE,
201             {
202                 str1 = message
203                 bool1 = qsExpanded
204                 int1 = qsMinExpansionHeight
205                 int2 = qsMaxExpansionHeight
206                 bool2 = stackScrollerOverscrolling
207                 bool3 = qsAnimatorExpand
208                 // 0 = false, 1 = true
209                 long1 = animatingQs.compareTo(false).toLong()
210             },
211             {
212                 "$str1 qsExpanded=$bool1,qsMinExpansionHeight=$int1,qsMaxExpansionHeight=$int2," +
213                     "stackScrollerOverscrolling=$bool2,qsAnimatorExpand=$bool3," +
214                     "animatingQs=$long1"
215             }
216         )
217     }
218 
219     fun logSingleTapUp(isDozing: Boolean, singleTapEnabled: Boolean, isNotDocked: Boolean) {
220         buffer.log(
221             TAG,
222             LogLevel.DEBUG,
223             {
224                 bool1 = isDozing
225                 bool2 = singleTapEnabled
226                 bool3 = isNotDocked
227             },
228             {
229                 "PulsingGestureListener#onSingleTapUp all of this must true for single " +
230                "tap to be detected: isDozing: $bool1, singleTapEnabled: $bool2, isNotDocked: $bool3"
231         })
232     }
233 
234     fun logSingleTapUpFalsingState(proximityIsNotNear: Boolean, isNotFalseTap: Boolean) {
235         buffer.log(
236             TAG,
237             LogLevel.DEBUG,
238             {
239                 bool1 = proximityIsNotNear
240                 bool2 = isNotFalseTap
241             },
242             {
243                 "PulsingGestureListener#onSingleTapUp all of this must true for single " +
244                     "tap to be detected: proximityIsNotNear: $bool1, isNotFalseTap: $bool2"
245             }
246         )
247     }
248 
249     fun logNotInterceptingTouchInstantExpanding(
250             instantExpanding: Boolean,
251             notificationsDragEnabled: Boolean,
252             touchDisabled: Boolean
253     ) {
254         buffer.log(
255             TAG,
256             LogLevel.VERBOSE,
257             {
258                 bool1 = instantExpanding
259                 bool2 = notificationsDragEnabled
260                 bool3 = touchDisabled
261             },
262             {
263                 "NPVC not intercepting touch, instantExpanding: $bool1, " +
264                     "!notificationsDragEnabled: $bool2, touchDisabled: $bool3"
265             }
266         )
267     }
268 
269     fun logLastFlingWasExpanding(expand: Boolean) {
270         buffer.log(
271             TAG,
272             LogLevel.VERBOSE,
273             { bool1 = expand },
274             { "NPVC mLastFlingWasExpanding set to: $bool1" }
275         )
276     }
277 
278     fun logFlingExpands(
279             vel: Float,
280             vectorVel: Float,
281             interactionType: Int,
282             minVelocityPxPerSecond: Float,
283             expansionOverHalf: Boolean,
284             allowExpandForSmallExpansion: Boolean
285     ) {
286         buffer.log(
287             TAG,
288             LogLevel.VERBOSE,
289             {
290                 int1 = interactionType
291                 long1 = vel.toLong()
292                 long2 = vectorVel.toLong()
293                 double1 = minVelocityPxPerSecond.toDouble()
294                 bool1 = expansionOverHalf
295                 bool2 = allowExpandForSmallExpansion
296             },
297             { "NPVC flingExpands called with vel: $long1, vectorVel: $long2, " +
298                     "interactionType: $int1, minVelocityPxPerSecond: $double1 " +
299                     "expansionOverHalf: $bool1, allowExpandForSmallExpansion: $bool2" }
300         )
301     }
302 
303     fun logEndMotionEvent(
304         msg: String,
305         forceCancel: Boolean,
306         expand: Boolean,
307     )
308     {
309         buffer.log(
310             TAG,
311             LogLevel.VERBOSE,
312             {
313                 str1 = msg
314                 bool1 = forceCancel
315                 bool2 = expand
316             },
317             { "$str1; force=$bool1; expand=$bool2" }
318         )
319     }
320 
321     fun logPanelClosedOnDown(
322         msg: String,
323         panelClosedOnDown: Boolean,
324         expandFraction: Float,
325     )
326     {
327         buffer.log(
328             TAG,
329             LogLevel.VERBOSE,
330             {
331                 str1 = msg
332                 bool1 = panelClosedOnDown
333                 double1 = expandFraction.toDouble()
334             },
335             { "$str1; mPanelClosedOnDown=$bool1; mExpandedFraction=$double1" }
336         )
337     }
338 
339     fun logPanelStateChanged(@PanelState panelState: Int) {
340         buffer.log(
341             TAG,
342             LogLevel.VERBOSE,
343             {
344                 str1 = panelState.panelStateToString()
345             },
346             { "New panel State: $str1" }
347         )
348     }
349 
350     fun flingQs(flingType: Int, isClick: Boolean) {
351         buffer.log(
352             TAG,
353             LogLevel.VERBOSE,
354             {
355                 str1 = flingTypeToString(flingType)
356                 bool1 = isClick
357             },
358             { "QS fling with type $str1, originated from click: $isClick" }
359         )
360     }
361 
362     private fun flingTypeToString(flingType: Int) = when (flingType) {
363         FLING_EXPAND -> "FLING_EXPAND"
364         FLING_COLLAPSE -> "FLING_COLLAPSE"
365         FLING_HIDE -> "FLING_HIDE"
366         else -> "UNKNOWN"
367     }
368 
369     fun logSplitShadeChanged(splitShadeEnabled: Boolean) {
370         buffer.log(
371             TAG,
372             LogLevel.VERBOSE,
373             { bool1 = splitShadeEnabled },
374             { "Split shade state changed: split shade ${if (bool1) "enabled" else "disabled"}" }
375         )
376     }
377 
378     fun logUpdateNotificationPanelTouchState(
379         disabled: Boolean,
380         isGoingToSleep: Boolean,
381         shouldControlScreenOff: Boolean,
382         deviceInteractive: Boolean,
383         isPulsing: Boolean,
384         isFrpActive: Boolean,
385     ) {
386         buffer.log(
387             TAG,
388             LogLevel.VERBOSE,
389             {
390                 bool1 = disabled
391                 bool2 = isGoingToSleep
392                 bool3 = shouldControlScreenOff
393                 bool4 = deviceInteractive
394                 str1 = isPulsing.toString()
395                 str2 = isFrpActive.toString()
396             },
397             {
398                 "CentralSurfaces updateNotificationPanelTouchState set disabled to: $bool1\n" +
399                         "isGoingToSleep: $bool2, !shouldControlScreenOff: $bool3," +
400                         "!mDeviceInteractive: $bool4, !isPulsing: $str1, isFrpActive: $str2"
401             }
402         )
403     }
404 }
405