diff --git a/WindowManager/app/build.gradle b/WindowManager/app/build.gradle index 4d3028ee4..496ed2b00 100644 --- a/WindowManager/app/build.gradle +++ b/WindowManager/app/build.gradle @@ -51,12 +51,11 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" - implementation 'androidx.appcompat:appcompat:1.3.0' - implementation 'androidx.core:core-ktx:1.5.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.core:core-ktx:1.6.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.0' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03' - def window_version = '1.0.0-alpha09' implementation "androidx.window:window:$window_version" implementation "androidx.window:window-java:$window_version" diff --git a/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/DisplayFeaturesActivityTest.kt b/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/DisplayFeaturesActivityTest.kt index cccb5e38a..038090381 100644 --- a/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/DisplayFeaturesActivityTest.kt +++ b/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/DisplayFeaturesActivityTest.kt @@ -22,14 +22,14 @@ import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withSubstring import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.window.FoldingFeature.Orientation.Companion.HORIZONTAL -import androidx.window.FoldingFeature.Orientation.Companion.VERTICAL -import androidx.window.FoldingFeature.State.Companion.FLAT -import androidx.window.FoldingFeature.State.Companion.HALF_OPENED -import androidx.window.WindowLayoutInfo -import androidx.window.testing.FoldingFeature -import androidx.window.testing.WindowLayoutInfoPublisherRule -import androidx.window.windowInfoRepository +import androidx.window.layout.FoldingFeature.Orientation.Companion.HORIZONTAL +import androidx.window.layout.FoldingFeature.Orientation.Companion.VERTICAL +import androidx.window.layout.FoldingFeature.State.Companion.FLAT +import androidx.window.layout.FoldingFeature.State.Companion.HALF_OPENED +import androidx.window.layout.WindowInfoRepository.Companion.windowInfoRepository +import androidx.window.layout.WindowLayoutInfo +import androidx.window.testing.layout.FoldingFeature +import androidx.window.testing.layout.WindowLayoutInfoPublisherRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlinx.coroutines.flow.take diff --git a/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/SplitLayoutActivityTest.kt b/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/SplitLayoutActivityTest.kt index f56811030..ca92df4f4 100644 --- a/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/SplitLayoutActivityTest.kt +++ b/WindowManager/app/src/androidTest/java/com/example/windowmanagersample/SplitLayoutActivityTest.kt @@ -18,20 +18,24 @@ package com.example.windowmanagersample import android.graphics.Rect import androidx.test.espresso.Espresso.onView -import androidx.test.espresso.assertion.ViewAssertions.matches -import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +import androidx.test.espresso.assertion.PositionAssertions.isBottomAlignedWith +import androidx.test.espresso.assertion.PositionAssertions.isCompletelyAbove +import androidx.test.espresso.assertion.PositionAssertions.isCompletelyLeftOf +import androidx.test.espresso.assertion.PositionAssertions.isLeftAlignedWith +import androidx.test.espresso.assertion.PositionAssertions.isRightAlignedWith +import androidx.test.espresso.assertion.PositionAssertions.isTopAlignedWith import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.ext.junit.rules.ActivityScenarioRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.window.FoldingFeature -import androidx.window.FoldingFeature.State.Companion.HALF_OPENED -import androidx.window.FoldingFeature.Type.Companion.FOLD -import androidx.window.WindowLayoutInfo -import androidx.window.testing.WindowLayoutInfoPublisherRule -import androidx.window.windowInfoRepository +import androidx.window.layout.FoldingFeature +import androidx.window.layout.FoldingFeature.State.Companion.HALF_OPENED +import androidx.window.layout.FoldingFeature.Type.Companion.FOLD +import androidx.window.layout.WindowInfoRepository.Companion.windowInfoRepository +import androidx.window.layout.WindowLayoutInfo +import androidx.window.layout.WindowMetricsCalculator +import androidx.window.testing.layout.WindowLayoutInfoPublisherRule import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async -import kotlinx.coroutines.delay import kotlinx.coroutines.flow.take import kotlinx.coroutines.flow.toCollection import kotlinx.coroutines.test.TestCoroutineScope @@ -58,21 +62,50 @@ class SplitLayoutActivityTest { testRule = RuleChain.outerRule(publisherRule).around(activityRule) } + @Test + fun testDeviceOpen_Flat(): Unit = testScope.runBlockingTest { + activityRule.scenario.onActivity { activity -> + val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf()).build() + + val values = mutableListOf() + val value = testScope.async { + activity.windowInfoRepository().windowLayoutInfo.take(1).toCollection(values) + } + publisherRule.overrideWindowLayoutInfo(expected) + runBlockingTest { + val newValues = value.await().toList() + Assert.assertEquals( + listOf(expected), + newValues + ) + } + } + + // Checks that the two views are overlapped if there's no FoldingFeature. + onView(withId(R.id.start_layout)).check(isBottomAlignedWith(withId(R.id.end_layout))) + onView(withId(R.id.start_layout)).check(isTopAlignedWith(withId(R.id.end_layout))) + onView(withId(R.id.start_layout)).check(isLeftAlignedWith(withId(R.id.end_layout))) + onView(withId(R.id.start_layout)).check(isRightAlignedWith(withId(R.id.end_layout))) + } + @Test fun testDeviceOpen_Vertical(): Unit = testScope.runBlockingTest { activityRule.scenario.onActivity { activity -> - val bounds = activity.windowInfoRepository().currentWindowMetrics.bounds - val center = bounds.centerX() + val windowMetrics = + WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity) + val center = windowMetrics.bounds.centerX() val feature = FoldingFeature( - Rect(center, 0, center, bounds.height()), + Rect(center, 0, center, windowMetrics.bounds.height()), FOLD, HALF_OPENED ) - val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build() + val expected = + WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build() val values = mutableListOf() val value = testScope.async { - activity.windowInfoRepository().windowLayoutInfo.take(1).toCollection(values) + activity.windowInfoRepository().windowLayoutInfo.take(1) + .toCollection(values) } publisherRule.overrideWindowLayoutInfo(expected) runBlockingTest { @@ -81,28 +114,32 @@ class SplitLayoutActivityTest { listOf(expected), newValues ) - delay(5000) } } - onView(withId(R.id.start_layout)).check(matches(isDisplayed())) - onView(withId(R.id.end_layout)).check(matches(isDisplayed())) + + // Checks that start_layout is on the left of end_layout with a vertical folding feature. + // This requires to run the test on a big enough screen to fit both views on screen + onView(withId(R.id.start_layout)).check(isCompletelyLeftOf(withId(R.id.end_layout))) } @Test fun testDeviceOpen_Horizontal(): Unit = testScope.runBlockingTest { activityRule.scenario.onActivity { activity -> - val bounds = activity.windowInfoRepository().currentWindowMetrics.bounds - val center = bounds.centerY() + val windowMetrics = + WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity) + val center = windowMetrics.bounds.centerY() val feature = FoldingFeature( - Rect(0, center, bounds.height(), center), + Rect(0, center, windowMetrics.bounds.height(), center), FOLD, HALF_OPENED ) - val expected = WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build() + val expected = + WindowLayoutInfo.Builder().setDisplayFeatures(listOf(feature)).build() val values = mutableListOf() val value = testScope.async { - activity.windowInfoRepository().windowLayoutInfo.take(1).toCollection(values) + activity.windowInfoRepository().windowLayoutInfo.take(1) + .toCollection(values) } publisherRule.overrideWindowLayoutInfo(expected) runBlockingTest { @@ -111,10 +148,11 @@ class SplitLayoutActivityTest { listOf(expected), newValues ) - delay(5000) } } - onView(withId(R.id.start_layout)).check(matches(isDisplayed())) - onView(withId(R.id.end_layout)).check(matches(isDisplayed())) + + // Checks that start_layout is above of end_layout with a horizontal folding feature. + // This requires to run the test on a big enough screen to fit both views on screen + onView(withId(R.id.start_layout)).check(isCompletelyAbove(withId(R.id.end_layout))) } } diff --git a/WindowManager/app/src/main/java/com/example/windowmanagersample/DisplayFeaturesActivity.kt b/WindowManager/app/src/main/java/com/example/windowmanagersample/DisplayFeaturesActivity.kt index 63878ed17..96b468940 100644 --- a/WindowManager/app/src/main/java/com/example/windowmanagersample/DisplayFeaturesActivity.kt +++ b/WindowManager/app/src/main/java/com/example/windowmanagersample/DisplayFeaturesActivity.kt @@ -23,10 +23,10 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle -import androidx.window.FoldingFeature -import androidx.window.WindowInfoRepo -import androidx.window.WindowLayoutInfo -import androidx.window.windowInfoRepository +import androidx.window.layout.FoldingFeature +import androidx.window.layout.WindowInfoRepository +import androidx.window.layout.WindowInfoRepository.Companion.windowInfoRepository +import androidx.window.layout.WindowLayoutInfo import com.example.windowmanagersample.databinding.ActivityDisplayFeaturesBinding import java.text.SimpleDateFormat import java.util.Date @@ -44,7 +44,7 @@ class DisplayFeaturesActivity : AppCompatActivity() { private val displayFeatureViews = ArrayList() private lateinit var binding: ActivityDisplayFeaturesBinding - private lateinit var windowInfoRepo: WindowInfoRepo + private lateinit var windowInfoRepo: WindowInfoRepository @ExperimentalCoroutinesApi override fun onCreate(savedInstanceState: Bundle?) { diff --git a/WindowManager/app/src/main/java/com/example/windowmanagersample/SampleTools.kt b/WindowManager/app/src/main/java/com/example/windowmanagersample/SampleTools.kt index 248bb9e2a..70ec79f4a 100644 --- a/WindowManager/app/src/main/java/com/example/windowmanagersample/SampleTools.kt +++ b/WindowManager/app/src/main/java/com/example/windowmanagersample/SampleTools.kt @@ -19,7 +19,7 @@ package com.example.windowmanagersample import android.graphics.Rect import android.view.View import android.widget.FrameLayout -import androidx.window.DisplayFeature +import androidx.window.layout.DisplayFeature /** * Gets the bounds of the display feature translated to the View's coordinate space and current diff --git a/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayout.kt b/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayout.kt index 69fd1ec0a..2371c9a61 100644 --- a/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayout.kt +++ b/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayout.kt @@ -23,9 +23,9 @@ import android.view.View import android.view.View.MeasureSpec.AT_MOST import android.view.View.MeasureSpec.EXACTLY import android.widget.FrameLayout -import androidx.window.DisplayFeature -import androidx.window.FoldingFeature -import androidx.window.WindowLayoutInfo +import androidx.window.layout.DisplayFeature +import androidx.window.layout.FoldingFeature +import androidx.window.layout.WindowLayoutInfo /** * An example of split-layout for two views, separated by a display feature that goes across the diff --git a/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayoutActivity.java b/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayoutActivity.java index 738f27172..857ffcf94 100644 --- a/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayoutActivity.java +++ b/WindowManager/app/src/main/java/com/example/windowmanagersample/SplitLayoutActivity.java @@ -20,14 +20,14 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.core.util.Consumer; -import androidx.window.WindowInfoRepo; -import androidx.window.WindowLayoutInfo; -import androidx.window.java.WindowInfoRepoJavaAdapter; +import androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter; +import androidx.window.layout.WindowInfoRepository; +import androidx.window.layout.WindowLayoutInfo; import com.example.windowmanagersample.databinding.ActivitySplitLayoutBinding; public class SplitLayoutActivity extends AppCompatActivity { - private WindowInfoRepoJavaAdapter windowInfoRepo; + private WindowInfoRepositoryCallbackAdapter windowInfoRepository; private ActivitySplitLayoutBinding binding; private final LayoutStateChangeCallback layoutStateChangeCallback = new LayoutStateChangeCallback(); @@ -39,19 +39,20 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { binding = ActivitySplitLayoutBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); - windowInfoRepo = new WindowInfoRepoJavaAdapter(WindowInfoRepo.create(this)); + windowInfoRepository = + new WindowInfoRepositoryCallbackAdapter(WindowInfoRepository.getOrCreate(this)); } @Override protected void onStart() { super.onStart(); - windowInfoRepo.addWindowLayoutInfoListener(Runnable::run, layoutStateChangeCallback); + windowInfoRepository.addWindowLayoutInfoListener(Runnable::run, layoutStateChangeCallback); } @Override protected void onStop() { super.onStop(); - windowInfoRepo.removeWindowLayoutInfoListener(layoutStateChangeCallback); + windowInfoRepository.removeWindowLayoutInfoListener(layoutStateChangeCallback); } class LayoutStateChangeCallback implements Consumer { diff --git a/WindowManager/build.gradle b/WindowManager/build.gradle index 8cc833a4a..aa3e392ec 100644 --- a/WindowManager/build.gradle +++ b/WindowManager/build.gradle @@ -15,15 +15,16 @@ */ buildscript { - ext.kotlin_version = '1.5.20' + ext.kotlin_version = '1.5.21' ext.coroutines_version = '1.5.0' ext.ktlint_version = '0.40.0' + ext.window_version = '1.0.0-alpha10' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:4.2.2' + classpath 'com.android.tools.build:gradle:7.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/WindowManager/gradle/wrapper/gradle-wrapper.properties b/WindowManager/gradle/wrapper/gradle-wrapper.properties index 4d9ca1649..0f80bbf51 100644 --- a/WindowManager/gradle/wrapper/gradle-wrapper.properties +++ b/WindowManager/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists