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