Merge "[AE FlickerTest] Enter PIP test" into udc-qpr-dev
This commit is contained in:
@@ -42,7 +42,7 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
|
|||||||
import com.android.server.wm.flicker.testapp.ActivityOptions.SplitScreen.Primary
|
import com.android.server.wm.flicker.testapp.ActivityOptions.SplitScreen.Primary
|
||||||
import org.junit.Assert.assertNotNull
|
import org.junit.Assert.assertNotNull
|
||||||
|
|
||||||
internal object SplitScreenUtils {
|
object SplitScreenUtils {
|
||||||
private const val TIMEOUT_MS = 3_000L
|
private const val TIMEOUT_MS = 3_000L
|
||||||
private const val DRAG_DURATION_MS = 1_000L
|
private const val DRAG_DURATION_MS = 1_000L
|
||||||
private const val NOTIFICATION_SCROLLER = "notification_stack_scroller"
|
private const val NOTIFICATION_SCROLLER = "notification_stack_scroller"
|
||||||
|
|||||||
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.wm.flicker.activityembedding
|
||||||
|
|
||||||
|
import android.platform.test.annotations.Presubmit
|
||||||
|
import android.tools.common.datatypes.Rect
|
||||||
|
import android.tools.common.traces.component.ComponentNameMatcher
|
||||||
|
import android.tools.common.traces.component.ComponentNameMatcher.Companion.TRANSITION_SNAPSHOT
|
||||||
|
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
|
||||||
|
import android.tools.device.flicker.legacy.FlickerBuilder
|
||||||
|
import android.tools.device.flicker.legacy.LegacyFlickerTest
|
||||||
|
import android.tools.device.flicker.legacy.LegacyFlickerTestFactory
|
||||||
|
import androidx.test.filters.RequiresDevice
|
||||||
|
import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper
|
||||||
|
import org.junit.FixMethodOrder
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.junit.runners.MethodSorters
|
||||||
|
import org.junit.runners.Parameterized
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test launching a secondary Activity into Picture-In-Picture mode.
|
||||||
|
*
|
||||||
|
* Setup: Start from a split A|B.
|
||||||
|
* Transition: B enters PIP, observe the window shrink to the bottom right corner on screen.
|
||||||
|
*
|
||||||
|
* To run this test: `atest FlickerTests:SecondaryActivityEnterPipTest`
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RequiresDevice
|
||||||
|
@RunWith(Parameterized::class)
|
||||||
|
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
class SecondaryActivityEnterPipTest (flicker: LegacyFlickerTest) :
|
||||||
|
ActivityEmbeddingTestBase(flicker) {
|
||||||
|
override val transition: FlickerBuilder.() -> Unit = {
|
||||||
|
setup {
|
||||||
|
tapl.setExpectedRotationCheckEnabled(false)
|
||||||
|
testApp.launchViaIntent(wmHelper)
|
||||||
|
testApp.launchSecondaryActivity(wmHelper)
|
||||||
|
startDisplayBounds =
|
||||||
|
wmHelper.currentState.layerState.physicalDisplayBounds
|
||||||
|
?: error("Can't get display bounds")
|
||||||
|
}
|
||||||
|
transitions {
|
||||||
|
testApp.secondaryActivityEnterPip(wmHelper)
|
||||||
|
}
|
||||||
|
teardown {
|
||||||
|
tapl.goHome()
|
||||||
|
testApp.exit(wmHelper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main and secondary activity start from a split each taking half of the screen.
|
||||||
|
*/
|
||||||
|
@Presubmit
|
||||||
|
@Test
|
||||||
|
fun layersStartFromEqualSplit() {
|
||||||
|
flicker.assertLayersStart {
|
||||||
|
val leftLayerRegion =
|
||||||
|
visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
val rightLayerRegion =
|
||||||
|
visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
|
||||||
|
// Compare dimensions of two splits, given we're using default split attributes,
|
||||||
|
// both activities take up the same visible size on the display.
|
||||||
|
check { "height" }
|
||||||
|
.that(leftLayerRegion.region.height).isEqual(rightLayerRegion.region.height)
|
||||||
|
check { "width" }
|
||||||
|
.that(leftLayerRegion.region.width).isEqual(rightLayerRegion.region.width)
|
||||||
|
leftLayerRegion.notOverlaps(rightLayerRegion.region)
|
||||||
|
leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds)
|
||||||
|
}
|
||||||
|
flicker.assertLayersEnd {
|
||||||
|
visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
.coversExactly(startDisplayBounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Activity is visible throughout the transition and becomes fullscreen.
|
||||||
|
*/
|
||||||
|
@Presubmit
|
||||||
|
@Test
|
||||||
|
fun mainActivityWindowBecomesFullScreen() {
|
||||||
|
flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
|
||||||
|
flicker.assertWmEnd {
|
||||||
|
visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
.coversExactly(startDisplayBounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main Activity is visible throughout the transition and becomes fullscreen.
|
||||||
|
*/
|
||||||
|
@Presubmit
|
||||||
|
@Test
|
||||||
|
fun mainActivityLayerBecomesFullScreen() {
|
||||||
|
flicker.assertLayers {
|
||||||
|
isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
.then()
|
||||||
|
.isVisible(TRANSITION_SNAPSHOT)
|
||||||
|
.isInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
.then()
|
||||||
|
.isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
}
|
||||||
|
flicker.assertLayersEnd {
|
||||||
|
visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
|
||||||
|
.coversExactly(startDisplayBounds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Secondary Activity is visible throughout the transition and shrinks to the bottom right
|
||||||
|
* corner.
|
||||||
|
*/
|
||||||
|
@Presubmit
|
||||||
|
@Test
|
||||||
|
fun secondaryWindowShrinks() {
|
||||||
|
flicker.assertWm {
|
||||||
|
isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
|
||||||
|
}
|
||||||
|
flicker.assertWmEnd {
|
||||||
|
val pipWindowRegion =
|
||||||
|
visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
|
||||||
|
check{"height"}
|
||||||
|
.that(pipWindowRegion.region.height)
|
||||||
|
.isLower(startDisplayBounds.height / 2)
|
||||||
|
check{"width"}
|
||||||
|
.that(pipWindowRegion.region.width).isLower(startDisplayBounds.width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* During the transition Secondary Activity shrinks to the bottom right corner.
|
||||||
|
*/
|
||||||
|
@Presubmit
|
||||||
|
@Test
|
||||||
|
fun secondaryLayerShrinks() {
|
||||||
|
flicker.assertLayers {
|
||||||
|
val pipLayerList = layers {
|
||||||
|
ComponentNameMatcher.PIP_CONTENT_OVERLAY.layerMatchesAnyOf(it) && it.isVisible
|
||||||
|
}
|
||||||
|
pipLayerList.zipWithNext { previous, current ->
|
||||||
|
// TODO(b/290987990): Add checks for visibleRegion.
|
||||||
|
current.screenBounds.isToTheRightBottom(previous.screenBounds.region, 3)
|
||||||
|
current.screenBounds.notBiggerThan(previous.screenBounds.region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flicker.assertLayersEnd {
|
||||||
|
val pipRegion = visibleRegion(
|
||||||
|
ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
|
||||||
|
check { "height" }
|
||||||
|
.that(pipRegion.region.height)
|
||||||
|
.isLower(startDisplayBounds.height / 2)
|
||||||
|
check { "width" }
|
||||||
|
.that(pipRegion.region.width).isLower(startDisplayBounds.width)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
private var startDisplayBounds = Rect.EMPTY
|
||||||
|
/**
|
||||||
|
* Creates the test configurations.
|
||||||
|
*
|
||||||
|
* See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and
|
||||||
|
* navigation modes.
|
||||||
|
*/
|
||||||
|
@Parameterized.Parameters(name = "{0}")
|
||||||
|
@JvmStatic
|
||||||
|
fun getParams() = LegacyFlickerTestFactory.nonRotationTests()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -113,6 +113,21 @@ constructor(
|
|||||||
.waitForAndVerify()
|
.waitForAndVerify()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun secondaryActivityEnterPip(wmHelper: WindowManagerStateHelper) {
|
||||||
|
val pipButton =
|
||||||
|
uiDevice.wait(
|
||||||
|
Until.findObject(By.res(getPackage(), "secondary_enter_pip_button")),
|
||||||
|
FIND_TIMEOUT
|
||||||
|
)
|
||||||
|
require(pipButton != null) { "Can't find enter pip button on screen." }
|
||||||
|
pipButton.click()
|
||||||
|
wmHelper
|
||||||
|
.StateSyncBuilder()
|
||||||
|
.withAppTransitionIdle()
|
||||||
|
.withPipShown()
|
||||||
|
.waitForAndVerify()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clicks the button to launch a secondary activity with alwaysExpand enabled, which will launch
|
* Clicks the button to launch a secondary activity with alwaysExpand enabled, which will launch
|
||||||
* a fullscreen window on top of the visible region.
|
* a fullscreen window on top of the visible region.
|
||||||
|
|||||||
@@ -224,6 +224,7 @@
|
|||||||
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
|
android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding"
|
||||||
android:theme="@style/CutoutShortEdges"
|
android:theme="@style/CutoutShortEdges"
|
||||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||||
|
android:supportsPictureInPicture="true"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ActivityEmbeddingThirdActivity"
|
android:name=".ActivityEmbeddingThirdActivity"
|
||||||
|
|||||||
@@ -35,4 +35,10 @@
|
|||||||
android:onClick="launchThirdActivity"
|
android:onClick="launchThirdActivity"
|
||||||
android:text="Launch a third activity" />
|
android:text="Launch a third activity" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/secondary_enter_pip_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:text="Enter pip" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -18,6 +18,7 @@ package com.android.server.wm.flicker.testapp;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.app.PictureInPictureParams;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -40,6 +41,16 @@ public class ActivityEmbeddingSecondaryActivity extends Activity {
|
|||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
findViewById(R.id.secondary_enter_pip_button).setOnClickListener(
|
||||||
|
new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
PictureInPictureParams.Builder picInPicParamsBuilder =
|
||||||
|
new PictureInPictureParams.Builder();
|
||||||
|
enterPictureInPictureMode(picInPicParamsBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void launchThirdActivity(View view) {
|
public void launchThirdActivity(View view) {
|
||||||
|
|||||||
Reference in New Issue
Block a user