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.ConstantStringsLogger 25 import com.android.systemui.log.ConstantStringsLoggerImpl 26 import com.android.systemui.log.LogBuffer 27 import com.android.systemui.log.core.LogLevel.DEBUG 28 import com.android.systemui.log.core.LogLevel.ERROR 29 import com.android.systemui.log.core.LogLevel.VERBOSE 30 import com.android.systemui.log.dagger.QSConfigLog 31 import com.android.systemui.log.dagger.QSLog 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, 44 ) : 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 374 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