/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.qs.logging import android.content.res.Configuration.ORIENTATION_LANDSCAPE import android.content.res.Configuration.ORIENTATION_PORTRAIT import android.content.res.Configuration.Orientation import android.service.quicksettings.Tile import android.view.View import com.android.systemui.log.ConstantStringsLogger import com.android.systemui.log.ConstantStringsLoggerImpl import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel.DEBUG import com.android.systemui.log.core.LogLevel.ERROR import com.android.systemui.log.core.LogLevel.VERBOSE import com.android.systemui.log.dagger.QSConfigLog import com.android.systemui.log.dagger.QSLog import com.android.systemui.plugins.qs.QSTile import com.android.systemui.statusbar.StatusBarState import com.google.errorprone.annotations.CompileTimeConstant import javax.inject.Inject private const val TAG = "QSLog" class QSLogger @Inject constructor( @QSLog private val buffer: LogBuffer, @QSConfigLog private val configChangedBuffer: LogBuffer, ) : ConstantStringsLogger by ConstantStringsLoggerImpl(buffer, TAG) { fun logException(@CompileTimeConstant logMsg: String, ex: Exception) { buffer.log(TAG, ERROR, {}, { logMsg }, exception = ex) } fun v(@CompileTimeConstant msg: String, arg: Any) { buffer.log(TAG, VERBOSE, { str1 = arg.toString() }, { "$msg: $str1" }) } fun d(@CompileTimeConstant msg: String, arg: Any) { buffer.log(TAG, DEBUG, { str1 = arg.toString() }, { "$msg: $str1" }) } fun logTileAdded(tileSpec: String) { buffer.log(TAG, DEBUG, { str1 = tileSpec }, { "[$str1] Tile added" }) } fun logTileDestroyed(tileSpec: String, reason: String) { buffer.log( TAG, DEBUG, { str1 = tileSpec str2 = reason }, { "[$str1] Tile destroyed. Reason: $str2" } ) } fun logTileChangeListening(tileSpec: String, listening: Boolean) { buffer.log( TAG, VERBOSE, { bool1 = listening str1 = tileSpec }, { "[$str1] Tile listening=$bool1" } ) } fun logAllTilesChangeListening(listening: Boolean, containerName: String, allSpecs: String) { buffer.log( TAG, DEBUG, { bool1 = listening str1 = containerName str2 = allSpecs }, { "Tiles listening=$bool1 in $str1. $str2" } ) } fun logTileClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) { buffer.log( TAG, DEBUG, { str1 = tileSpec int1 = eventId str2 = StatusBarState.toString(statusBarState) str3 = toStateString(state) }, { "[$str1][$int1] Tile clicked. StatusBarState=$str2. TileState=$str3" } ) } fun logHandleClick(tileSpec: String, eventId: Int) { buffer.log( TAG, DEBUG, { str1 = tileSpec int1 = eventId }, { "[$str1][$int1] Tile handling click." } ) } fun logTileSecondaryClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) { buffer.log( TAG, DEBUG, { str1 = tileSpec int1 = eventId str2 = StatusBarState.toString(statusBarState) str3 = toStateString(state) }, { "[$str1][$int1] Tile secondary clicked. StatusBarState=$str2. TileState=$str3" } ) } fun logHandleSecondaryClick(tileSpec: String, eventId: Int) { buffer.log( TAG, DEBUG, { str1 = tileSpec int1 = eventId }, { "[$str1][$int1] Tile handling secondary click." } ) } fun logTileLongClick(tileSpec: String, statusBarState: Int, state: Int, eventId: Int) { buffer.log( TAG, DEBUG, { str1 = tileSpec int1 = eventId str2 = StatusBarState.toString(statusBarState) str3 = toStateString(state) }, { "[$str1][$int1] Tile long clicked. StatusBarState=$str2. TileState=$str3" } ) } fun logHandleLongClick(tileSpec: String, eventId: Int) { buffer.log( TAG, DEBUG, { str1 = tileSpec int1 = eventId }, { "[$str1][$int1] Tile handling long click." } ) } fun logInternetTileUpdate(tileSpec: String, lastType: Int, callback: String) { buffer.log( TAG, VERBOSE, { str1 = tileSpec int1 = lastType str2 = callback }, { "[$str1] mLastTileState=$int1, Callback=$str2." } ) } // TODO(b/250618218): Remove this method once we know the root cause of b/250618218. fun logTileBackgroundColorUpdateIfInternetTile( tileSpec: String, state: Int, disabledByPolicy: Boolean, color: Int ) { // This method is added to further debug b/250618218 which has only been observed from the // InternetTile, so we are only logging the background color change for the InternetTile // to avoid spamming the QSLogger. if (tileSpec != "internet") { return } buffer.log( TAG, VERBOSE, { str1 = tileSpec int1 = state bool1 = disabledByPolicy int2 = color }, { "[$str1] state=$int1, disabledByPolicy=$bool1, color=$int2." } ) } fun logTileUpdated(tileSpec: String, state: QSTile.State) { buffer.log( TAG, VERBOSE, { str1 = tileSpec str2 = state.label?.toString() str3 = state.icon?.toString() int1 = state.state if (state is QSTile.SignalState) { bool1 = true bool2 = state.activityIn bool3 = state.activityOut } }, { "[$str1] Tile updated. Label=$str2. State=$int1. Icon=$str3." + if (bool1) " Activity in/out=$bool2/$bool3" else "" } ) } fun logPanelExpanded(expanded: Boolean, containerName: String) { buffer.log( TAG, DEBUG, { str1 = containerName bool1 = expanded }, { "$str1 expanded=$bool1" } ) } fun logOnViewAttached(orientation: Int, containerName: String) { buffer.log( TAG, DEBUG, { str1 = containerName int1 = orientation }, { "onViewAttached: $str1 orientation $int1" } ) } fun logOnViewDetached(orientation: Int, containerName: String) { buffer.log( TAG, DEBUG, { str1 = containerName int1 = orientation }, { "onViewDetached: $str1 orientation $int1" } ) } fun logOnConfigurationChanged( @Orientation oldOrientation: Int, @Orientation newOrientation: Int, newShouldUseSplitShade: Boolean, oldShouldUseSplitShade: Boolean, containerName: String ) { configChangedBuffer.log( TAG, DEBUG, { str1 = containerName int1 = oldOrientation int2 = newOrientation bool1 = oldShouldUseSplitShade bool2 = newShouldUseSplitShade }, { "config change: " + "$str1 orientation=${toOrientationString(int2)} " + "(was ${toOrientationString(int1)}), " + "splitShade=$bool2 (was $bool1)" } ) } fun logSwitchTileLayout( after: Boolean, before: Boolean, force: Boolean, containerName: String ) { buffer.log( TAG, DEBUG, { str1 = containerName bool1 = after bool2 = before bool3 = force }, { "change tile layout: $str1 horizontal=$bool1 (was $bool2), force? $bool3" } ) } fun logTileDistributionInProgress(tilesPerPageCount: Int, totalTilesCount: Int) { buffer.log( TAG, DEBUG, { int1 = tilesPerPageCount int2 = totalTilesCount }, { "Distributing tiles: [tilesPerPageCount=$int1] [totalTilesCount=$int2]" } ) } fun logTileDistributed(tileName: String, pageIndex: Int) { buffer.log( TAG, DEBUG, { str1 = tileName int1 = pageIndex }, { "Adding $str1 to page number $int1" } ) } private fun toStateString(state: Int): String { return when (state) { Tile.STATE_ACTIVE -> "active" Tile.STATE_INACTIVE -> "inactive" Tile.STATE_UNAVAILABLE -> "unavailable" else -> "wrong state" } } fun logVisibility(viewName: String, @View.Visibility visibility: Int) { buffer.log( TAG, DEBUG, { str1 = viewName str2 = toVisibilityString(visibility) }, { "$str1 visibility: $str2" } ) } private fun toVisibilityString(visibility: Int): String { return when (visibility) { View.VISIBLE -> "VISIBLE" View.INVISIBLE -> "INVISIBLE" View.GONE -> "GONE" else -> "undefined" } } } private inline fun toOrientationString(@Orientation orientation: Int): String { return when (orientation) { ORIENTATION_LANDSCAPE -> "land" ORIENTATION_PORTRAIT -> "port" else -> "undefined" } }