diff options
4 files changed, 228 insertions, 0 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadePositionRepositoryTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadePositionRepositoryTest.kt new file mode 100644 index 000000000000..a9a5cac6112e --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/data/repository/ShadePositionRepositoryTest.kt @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2023 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.shade.data.repository + +import android.view.Display +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.kosmos.testScope +import com.android.systemui.statusbar.commandline.commandRegistry +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import java.io.PrintWriter +import java.io.StringWriter +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class ShadePositionRepositoryTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val commandRegistry = kosmos.commandRegistry + private val pw = PrintWriter(StringWriter()) + + private val underTest = ShadePositionRepositoryImpl(commandRegistry) + + @Before + fun setUp() { + underTest.start() + } + + @Test + fun commandDisplayOverride_updatesDisplayId() = + testScope.runTest { + val displayId by collectLastValue(underTest.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 { + val displayId by collectLastValue(underTest.displayId) + assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY) + + val newDisplayId = 2 + commandRegistry.onShellCommand( + pw, + arrayOf("shade_display_override", newDisplayId.toString()), + ) + assertThat(displayId).isEqualTo(newDisplayId) + + commandRegistry.onShellCommand(pw, arrayOf("shade_display_override", "reset")) + assertThat(displayId).isEqualTo(Display.DEFAULT_DISPLAY) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt index 42d4effbac3a..63510b873951 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt @@ -20,6 +20,7 @@ import android.content.Context import android.content.res.Resources import android.view.LayoutInflater import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY +import com.android.systemui.CoreStartable import com.android.systemui.common.ui.ConfigurationState import com.android.systemui.common.ui.ConfigurationStateImpl import com.android.systemui.common.ui.GlobalConfig @@ -29,12 +30,16 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractorImpl import com.android.systemui.dagger.SysUISingleton import com.android.systemui.res.R +import com.android.systemui.shade.data.repository.ShadePositionRepository +import com.android.systemui.shade.data.repository.ShadePositionRepositoryImpl import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround import com.android.systemui.statusbar.phone.ConfigurationControllerImpl import com.android.systemui.statusbar.phone.ConfigurationForwarder import com.android.systemui.statusbar.policy.ConfigurationController import dagger.Module import dagger.Provides +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap /** * Module responsible for managing display-specific components and resources for the notification @@ -149,4 +154,25 @@ object ShadeDisplayAwareModule { configurationInteractor } } + + @SysUISingleton + @Provides + @ShadeDisplayAware + fun provideShadePositionRepository(impl: ShadePositionRepositoryImpl): ShadePositionRepository { + ShadeWindowGoesAround.isUnexpectedlyInLegacyMode() + return impl + } + + @Provides + @IntoMap + @ClassKey(ShadePositionRepositoryImpl::class) + fun provideShadePositionRepositoryAsCoreStartable( + impl: ShadePositionRepositoryImpl + ): CoreStartable { + return if (ShadeWindowGoesAround.isEnabled) { + impl + } else { + CoreStartable.NOP + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadePrimaryDisplayCommand.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadePrimaryDisplayCommand.kt new file mode 100644 index 000000000000..802fc0edb533 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadePrimaryDisplayCommand.kt @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2024 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.shade + +import android.view.Display +import com.android.systemui.shade.data.repository.ShadePositionRepository +import com.android.systemui.statusbar.commandline.Command +import java.io.PrintWriter + +class ShadePrimaryDisplayCommand(private val positionRepository: ShadePositionRepository) : + Command { + + override fun execute(pw: PrintWriter, args: List<String>) { + if (args[0].lowercase() == "reset") { + positionRepository.resetDisplayId() + pw.println("Reset shade primary display id to ${Display.DEFAULT_DISPLAY}") + return + } + + val displayId: Int = + try { + args[0].toInt() + } catch (e: NumberFormatException) { + pw.println("Error: task id should be an integer") + return + } + + if (displayId < 0) { + pw.println("Error: display id should be positive integer") + } + + positionRepository.setDisplayId(displayId) + pw.println("New shade primary display id is $displayId") + } + + override fun help(pw: PrintWriter) { + pw.println("shade_display_override <displayId> ") + pw.println("Set the display which is holding the shade.") + pw.println("shade_display_override reset ") + pw.println("Reset the display which is holding the shade.") + } +} diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadePositionRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadePositionRepository.kt new file mode 100644 index 000000000000..24c067ae2371 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadePositionRepository.kt @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 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.shade.data.repository + +import android.view.Display +import com.android.systemui.CoreStartable +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.shade.ShadePrimaryDisplayCommand +import com.android.systemui.statusbar.commandline.CommandRegistry +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +interface ShadePositionRepository { + /** ID of the display which currently hosts the shade */ + val displayId: StateFlow<Int> + + /** + * Updates the value of the shade display id stored, emitting to the new display id to every + * component dependent on the shade display id + */ + fun setDisplayId(displayId: Int) + + /** Resets value of shade primary display to the default display */ + fun resetDisplayId() +} + +/** Source of truth for the display currently holding the shade. */ +@SysUISingleton +class ShadePositionRepositoryImpl +@Inject +constructor(private val commandRegistry: CommandRegistry) : ShadePositionRepository, CoreStartable { + private val _displayId = MutableStateFlow(Display.DEFAULT_DISPLAY) + + override val displayId: StateFlow<Int> + get() = _displayId + + override fun setDisplayId(displayId: Int) { + _displayId.value = displayId + } + + override fun resetDisplayId() { + _displayId.value = Display.DEFAULT_DISPLAY + } + + override fun start() { + commandRegistry.registerCommand("shade_display_override") { + ShadePrimaryDisplayCommand(this) + } + } +} |