Loading core/java/android/app/StatusBarManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ import java.lang.annotation.RetentionPolicy; */ @SystemService(Context.STATUS_BAR_SERVICE) public class StatusBarManager { // LINT.IfChange /** @hide */ public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND; /** @hide */ Loading Loading @@ -144,6 +144,7 @@ public class StatusBarManager { }) @Retention(RetentionPolicy.SOURCE) public @interface Disable2Flags {} // LINT.ThenChange(frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt) /** * Default disable flags for setup Loading packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt 0 → 100644 +210 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.statusbar import android.app.StatusBarManager.DISABLE_BACK import android.app.StatusBarManager.DISABLE_CLOCK import android.app.StatusBarManager.DISABLE_EXPAND import android.app.StatusBarManager.DISABLE_HOME import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS import android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP import android.app.StatusBarManager.DISABLE_RECENT import android.app.StatusBarManager.DISABLE_SEARCH import android.app.StatusBarManager.DISABLE_SYSTEM_INFO import android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE import android.app.StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject /** * A singleton that creates concise but readable strings representing the values of the disable * flags for debugging. * * See [CommandQueue.disable] for information about disable flags. * * Note that, for both lists passed in, each flag must have a distinct [DisableFlag.flagIsSetSymbol] * and distinct [DisableFlag.flagNotSetSymbol] within the list. If this isn't true, the logs could * be ambiguous so an [IllegalArgumentException] is thrown. */ @SysUISingleton class DisableFlagsLogger constructor( private val disable1FlagsList: List<DisableFlag>, private val disable2FlagsList: List<DisableFlag> ) { @Inject constructor() : this(defaultDisable1FlagsList, defaultDisable2FlagsList) init { if (flagsListHasDuplicateSymbols(disable1FlagsList)) { throw IllegalArgumentException("disable1 flags must have unique symbols") } if (flagsListHasDuplicateSymbols(disable2FlagsList)) { throw IllegalArgumentException("disable2 flags must have unique symbols") } } private fun flagsListHasDuplicateSymbols(list: List<DisableFlag>): Boolean { val numDistinctFlagOffStatus = list.map { it.getFlagStatus(0) }.distinct().count() val numDistinctFlagOnStatus = list .map { it.getFlagStatus(Int.MAX_VALUE) } .distinct() .count() return numDistinctFlagOffStatus < list.count() || numDistinctFlagOnStatus < list.count() } /** * Returns a string representing the, old, new, and new-after-modification disable flag states, * as well as the differences between each of the states. * * Example: * Old: EnaiHbcRso.qINgr | New: EnaihBcRso.qiNGR (hB.iGR) | New after local modification: * EnaihBcRso.qInGR (.n) * * A capital character signifies the flag is set and a lowercase character signifies that the * flag isn't set. The flag states will be logged in the same order as the passed-in lists. * * The difference between states is written between parentheses, and won't be included if there * is no difference. the new-after-modification state also won't be included if there's no * difference from the new state. * * @param old the disable state that had been previously sent. * @param new the new disable state that has just been sent. * @param newAfterLocalModification the new disable states after a class has locally modified * them. Null if the class does not locally modify. */ fun getDisableFlagsString( old: DisableState, new: DisableState, newAfterLocalModification: DisableState? = null ): String { val builder = StringBuilder("Received new disable state. ") builder.append("Old: ") builder.append(getFlagsString(old)) builder.append(" | New: ") if (old != new) { builder.append(getFlagsStringWithDiff(old, new)) } else { builder.append(getFlagsString(old)) } if (newAfterLocalModification != null && new != newAfterLocalModification) { builder.append(" | New after local modification: ") builder.append(getFlagsStringWithDiff(new, newAfterLocalModification)) } return builder.toString() } /** * Returns a string representing [new] state, as well as the difference from [old] to [new] * (if there is one). */ private fun getFlagsStringWithDiff(old: DisableState, new: DisableState): String { val builder = StringBuilder() builder.append(getFlagsString(new)) builder.append(" ") builder.append(getDiffString(old, new)) return builder.toString() } /** * Returns a string representing the difference between [old] and [new], or an empty string if * there is no difference. * * For example, if old was "abc.DE" and new was "aBC.De", the difference returned would be * "(BC.e)". */ private fun getDiffString(old: DisableState, new: DisableState): String { if (old == new) { return "" } val builder = StringBuilder("(") disable1FlagsList.forEach { val newSymbol = it.getFlagStatus(new.disable1) if (it.getFlagStatus(old.disable1) != newSymbol) { builder.append(newSymbol) } } builder.append(".") disable2FlagsList.forEach { val newSymbol = it.getFlagStatus(new.disable2) if (it.getFlagStatus(old.disable2) != newSymbol) { builder.append(newSymbol) } } builder.append(")") return builder.toString() } /** Returns a string representing the disable flag states, e.g. "EnaihBcRso.qiNGR". */ private fun getFlagsString(state: DisableState): String { val builder = StringBuilder("") disable1FlagsList.forEach { builder.append(it.getFlagStatus(state.disable1)) } builder.append(".") disable2FlagsList.forEach { builder.append(it.getFlagStatus(state.disable2)) } return builder.toString() } /** A POJO representing each disable flag. */ class DisableFlag( private val bitMask: Int, private val flagIsSetSymbol: Char, private val flagNotSetSymbol: Char ) { /** * Returns a character representing whether or not this flag is set in [state]. * * A capital character signifies the flag is set and a lowercase character signifies that * the flag isn't set. */ internal fun getFlagStatus(state: Int): Char = if (0 != state and this.bitMask) this.flagIsSetSymbol else this.flagNotSetSymbol } /** POJO to hold [disable1] and [disable2]. */ data class DisableState(val disable1: Int, val disable2: Int) } // LINT.IfChange private val defaultDisable1FlagsList: List<DisableFlagsLogger.DisableFlag> = listOf( DisableFlagsLogger.DisableFlag(DISABLE_EXPAND, 'E', 'e'), DisableFlagsLogger.DisableFlag(DISABLE_NOTIFICATION_ICONS, 'N', 'n'), DisableFlagsLogger.DisableFlag(DISABLE_NOTIFICATION_ALERTS, 'A', 'a'), DisableFlagsLogger.DisableFlag(DISABLE_SYSTEM_INFO, 'I', 'i'), DisableFlagsLogger.DisableFlag(DISABLE_HOME, 'H', 'h'), DisableFlagsLogger.DisableFlag(DISABLE_BACK, 'B', 'b'), DisableFlagsLogger.DisableFlag(DISABLE_CLOCK, 'C', 'c'), DisableFlagsLogger.DisableFlag(DISABLE_RECENT, 'R', 'r'), DisableFlagsLogger.DisableFlag(DISABLE_SEARCH, 'S', 's'), DisableFlagsLogger.DisableFlag(DISABLE_ONGOING_CALL_CHIP, 'O', 'o') ) private val defaultDisable2FlagsList: List<DisableFlagsLogger.DisableFlag> = listOf( DisableFlagsLogger.DisableFlag(DISABLE2_QUICK_SETTINGS, 'Q', 'q'), DisableFlagsLogger.DisableFlag(DISABLE2_SYSTEM_ICONS, 'I', 'i'), DisableFlagsLogger.DisableFlag(DISABLE2_NOTIFICATION_SHADE, 'N', 'n'), DisableFlagsLogger.DisableFlag(DISABLE2_GLOBAL_ACTIONS, 'G', 'g'), DisableFlagsLogger.DisableFlag(DISABLE2_ROTATE_SUGGESTIONS, 'R', 'r') ) // LINT.ThenChange(frameworks/base/core/java/android/app/StatusBarManager.java) No newline at end of file packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java +14 −37 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.qs.QSPanelController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; Loading Loading @@ -98,6 +99,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { private final VibratorHelper mVibratorHelper; private final Optional<Vibrator> mVibratorOptional; private final LightBarController mLightBarController; private final DisableFlagsLogger mDisableFlagsLogger; private final int mDisplayId; private final boolean mVibrateOnOpening; private final VibrationEffect mCameraLaunchGestureVibrationEffect; Loading Loading @@ -134,6 +136,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { VibratorHelper vibratorHelper, Optional<Vibrator> vibratorOptional, LightBarController lightBarController, DisableFlagsLogger disableFlagsLogger, @DisplayId int displayId) { mStatusBar = statusBar; Loading @@ -159,6 +162,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { mVibratorHelper = vibratorHelper; mVibratorOptional = vibratorOptional; mLightBarController = lightBarController; mDisableFlagsLogger = disableFlagsLogger; mDisplayId = displayId; mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation); Loading Loading @@ -267,7 +271,17 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { if (displayId != mDisplayId) { return; } int state2BeforeAdjustment = state2; state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2); Log.d(StatusBar.TAG, mDisableFlagsLogger.getDisableFlagsString( /* old= */ new DisableFlagsLogger.DisableState( mStatusBar.getDisabled1(), mStatusBar.getDisabled2()), /* new= */ new DisableFlagsLogger.DisableState( state1, state2BeforeAdjustment), /* newStateAfterLocalModification= */ new DisableFlagsLogger.DisableState( state1, state2))); final int old1 = mStatusBar.getDisabled1(); final int diff1 = state1 ^ old1; Loading @@ -277,43 +291,6 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { final int diff2 = state2 ^ old2; mStatusBar.setDisabled2(state2); if (StatusBar.DEBUG) { Log.d(StatusBar.TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)", old1, state1, diff1)); Log.d(StatusBar.TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)", old2, state2, diff2)); } StringBuilder flagdbg = new StringBuilder(); flagdbg.append("disable<"); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND)) ? 'E' : 'e'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_EXPAND)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? 'I' : 'i'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? 'A' : 'a'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK)) ? 'B' : 'b'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_BACK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME)) ? 'H' : 'h'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_HOME)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT)) ? 'R' : 'r'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_RECENT)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK)) ? 'C' : 'c'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' '); flagdbg.append("> disable2<"); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' '); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' '); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? 'N' : 'n'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? '!' : ' '); flagdbg.append('>'); Log.d(StatusBar.TAG, flagdbg.toString()); if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { mShadeController.animateCollapsePanels(); Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt 0 → 100644 +188 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.statusbar import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertThrows import org.junit.Test @SmallTest class DisableFlagsLoggerTest : SysuiTestCase() { private val disable1Flags = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'B', 'b'), DisableFlagsLogger.DisableFlag(0b001, 'C', 'c'), ) private val disable2Flags = listOf( DisableFlagsLogger.DisableFlag(0b10, 'M', 'm'), DisableFlagsLogger.DisableFlag(0b01, 'N', 'n'), ) private val disableFlagsLogger = DisableFlagsLogger(disable1Flags, disable2Flags) @Test fun getDisableFlagsString_oldAndNewSame_statesLoggedButDiffsNotLogged() { val state = DisableFlagsLogger.DisableState( 0b111, // ABC 0b01 // mN ) val result = disableFlagsLogger.getDisableFlagsString(state, state) assertThat(result).contains("Old: ABC.mN") assertThat(result).contains("New: ABC.mN") assertThat(result).doesNotContain("(") assertThat(result).doesNotContain(")") } @Test fun getDisableFlagsString_oldAndNewDifferent_statesAndDiffLogged() { val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState( 0b111, // ABC 0b01, // mN ), DisableFlagsLogger.DisableState( 0b001, // abC 0b10 // Mn ) ) assertThat(result).contains("Old: ABC.mN") assertThat(result).contains("New: abC.Mn") assertThat(result).contains("(ab.Mn)") } @Test fun getDisableFlagsString_onlyDisable2Different_diffLoggedCorrectly() { val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState( 0b001, // abC 0b01, // mN ), DisableFlagsLogger.DisableState( 0b001, // abC 0b00 // mn ) ) assertThat(result).contains("(.n)") } @Test fun getDisableFlagsString_nullLocalModification_localModNotLogged() { val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState(0, 0), DisableFlagsLogger.DisableState(1, 1), newAfterLocalModification = null ) assertThat(result).doesNotContain("local modification") } @Test fun getDisableFlagsString_newAfterLocalModificationSameAsNew_localModNotLogged() { val newState = DisableFlagsLogger.DisableState( 0b001, // abC 0b10 // mn ) val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState(0, 0), newState, newState ) assertThat(result).doesNotContain("local modification") } @Test fun getDisableFlagsString_newAfterLocalModificationDifferent_localModAndDiffLogged() { val result = disableFlagsLogger.getDisableFlagsString( old = DisableFlagsLogger.DisableState(0, 0), new = DisableFlagsLogger.DisableState( 0b000, // abc 0b00 // mn ), newAfterLocalModification = DisableFlagsLogger.DisableState( 0b100, // Abc 0b10 // Mn ) ) assertThat(result).contains("local modification: Abc.Mn (A.M)") } @Test fun constructor_defaultDisableFlags_noException() { // Just creating the logger with the default params will trigger the exception if there // is one. DisableFlagsLogger() } @Test fun constructor_disable1_FlagIsSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'A', 'b'), ), listOf() ) } } @Test fun constructor_disable1_FlagNotSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'B', 'a'), ), listOf() ) } } @Test fun constructor_disable2_FlagIsSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf(), disable2FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'A', 'b'), ), ) } } @Test fun constructor_disable2_FlagNotSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf(), disable2FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'B', 'a'), ), ) } } } packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacksTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.assist.AssistManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; Loading Loading @@ -112,6 +113,7 @@ public class StatusBarCommandQueueCallbacksTest extends SysuiTestCase { mVibratorHelper, Optional.of(mVibrator), mLightBarController, new DisableFlagsLogger(), DEFAULT_DISPLAY); when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true); Loading Loading
core/java/android/app/StatusBarManager.java +2 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,7 @@ import java.lang.annotation.RetentionPolicy; */ @SystemService(Context.STATUS_BAR_SERVICE) public class StatusBarManager { // LINT.IfChange /** @hide */ public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND; /** @hide */ Loading Loading @@ -144,6 +144,7 @@ public class StatusBarManager { }) @Retention(RetentionPolicy.SOURCE) public @interface Disable2Flags {} // LINT.ThenChange(frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt) /** * Default disable flags for setup Loading
packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt 0 → 100644 +210 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.statusbar import android.app.StatusBarManager.DISABLE_BACK import android.app.StatusBarManager.DISABLE_CLOCK import android.app.StatusBarManager.DISABLE_EXPAND import android.app.StatusBarManager.DISABLE_HOME import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS import android.app.StatusBarManager.DISABLE_ONGOING_CALL_CHIP import android.app.StatusBarManager.DISABLE_RECENT import android.app.StatusBarManager.DISABLE_SEARCH import android.app.StatusBarManager.DISABLE_SYSTEM_INFO import android.app.StatusBarManager.DISABLE2_GLOBAL_ACTIONS import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE import android.app.StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject /** * A singleton that creates concise but readable strings representing the values of the disable * flags for debugging. * * See [CommandQueue.disable] for information about disable flags. * * Note that, for both lists passed in, each flag must have a distinct [DisableFlag.flagIsSetSymbol] * and distinct [DisableFlag.flagNotSetSymbol] within the list. If this isn't true, the logs could * be ambiguous so an [IllegalArgumentException] is thrown. */ @SysUISingleton class DisableFlagsLogger constructor( private val disable1FlagsList: List<DisableFlag>, private val disable2FlagsList: List<DisableFlag> ) { @Inject constructor() : this(defaultDisable1FlagsList, defaultDisable2FlagsList) init { if (flagsListHasDuplicateSymbols(disable1FlagsList)) { throw IllegalArgumentException("disable1 flags must have unique symbols") } if (flagsListHasDuplicateSymbols(disable2FlagsList)) { throw IllegalArgumentException("disable2 flags must have unique symbols") } } private fun flagsListHasDuplicateSymbols(list: List<DisableFlag>): Boolean { val numDistinctFlagOffStatus = list.map { it.getFlagStatus(0) }.distinct().count() val numDistinctFlagOnStatus = list .map { it.getFlagStatus(Int.MAX_VALUE) } .distinct() .count() return numDistinctFlagOffStatus < list.count() || numDistinctFlagOnStatus < list.count() } /** * Returns a string representing the, old, new, and new-after-modification disable flag states, * as well as the differences between each of the states. * * Example: * Old: EnaiHbcRso.qINgr | New: EnaihBcRso.qiNGR (hB.iGR) | New after local modification: * EnaihBcRso.qInGR (.n) * * A capital character signifies the flag is set and a lowercase character signifies that the * flag isn't set. The flag states will be logged in the same order as the passed-in lists. * * The difference between states is written between parentheses, and won't be included if there * is no difference. the new-after-modification state also won't be included if there's no * difference from the new state. * * @param old the disable state that had been previously sent. * @param new the new disable state that has just been sent. * @param newAfterLocalModification the new disable states after a class has locally modified * them. Null if the class does not locally modify. */ fun getDisableFlagsString( old: DisableState, new: DisableState, newAfterLocalModification: DisableState? = null ): String { val builder = StringBuilder("Received new disable state. ") builder.append("Old: ") builder.append(getFlagsString(old)) builder.append(" | New: ") if (old != new) { builder.append(getFlagsStringWithDiff(old, new)) } else { builder.append(getFlagsString(old)) } if (newAfterLocalModification != null && new != newAfterLocalModification) { builder.append(" | New after local modification: ") builder.append(getFlagsStringWithDiff(new, newAfterLocalModification)) } return builder.toString() } /** * Returns a string representing [new] state, as well as the difference from [old] to [new] * (if there is one). */ private fun getFlagsStringWithDiff(old: DisableState, new: DisableState): String { val builder = StringBuilder() builder.append(getFlagsString(new)) builder.append(" ") builder.append(getDiffString(old, new)) return builder.toString() } /** * Returns a string representing the difference between [old] and [new], or an empty string if * there is no difference. * * For example, if old was "abc.DE" and new was "aBC.De", the difference returned would be * "(BC.e)". */ private fun getDiffString(old: DisableState, new: DisableState): String { if (old == new) { return "" } val builder = StringBuilder("(") disable1FlagsList.forEach { val newSymbol = it.getFlagStatus(new.disable1) if (it.getFlagStatus(old.disable1) != newSymbol) { builder.append(newSymbol) } } builder.append(".") disable2FlagsList.forEach { val newSymbol = it.getFlagStatus(new.disable2) if (it.getFlagStatus(old.disable2) != newSymbol) { builder.append(newSymbol) } } builder.append(")") return builder.toString() } /** Returns a string representing the disable flag states, e.g. "EnaihBcRso.qiNGR". */ private fun getFlagsString(state: DisableState): String { val builder = StringBuilder("") disable1FlagsList.forEach { builder.append(it.getFlagStatus(state.disable1)) } builder.append(".") disable2FlagsList.forEach { builder.append(it.getFlagStatus(state.disable2)) } return builder.toString() } /** A POJO representing each disable flag. */ class DisableFlag( private val bitMask: Int, private val flagIsSetSymbol: Char, private val flagNotSetSymbol: Char ) { /** * Returns a character representing whether or not this flag is set in [state]. * * A capital character signifies the flag is set and a lowercase character signifies that * the flag isn't set. */ internal fun getFlagStatus(state: Int): Char = if (0 != state and this.bitMask) this.flagIsSetSymbol else this.flagNotSetSymbol } /** POJO to hold [disable1] and [disable2]. */ data class DisableState(val disable1: Int, val disable2: Int) } // LINT.IfChange private val defaultDisable1FlagsList: List<DisableFlagsLogger.DisableFlag> = listOf( DisableFlagsLogger.DisableFlag(DISABLE_EXPAND, 'E', 'e'), DisableFlagsLogger.DisableFlag(DISABLE_NOTIFICATION_ICONS, 'N', 'n'), DisableFlagsLogger.DisableFlag(DISABLE_NOTIFICATION_ALERTS, 'A', 'a'), DisableFlagsLogger.DisableFlag(DISABLE_SYSTEM_INFO, 'I', 'i'), DisableFlagsLogger.DisableFlag(DISABLE_HOME, 'H', 'h'), DisableFlagsLogger.DisableFlag(DISABLE_BACK, 'B', 'b'), DisableFlagsLogger.DisableFlag(DISABLE_CLOCK, 'C', 'c'), DisableFlagsLogger.DisableFlag(DISABLE_RECENT, 'R', 'r'), DisableFlagsLogger.DisableFlag(DISABLE_SEARCH, 'S', 's'), DisableFlagsLogger.DisableFlag(DISABLE_ONGOING_CALL_CHIP, 'O', 'o') ) private val defaultDisable2FlagsList: List<DisableFlagsLogger.DisableFlag> = listOf( DisableFlagsLogger.DisableFlag(DISABLE2_QUICK_SETTINGS, 'Q', 'q'), DisableFlagsLogger.DisableFlag(DISABLE2_SYSTEM_ICONS, 'I', 'i'), DisableFlagsLogger.DisableFlag(DISABLE2_NOTIFICATION_SHADE, 'N', 'n'), DisableFlagsLogger.DisableFlag(DISABLE2_GLOBAL_ACTIONS, 'G', 'g'), DisableFlagsLogger.DisableFlag(DISABLE2_ROTATE_SUGGESTIONS, 'R', 'r') ) // LINT.ThenChange(frameworks/base/core/java/android/app/StatusBarManager.java) No newline at end of file
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java +14 −37 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.qs.QSPanelController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; Loading Loading @@ -98,6 +99,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { private final VibratorHelper mVibratorHelper; private final Optional<Vibrator> mVibratorOptional; private final LightBarController mLightBarController; private final DisableFlagsLogger mDisableFlagsLogger; private final int mDisplayId; private final boolean mVibrateOnOpening; private final VibrationEffect mCameraLaunchGestureVibrationEffect; Loading Loading @@ -134,6 +136,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { VibratorHelper vibratorHelper, Optional<Vibrator> vibratorOptional, LightBarController lightBarController, DisableFlagsLogger disableFlagsLogger, @DisplayId int displayId) { mStatusBar = statusBar; Loading @@ -159,6 +162,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { mVibratorHelper = vibratorHelper; mVibratorOptional = vibratorOptional; mLightBarController = lightBarController; mDisableFlagsLogger = disableFlagsLogger; mDisplayId = displayId; mVibrateOnOpening = resources.getBoolean(R.bool.config_vibrateOnIconAnimation); Loading Loading @@ -267,7 +271,17 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { if (displayId != mDisplayId) { return; } int state2BeforeAdjustment = state2; state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2); Log.d(StatusBar.TAG, mDisableFlagsLogger.getDisableFlagsString( /* old= */ new DisableFlagsLogger.DisableState( mStatusBar.getDisabled1(), mStatusBar.getDisabled2()), /* new= */ new DisableFlagsLogger.DisableState( state1, state2BeforeAdjustment), /* newStateAfterLocalModification= */ new DisableFlagsLogger.DisableState( state1, state2))); final int old1 = mStatusBar.getDisabled1(); final int diff1 = state1 ^ old1; Loading @@ -277,43 +291,6 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks { final int diff2 = state2 ^ old2; mStatusBar.setDisabled2(state2); if (StatusBar.DEBUG) { Log.d(StatusBar.TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)", old1, state1, diff1)); Log.d(StatusBar.TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)", old2, state2, diff2)); } StringBuilder flagdbg = new StringBuilder(); flagdbg.append("disable<"); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND)) ? 'E' : 'e'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_EXPAND)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? 'I' : 'i'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? 'A' : 'a'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK)) ? 'B' : 'b'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_BACK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME)) ? 'H' : 'h'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_HOME)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT)) ? 'R' : 'r'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_RECENT)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK)) ? 'C' : 'c'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' '); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's'); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' '); flagdbg.append("> disable2<"); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' '); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' '); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? 'N' : 'n'); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? '!' : ' '); flagdbg.append('>'); Log.d(StatusBar.TAG, flagdbg.toString()); if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) { if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) { mShadeController.animateCollapsePanels(); Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt 0 → 100644 +188 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.statusbar import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.google.common.truth.Truth.assertThat import org.junit.Assert.assertThrows import org.junit.Test @SmallTest class DisableFlagsLoggerTest : SysuiTestCase() { private val disable1Flags = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'B', 'b'), DisableFlagsLogger.DisableFlag(0b001, 'C', 'c'), ) private val disable2Flags = listOf( DisableFlagsLogger.DisableFlag(0b10, 'M', 'm'), DisableFlagsLogger.DisableFlag(0b01, 'N', 'n'), ) private val disableFlagsLogger = DisableFlagsLogger(disable1Flags, disable2Flags) @Test fun getDisableFlagsString_oldAndNewSame_statesLoggedButDiffsNotLogged() { val state = DisableFlagsLogger.DisableState( 0b111, // ABC 0b01 // mN ) val result = disableFlagsLogger.getDisableFlagsString(state, state) assertThat(result).contains("Old: ABC.mN") assertThat(result).contains("New: ABC.mN") assertThat(result).doesNotContain("(") assertThat(result).doesNotContain(")") } @Test fun getDisableFlagsString_oldAndNewDifferent_statesAndDiffLogged() { val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState( 0b111, // ABC 0b01, // mN ), DisableFlagsLogger.DisableState( 0b001, // abC 0b10 // Mn ) ) assertThat(result).contains("Old: ABC.mN") assertThat(result).contains("New: abC.Mn") assertThat(result).contains("(ab.Mn)") } @Test fun getDisableFlagsString_onlyDisable2Different_diffLoggedCorrectly() { val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState( 0b001, // abC 0b01, // mN ), DisableFlagsLogger.DisableState( 0b001, // abC 0b00 // mn ) ) assertThat(result).contains("(.n)") } @Test fun getDisableFlagsString_nullLocalModification_localModNotLogged() { val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState(0, 0), DisableFlagsLogger.DisableState(1, 1), newAfterLocalModification = null ) assertThat(result).doesNotContain("local modification") } @Test fun getDisableFlagsString_newAfterLocalModificationSameAsNew_localModNotLogged() { val newState = DisableFlagsLogger.DisableState( 0b001, // abC 0b10 // mn ) val result = disableFlagsLogger.getDisableFlagsString( DisableFlagsLogger.DisableState(0, 0), newState, newState ) assertThat(result).doesNotContain("local modification") } @Test fun getDisableFlagsString_newAfterLocalModificationDifferent_localModAndDiffLogged() { val result = disableFlagsLogger.getDisableFlagsString( old = DisableFlagsLogger.DisableState(0, 0), new = DisableFlagsLogger.DisableState( 0b000, // abc 0b00 // mn ), newAfterLocalModification = DisableFlagsLogger.DisableState( 0b100, // Abc 0b10 // Mn ) ) assertThat(result).contains("local modification: Abc.Mn (A.M)") } @Test fun constructor_defaultDisableFlags_noException() { // Just creating the logger with the default params will trigger the exception if there // is one. DisableFlagsLogger() } @Test fun constructor_disable1_FlagIsSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'A', 'b'), ), listOf() ) } } @Test fun constructor_disable1_FlagNotSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'B', 'a'), ), listOf() ) } } @Test fun constructor_disable2_FlagIsSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf(), disable2FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'A', 'b'), ), ) } } @Test fun constructor_disable2_FlagNotSetSymbolNotUnique_exception() { assertThrows(IllegalArgumentException::class.java) { DisableFlagsLogger( disable1FlagsList = listOf(), disable2FlagsList = listOf( DisableFlagsLogger.DisableFlag(0b100, 'A', 'a'), DisableFlagsLogger.DisableFlag(0b010, 'B', 'a'), ), ) } } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacksTest.java +2 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.assist.AssistManager; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.DisableFlagsLogger; import com.android.systemui.statusbar.StatusBarStateControllerImpl; import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; Loading Loading @@ -112,6 +113,7 @@ public class StatusBarCommandQueueCallbacksTest extends SysuiTestCase { mVibratorHelper, Optional.of(mVibrator), mLightBarController, new DisableFlagsLogger(), DEFAULT_DISPLAY); when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true); Loading