Loading packages/SystemUI/aconfig/systemui.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -475,6 +475,13 @@ flag { } } flag { name: "status_bar_always_use_region_sampling" namespace: "systemui" description: "Have the status bar *always* use region sampling to calculate icon contrast" bug: "365120736" } flag { name: "icon_refresh_2025" namespace: "systemui" Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt +38 −3 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import com.android.internal.view.AppearanceRegion import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.StatusBarAlwaysUseRegionSampling import com.android.systemui.statusbar.StatusBarRegionSampling import com.android.systemui.statusbar.core.StatusBarRootModernization import com.android.systemui.statusbar.data.model.StatusBarMode Loading Loading @@ -404,7 +405,8 @@ class StatusBarModeRepositoryImplTest : SysuiTestCase() { @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) fun statusBarAppearance_sampledAvailable_usesSampledAppearance() = @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun statusBarAppearance_a11ySamplingFlagOn_usesSampledAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) Loading @@ -419,8 +421,25 @@ class StatusBarModeRepositoryImplTest : SysuiTestCase() { } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) @DisableFlags(StatusBarRegionSampling.FLAG_NAME) fun statusBarAppearance_sampledAvailable_flagDisabled_usesDisplayPolicyProvidedAppearance() = fun statusBarAppearance_alwaysSamplingFlagOn_usesSampledAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) underTest.setSampledAppearanceRegions(SAMPLED_APPEARANCE_REGIONS) onSystemBarAttributesChanged( appearance = APPEARANCE, appearanceRegions = APPEARANCE_REGIONS.toTypedArray(), letterboxDetails = emptyArray(), ) assertThat(latest!!.appearanceRegions).isEqualTo(SAMPLED_APPEARANCE_REGIONS) } @Test @DisableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun statusBarAppearance_bothFlagsDisabled_sampledAvailable_usesDisplayPolicyProvidedAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) Loading @@ -436,7 +455,23 @@ class StatusBarModeRepositoryImplTest : SysuiTestCase() { @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) fun statusBarAppearance_sampledUnavailable_usesDisplayPolicyProvidedAppearance() = fun statusBarAppearance_a11yFlagEnabled_sampledUnavailable_usesDisplayPolicyProvidedAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) underTest.setSampledAppearanceRegions(listOf()) onSystemBarAttributesChanged( appearance = APPEARANCE, appearanceRegions = APPEARANCE_REGIONS.toTypedArray(), letterboxDetails = emptyArray(), ) assertThat(latest!!.appearanceRegions).isEqualTo(APPEARANCE_REGIONS) } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun statusBarAppearance_alwaysFlagEnabled_sampledUnavailable_usesDisplayPolicyProvidedAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/domain/interactor/StatusBarRegionSamplingInteractorTest.kt +63 −6 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.statusbar.StatusBarAlwaysUseRegionSampling import com.android.systemui.statusbar.StatusBarRegionSampling import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository import com.android.systemui.testKosmos Loading @@ -44,7 +45,8 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { private val Kosmos.underTest by Kosmos.Fixture { kosmos.statusBarRegionSamplingInteractor } @Test fun isRegionSamplingEnabled_forceInvertOff_returnsFalse() = @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_alwaysUseFlagOff_forceInvertOff_returnsFalse() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) Loading @@ -55,7 +57,8 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_flagEnabled_returnsTrue() = @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_onlyA11yFlagEnabled_returnsTrue() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) Loading @@ -65,8 +68,8 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { } @Test @DisableFlags(StatusBarRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_flagDisabled_returnsFalse() = @DisableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_bothFlagsDisabled_returnsFalse() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) Loading @@ -76,7 +79,29 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { } @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_alwaysUseFlagEnabled_forceInvertDark_returnsTrue() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) fakeForceInvertRepository.setForceInvertDark(true) assertThat(latest).isTrue() } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_alwaysUseFlagEnabled_forceInvertOff_returnsTrue() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) fakeForceInvertRepository.setForceInvertDark(false) assertThat(latest).isTrue() } @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_propagatesNonNullToStatusBarModeRepository() = kosmos.runTest { val firstRegion = AppearanceRegion(0, Rect()) Loading @@ -91,8 +116,40 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { } @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_onlyA11yFlagEnabled_propagates() = kosmos.runTest { val firstRegion = AppearanceRegion(0, Rect()) val secondRegion = null val thirdRegion = AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, Rect()) val appearanceRegions = listOf(firstRegion, secondRegion, thirdRegion) underTest.setSampledAppearanceRegions(Display.DEFAULT_DISPLAY, appearanceRegions) assertThat(fakeStatusBarModeRepository.defaultDisplay.fakeSampledAppearanceRegions) .containsExactly(firstRegion, thirdRegion) } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) @DisableFlags(StatusBarRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_flagDisabled_doesNothing() = fun setSampledAppearanceRegions_onlyAlwaysFlagEnabled_propagates() = kosmos.runTest { val firstRegion = AppearanceRegion(0, Rect()) val secondRegion = null val thirdRegion = AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, Rect()) val appearanceRegions = listOf(firstRegion, secondRegion, thirdRegion) underTest.setSampledAppearanceRegions(Display.DEFAULT_DISPLAY, appearanceRegions) assertThat(fakeStatusBarModeRepository.defaultDisplay.fakeSampledAppearanceRegions) .containsExactly(firstRegion, thirdRegion) } @Test @DisableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_bothFlagsDisabled_doesNothing() = kosmos.runTest { val region = AppearanceRegion(0, Rect()) Loading packages/SystemUI/src/com/android/systemui/statusbar/StatusBarAlwaysUseRegionSampling.kt 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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 com.android.systemui.Flags import com.android.systemui.flags.FlagToken /** * Helper for reading or using the status bar always use region sampling flag state. * * This flag enables region sampling for *all* users, regardless of accessibility settings. See * also: [StatusBarRegionSampling]. */ @Suppress("NOTHING_TO_INLINE") object StatusBarAlwaysUseRegionSampling { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_STATUS_BAR_ALWAYS_USE_REGION_SAMPLING /** A token used for dependency declaration */ val token: FlagToken get() = FlagToken(FLAG_NAME, isEnabled) /** Is the refactor enabled */ @JvmStatic inline val isEnabled get() = Flags.statusBarAlwaysUseRegionSampling() /** Returns true if any kind of region sampling is enabled. */ inline val isAnyRegionSamplingEnabled get() = isEnabled || StatusBarRegionSampling.isEnabled } packages/SystemUI/src/com/android/systemui/statusbar/StatusBarRegionSampling.kt +6 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,12 @@ import com.android.systemui.Flags import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the status bar region sampling flag state. */ /** * Helper for reading or using the status bar region sampling flag state. * * This flag enables region sampling if users have the force-dark-theme accessibility setting on. * See also: [StatusBarAlwaysUseRegionSampling]. */ @Suppress("NOTHING_TO_INLINE") object StatusBarRegionSampling { /** The aconfig flag name */ Loading Loading
packages/SystemUI/aconfig/systemui.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -475,6 +475,13 @@ flag { } } flag { name: "status_bar_always_use_region_sampling" namespace: "systemui" description: "Have the status bar *always* use region sampling to calculate icon contrast" bug: "365120736" } flag { name: "icon_refresh_2025" namespace: "systemui" Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt +38 −3 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import com.android.internal.view.AppearanceRegion import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.StatusBarAlwaysUseRegionSampling import com.android.systemui.statusbar.StatusBarRegionSampling import com.android.systemui.statusbar.core.StatusBarRootModernization import com.android.systemui.statusbar.data.model.StatusBarMode Loading Loading @@ -404,7 +405,8 @@ class StatusBarModeRepositoryImplTest : SysuiTestCase() { @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) fun statusBarAppearance_sampledAvailable_usesSampledAppearance() = @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun statusBarAppearance_a11ySamplingFlagOn_usesSampledAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) Loading @@ -419,8 +421,25 @@ class StatusBarModeRepositoryImplTest : SysuiTestCase() { } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) @DisableFlags(StatusBarRegionSampling.FLAG_NAME) fun statusBarAppearance_sampledAvailable_flagDisabled_usesDisplayPolicyProvidedAppearance() = fun statusBarAppearance_alwaysSamplingFlagOn_usesSampledAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) underTest.setSampledAppearanceRegions(SAMPLED_APPEARANCE_REGIONS) onSystemBarAttributesChanged( appearance = APPEARANCE, appearanceRegions = APPEARANCE_REGIONS.toTypedArray(), letterboxDetails = emptyArray(), ) assertThat(latest!!.appearanceRegions).isEqualTo(SAMPLED_APPEARANCE_REGIONS) } @Test @DisableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun statusBarAppearance_bothFlagsDisabled_sampledAvailable_usesDisplayPolicyProvidedAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) Loading @@ -436,7 +455,23 @@ class StatusBarModeRepositoryImplTest : SysuiTestCase() { @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) fun statusBarAppearance_sampledUnavailable_usesDisplayPolicyProvidedAppearance() = fun statusBarAppearance_a11yFlagEnabled_sampledUnavailable_usesDisplayPolicyProvidedAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) underTest.setSampledAppearanceRegions(listOf()) onSystemBarAttributesChanged( appearance = APPEARANCE, appearanceRegions = APPEARANCE_REGIONS.toTypedArray(), letterboxDetails = emptyArray(), ) assertThat(latest!!.appearanceRegions).isEqualTo(APPEARANCE_REGIONS) } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun statusBarAppearance_alwaysFlagEnabled_sampledUnavailable_usesDisplayPolicyProvidedAppearance() = testScope.runTest { val latest by collectLastValue(underTest.statusBarAppearance) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/domain/interactor/StatusBarRegionSamplingInteractorTest.kt +63 −6 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.statusbar.StatusBarAlwaysUseRegionSampling import com.android.systemui.statusbar.StatusBarRegionSampling import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository import com.android.systemui.testKosmos Loading @@ -44,7 +45,8 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { private val Kosmos.underTest by Kosmos.Fixture { kosmos.statusBarRegionSamplingInteractor } @Test fun isRegionSamplingEnabled_forceInvertOff_returnsFalse() = @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_alwaysUseFlagOff_forceInvertOff_returnsFalse() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) Loading @@ -55,7 +57,8 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_flagEnabled_returnsTrue() = @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_onlyA11yFlagEnabled_returnsTrue() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) Loading @@ -65,8 +68,8 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { } @Test @DisableFlags(StatusBarRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_flagDisabled_returnsFalse() = @DisableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_forceInvertDark_bothFlagsDisabled_returnsFalse() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) Loading @@ -76,7 +79,29 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { } @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_alwaysUseFlagEnabled_forceInvertDark_returnsTrue() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) fakeForceInvertRepository.setForceInvertDark(true) assertThat(latest).isTrue() } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun isRegionSamplingEnabled_alwaysUseFlagEnabled_forceInvertOff_returnsTrue() = kosmos.runTest { val latest by collectLastValue(underTest.isRegionSamplingEnabled) fakeForceInvertRepository.setForceInvertDark(false) assertThat(latest).isTrue() } @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_propagatesNonNullToStatusBarModeRepository() = kosmos.runTest { val firstRegion = AppearanceRegion(0, Rect()) Loading @@ -91,8 +116,40 @@ class StatusBarRegionSamplingInteractorTest : SysuiTestCase() { } @Test @EnableFlags(StatusBarRegionSampling.FLAG_NAME) @DisableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_onlyA11yFlagEnabled_propagates() = kosmos.runTest { val firstRegion = AppearanceRegion(0, Rect()) val secondRegion = null val thirdRegion = AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, Rect()) val appearanceRegions = listOf(firstRegion, secondRegion, thirdRegion) underTest.setSampledAppearanceRegions(Display.DEFAULT_DISPLAY, appearanceRegions) assertThat(fakeStatusBarModeRepository.defaultDisplay.fakeSampledAppearanceRegions) .containsExactly(firstRegion, thirdRegion) } @Test @EnableFlags(StatusBarAlwaysUseRegionSampling.FLAG_NAME) @DisableFlags(StatusBarRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_flagDisabled_doesNothing() = fun setSampledAppearanceRegions_onlyAlwaysFlagEnabled_propagates() = kosmos.runTest { val firstRegion = AppearanceRegion(0, Rect()) val secondRegion = null val thirdRegion = AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, Rect()) val appearanceRegions = listOf(firstRegion, secondRegion, thirdRegion) underTest.setSampledAppearanceRegions(Display.DEFAULT_DISPLAY, appearanceRegions) assertThat(fakeStatusBarModeRepository.defaultDisplay.fakeSampledAppearanceRegions) .containsExactly(firstRegion, thirdRegion) } @Test @DisableFlags(StatusBarRegionSampling.FLAG_NAME, StatusBarAlwaysUseRegionSampling.FLAG_NAME) fun setSampledAppearanceRegions_bothFlagsDisabled_doesNothing() = kosmos.runTest { val region = AppearanceRegion(0, Rect()) Loading
packages/SystemUI/src/com/android/systemui/statusbar/StatusBarAlwaysUseRegionSampling.kt 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 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 com.android.systemui.Flags import com.android.systemui.flags.FlagToken /** * Helper for reading or using the status bar always use region sampling flag state. * * This flag enables region sampling for *all* users, regardless of accessibility settings. See * also: [StatusBarRegionSampling]. */ @Suppress("NOTHING_TO_INLINE") object StatusBarAlwaysUseRegionSampling { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_STATUS_BAR_ALWAYS_USE_REGION_SAMPLING /** A token used for dependency declaration */ val token: FlagToken get() = FlagToken(FLAG_NAME, isEnabled) /** Is the refactor enabled */ @JvmStatic inline val isEnabled get() = Flags.statusBarAlwaysUseRegionSampling() /** Returns true if any kind of region sampling is enabled. */ inline val isAnyRegionSamplingEnabled get() = isEnabled || StatusBarRegionSampling.isEnabled }
packages/SystemUI/src/com/android/systemui/statusbar/StatusBarRegionSampling.kt +6 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,12 @@ import com.android.systemui.Flags import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the status bar region sampling flag state. */ /** * Helper for reading or using the status bar region sampling flag state. * * This flag enables region sampling if users have the force-dark-theme accessibility setting on. * See also: [StatusBarAlwaysUseRegionSampling]. */ @Suppress("NOTHING_TO_INLINE") object StatusBarRegionSampling { /** The aconfig flag name */ Loading