summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt37
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt13
5 files changed, 48 insertions, 67 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
index a8d5c31873de..e93d0effe742 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorTest.kt
@@ -16,32 +16,26 @@
package com.android.systemui.shade.domain.interactor
-import android.content.mockedContext
import android.content.res.Configuration
import android.content.res.mockResources
import android.view.Display
-import android.view.mockWindowManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.scene.ui.view.mockShadeRootView
import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
import com.android.systemui.testKosmos
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.advanceUntilIdle
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
-import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.whenever
-@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@SmallTest
class ShadeDisplaysInteractorTest : SysuiTestCase() {
@@ -49,9 +43,7 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() {
private val shadeRootview = kosmos.mockShadeRootView
private val positionRepository = kosmos.fakeShadeDisplaysRepository
- private val shadeContext = kosmos.mockedContext
- private val testScope = kosmos.testScope
- private val shadeWm = kosmos.mockWindowManager
+ private val shadeContext = kosmos.mockedWindowContext
private val resources = kosmos.mockResources
private val configuration = mock<Configuration>()
private val display = mock<Display>()
@@ -66,8 +58,8 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() {
whenever(resources.configuration).thenReturn(configuration)
whenever(shadeContext.displayId).thenReturn(0)
- whenever(shadeContext.getSystemService(any())).thenReturn(shadeWm)
whenever(shadeContext.resources).thenReturn(resources)
+ whenever(shadeContext.display).thenReturn(display)
}
@Test
@@ -77,7 +69,7 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() {
underTest.start()
- verifyNoMoreInteractions(shadeWm)
+ verify(shadeContext, never()).reparentToDisplay(any())
}
@Test
@@ -87,24 +79,6 @@ class ShadeDisplaysInteractorTest : SysuiTestCase() {
underTest.start()
- inOrder(shadeWm).apply {
- verify(shadeWm).removeView(eq(shadeRootview))
- verify(shadeWm).addView(eq(shadeRootview), any())
- }
- }
-
- @Test
- fun start_shadePositionChanges_removedThenAdded() {
- whenever(display.displayId).thenReturn(0)
- positionRepository.setDisplayId(0)
- underTest.start()
-
- positionRepository.setDisplayId(1)
- testScope.advanceUntilIdle()
-
- inOrder(shadeWm).apply {
- verify(shadeWm).removeView(eq(shadeRootview))
- verify(shadeWm).addView(eq(shadeRootview), any())
- }
+ verify(shadeContext).reparentToDisplay(eq(1))
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index f5fc1f414f82..bf672be3c8d0 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -166,6 +166,15 @@ public class NotificationShadeWindowView extends WindowRootView {
}
@Override
+ public void onMovedToDisplay(int displayId, Configuration config) {
+ super.onMovedToDisplay(displayId, config);
+ ShadeWindowGoesAround.isUnexpectedlyInLegacyMode();
+ // When the window is moved we're only receiving a call to this method instead of the
+ // onConfigurationChange itself. Let's just trigegr a normal config change.
+ onConfigurationChanged(config);
+ }
+
+ @Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (mConfigurationForwarder != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
index ff39a3ddc17c..a002aa53736a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAwareModule.kt
@@ -22,6 +22,7 @@ import android.view.LayoutInflater
import android.view.WindowManager
import android.view.WindowManager.LayoutParams
import android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE
+import android.window.WindowContext
import com.android.systemui.CoreStartable
import com.android.systemui.common.ui.ConfigurationState
import com.android.systemui.common.ui.ConfigurationStateImpl
@@ -81,6 +82,19 @@ object ShadeDisplayAwareModule {
@Provides
@ShadeDisplayAware
@SysUISingleton
+ fun provideShadeDisplayAwareWindowContext(@ShadeDisplayAware context: Context): WindowContext {
+ ShadeWindowGoesAround.isUnexpectedlyInLegacyMode()
+ // We rely on the fact context is a WindowContext as the API to reparent windows is only
+ // available there.
+ return (context as? WindowContext)
+ ?: error(
+ "ShadeDisplayAware context must be a window context to allow window reparenting."
+ )
+ }
+
+ @Provides
+ @ShadeDisplayAware
+ @SysUISingleton
fun provideShadeWindowLayoutParams(@ShadeDisplayAware context: Context): LayoutParams {
return ShadeWindowLayoutParams.create(context)
}
@@ -203,7 +217,9 @@ object ShadeDisplayAwareModule {
@Provides
@IntoMap
@ClassKey(ShadePrimaryDisplayCommand::class)
- fun provideShadePrimaryDisplayCommand(impl: Provider<ShadePrimaryDisplayCommand>): CoreStartable {
+ fun provideShadePrimaryDisplayCommand(
+ impl: Provider<ShadePrimaryDisplayCommand>
+ ): CoreStartable {
return if (ShadeWindowGoesAround.isEnabled) {
impl.get()
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
index 34148671cf2a..08c03e28d596 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractor.kt
@@ -16,10 +16,8 @@
package com.android.systemui.shade.domain.interactor
-import android.content.Context
import android.util.Log
-import android.view.WindowManager
-import android.view.WindowManager.LayoutParams
+import android.window.WindowContext
import androidx.annotation.UiThread
import com.android.app.tracing.coroutines.launchTraced
import com.android.app.tracing.traceSection
@@ -45,9 +43,7 @@ class ShadeDisplaysInteractor
constructor(
optionalShadeRootView: Optional<WindowRootView>,
private val shadePositionRepository: ShadeDisplaysRepository,
- @ShadeDisplayAware private val shadeContext: Context,
- @ShadeDisplayAware private val shadeLayoutParams: LayoutParams,
- @ShadeDisplayAware private val wm: WindowManager,
+ @ShadeDisplayAware private val shadeContext: WindowContext,
@Background private val bgScope: CoroutineScope,
@Main private val mainThreadContext: CoroutineContext,
) : CoreStartable {
@@ -72,7 +68,11 @@ constructor(
/** Tries to move the shade. If anything wrong happens, fails gracefully without crashing. */
private suspend fun moveShadeWindowTo(destinationId: Int) {
Log.d(TAG, "Trying to move shade window to display with id $destinationId")
- val currentDisplay = shadeRootView.display
+ // Why using the shade context here instead of the view's Display?
+ // The context's display is updated before the view one, so it is a better indicator of
+ // which display the shade is supposed to be at. The View display is updated after the first
+ // rendering with the new config.
+ val currentDisplay = shadeContext.display
if (currentDisplay == null) {
Log.w(TAG, "Current shade display is null")
return
@@ -83,7 +83,7 @@ constructor(
return
}
try {
- withContext(mainThreadContext) { moveShadeWindow(toId = destinationId) }
+ withContext(mainThreadContext) { reparentToDisplayId(id = destinationId) }
} catch (e: IllegalStateException) {
Log.e(
TAG,
@@ -94,25 +94,8 @@ constructor(
}
@UiThread
- private fun moveShadeWindow(toId: Int) {
- traceSection({ "moveShadeWindow to $toId" }) {
- removeShadeWindow()
- updateContextDisplay(toId)
- addShadeWindow()
- }
- }
-
- @UiThread
- private fun removeShadeWindow(): Unit =
- traceSection("removeShadeWindow") { wm.removeView(shadeRootView) }
-
- @UiThread
- private fun addShadeWindow(): Unit =
- traceSection("addShadeWindow") { wm.addView(shadeRootView, shadeLayoutParams) }
-
- @UiThread
- private fun updateContextDisplay(newDisplayId: Int) {
- traceSection("updateContextDisplay") { shadeContext.updateDisplay(newDisplayId) }
+ private fun reparentToDisplayId(id: Int) {
+ traceSection({ "reparentToDisplayId(id=$id)" }) { shadeContext.reparentToDisplay(id) }
}
private companion object {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
index db4df38e038a..f2af619a4ad7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeDisplaysInteractorKosmos.kt
@@ -17,25 +17,24 @@
package com.android.systemui.shade.domain.interactor
import android.content.mockedContext
-import android.view.mockWindowManager
+import android.window.WindowContext
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.ui.view.mockShadeRootView
import com.android.systemui.shade.ShadeWindowLayoutParams
import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
import java.util.Optional
+import org.mockito.kotlin.mock
-val Kosmos.shadeLayoutParams by Kosmos.Fixture {
- ShadeWindowLayoutParams.create(mockedContext)
-}
+val Kosmos.shadeLayoutParams by Kosmos.Fixture { ShadeWindowLayoutParams.create(mockedContext) }
+
+val Kosmos.mockedWindowContext by Kosmos.Fixture { mock<WindowContext>() }
val Kosmos.shadeDisplaysInteractor by
Kosmos.Fixture {
ShadeDisplaysInteractor(
Optional.of(mockShadeRootView),
fakeShadeDisplaysRepository,
- mockedContext,
- shadeLayoutParams,
- mockWindowManager,
+ mockedWindowContext,
testScope.backgroundScope,
testScope.backgroundScope.coroutineContext,
)