1 /*
2 * Copyright (C) 2019 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.logging
18
19 import android.content.res.Configuration.ORIENTATION_LANDSCAPE
20 import android.content.res.Configuration.ORIENTATION_PORTRAIT
21 import android.content.res.Configuration.Orientation
22 import android.content.res.Configuration.SCREENLAYOUT_LONG_NO
23 import android.content.res.Configuration.SCREENLAYOUT_LONG_YES
24 import android.service.quicksettings.Tile
25 import android.view.View
26 import com.android.systemui.log.ConstantStringsLogger
27 import com.android.systemui.log.ConstantStringsLoggerImpl
28 import com.android.systemui.log.LogBuffer
29 import com.android.systemui.log.core.LogLevel.DEBUG
30 import com.android.systemui.log.core.LogLevel.ERROR
31 import com.android.systemui.log.core.LogLevel.INFO
32 import com.android.systemui.log.core.LogLevel.VERBOSE
33 import com.android.systemui.log.dagger.QSConfigLog
34 import com.android.systemui.log.dagger.QSLog
35 import com.android.systemui.plugins.qs.QSTile
36 import com.android.systemui.plugins.qs.QSTile.State
37 import com.android.systemui.statusbar.StatusBarState
38 import com.google.errorprone.annotations.CompileTimeConstant
39 import javax.inject.Inject
40
41 private const val TAG = "QSLog"
42
43 class QSLogger
44 @Inject
45 constructor(
46 @QSLog private val buffer: LogBuffer,
47 @QSConfigLog private val configChangedBuffer: LogBuffer,
<lambda>null48 ) : ConstantStringsLogger by ConstantStringsLoggerImpl(buffer, TAG) {
49
50 fun logException(@CompileTimeConstant logMsg: String, ex: Exception) {
51 buffer.log(TAG, ERROR, {}, { logMsg }, exception = ex)
52 }
53
54 fun v(@CompileTimeConstant msg: String, arg: Any) {
55 buffer.log(TAG, VERBOSE, { str1 = arg.toString() }, { "$msg: $str1" })
56 }
57
58 fun d(@CompileTimeConstant msg: String, arg: Any) {
59 buffer.log(TAG, DEBUG, { str1 = arg.toString() }, { "$msg: $str1" })
60 }
61
62 fun i(@CompileTimeConstant msg: String, arg: Any) {
63 buffer.log(TAG, INFO, { str1 = arg.toString() }, { "$msg: $str1" })
64 }
65
66 fun logTileAdded(tileSpec: String) {
67 buffer.log(TAG, DEBUG, { str1 = tileSpec }, { "[$str1] Tile added" })
68 }
69
70 fun logTileDestroyed(tileSpec: String, reason: String) {
71 buffer.log(
72 TAG,
73 DEBUG,
74 {
75 str1 = tileSpec
76 str2 = reason
77 },
78 { "[$str1] Tile destroyed. Reason: $str2" },
79 )
80 }
81
82 fun logStateChanged(tileSpec: String, state: State) {
83 buffer.log(
84 TAG,
85 DEBUG,
86 {
87 str1 = tileSpec
88 str2 = state.toString()
89 },
90 { "[$str1] Tile state=$str2" },
91 )
92 }
93
94 fun logTileChangeListening(tileSpec: String, listening: Boolean) {
95 buffer.log(
96 TAG,
97 VERBOSE,
98 {
99 bool1 = listening
100 str1 = tileSpec
101 },
102 { "[$str1] Tile listening=$bool1" },
103 )
104 }
105
106 fun logAllTilesChangeListening(listening: Boolean, containerName: String, allSpecs: String) {
107 buffer.log(
108 TAG,
109 DEBUG,
110 {
111 bool1 = listening
112 str1 = containerName
113 str2 = allSpecs
114 },
115 { "Tiles listening=$bool1 in $str1. $str2" },
116 )
117 }
118
119 fun logTileClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) {
120 buffer.log(
121 TAG,
122 DEBUG,
123 {
124 str1 = tileSpec
125 int1 = eventId
126 str2 = StatusBarState.toString(statusBarState)
127 str3 = toStateString(state)
128 },
129 { "[$str1][$int1] Tile clicked. StatusBarState=$str2. TileState=$str3" },
130 )
131 }
132
133 fun logHandleClick(tileSpec: String, eventId: Int) {
134 buffer.log(
135 TAG,
136 DEBUG,
137 {
138 str1 = tileSpec
139 int1 = eventId
140 },
141 { "[$str1][$int1] Tile handling click." },
142 )
143 }
144
145 fun logTileSecondaryClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) {
146 buffer.log(
147 TAG,
148 DEBUG,
149 {
150 str1 = tileSpec
151 int1 = eventId
152 str2 = StatusBarState.toString(statusBarState)
153 str3 = toStateString(state)
154 },
155 { "[$str1][$int1] Tile secondary clicked. StatusBarState=$str2. TileState=$str3" },
156 )
157 }
158
159 fun logHandleSecondaryClick(tileSpec: String, eventId: Int) {
160 buffer.log(
161 TAG,
162 DEBUG,
163 {
164 str1 = tileSpec
165 int1 = eventId
166 },
167 { "[$str1][$int1] Tile handling secondary click." },
168 )
169 }
170
171 fun logTileLongClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) {
172 buffer.log(
173 TAG,
174 DEBUG,
175 {
176 str1 = tileSpec
177 int1 = eventId
178 str2 = StatusBarState.toString(statusBarState)
179 str3 = toStateString(state)
180 },
181 { "[$str1][$int1] Tile long clicked. StatusBarState=$str2. TileState=$str3" },
182 )
183 }
184
185 fun logHandleLongClick(tileSpec: String, eventId: Int) {
186 buffer.log(
187 TAG,
188 DEBUG,
189 {
190 str1 = tileSpec
191 int1 = eventId
192 },
193 { "[$str1][$int1] Tile handling long click." },
194 )
195 }
196
197 fun logInternetTileUpdate(tileSpec: String, lastType: Int, callback: String) {
198 buffer.log(
199 TAG,
200 VERBOSE,
201 {
202 str1 = tileSpec
203 int1 = lastType
204 str2 = callback
205 },
206 { "[$str1] mLastTileState=$int1, Callback=$str2." },
207 )
208 }
209
210 // TODO(b/250618218): Remove this method once we know the root cause of b/250618218.
211 fun logTileBackgroundColorUpdateIfInternetTile(
212 tileSpec: String?,
213 state: Int,
214 disabledByPolicy: Boolean,
215 color: Int,
216 ) {
217 // This method is added to further debug b/250618218 which has only been observed from the
218 // InternetTile, so we are only logging the background color change for the InternetTile
219 // to avoid spamming the QSLogger.
220 if (tileSpec != "internet") {
221 return
222 }
223 buffer.log(
224 TAG,
225 VERBOSE,
226 {
227 str1 = tileSpec
228 int1 = state
229 bool1 = disabledByPolicy
230 int2 = color
231 },
232 { "[$str1] state=$int1, disabledByPolicy=$bool1, color=$int2." },
233 )
234 }
235
236 fun logTileUpdated(tileSpec: String, state: QSTile.State) {
237 buffer.log(
238 TAG,
239 VERBOSE,
240 {
241 str1 = tileSpec
242 str2 = state.label?.toString()
243 str3 = state.icon?.toString()
244 int1 = state.state
245 },
246 { "[$str1] Tile updated. Label=$str2. State=$int1. Icon=$str3." },
247 )
248 }
249
250 fun logPanelExpanded(expanded: Boolean, containerName: String) {
251 buffer.log(
252 TAG,
253 DEBUG,
254 {
255 str1 = containerName
256 bool1 = expanded
257 },
258 { "$str1 expanded=$bool1" },
259 )
260 }
261
262 fun logOnViewAttached(orientation: Int, containerName: String) {
263 buffer.log(
264 TAG,
265 DEBUG,
266 {
267 str1 = containerName
268 int1 = orientation
269 },
270 { "onViewAttached: $str1 orientation $int1" },
271 )
272 }
273
274 fun logOnViewDetached(orientation: Int, containerName: String) {
275 buffer.log(
276 TAG,
277 DEBUG,
278 {
279 str1 = containerName
280 int1 = orientation
281 },
282 { "onViewDetached: $str1 orientation $int1" },
283 )
284 }
285
286 fun logOnConfigurationChanged(
287 @Orientation oldOrientation: Int,
288 @Orientation newOrientation: Int,
289 oldShouldUseSplitShade: Boolean,
290 newShouldUseSplitShade: Boolean,
291 oldScreenLayout: Int,
292 newScreenLayout: Int,
293 containerName: String,
294 ) {
295 configChangedBuffer.log(
296 TAG,
297 DEBUG,
298 {
299 str1 = containerName
300 int1 = oldOrientation
301 int2 = newOrientation
302 long1 = oldScreenLayout.toLong()
303 long2 = newScreenLayout.toLong()
304 bool1 = oldShouldUseSplitShade
305 bool2 = newShouldUseSplitShade
306 },
307 {
308 "config change: " +
309 "$str1 orientation=${toOrientationString(int2)} " +
310 "(was ${toOrientationString(int1)}), " +
311 "screen layout=${toScreenLayoutString(long1.toInt())} " +
312 "(was ${toScreenLayoutString(long2.toInt())}), " +
313 "splitShade=$bool2 (was $bool1)"
314 },
315 )
316 }
317
318 fun logSwitchTileLayout(
319 after: Boolean,
320 before: Boolean,
321 force: Boolean,
322 containerName: String,
323 ) {
324 buffer.log(
325 TAG,
326 DEBUG,
327 {
328 str1 = containerName
329 bool1 = after
330 bool2 = before
331 bool3 = force
332 },
333 { "change tile layout: $str1 horizontal=$bool1 (was $bool2), force? $bool3" },
334 )
335 }
336
337 fun logTileDistributionInProgress(tilesPerPageCount: Int, totalTilesCount: Int) {
338 buffer.log(
339 TAG,
340 DEBUG,
341 {
342 int1 = tilesPerPageCount
343 int2 = totalTilesCount
344 },
345 { "Distributing tiles: [tilesPerPageCount=$int1] [totalTilesCount=$int2]" },
346 )
347 }
348
349 fun logTileDistributed(tileName: String, pageIndex: Int) {
350 buffer.log(
351 TAG,
352 DEBUG,
353 {
354 str1 = tileName
355 int1 = pageIndex
356 },
357 { "Adding $str1 to page number $int1" },
358 )
359 }
360
361 private fun toStateString(state: Int): String {
362 return when (state) {
363 Tile.STATE_ACTIVE -> "active"
364 Tile.STATE_INACTIVE -> "inactive"
365 Tile.STATE_UNAVAILABLE -> "unavailable"
366 else -> "wrong state"
367 }
368 }
369
370 fun logVisibility(viewName: String, @View.Visibility visibility: Int) {
371 buffer.log(
372 TAG,
373 DEBUG,
374 {
375 str1 = viewName
376 str2 = toVisibilityString(visibility)
377 },
378 { "$str1 visibility: $str2" },
379 )
380 }
381
382 private fun toVisibilityString(visibility: Int): String {
383 return when (visibility) {
384 View.VISIBLE -> "VISIBLE"
385 View.INVISIBLE -> "INVISIBLE"
386 View.GONE -> "GONE"
387 else -> "undefined"
388 }
389 }
390 }
391
toOrientationStringnull392 private inline fun toOrientationString(@Orientation orientation: Int): String {
393 return when (orientation) {
394 ORIENTATION_LANDSCAPE -> "land"
395 ORIENTATION_PORTRAIT -> "port"
396 else -> "undefined"
397 }
398 }
399
toScreenLayoutStringnull400 private inline fun toScreenLayoutString(screenLayout: Int): String {
401 return when (screenLayout) {
402 SCREENLAYOUT_LONG_YES -> "long"
403 SCREENLAYOUT_LONG_NO -> "notlong"
404 else -> "undefined"
405 }
406 }
407