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