Loading packages/SettingsLib/res/values/arrays.xml +3 −3 Original line number Diff line number Diff line Loading @@ -683,9 +683,9 @@ <!-- Values for showing shade on external display for developers --> <string-array name="shade_display_awareness_values" > <item>device-display</item> <item>external-display</item> <item>focus-based</item> <item>default_display</item> <item>any_external_display</item> <item>status_bar_latest_touch</item> </string-array> </resources> packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryTest.kt +51 −30 Original line number Diff line number Diff line Loading @@ -16,17 +16,20 @@ package com.android.systemui.shade.data.repository import android.provider.Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.display.data.repository.displayRepository import com.android.systemui.kosmos.testScope import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.shade.display.SpecificDisplayIdPolicy import com.android.systemui.shade.display.AnyExternalShadeDisplayPolicy import com.android.systemui.shade.display.DefaultDisplayShadePolicy import com.android.systemui.shade.display.StatusBarTouchShadeDisplayPolicy import com.android.systemui.testKosmos import com.android.systemui.util.settings.fakeGlobalSettings import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith Loading @@ -36,54 +39,72 @@ import org.junit.runner.RunWith class ShadeDisplaysRepositoryTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val defaultPolicy = SpecificDisplayIdPolicy(0) private val shadeDisplaysRepository = ShadeDisplaysRepositoryImpl(defaultPolicy, testScope.backgroundScope) private val globalSettings = kosmos.fakeGlobalSettings private val displayRepository = kosmos.displayRepository private val defaultPolicy = DefaultDisplayShadePolicy() private val policies = kosmos.shadeDisplayPolicies private val underTest = ShadeDisplaysRepositoryImpl( globalSettings, defaultPolicy, testScope.backgroundScope, policies, ) @Test fun policy_changing_propagatedFromTheLatestPolicy() = testScope.runTest { val displayIds by collectValues(shadeDisplaysRepository.displayId) val policy1 = MutablePolicy() val policy2 = MutablePolicy() val displayIds by collectValues(underTest.displayId) assertThat(displayIds).containsExactly(0) shadeDisplaysRepository.policy.value = policy1 globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "any_external_display") policy1.sendDisplayId(1) displayRepository.addDisplay(displayId = 1) assertThat(displayIds).containsExactly(0, 1) policy1.sendDisplayId(2) displayRepository.addDisplay(displayId = 2) assertThat(displayIds).containsExactly(0, 1, 2) assertThat(displayIds).containsExactly(0, 1) shadeDisplaysRepository.policy.value = policy2 displayRepository.removeDisplay(displayId = 1) assertThat(displayIds).containsExactly(0, 1, 2, 0) assertThat(displayIds).containsExactly(0, 1, 2) policy1.sendDisplayId(4) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "default_display") // Changes to the first policy don't affect the output now assertThat(displayIds).containsExactly(0, 1, 2, 0) } @Test fun policy_updatesBasedOnSettingValue_defaultDisplay() = testScope.runTest { val policy by collectLastValue(underTest.policy) policy2.sendDisplayId(5) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "default_display") assertThat(displayIds).containsExactly(0, 1, 2, 0, 5) assertThat(policy).isInstanceOf(DefaultDisplayShadePolicy::class.java) } private class MutablePolicy : ShadeDisplayPolicy { fun sendDisplayId(id: Int) { _displayId.value = id @Test fun policy_updatesBasedOnSettingValue_anyExternal() = testScope.runTest { val policy by collectLastValue(underTest.policy) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "any_external_display") assertThat(policy).isInstanceOf(AnyExternalShadeDisplayPolicy::class.java) } private val _displayId = MutableStateFlow(0) override val name: String get() = "mutable_policy" @Test fun policy_updatesBasedOnSettingValue_focusBased() = testScope.runTest { val policy by collectLastValue(underTest.policy) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "status_bar_latest_touch") override val displayId: StateFlow<Int> get() = _displayId assertThat(policy).isInstanceOf(StatusBarTouchShadeDisplayPolicy::class.java) } } packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadePrimaryDisplayCommandTest.kt +14 −24 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.systemui.shade.ShadePrimaryDisplayCommand import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.statusbar.commandline.commandRegistry import com.android.systemui.testKosmos import com.android.systemui.util.settings.fakeGlobalSettings import com.google.common.truth.StringSubject import com.google.common.truth.Truth.assertThat import java.io.PrintWriter Loading @@ -44,18 +45,17 @@ import org.junit.runner.RunWith class ShadePrimaryDisplayCommandTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val globalSettings = kosmos.fakeGlobalSettings private val commandRegistry = kosmos.commandRegistry private val displayRepository = kosmos.displayRepository private val defaultPolicy = kosmos.defaultShadeDisplayPolicy private val policy1 = makePolicy("policy_1") private val shadeDisplaysRepository = kosmos.shadeDisplaysRepository private val policies = kosmos.shadeDisplayPolicies private val pw = PrintWriter(StringWriter()) private val policies = setOf(defaultPolicy, policy1, makePolicy("policy_2"), makePolicy("policy_3")) private val underTest = ShadePrimaryDisplayCommand( globalSettings, commandRegistry, displayRepository, shadeDisplaysRepository, Loading @@ -68,21 +68,6 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { underTest.start() } @Test fun commandDisplayOverride_updatesDisplayId() = testScope.runTest { val displayId by collectLastValue(shadeDisplaysRepository.displayId) assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY) val newDisplayId = 2 commandRegistry.onShellCommand( pw, arrayOf("shade_display_override", newDisplayId.toString()), ) assertThat(displayId).isEqualTo(newDisplayId) } @Test fun commandShadeDisplayOverride_resetsDisplayId() = testScope.runTest { Loading @@ -90,9 +75,10 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY) val newDisplayId = 2 displayRepository.addDisplay(displayId = newDisplayId) commandRegistry.onShellCommand( pw, arrayOf("shade_display_override", newDisplayId.toString()), arrayOf("shade_display_override", "any_external_display"), ) assertThat(displayId).isEqualTo(newDisplayId) Loading @@ -108,7 +94,10 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { val newDisplayId = 2 displayRepository.addDisplay(displayId = newDisplayId) commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", "any_external")) commandRegistry.onShellCommand( pw, arrayOf("shade_display_override", "any_external_display"), ) assertThat(displayId).isEqualTo(newDisplayId) } Loading @@ -127,13 +116,14 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { } @Test fun policies_setsSpecificPolicy() = fun policies_setsNewPolicy() = testScope.runTest { val policy by collectLastValue(shadeDisplaysRepository.policy) val newPolicy = policies.last().name commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", policy1.name)) commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", newPolicy)) assertThat(policy!!.name).isEqualTo(policy1.name) assertThat(policy!!.name).isEqualTo(newPolicy) } private fun makePolicy(policyName: String): ShadeDisplayPolicy { Loading packages/SystemUI/src/com/android/systemui/shade/ShadePrimaryDisplayCommand.kt +10 −42 Original line number Diff line number Diff line Loading @@ -16,23 +16,23 @@ package com.android.systemui.shade import android.view.Display import android.provider.Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.shade.data.repository.MutableShadeDisplaysRepository import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.shade.display.SpecificDisplayIdPolicy import com.android.systemui.statusbar.commandline.Command import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.util.settings.GlobalSettings import java.io.PrintWriter import javax.inject.Inject import kotlin.text.toIntOrNull @SysUISingleton class ShadePrimaryDisplayCommand @Inject constructor( private val globalSettings: GlobalSettings, private val commandRegistry: CommandRegistry, private val displaysRepository: DisplayRepository, private val positionRepository: MutableShadeDisplaysRepository, Loading @@ -45,7 +45,7 @@ constructor( } override fun help(pw: PrintWriter) { pw.println("shade_display_override (<displayId>|<policyName>) ") pw.println("shade_display_override <policyName> ") pw.println("Set the display which is holding the shade, or the policy that defines it.") pw.println() pw.println("shade_display_override policies") Loading @@ -56,9 +56,6 @@ constructor( pw.println() pw.println("shade_display_override (list|status) ") pw.println("Lists available displays and which has the shade") pw.println() pw.println("shade_display_override any_external") pw.println("Moves the shade to the first not-default display available") } override fun execute(pw: PrintWriter, args: List<String>) { Loading @@ -74,28 +71,24 @@ constructor( fun execute() { when (val command = args.getOrNull(0)?.lowercase()) { "reset" -> reset() "policies" -> printPolicies() "list", "status" -> printStatus() "policies" -> printPolicies() "any_external" -> anyExternal() null -> help(pw) else -> parsePolicy(command) } } private fun parsePolicy(policyIdentifier: String) { val displayId = policyIdentifier.toIntOrNull() when { displayId != null -> changeDisplay(displayId = displayId) policies.any { it.name == policyIdentifier } -> { positionRepository.policy.value = policies.first { it.name == policyIdentifier } } else -> help(pw) if (policies.any { it.name == policyIdentifier }) { globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, policyIdentifier) } else { help(pw) } } private fun reset() { positionRepository.policy.value = defaultPolicy globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, defaultPolicy.name) pw.println("Reset shade display policy to default policy: ${defaultPolicy.name}") } Loading @@ -117,30 +110,5 @@ constructor( pw.println(if (currentPolicyName == it.name) " (Current policy)" else "") } } private fun anyExternal() { val anyExternalDisplay = displaysRepository.displays.value.firstOrNull { it.displayId != Display.DEFAULT_DISPLAY } if (anyExternalDisplay == null) { pw.println("No external displays available.") return } setDisplay(anyExternalDisplay.displayId) } private fun changeDisplay(displayId: Int) { if (displayId < 0) { pw.println("Error: display id should be positive integer") } setDisplay(displayId) } private fun setDisplay(id: Int) { positionRepository.policy.value = SpecificDisplayIdPolicy(id) pw.println("New shade primary display id is $id") } } } packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt +28 −5 Original line number Diff line number Diff line Loading @@ -16,17 +16,22 @@ package com.android.systemui.shade.data.repository import android.provider.Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS import android.view.Display import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn /** Source of truth for the display currently holding the shade. */ Loading @@ -38,7 +43,7 @@ interface ShadeDisplaysRepository { /** Allows to change the policy that determines in which display the Shade window is visible. */ interface MutableShadeDisplaysRepository : ShadeDisplaysRepository { /** Updates the policy to select where the shade is visible. */ val policy: MutableStateFlow<ShadeDisplayPolicy> val policy: StateFlow<ShadeDisplayPolicy> } /** Keeps the policy and propagates the display id for the shade from it. */ Loading @@ -46,9 +51,27 @@ interface MutableShadeDisplaysRepository : ShadeDisplaysRepository { @OptIn(ExperimentalCoroutinesApi::class) class ShadeDisplaysRepositoryImpl @Inject constructor(defaultPolicy: ShadeDisplayPolicy, @Background bgScope: CoroutineScope) : MutableShadeDisplaysRepository { override val policy = MutableStateFlow<ShadeDisplayPolicy>(defaultPolicy) constructor( globalSettings: GlobalSettings, defaultPolicy: ShadeDisplayPolicy, @Background bgScope: CoroutineScope, policies: Set<@JvmSuppressWildcards ShadeDisplayPolicy>, ) : MutableShadeDisplaysRepository { override val policy: StateFlow<ShadeDisplayPolicy> = globalSettings .observerFlow(DEVELOPMENT_SHADE_DISPLAY_AWARENESS) .onStart { emit(Unit) } .map { val current = globalSettings.getString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS) for (policy in policies) { if (policy.name == current) return@map policy } globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, defaultPolicy.name) return@map defaultPolicy } .distinctUntilChanged() .stateIn(bgScope, SharingStarted.WhileSubscribed(), defaultPolicy) override val displayId: StateFlow<Int> = policy Loading Loading
packages/SettingsLib/res/values/arrays.xml +3 −3 Original line number Diff line number Diff line Loading @@ -683,9 +683,9 @@ <!-- Values for showing shade on external display for developers --> <string-array name="shade_display_awareness_values" > <item>device-display</item> <item>external-display</item> <item>focus-based</item> <item>default_display</item> <item>any_external_display</item> <item>status_bar_latest_touch</item> </string-array> </resources>
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepositoryTest.kt +51 −30 Original line number Diff line number Diff line Loading @@ -16,17 +16,20 @@ package com.android.systemui.shade.data.repository import android.provider.Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.display.data.repository.displayRepository import com.android.systemui.kosmos.testScope import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.shade.display.SpecificDisplayIdPolicy import com.android.systemui.shade.display.AnyExternalShadeDisplayPolicy import com.android.systemui.shade.display.DefaultDisplayShadePolicy import com.android.systemui.shade.display.StatusBarTouchShadeDisplayPolicy import com.android.systemui.testKosmos import com.android.systemui.util.settings.fakeGlobalSettings import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith Loading @@ -36,54 +39,72 @@ import org.junit.runner.RunWith class ShadeDisplaysRepositoryTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope private val defaultPolicy = SpecificDisplayIdPolicy(0) private val shadeDisplaysRepository = ShadeDisplaysRepositoryImpl(defaultPolicy, testScope.backgroundScope) private val globalSettings = kosmos.fakeGlobalSettings private val displayRepository = kosmos.displayRepository private val defaultPolicy = DefaultDisplayShadePolicy() private val policies = kosmos.shadeDisplayPolicies private val underTest = ShadeDisplaysRepositoryImpl( globalSettings, defaultPolicy, testScope.backgroundScope, policies, ) @Test fun policy_changing_propagatedFromTheLatestPolicy() = testScope.runTest { val displayIds by collectValues(shadeDisplaysRepository.displayId) val policy1 = MutablePolicy() val policy2 = MutablePolicy() val displayIds by collectValues(underTest.displayId) assertThat(displayIds).containsExactly(0) shadeDisplaysRepository.policy.value = policy1 globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "any_external_display") policy1.sendDisplayId(1) displayRepository.addDisplay(displayId = 1) assertThat(displayIds).containsExactly(0, 1) policy1.sendDisplayId(2) displayRepository.addDisplay(displayId = 2) assertThat(displayIds).containsExactly(0, 1, 2) assertThat(displayIds).containsExactly(0, 1) shadeDisplaysRepository.policy.value = policy2 displayRepository.removeDisplay(displayId = 1) assertThat(displayIds).containsExactly(0, 1, 2, 0) assertThat(displayIds).containsExactly(0, 1, 2) policy1.sendDisplayId(4) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "default_display") // Changes to the first policy don't affect the output now assertThat(displayIds).containsExactly(0, 1, 2, 0) } @Test fun policy_updatesBasedOnSettingValue_defaultDisplay() = testScope.runTest { val policy by collectLastValue(underTest.policy) policy2.sendDisplayId(5) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "default_display") assertThat(displayIds).containsExactly(0, 1, 2, 0, 5) assertThat(policy).isInstanceOf(DefaultDisplayShadePolicy::class.java) } private class MutablePolicy : ShadeDisplayPolicy { fun sendDisplayId(id: Int) { _displayId.value = id @Test fun policy_updatesBasedOnSettingValue_anyExternal() = testScope.runTest { val policy by collectLastValue(underTest.policy) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "any_external_display") assertThat(policy).isInstanceOf(AnyExternalShadeDisplayPolicy::class.java) } private val _displayId = MutableStateFlow(0) override val name: String get() = "mutable_policy" @Test fun policy_updatesBasedOnSettingValue_focusBased() = testScope.runTest { val policy by collectLastValue(underTest.policy) globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, "status_bar_latest_touch") override val displayId: StateFlow<Int> get() = _displayId assertThat(policy).isInstanceOf(StatusBarTouchShadeDisplayPolicy::class.java) } }
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadePrimaryDisplayCommandTest.kt +14 −24 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import com.android.systemui.shade.ShadePrimaryDisplayCommand import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.statusbar.commandline.commandRegistry import com.android.systemui.testKosmos import com.android.systemui.util.settings.fakeGlobalSettings import com.google.common.truth.StringSubject import com.google.common.truth.Truth.assertThat import java.io.PrintWriter Loading @@ -44,18 +45,17 @@ import org.junit.runner.RunWith class ShadePrimaryDisplayCommandTest : SysuiTestCase() { private val kosmos = testKosmos().useUnconfinedTestDispatcher() private val testScope = kosmos.testScope private val globalSettings = kosmos.fakeGlobalSettings private val commandRegistry = kosmos.commandRegistry private val displayRepository = kosmos.displayRepository private val defaultPolicy = kosmos.defaultShadeDisplayPolicy private val policy1 = makePolicy("policy_1") private val shadeDisplaysRepository = kosmos.shadeDisplaysRepository private val policies = kosmos.shadeDisplayPolicies private val pw = PrintWriter(StringWriter()) private val policies = setOf(defaultPolicy, policy1, makePolicy("policy_2"), makePolicy("policy_3")) private val underTest = ShadePrimaryDisplayCommand( globalSettings, commandRegistry, displayRepository, shadeDisplaysRepository, Loading @@ -68,21 +68,6 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { underTest.start() } @Test fun commandDisplayOverride_updatesDisplayId() = testScope.runTest { val displayId by collectLastValue(shadeDisplaysRepository.displayId) assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY) val newDisplayId = 2 commandRegistry.onShellCommand( pw, arrayOf("shade_display_override", newDisplayId.toString()), ) assertThat(displayId).isEqualTo(newDisplayId) } @Test fun commandShadeDisplayOverride_resetsDisplayId() = testScope.runTest { Loading @@ -90,9 +75,10 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY) val newDisplayId = 2 displayRepository.addDisplay(displayId = newDisplayId) commandRegistry.onShellCommand( pw, arrayOf("shade_display_override", newDisplayId.toString()), arrayOf("shade_display_override", "any_external_display"), ) assertThat(displayId).isEqualTo(newDisplayId) Loading @@ -108,7 +94,10 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { val newDisplayId = 2 displayRepository.addDisplay(displayId = newDisplayId) commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", "any_external")) commandRegistry.onShellCommand( pw, arrayOf("shade_display_override", "any_external_display"), ) assertThat(displayId).isEqualTo(newDisplayId) } Loading @@ -127,13 +116,14 @@ class ShadePrimaryDisplayCommandTest : SysuiTestCase() { } @Test fun policies_setsSpecificPolicy() = fun policies_setsNewPolicy() = testScope.runTest { val policy by collectLastValue(shadeDisplaysRepository.policy) val newPolicy = policies.last().name commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", policy1.name)) commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", newPolicy)) assertThat(policy!!.name).isEqualTo(policy1.name) assertThat(policy!!.name).isEqualTo(newPolicy) } private fun makePolicy(policyName: String): ShadeDisplayPolicy { Loading
packages/SystemUI/src/com/android/systemui/shade/ShadePrimaryDisplayCommand.kt +10 −42 Original line number Diff line number Diff line Loading @@ -16,23 +16,23 @@ package com.android.systemui.shade import android.view.Display import android.provider.Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.shade.data.repository.MutableShadeDisplaysRepository import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.shade.display.SpecificDisplayIdPolicy import com.android.systemui.statusbar.commandline.Command import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.util.settings.GlobalSettings import java.io.PrintWriter import javax.inject.Inject import kotlin.text.toIntOrNull @SysUISingleton class ShadePrimaryDisplayCommand @Inject constructor( private val globalSettings: GlobalSettings, private val commandRegistry: CommandRegistry, private val displaysRepository: DisplayRepository, private val positionRepository: MutableShadeDisplaysRepository, Loading @@ -45,7 +45,7 @@ constructor( } override fun help(pw: PrintWriter) { pw.println("shade_display_override (<displayId>|<policyName>) ") pw.println("shade_display_override <policyName> ") pw.println("Set the display which is holding the shade, or the policy that defines it.") pw.println() pw.println("shade_display_override policies") Loading @@ -56,9 +56,6 @@ constructor( pw.println() pw.println("shade_display_override (list|status) ") pw.println("Lists available displays and which has the shade") pw.println() pw.println("shade_display_override any_external") pw.println("Moves the shade to the first not-default display available") } override fun execute(pw: PrintWriter, args: List<String>) { Loading @@ -74,28 +71,24 @@ constructor( fun execute() { when (val command = args.getOrNull(0)?.lowercase()) { "reset" -> reset() "policies" -> printPolicies() "list", "status" -> printStatus() "policies" -> printPolicies() "any_external" -> anyExternal() null -> help(pw) else -> parsePolicy(command) } } private fun parsePolicy(policyIdentifier: String) { val displayId = policyIdentifier.toIntOrNull() when { displayId != null -> changeDisplay(displayId = displayId) policies.any { it.name == policyIdentifier } -> { positionRepository.policy.value = policies.first { it.name == policyIdentifier } } else -> help(pw) if (policies.any { it.name == policyIdentifier }) { globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, policyIdentifier) } else { help(pw) } } private fun reset() { positionRepository.policy.value = defaultPolicy globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, defaultPolicy.name) pw.println("Reset shade display policy to default policy: ${defaultPolicy.name}") } Loading @@ -117,30 +110,5 @@ constructor( pw.println(if (currentPolicyName == it.name) " (Current policy)" else "") } } private fun anyExternal() { val anyExternalDisplay = displaysRepository.displays.value.firstOrNull { it.displayId != Display.DEFAULT_DISPLAY } if (anyExternalDisplay == null) { pw.println("No external displays available.") return } setDisplay(anyExternalDisplay.displayId) } private fun changeDisplay(displayId: Int) { if (displayId < 0) { pw.println("Error: display id should be positive integer") } setDisplay(displayId) } private fun setDisplay(id: Int) { positionRepository.policy.value = SpecificDisplayIdPolicy(id) pw.println("New shade primary display id is $id") } } }
packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeDisplaysRepository.kt +28 −5 Original line number Diff line number Diff line Loading @@ -16,17 +16,22 @@ package com.android.systemui.shade.data.repository import android.provider.Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS import android.view.Display import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.shade.display.ShadeDisplayPolicy import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn /** Source of truth for the display currently holding the shade. */ Loading @@ -38,7 +43,7 @@ interface ShadeDisplaysRepository { /** Allows to change the policy that determines in which display the Shade window is visible. */ interface MutableShadeDisplaysRepository : ShadeDisplaysRepository { /** Updates the policy to select where the shade is visible. */ val policy: MutableStateFlow<ShadeDisplayPolicy> val policy: StateFlow<ShadeDisplayPolicy> } /** Keeps the policy and propagates the display id for the shade from it. */ Loading @@ -46,9 +51,27 @@ interface MutableShadeDisplaysRepository : ShadeDisplaysRepository { @OptIn(ExperimentalCoroutinesApi::class) class ShadeDisplaysRepositoryImpl @Inject constructor(defaultPolicy: ShadeDisplayPolicy, @Background bgScope: CoroutineScope) : MutableShadeDisplaysRepository { override val policy = MutableStateFlow<ShadeDisplayPolicy>(defaultPolicy) constructor( globalSettings: GlobalSettings, defaultPolicy: ShadeDisplayPolicy, @Background bgScope: CoroutineScope, policies: Set<@JvmSuppressWildcards ShadeDisplayPolicy>, ) : MutableShadeDisplaysRepository { override val policy: StateFlow<ShadeDisplayPolicy> = globalSettings .observerFlow(DEVELOPMENT_SHADE_DISPLAY_AWARENESS) .onStart { emit(Unit) } .map { val current = globalSettings.getString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS) for (policy in policies) { if (policy.name == current) return@map policy } globalSettings.putString(DEVELOPMENT_SHADE_DISPLAY_AWARENESS, defaultPolicy.name) return@map defaultPolicy } .distinctUntilChanged() .stateIn(bgScope, SharingStarted.WhileSubscribed(), defaultPolicy) override val displayId: StateFlow<Int> = policy Loading