Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3eac9fde authored by Caitlin Cassidy's avatar Caitlin Cassidy Committed by Android (Google) Code Review
Browse files

Merge "[Disable Flags] Move disable flag logging to a helper class and use it...

Merge "[Disable Flags] Move disable flag logging to a helper class and use it for StatusBar." into sc-v2-dev
parents 959324fe 8798f2ee
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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 */
@@ -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
+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
+14 −37
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -134,6 +136,7 @@ public class StatusBarCommandQueueCallbacks implements CommandQueue.Callbacks {
            VibratorHelper vibratorHelper,
            Optional<Vibrator> vibratorOptional,
            LightBarController lightBarController,
            DisableFlagsLogger disableFlagsLogger,
            @DisplayId int displayId) {

        mStatusBar = statusBar;
@@ -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);
@@ -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;
@@ -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();
+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'),
                    ),
            )
        }
    }
}
+2 −0
Original line number Diff line number Diff line
@@ -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;
@@ -112,6 +113,7 @@ public class StatusBarCommandQueueCallbacksTest extends SysuiTestCase {
                mVibratorHelper,
                Optional.of(mVibrator),
                mLightBarController,
                new DisableFlagsLogger(),
                DEFAULT_DISPLAY);

        when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);