Add test artifact to support testing
Add test artifact to support testing.
Add EmptyWindowLayoutInfoRule to always produce an empty set of features
Relnote: Add test artifact for WindowManager Jetpack Library.
Bug: 184266682
Test: ./gradlew window:window-test:cAT
Change-Id: I57f66ad83498ff5e09d0a1d1c9cda0554c2c04e1
diff --git a/docs-tip-of-tree/build.gradle b/docs-tip-of-tree/build.gradle
index 1ffc337..e4a46cc 100644
--- a/docs-tip-of-tree/build.gradle
+++ b/docs-tip-of-tree/build.gradle
@@ -279,6 +279,7 @@
docs(project(":window:window-rxjava3"))
stubs(project(":window:window-sidecar"))
stubs(project(":window:window-extensions"))
+ docs(project(":window:window-testing"))
docs(project(":work:work-gcm"))
docs(project(":work:work-multiprocess"))
docs(project(":work:work-runtime"))
diff --git a/settings.gradle b/settings.gradle
index ba10801..ee9269e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -622,6 +622,7 @@
includeProject(":window:window-rxjava3", "window/window-rxjava3", [BuildType.MAIN])
includeProject(":window:window-samples", "window/window-samples", [BuildType.MAIN])
includeProject(":window:window-sidecar", "window/window-sidecar", [BuildType.MAIN])
+includeProject(":window:window-testing", "window/window-testing", [BuildType.MAIN])
includeProject(":work:integration-tests:testapp", "work/integration-tests/testapp", [BuildType.MAIN])
includeProject(":work:work-benchmark", "work/workmanager-benchmark", [BuildType.MAIN])
includeProject(":work:work-gcm", "work/workmanager-gcm", [BuildType.MAIN])
diff --git a/window/window-java/api/current.txt b/window/window-java/api/current.txt
index c041785..b4bdb38 100644
--- a/window/window-java/api/current.txt
+++ b/window/window-java/api/current.txt
@@ -4,10 +4,10 @@
public final class WindowInfoRepoJavaAdapter implements androidx.window.WindowInfoRepo {
ctor public WindowInfoRepoJavaAdapter(androidx.window.WindowInfoRepo repo);
method public void addWindowLayoutInfoListener(java.util.concurrent.Executor executor, androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> consumer);
- method public androidx.window.WindowMetrics currentWindowMetrics();
- method public androidx.window.WindowMetrics maximumWindowMetrics();
+ method public androidx.window.WindowMetrics getCurrentWindowMetrics();
+ method public androidx.window.WindowMetrics getMaximumWindowMetrics();
+ method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> getWindowLayoutInfo();
method public void removeWindowLayoutInfoListener(androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> consumer);
- method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
}
}
diff --git a/window/window-java/api/public_plus_experimental_current.txt b/window/window-java/api/public_plus_experimental_current.txt
index c041785..b4bdb38 100644
--- a/window/window-java/api/public_plus_experimental_current.txt
+++ b/window/window-java/api/public_plus_experimental_current.txt
@@ -4,10 +4,10 @@
public final class WindowInfoRepoJavaAdapter implements androidx.window.WindowInfoRepo {
ctor public WindowInfoRepoJavaAdapter(androidx.window.WindowInfoRepo repo);
method public void addWindowLayoutInfoListener(java.util.concurrent.Executor executor, androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> consumer);
- method public androidx.window.WindowMetrics currentWindowMetrics();
- method public androidx.window.WindowMetrics maximumWindowMetrics();
+ method public androidx.window.WindowMetrics getCurrentWindowMetrics();
+ method public androidx.window.WindowMetrics getMaximumWindowMetrics();
+ method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> getWindowLayoutInfo();
method public void removeWindowLayoutInfoListener(androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> consumer);
- method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
}
}
diff --git a/window/window-java/api/restricted_current.txt b/window/window-java/api/restricted_current.txt
index c041785..b4bdb38 100644
--- a/window/window-java/api/restricted_current.txt
+++ b/window/window-java/api/restricted_current.txt
@@ -4,10 +4,10 @@
public final class WindowInfoRepoJavaAdapter implements androidx.window.WindowInfoRepo {
ctor public WindowInfoRepoJavaAdapter(androidx.window.WindowInfoRepo repo);
method public void addWindowLayoutInfoListener(java.util.concurrent.Executor executor, androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> consumer);
- method public androidx.window.WindowMetrics currentWindowMetrics();
- method public androidx.window.WindowMetrics maximumWindowMetrics();
+ method public androidx.window.WindowMetrics getCurrentWindowMetrics();
+ method public androidx.window.WindowMetrics getMaximumWindowMetrics();
+ method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> getWindowLayoutInfo();
method public void removeWindowLayoutInfoListener(androidx.core.util.Consumer<androidx.window.WindowLayoutInfo> consumer);
- method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
}
}
diff --git a/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt b/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt
index 46041e5..688df0e 100644
--- a/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt
+++ b/window/window-java/src/androidTest/java/androidx/window/java/WindowInfoRepoJavaAdapterTest.kt
@@ -42,10 +42,10 @@
public fun testCurrentWindowMetrics_delegatesToRepo() {
val expected = WindowMetrics(Rect(0, 1, 2, 3))
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.currentWindowMetrics()).thenReturn(expected)
+ whenever(mockRepo.currentWindowMetrics).thenReturn(expected)
val unitUnderTest = WindowInfoRepoJavaAdapter(mockRepo)
- val acutal = unitUnderTest.currentWindowMetrics()
+ val acutal = unitUnderTest.currentWindowMetrics
assertEquals(expected, acutal)
}
@@ -54,10 +54,10 @@
public fun testMaximumWindowMetrics_delegatesToRepo() {
val expected = WindowMetrics(Rect(0, 1, 2, 3))
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.maximumWindowMetrics()).thenReturn(expected)
+ whenever(mockRepo.maximumWindowMetrics).thenReturn(expected)
val unitUnderTest = WindowInfoRepoJavaAdapter(mockRepo)
- val acutal = unitUnderTest.maximumWindowMetrics()
+ val acutal = unitUnderTest.maximumWindowMetrics
assertEquals(expected, acutal)
}
@@ -71,7 +71,7 @@
)
val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(flowOf(expected))
+ whenever(mockRepo.windowLayoutInfo).thenReturn(flowOf(expected))
val unitUnderTest = WindowInfoRepoJavaAdapter(mockRepo)
val testConsumer = TestConsumer<WindowLayoutInfo>()
@@ -89,7 +89,7 @@
)
val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(flowOf(expected))
+ whenever(mockRepo.windowLayoutInfo).thenReturn(flowOf(expected))
val unitUnderTest = WindowInfoRepoJavaAdapter(mockRepo)
val testConsumer = TestConsumer<WindowLayoutInfo>()
@@ -110,7 +110,7 @@
val info = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
val channel = Channel<WindowLayoutInfo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(channel.receiveAsFlow())
+ whenever(mockRepo.windowLayoutInfo).thenReturn(channel.receiveAsFlow())
val unitUnderTest = WindowInfoRepoJavaAdapter(mockRepo)
val testConsumer = TestConsumer<WindowLayoutInfo>()
diff --git a/window/window-java/src/main/java/androidx/window/java/WindowInfoRepoJavaAdapter.kt b/window/window-java/src/main/java/androidx/window/java/WindowInfoRepoJavaAdapter.kt
index 561d759..80b3c1d 100644
--- a/window/window-java/src/main/java/androidx/window/java/WindowInfoRepoJavaAdapter.kt
+++ b/window/window-java/src/main/java/androidx/window/java/WindowInfoRepoJavaAdapter.kt
@@ -42,7 +42,7 @@
/**
* Register a listener to consume [WindowLayoutInfo] values. If the same consumer is
* registered twice then this method is a no-op.
- * @see WindowInfoRepo.windowLayoutInfo
+ * @see WindowInfoRepo.getWindowLayoutInfo
*/
public fun addWindowLayoutInfoListener(
executor: Executor,
@@ -52,7 +52,7 @@
if (consumerToJobMap[consumer] == null) {
val scope = CoroutineScope(executor.asCoroutineDispatcher())
consumerToJobMap[consumer] = scope.launch {
- repo.windowLayoutInfo().collect(consumer::accept)
+ repo.windowLayoutInfo.collect(consumer::accept)
}
}
}
@@ -61,7 +61,7 @@
/**
* Remove a listener to stop consuming [WindowLayoutInfo] values. If the listener has already
* been removed then this is a no-op.
- * @see WindowInfoRepo.windowLayoutInfo
+ * @see WindowInfoRepo.getWindowLayoutInfo
*/
public fun removeWindowLayoutInfoListener(consumer: Consumer<WindowLayoutInfo>) {
lock.withLock {
diff --git a/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/WindowInfoRepoRxTest.kt b/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/WindowInfoRepoRxTest.kt
index 5ca2325..214ca23 100644
--- a/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/WindowInfoRepoRxTest.kt
+++ b/window/window-rxjava2/src/androidTest/java/androidx/window/rxjava2/WindowInfoRepoRxTest.kt
@@ -41,7 +41,7 @@
)
val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(flowOf(expected))
+ whenever(mockRepo.windowLayoutInfo).thenReturn(flowOf(expected))
val testSubscriber = mockRepo.windowLayoutInfoObservable().test()
@@ -58,7 +58,7 @@
)
val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(flowOf(expected))
+ whenever(mockRepo.windowLayoutInfo).thenReturn(flowOf(expected))
val testSubscriber = mockRepo.windowLayoutInfoFlowable().test()
diff --git a/window/window-rxjava2/src/main/java/androidx/window/rxjava2/WindowInfoRepoRx.kt b/window/window-rxjava2/src/main/java/androidx/window/rxjava2/WindowInfoRepoRx.kt
index 5ee31b8..940cf75 100644
--- a/window/window-rxjava2/src/main/java/androidx/window/rxjava2/WindowInfoRepoRx.kt
+++ b/window/window-rxjava2/src/main/java/androidx/window/rxjava2/WindowInfoRepoRx.kt
@@ -27,18 +27,18 @@
/**
* Return an [Observable] stream of [WindowLayoutInfo].
- * @see WindowInfoRepo.windowLayoutInfo
+ * @see WindowInfoRepo.getWindowLayoutInfo
*/
@ExperimentalCoroutinesApi
public fun WindowInfoRepo.windowLayoutInfoObservable(): Observable<WindowLayoutInfo> {
- return windowLayoutInfo().asObservable()
+ return windowLayoutInfo.asObservable()
}
/**
* Return a [Flowable] stream of [WindowLayoutInfo].
- * @see WindowInfoRepo.windowLayoutInfo
+ * @see WindowInfoRepo.getWindowLayoutInfo
*/
@ExperimentalCoroutinesApi
public fun WindowInfoRepo.windowLayoutInfoFlowable(): Flowable<WindowLayoutInfo> {
- return windowLayoutInfo().asFlowable()
+ return windowLayoutInfo.asFlowable()
}
\ No newline at end of file
diff --git a/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/WindowInfoRepoRxTest.kt b/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/WindowInfoRepoRxTest.kt
index 8ca7e0b..b02f00d 100644
--- a/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/WindowInfoRepoRxTest.kt
+++ b/window/window-rxjava3/src/androidTest/java/androidx/window/rxjava3/WindowInfoRepoRxTest.kt
@@ -43,7 +43,7 @@
)
val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(flowOf(expected))
+ whenever(mockRepo.windowLayoutInfo).thenReturn(flowOf(expected))
val testSubscriber = mockRepo.windowLayoutInfoObservable().test()
@@ -60,7 +60,7 @@
)
val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build()
val mockRepo = mock<WindowInfoRepo>()
- whenever(mockRepo.windowLayoutInfo()).thenReturn(flowOf(expected))
+ whenever(mockRepo.windowLayoutInfo).thenReturn(flowOf(expected))
val testSubscriber = mockRepo.windowLayoutInfoFlowable().test()
diff --git a/window/window-rxjava3/src/main/java/androidx/window/rxjava3/WindowInfoRepoRx.kt b/window/window-rxjava3/src/main/java/androidx/window/rxjava3/WindowInfoRepoRx.kt
index 26cacef..d9ef9e6 100644
--- a/window/window-rxjava3/src/main/java/androidx/window/rxjava3/WindowInfoRepoRx.kt
+++ b/window/window-rxjava3/src/main/java/androidx/window/rxjava3/WindowInfoRepoRx.kt
@@ -27,18 +27,18 @@
/**
* Return an [Observable] stream of [WindowLayoutInfo].
- * @see WindowInfoRepo.windowLayoutInfo
+ * @see WindowInfoRepo.getWindowLayoutInfo
*/
@ExperimentalCoroutinesApi
public fun WindowInfoRepo.windowLayoutInfoObservable(): Observable<WindowLayoutInfo> {
- return windowLayoutInfo().asObservable()
+ return windowLayoutInfo.asObservable()
}
/**
* Return a [Flowable] stream of [WindowLayoutInfo].
- * @see WindowInfoRepo.windowLayoutInfo
+ * @see WindowInfoRepo.getWindowLayoutInfo
*/
@ExperimentalCoroutinesApi
public fun WindowInfoRepo.windowLayoutInfoFlowable(): Flowable<WindowLayoutInfo> {
- return windowLayoutInfo().asFlowable()
+ return windowLayoutInfo.asFlowable()
}
diff --git a/window/window-testing/api/current.txt b/window/window-testing/api/current.txt
new file mode 100644
index 0000000..e0d15ce
--- /dev/null
+++ b/window/window-testing/api/current.txt
@@ -0,0 +1,11 @@
+// Signature format: 4.0
+package androidx.window.test {
+
+ public final class WindowLayoutInfoPublisherRule implements org.junit.rules.TestRule {
+ ctor public WindowLayoutInfoPublisherRule();
+ method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+ method public void overrideWindowLayoutInfo(androidx.window.WindowLayoutInfo info);
+ }
+
+}
+
diff --git a/window/window-testing/api/public_plus_experimental_current.txt b/window/window-testing/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..f00e796
--- /dev/null
+++ b/window/window-testing/api/public_plus_experimental_current.txt
@@ -0,0 +1,11 @@
+// Signature format: 4.0
+package androidx.window.test {
+
+ public final class WindowLayoutInfoPublisherRule implements org.junit.rules.TestRule {
+ ctor public WindowLayoutInfoPublisherRule();
+ method @kotlinx.coroutines.ExperimentalCoroutinesApi public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+ method public void overrideWindowLayoutInfo(androidx.window.WindowLayoutInfo info);
+ }
+
+}
+
diff --git a/window/window-testing/api/res-current.txt b/window/window-testing/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/window/window-testing/api/res-current.txt
diff --git a/window/window-testing/api/restricted_current.txt b/window/window-testing/api/restricted_current.txt
new file mode 100644
index 0000000..e0d15ce
--- /dev/null
+++ b/window/window-testing/api/restricted_current.txt
@@ -0,0 +1,11 @@
+// Signature format: 4.0
+package androidx.window.test {
+
+ public final class WindowLayoutInfoPublisherRule implements org.junit.rules.TestRule {
+ ctor public WindowLayoutInfoPublisherRule();
+ method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
+ method public void overrideWindowLayoutInfo(androidx.window.WindowLayoutInfo info);
+ }
+
+}
+
diff --git a/window/window-testing/build.gradle b/window/window-testing/build.gradle
new file mode 100644
index 0000000..5a706af
--- /dev/null
+++ b/window/window-testing/build.gradle
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+import static androidx.build.dependencies.DependenciesKt.*
+import androidx.build.LibraryGroups
+import androidx.build.LibraryType
+import androidx.build.LibraryVersions
+
+plugins {
+ id("AndroidXPlugin")
+ id("com.android.library")
+ id("org.jetbrains.kotlin.android")
+}
+
+android {
+ defaultConfig {
+ multiDexEnabled = true
+ }
+}
+
+dependencies {
+ api(KOTLIN_STDLIB)
+ api(project(":window:window"))
+ api(JUNIT)
+ implementation("androidx.core:core:1.3.2")
+
+ androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
+ androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(ANDROIDX_TEST_RULES)
+ androidTestImplementation(KOTLIN_COROUTINES_TEST)
+ androidTestImplementation(MULTIDEX)
+ androidTestImplementation(TRUTH)
+}
+
+androidx {
+ name = "WindowManager Test Library"
+ type = LibraryType.PUBLISHED_LIBRARY
+ mavenVersion = LibraryVersions.WINDOW
+ mavenGroup = LibraryGroups.WINDOW
+ inceptionYear = "2021"
+ description = "WindowManager Test Library"
+}
+
+// Allow usage of Kotlin's @OptIn.
+tasks.withType(KotlinCompile).configureEach {
+ kotlinOptions {
+ freeCompilerArgs += ["-Xopt-in=kotlin.RequiresOptIn"]
+ }
+}
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/AndroidManifest.xml b/window/window-testing/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..7d587da
--- /dev/null
+++ b/window/window-testing/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.window.test">
+ <application>
+ <activity android:name="TestActivity"/>
+ </application>
+</manifest>
diff --git a/window/window/src/main/java/androidx/window/WindowServices.kt b/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
similarity index 60%
rename from window/window/src/main/java/androidx/window/WindowServices.kt
rename to window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
index fd3881d..3d934fd 100644
--- a/window/window/src/main/java/androidx/window/WindowServices.kt
+++ b/window/window-testing/src/androidTest/java/androidx/window/test/TestActivity.kt
@@ -13,21 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@file:JvmName("WindowServices")
-package androidx.window
+package androidx.window.test
import android.app.Activity
-import kotlinx.coroutines.ExperimentalCoroutinesApi
/**
- * Provide an instance of [WindowInfoRepo] that is associated to the given [Activity]
+ * A test [Activity] for testing purposes.
*/
-@ExperimentalCoroutinesApi
-public fun Activity.windowInfoRepository(): WindowInfoRepo {
- return WindowInfoRepoImp(
- this,
- WindowBoundsHelper.instance,
- ExtensionWindowBackend.getInstance(this)
- )
-}
+public class TestActivity : Activity()
\ No newline at end of file
diff --git a/window/window-testing/src/androidTest/java/androidx/window/test/WindowLayoutInfoPublisherRuleTest.kt b/window/window-testing/src/androidTest/java/androidx/window/test/WindowLayoutInfoPublisherRuleTest.kt
new file mode 100644
index 0000000..a93682b
--- /dev/null
+++ b/window/window-testing/src/androidTest/java/androidx/window/test/WindowLayoutInfoPublisherRuleTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright 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 androidx.window.test
+
+import android.graphics.Rect
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.window.DisplayFeature
+import androidx.window.WindowLayoutInfo
+import androidx.window.windowInfoRepository
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.flow.toCollection
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.RuleChain
+import org.junit.rules.TestRule
+import org.junit.runner.RunWith
+
+@LargeTest
+@RunWith(AndroidJUnit4::class)
+public class WindowLayoutInfoPublisherRuleTest {
+
+ private val activityRule = ActivityScenarioRule(TestActivity::class.java)
+ private val publisherRule = WindowLayoutInfoPublisherRule()
+
+ @get:Rule
+ public val testRule: TestRule
+
+ init {
+ testRule = RuleChain.outerRule(publisherRule).around(activityRule)
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ public fun testWindowLayoutInfo_relayValue(): Unit = runBlockingTest {
+ val expected = WindowLayoutInfo.Builder().setDisplayFeatures(emptyList()).build()
+ activityRule.scenario.onActivity { activity ->
+ val value = async {
+ activity.windowInfoRepository().windowLayoutInfo.first()
+ }
+ publisherRule.overrideWindowLayoutInfo(expected)
+ runBlockingTest {
+ val actual = value.await()
+ assertEquals(expected, actual)
+ }
+ }
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ @Test
+ public fun testWindowLayoutInfo_multipleValues(): Unit = runBlockingTest {
+ val feature1 = object : DisplayFeature {
+ override val bounds: Rect
+ get() = Rect()
+ }
+ val feature2 = object : DisplayFeature {
+ override val bounds: Rect
+ get() = Rect()
+ }
+ val expected1 = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature1)).build()
+ val expected2 = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature2)).build()
+ activityRule.scenario.onActivity { activity ->
+ val values = mutableListOf<WindowLayoutInfo>()
+ val value = async {
+ activity.windowInfoRepository().windowLayoutInfo.take(4).toCollection(values)
+ }
+ publisherRule.overrideWindowLayoutInfo(expected1)
+ publisherRule.overrideWindowLayoutInfo(expected2)
+ publisherRule.overrideWindowLayoutInfo(expected1)
+ publisherRule.overrideWindowLayoutInfo(expected2)
+ runBlockingTest {
+ assertEquals(
+ listOf(expected1, expected2, expected1, expected2),
+ value.await().toList()
+ )
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/window/window-testing/src/main/AndroidManifest.xml b/window/window-testing/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4bd698f
--- /dev/null
+++ b/window/window-testing/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="androidx.window.test">
+</manifest>
\ No newline at end of file
diff --git a/window/window-testing/src/main/java/androidx/window/test/PublishLayoutInfoRepo.kt b/window/window-testing/src/main/java/androidx/window/test/PublishLayoutInfoRepo.kt
new file mode 100644
index 0000000..b3591df
--- /dev/null
+++ b/window/window-testing/src/main/java/androidx/window/test/PublishLayoutInfoRepo.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 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 androidx.window.test
+
+import androidx.window.WindowInfoRepo
+import androidx.window.WindowLayoutInfo
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+
+internal class PublishLayoutInfoRepo(
+ private val core: WindowInfoRepo,
+ private val flow: MutableSharedFlow<WindowLayoutInfo>
+) : WindowInfoRepo by core {
+ override val windowLayoutInfo: Flow<WindowLayoutInfo>
+ get() = flow
+}
\ No newline at end of file
diff --git a/window/window-testing/src/main/java/androidx/window/test/PublishWindowInfoRepoDecorator.kt b/window/window-testing/src/main/java/androidx/window/test/PublishWindowInfoRepoDecorator.kt
new file mode 100644
index 0000000..7cf34ba
--- /dev/null
+++ b/window/window-testing/src/main/java/androidx/window/test/PublishWindowInfoRepoDecorator.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright 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 androidx.window.test
+
+import androidx.window.WindowInfoRepo
+import androidx.window.WindowInfoRepoDecorator
+import androidx.window.WindowLayoutInfo
+import kotlinx.coroutines.flow.MutableSharedFlow
+
+internal class PublishWindowInfoRepoDecorator(
+ private val flow: MutableSharedFlow<WindowLayoutInfo>
+) : WindowInfoRepoDecorator {
+ override fun decorate(repo: WindowInfoRepo): WindowInfoRepo {
+ return PublishLayoutInfoRepo(repo, flow)
+ }
+}
\ No newline at end of file
diff --git a/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisher.kt b/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisher.kt
new file mode 100644
index 0000000..2261e68
--- /dev/null
+++ b/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisher.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright 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 androidx.window.test
+
+import androidx.window.WindowInfoRepo
+import androidx.window.WindowLayoutInfo
+import androidx.window.WindowMetrics
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.StateFlow
+
+internal class WindowLayoutInfoPublisher(
+ private val core: WindowInfoRepo,
+ private val flow: StateFlow<WindowLayoutInfo>
+) : WindowInfoRepo {
+
+ override val currentWindowMetrics: WindowMetrics
+ get() {
+ return core.currentWindowMetrics
+ }
+
+ override val maximumWindowMetrics: WindowMetrics
+ get() {
+ return core.maximumWindowMetrics
+ }
+
+ override val windowLayoutInfo: Flow<WindowLayoutInfo>
+ get() {
+ return flow
+ }
+}
\ No newline at end of file
diff --git a/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisherRule.kt b/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisherRule.kt
new file mode 100644
index 0000000..f9e92fc
--- /dev/null
+++ b/window/window-testing/src/main/java/androidx/window/test/WindowLayoutInfoPublisherRule.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 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 androidx.window.test
+
+import androidx.window.WindowInfoRepo
+import androidx.window.WindowLayoutInfo
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.BufferOverflow.DROP_OLDEST
+import kotlinx.coroutines.flow.MutableSharedFlow
+import org.junit.rules.TestRule
+import org.junit.runner.Description
+import org.junit.runners.model.Statement
+
+/**
+ * A [TestRule] to help test consuming a stream of [WindowLayoutInfo] values.
+ * [WindowLayoutInfoPublisherRule] allows you to push through different [WindowLayoutInfo] values
+ * on demand.
+ *
+ * Here are some recommended testing scenarios.
+ *
+ * To test the scenario where no [WindowLayoutInfo] is ever emitted. Just set the rule as a
+ * standard rule.
+ *
+ * To test sending a generic feature build your own [WindowLayoutInfo] and publish it through the
+ * method [WindowLayoutInfoPublisherRule.overrideWindowLayoutInfo].
+ *
+ * Some helper methods are provided to test the following scenarios.
+ * <ul>
+ * <li>A fold in the middle and the dimension matches the shortest window dimension.</li>
+ * <li>A fold in the middle and the dimension matches the longest window dimension.</li>
+ * <li>A fold in the middle and has vertical orientation.</li>
+ * <li>A fold in the middle and has horizontal orientation.</li>
+ * </ul>
+ */
+public class WindowLayoutInfoPublisherRule() : TestRule {
+
+ private val flow = MutableSharedFlow<WindowLayoutInfo>(
+ extraBufferCapacity = 1,
+ onBufferOverflow = DROP_OLDEST
+ )
+ private val overrideServices = PublishWindowInfoRepoDecorator(flow)
+
+ @ExperimentalCoroutinesApi
+ override fun apply(base: Statement, description: Description): Statement {
+ return object : Statement() {
+ override fun evaluate() {
+ WindowInfoRepo.overrideDecorator(overrideServices)
+ base.evaluate()
+ WindowInfoRepo.reset()
+ }
+ }
+ }
+
+ /**
+ * Send an arbitrary [WindowLayoutInfo] through
+ * [androidx.window.WindowInfoRepo.windowLayoutInfo]. Each event is sent only once.
+ */
+ public fun overrideWindowLayoutInfo(info: WindowLayoutInfo) {
+ flow.tryEmit(info)
+ }
+}
\ No newline at end of file
diff --git a/window/window/api/current.txt b/window/window/api/current.txt
index c82eaa4..d5386e1 100644
--- a/window/window/api/current.txt
+++ b/window/window/api/current.txt
@@ -41,9 +41,16 @@
}
public interface WindowInfoRepo {
- method public androidx.window.WindowMetrics currentWindowMetrics();
- method public androidx.window.WindowMetrics maximumWindowMetrics();
- method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
+ method public androidx.window.WindowMetrics getCurrentWindowMetrics();
+ method public androidx.window.WindowMetrics getMaximumWindowMetrics();
+ method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> getWindowLayoutInfo();
+ property public abstract androidx.window.WindowMetrics currentWindowMetrics;
+ property public abstract androidx.window.WindowMetrics maximumWindowMetrics;
+ property public abstract kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo;
+ field public static final androidx.window.WindowInfoRepo.Companion Companion;
+ }
+
+ public static final class WindowInfoRepo.Companion {
}
public final class WindowLayoutInfo {
@@ -72,8 +79,5 @@
property public final android.graphics.Rect bounds;
}
- public final class WindowServices {
- }
-
}
diff --git a/window/window/api/public_plus_experimental_current.txt b/window/window/api/public_plus_experimental_current.txt
index c6788d2..5ef6e22 100644
--- a/window/window/api/public_plus_experimental_current.txt
+++ b/window/window/api/public_plus_experimental_current.txt
@@ -2,6 +2,7 @@
package androidx.window {
public final class ActivityExtKt {
+ method @kotlinx.coroutines.ExperimentalCoroutinesApi public static androidx.window.WindowInfoRepo windowInfoRepository(android.app.Activity);
}
public interface DisplayFeature {
@@ -41,9 +42,26 @@
}
public interface WindowInfoRepo {
- method public androidx.window.WindowMetrics currentWindowMetrics();
- method public androidx.window.WindowMetrics maximumWindowMetrics();
- method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
+ method @kotlinx.coroutines.ExperimentalCoroutinesApi public default static androidx.window.WindowInfoRepo create(android.app.Activity activity);
+ method public androidx.window.WindowMetrics getCurrentWindowMetrics();
+ method public androidx.window.WindowMetrics getMaximumWindowMetrics();
+ method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> getWindowLayoutInfo();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public default static void overrideDecorator(androidx.window.WindowInfoRepoDecorator overridingDecorator);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public default static void reset();
+ property public abstract androidx.window.WindowMetrics currentWindowMetrics;
+ property public abstract androidx.window.WindowMetrics maximumWindowMetrics;
+ property public abstract kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo;
+ field public static final androidx.window.WindowInfoRepo.Companion Companion;
+ }
+
+ public static final class WindowInfoRepo.Companion {
+ method @kotlinx.coroutines.ExperimentalCoroutinesApi public androidx.window.WindowInfoRepo create(android.app.Activity activity);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void overrideDecorator(androidx.window.WindowInfoRepoDecorator overridingDecorator);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void reset();
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public interface WindowInfoRepoDecorator {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public androidx.window.WindowInfoRepo decorate(androidx.window.WindowInfoRepo repo);
}
public final class WindowLayoutInfo {
@@ -72,9 +90,5 @@
property public final android.graphics.Rect bounds;
}
- public final class WindowServices {
- method @kotlinx.coroutines.ExperimentalCoroutinesApi public static androidx.window.WindowInfoRepo windowInfoRepository(android.app.Activity);
- }
-
}
diff --git a/window/window/api/restricted_current.txt b/window/window/api/restricted_current.txt
index c82eaa4..0f592ee 100644
--- a/window/window/api/restricted_current.txt
+++ b/window/window/api/restricted_current.txt
@@ -41,9 +41,24 @@
}
public interface WindowInfoRepo {
- method public androidx.window.WindowMetrics currentWindowMetrics();
- method public androidx.window.WindowMetrics maximumWindowMetrics();
- method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo();
+ method public androidx.window.WindowMetrics getCurrentWindowMetrics();
+ method public androidx.window.WindowMetrics getMaximumWindowMetrics();
+ method public kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> getWindowLayoutInfo();
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public default static void overrideDecorator(androidx.window.WindowInfoRepoDecorator overridingDecorator);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public default static void reset();
+ property public abstract androidx.window.WindowMetrics currentWindowMetrics;
+ property public abstract androidx.window.WindowMetrics maximumWindowMetrics;
+ property public abstract kotlinx.coroutines.flow.Flow<androidx.window.WindowLayoutInfo> windowLayoutInfo;
+ field public static final androidx.window.WindowInfoRepo.Companion Companion;
+ }
+
+ public static final class WindowInfoRepo.Companion {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void overrideDecorator(androidx.window.WindowInfoRepoDecorator overridingDecorator);
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public void reset();
+ }
+
+ @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public interface WindowInfoRepoDecorator {
+ method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public androidx.window.WindowInfoRepo decorate(androidx.window.WindowInfoRepo repo);
}
public final class WindowLayoutInfo {
@@ -72,8 +87,5 @@
property public final android.graphics.Rect bounds;
}
- public final class WindowServices {
- }
-
}
diff --git a/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt b/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt
index 724e6e3..6310418 100644
--- a/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt
+++ b/window/window/src/androidTest/java/androidx/window/WindowInfoRepoImpTest.kt
@@ -49,7 +49,7 @@
)
val expectedBounds = windowBoundsHelper.computeCurrentWindowBounds(testActivity)
val expected = WindowMetrics(expectedBounds)
- val actual = repo.currentWindowMetrics()
+ val actual = repo.currentWindowMetrics
assertEquals(expected, actual)
}
}
@@ -65,7 +65,7 @@
)
val expectedBounds = windowBoundsHelper.computeMaximumWindowBounds(testActivity)
val expected = WindowMetrics(expectedBounds)
- val actual = repo.maximumWindowMetrics()
+ val actual = repo.maximumWindowMetrics
assertEquals(expected, actual)
}
}
@@ -82,7 +82,7 @@
)
val collector = TestConsumer<WindowLayoutInfo>()
testScope.launch {
- repo.windowLayoutInfo().collect(collector::accept)
+ repo.windowLayoutInfo.collect(collector::accept)
}
fakeBackend.triggerSignal(WindowLayoutInfo(emptyList()))
collector.assertValue(WindowLayoutInfo(emptyList()))
diff --git a/window/window/src/main/java/androidx/window/ActivityExt.kt b/window/window/src/main/java/androidx/window/ActivityExt.kt
index a5149ca..ab6fcf9 100644
--- a/window/window/src/main/java/androidx/window/ActivityExt.kt
+++ b/window/window/src/main/java/androidx/window/ActivityExt.kt
@@ -17,6 +17,8 @@
import android.app.Activity
import android.os.IBinder
+import android.os.Looper
+import kotlinx.coroutines.ExperimentalCoroutinesApi
/**
* A utility method [Activity] to return an optional [IBinder] window token from an [Activity].
@@ -24,3 +26,29 @@
internal fun getActivityWindowToken(activity: Activity?): IBinder? {
return activity?.window?.attributes?.token
}
+
+internal inline fun <reified T> Activity.getTag(id: Int): T? {
+ return window.decorView.getTag(id) as? T
+}
+
+/**
+ * Checks to see if an object of type [T] is associated with the tag [id]. If it is available
+ * then it is returned. Otherwise set an object crated using the [producer] and return that value.
+ * @return object associated with the tag.
+ */
+internal inline fun <reified T> Activity.getOrCreateTag(id: Int, producer: () -> T): T {
+ return (window.decorView.getTag(id) as? T) ?: run {
+ assert(Looper.getMainLooper() == Looper.myLooper())
+ val value = producer()
+ window.decorView.setTag(id, value)
+ value
+ }
+}
+
+/**
+ * Provide an instance of [WindowInfoRepo] that is associated to the given [Activity]
+ */
+@ExperimentalCoroutinesApi
+public fun Activity.windowInfoRepository(): WindowInfoRepo {
+ return WindowInfoRepo.create(this)
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/WindowBoundsHelper.kt b/window/window/src/main/java/androidx/window/WindowBoundsHelper.kt
index 6434d39..4a53719 100644
--- a/window/window/src/main/java/androidx/window/WindowBoundsHelper.kt
+++ b/window/window/src/main/java/androidx/window/WindowBoundsHelper.kt
@@ -27,6 +27,9 @@
import android.view.Display
import android.view.DisplayCutout
import androidx.annotation.RequiresApi
+import androidx.annotation.RestrictTo
+import androidx.annotation.RestrictTo.Scope.LIBRARY
+import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
import androidx.annotation.VisibleForTesting
import androidx.window.ActivityCompatHelperApi24.isInMultiWindowMode
import androidx.window.ActivityCompatHelperApi30.currentWindowBounds
@@ -83,7 +86,8 @@
* @see android.view.WindowManager.getCurrentWindowMetrics
* @see android.view.WindowMetrics.getBounds
*/
- open fun computeCurrentWindowBounds(activity: Activity): Rect {
+ @RestrictTo(LIBRARY)
+ public open fun computeCurrentWindowBounds(activity: Activity): Rect {
return if (Build.VERSION.SDK_INT >= VERSION_CODES.R) {
currentWindowBounds(activity)
} else if (Build.VERSION.SDK_INT >= VERSION_CODES.Q) {
@@ -108,7 +112,8 @@
*
* @see android.view.WindowManager.getMaximumWindowMetrics
*/
- open fun computeMaximumWindowBounds(activity: Activity): Rect {
+ @RestrictTo(LIBRARY_GROUP)
+ public open fun computeMaximumWindowBounds(activity: Activity): Rect {
return if (Build.VERSION.SDK_INT >= VERSION_CODES.R) {
maximumWindowBounds(activity)
} else {
@@ -121,7 +126,7 @@
}
}
- companion object {
+ internal companion object {
private const val TAG = "WindowBoundsHelper"
private val globalInstance = WindowBoundsHelper()
private var testInstance: WindowBoundsHelper? = null
diff --git a/window/window/src/main/java/androidx/window/WindowInfoRepo.kt b/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
index 053bdb3..7b3b623 100644
--- a/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
+++ b/window/window/src/main/java/androidx/window/WindowInfoRepo.kt
@@ -16,7 +16,11 @@
package androidx.window
+import android.app.Activity
import android.content.Context
+import androidx.annotation.RestrictTo
+import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
/**
@@ -41,7 +45,7 @@
* @see maximumWindowMetrics
* @see android.view.WindowManager.getCurrentWindowMetrics
*/
- public fun currentWindowMetrics(): WindowMetrics
+ public val currentWindowMetrics: WindowMetrics
/**
* Returns the largest [WindowMetrics] an app may expect in the current system state.
@@ -61,17 +65,63 @@
* areas of the display are not available to windows created for the associated [Context].
* For example, devices with foldable displays that wrap around the enclosure may split the
* physical display into different regions, one for the front and one for the back, each acting
- * as different logical displays. In this case [getMaximumWindowMetrics] would return
+ * as different logical displays. In this case [maximumWindowMetrics] would return
* the region describing the side of the device the associated [context's][Context]
* window is placed.
*
* @see currentWindowMetrics
* @see android.view.WindowManager.getMaximumWindowMetrics
*/
- public fun maximumWindowMetrics(): WindowMetrics
+ public val maximumWindowMetrics: WindowMetrics
/**
* A [Flow] of [WindowLayoutInfo] that contains all the available features.
*/
- public fun windowLayoutInfo(): Flow<WindowLayoutInfo>
+ public val windowLayoutInfo: Flow<WindowLayoutInfo>
+
+ public companion object {
+
+ private var decorator: WindowInfoRepoDecorator = EmptyDecorator
+
+ @JvmStatic
+ @ExperimentalCoroutinesApi
+ public fun create(activity: Activity): WindowInfoRepo {
+ val taggedRepo = activity.getTag(R.id.androidx_window_activity_scope) as? WindowInfoRepo
+ val repo = taggedRepo ?: activity.getOrCreateTag(R.id.androidx_window_activity_scope) {
+ WindowInfoRepoImp(
+ activity,
+ WindowBoundsHelper(),
+ ExtensionWindowBackend.getInstance(activity)
+ )
+ }
+ return decorator.decorate(repo)
+ }
+
+ @JvmStatic
+ @RestrictTo(LIBRARY_GROUP)
+ public fun overrideDecorator(overridingDecorator: WindowInfoRepoDecorator) {
+ decorator = overridingDecorator
+ }
+
+ @JvmStatic
+ @RestrictTo(LIBRARY_GROUP)
+ public fun reset() {
+ decorator = EmptyDecorator
+ }
+ }
}
+
+@RestrictTo(LIBRARY_GROUP)
+public interface WindowInfoRepoDecorator {
+ /**
+ * Returns an instance of [WindowInfoRepo] associated to the [Activity]
+ */
+ @RestrictTo(LIBRARY_GROUP)
+ public fun decorate(repo: WindowInfoRepo): WindowInfoRepo
+}
+
+private object EmptyDecorator : WindowInfoRepoDecorator {
+ override fun decorate(repo: WindowInfoRepo): WindowInfoRepo {
+ return repo
+ }
+}
\ No newline at end of file
diff --git a/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt b/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
index 817459f..f3f0105 100644
--- a/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
+++ b/window/window/src/main/java/androidx/window/WindowInfoRepoImp.kt
@@ -58,9 +58,10 @@
* @see maximumWindowMetrics
* @see android.view.WindowManager.getCurrentWindowMetrics
*/
- override fun currentWindowMetrics(): WindowMetrics {
- return WindowMetrics(windowBoundsHelper.computeCurrentWindowBounds(activity))
- }
+ override val currentWindowMetrics: WindowMetrics
+ get() {
+ return WindowMetrics(windowBoundsHelper.computeCurrentWindowBounds(activity))
+ }
/**
* Returns the largest [WindowMetrics] an app may expect in the current system state.
@@ -87,18 +88,20 @@
* @see currentWindowMetrics
* @see android.view.WindowManager.getMaximumWindowMetrics
*/
- override fun maximumWindowMetrics(): WindowMetrics {
- return WindowMetrics(windowBoundsHelper.computeMaximumWindowBounds(activity))
- }
+ override val maximumWindowMetrics: WindowMetrics
+ get() {
+ return WindowMetrics(windowBoundsHelper.computeMaximumWindowBounds(activity))
+ }
/**
* A [Flow] of window layout changes in the current visual [Context].
*
* @see Activity.onAttachedToWindow
*/
- override fun windowLayoutInfo(): Flow<WindowLayoutInfo> = callbackFlow {
- val callback = Consumer<WindowLayoutInfo> { info -> offer(info) }
- windowBackend.registerLayoutChangeCallback(activity, Runnable::run, callback)
- awaitClose { windowBackend.unregisterLayoutChangeCallback(callback) }
- }.buffer(capacity = UNLIMITED)
+ override val windowLayoutInfo: Flow<WindowLayoutInfo>
+ get() = callbackFlow {
+ val callback = Consumer<WindowLayoutInfo> { info -> offer(info) }
+ windowBackend.registerLayoutChangeCallback(activity, Runnable::run, callback)
+ awaitClose { windowBackend.unregisterLayoutChangeCallback(callback) }
+ }.buffer(capacity = UNLIMITED)
}
diff --git a/window/window/src/main/res/values/ids.xml b/window/window/src/main/res/values/ids.xml
new file mode 100644
index 0000000..c49bffa
--- /dev/null
+++ b/window/window/src/main/res/values/ids.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<resources>
+ <item name="androidx_window_activity_scope" type="id"/>
+</resources>
\ No newline at end of file