Merge changes from topic "wmflicker-kotlin"

* changes:
  Move tests into specific packages
  Use kotlin lambdas on flicker assertions
  Convert flicker tests to kotlin
This commit is contained in:
Nataniel Borges
2020-07-10 08:35:50 +00:00
committed by Android (Google) Code Review
46 changed files with 2490 additions and 2439 deletions

View File

@@ -16,7 +16,7 @@
android_test {
name: "FlickerTests",
srcs: ["src/**/*.java"],
srcs: ["src/**/*.java", "src/**/*.kt"],
manifest: "AndroidManifest.xml",
test_config: "AndroidTest.xml",
platform_apis: true,

View File

@@ -1,174 +0,0 @@
/*
* Copyright (C) 2018 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;
import static android.view.Surface.rotationToString;
import static com.android.server.wm.flicker.CommonTransitions.changeAppRotation;
import static com.android.server.wm.flicker.WindowUtils.getAppPosition;
import static com.android.server.wm.flicker.WindowUtils.getNavigationBarPosition;
import static com.android.server.wm.flicker.WindowUtils.getStatusBarPosition;
import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
import android.graphics.Rect;
import android.util.Log;
import android.view.Surface;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.ArrayList;
import java.util.Collection;
/**
* Cycle through supported app rotations.
* To run this test: {@code atest FlickerTest:ChangeAppRotationTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ChangeAppRotationTest extends FlickerTestBase {
private int mBeginRotation;
private int mEndRotation;
public ChangeAppRotationTest(String beginRotationName, String endRotationName,
int beginRotation, int endRotation) {
this.mTestApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
this.mBeginRotation = beginRotation;
this.mEndRotation = endRotation;
}
@Parameters(name = "{0}-{1}")
public static Collection<Object[]> getParams() {
int[] supportedRotations =
{Surface.ROTATION_0, Surface.ROTATION_90};
Collection<Object[]> params = new ArrayList<>();
for (int begin : supportedRotations) {
for (int end : supportedRotations) {
if (begin != end) {
params.add(new Object[]{rotationToString(begin), rotationToString(end), begin,
end});
}
}
}
return params;
}
@Override
TransitionRunner getTransitionToRun() {
return changeAppRotation(mTestApp, mUiDevice, mBeginRotation, mEndRotation)
.includeJankyRuns().build();
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults(result -> assertThat(result)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults(result -> assertThat(result)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
}
@Test
public void checkPosition_navBarLayerRotatesAndScales() {
Rect startingPos = getNavigationBarPosition(mBeginRotation);
Rect endingPos = getNavigationBarPosition(mEndRotation);
checkResults(result -> {
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
.inTheBeginning();
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos).atTheEnd();
}
);
}
@Test
public void checkPosition_appLayerRotates() {
Rect startingPos = getAppPosition(mBeginRotation);
Rect endingPos = getAppPosition(mEndRotation);
Log.e(TAG, "startingPos=" + startingPos + " endingPos=" + endingPos);
checkResults(result -> {
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(mTestApp.getPackage(), startingPos).inTheBeginning();
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(mTestApp.getPackage(), endingPos).atTheEnd();
}
);
}
@Test
public void checkPosition_statusBarLayerScales() {
Rect startingPos = getStatusBarPosition(mBeginRotation);
Rect endingPos = getStatusBarPosition(mEndRotation);
checkResults(result -> {
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, startingPos)
.inTheBeginning();
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, endingPos).atTheEnd();
}
);
}
@Ignore("Flaky. Pending debug")
@Test
public void checkVisibility_screenshotLayerBecomesInvisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(mTestApp.getPackage())
.then()
.replaceVisibleLayer(mTestApp.getPackage(), SCREENSHOT_LAYER)
.then()
.showsLayer(mTestApp.getPackage()).and().showsLayer(SCREENSHOT_LAYER)
.then()
.replaceVisibleLayer(SCREENSHOT_LAYER, mTestApp.getPackage())
.forAllEntries());
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_navBarLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_statusBarLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries());
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2019 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;
import static com.android.server.wm.flicker.CommonTransitions.editTextLoseFocusToApp;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test IME window closing back to app window transitions.
* To run this test: {@code atest FlickerTests:CloseImeWindowToAppTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CloseImeAutoOpenWindowToAppTest extends CloseImeWindowToAppTest {
public CloseImeAutoOpenWindowToAppTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
mTestApp = new ImeAppAutoFocusHelper(InstrumentationRegistry.getInstrumentation());
}
@Override
TransitionRunner getTransitionToRun() {
return editTextLoseFocusToApp((ImeAppAutoFocusHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_imeLayerBecomesInvisible() {
super.checkVisibility_imeLayerBecomesInvisible();
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_imeAppLayerIsAlwaysVisible() {
super.checkVisibility_imeAppLayerIsAlwaysVisible();
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_imeAppWindowIsAlwaysVisible() {
super.checkVisibility_imeAppWindowIsAlwaysVisible();
}
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (C) 2019 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;
import static com.android.server.wm.flicker.CommonTransitions.editTextLoseFocusToHome;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test IME window closing back to app window transitions.
* To run this test: {@code atest FlickerTests:CloseImeWindowToAppTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CloseImeAutoOpenWindowToHomeTest extends CloseImeWindowToHomeTest {
public CloseImeAutoOpenWindowToHomeTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
mTestApp = new ImeAppAutoFocusHelper(InstrumentationRegistry.getInstrumentation());
}
@Override
TransitionRunner getTransitionToRun() {
return editTextLoseFocusToHome((ImeAppAutoFocusHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_imeWindowBecomesInvisible() {
super.checkVisibility_imeWindowBecomesInvisible();
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_imeLayerBecomesInvisible() {
super.checkVisibility_imeLayerBecomesInvisible();
}
@FlakyTest(bugId = 157449248)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_imeAppWindowBecomesInvisible() {
super.checkVisibility_imeAppWindowBecomesInvisible();
}
}

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.editTextLoseFocusToApp;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.ImeAppHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test IME window closing back to app window transitions.
* To run this test: {@code atest FlickerTests:CloseImeWindowToAppTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CloseImeWindowToAppTest extends NonRotationTestBase {
static final String IME_WINDOW_TITLE = "InputMethod";
public CloseImeWindowToAppTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
mTestApp = new ImeAppHelper(InstrumentationRegistry.getInstrumentation());
}
@Override
TransitionRunner getTransitionToRun() {
return editTextLoseFocusToApp((ImeAppHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Ignore("Flaky. Pending debug")
@Test
public void checkVisibility_imeLayerBecomesInvisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(IME_WINDOW_TITLE)
.then()
.hidesLayer(IME_WINDOW_TITLE)
.forAllEntries());
}
@Test
public void checkVisibility_imeAppLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(mTestApp.getPackage())
.forAllEntries());
}
@Test
public void checkVisibility_imeAppWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAppWindowOnTop(mTestApp.getPackage())
.forAllEntries());
}
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.editTextLoseFocusToHome;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.ImeAppHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test IME window closing to home transitions.
* To run this test: {@code atest FlickerTests:CloseImeWindowToHomeTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class CloseImeWindowToHomeTest extends NonRotationTestBase {
static final String IME_WINDOW_TITLE = "InputMethod";
public CloseImeWindowToHomeTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
mTestApp = new ImeAppHelper(InstrumentationRegistry.getInstrumentation());
}
@Override
TransitionRunner getTransitionToRun() {
return editTextLoseFocusToHome((ImeAppHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Test
public void checkVisibility_imeWindowBecomesInvisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsImeWindow(IME_WINDOW_TITLE)
.then()
.hidesImeWindow(IME_WINDOW_TITLE)
.forAllEntries());
}
@FlakyTest(bugId = 153739621)
@Ignore
@Test
public void checkVisibility_imeLayerBecomesInvisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.skipUntilFirstAssertion()
.showsLayer(IME_WINDOW_TITLE)
.then()
.hidesLayer(IME_WINDOW_TITLE)
.forAllEntries());
}
@FlakyTest(bugId = 153739621)
@Ignore
@Test
public void checkVisibility_imeAppLayerBecomesInvisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.skipUntilFirstAssertion()
.showsLayer(mTestApp.getPackage())
.then()
.hidesLayer(mTestApp.getPackage())
.forAllEntries());
}
@Test
public void checkVisibility_imeAppWindowBecomesInvisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAppWindowOnTop(mTestApp.getPackage())
.then()
.hidesAppWindowOnTop(mTestApp.getPackage())
.forAllEntries());
}
}

View File

@@ -1,399 +0,0 @@
/*
* Copyright (C) 2018 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;
import static android.os.SystemClock.sleep;
import static android.view.Surface.rotationToString;
import static com.android.server.wm.flicker.helpers.AutomationUtils.clearRecents;
import static com.android.server.wm.flicker.helpers.AutomationUtils.exitSplitScreen;
import static com.android.server.wm.flicker.helpers.AutomationUtils.expandPipWindow;
import static com.android.server.wm.flicker.helpers.AutomationUtils.launchSplitScreen;
import static com.android.server.wm.flicker.helpers.AutomationUtils.stopPackage;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.platform.helpers.IAppHelper;
import android.util.Rational;
import android.view.Surface;
import androidx.annotation.Nullable;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
import com.android.server.wm.flicker.TransitionRunner.TransitionBuilder;
import com.android.server.wm.flicker.helpers.AutomationUtils;
import com.android.server.wm.flicker.helpers.ImeAppHelper;
import com.android.server.wm.flicker.helpers.PipAppHelper;
/**
* Collection of common transitions which can be used to test different apps or scenarios.
*/
class CommonTransitions {
public static final int ITERATIONS = 1;
private static final String TAG = "FLICKER";
private static final long APP_LAUNCH_TIMEOUT = 10000;
private static void setRotation(UiDevice device, int rotation) {
try {
switch (rotation) {
case Surface.ROTATION_270:
device.setOrientationLeft();
break;
case Surface.ROTATION_90:
device.setOrientationRight();
break;
case Surface.ROTATION_0:
default:
device.setOrientationNatural();
}
// Wait for animation to complete
sleep(1000);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
/**
* Build a test tag for the test
* @param testName Name of the transition(s) being tested
* @param app App being launcher
* @param rotation Initial screen rotation
*
* @return test tag with pattern <NAME>__<APP>__<ROTATION>
*/
private static String buildTestTag(String testName, IAppHelper app, int rotation) {
return buildTestTag(
testName, app, /* app2 */ null, rotation, rotation, /* description */ "");
}
/**
* Build a test tag for the test
* @param testName Name of the transition(s) being tested
* @param app App being launcher
* @param beginRotation Initial screen rotation
* @param endRotation End screen rotation (if any, otherwise use same as initial)
*
* @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
*/
private static String buildTestTag(String testName, IAppHelper app, int beginRotation,
int endRotation) {
return buildTestTag(
testName, app, /* app2 */ null, beginRotation, endRotation, /* description */ "");
}
/**
* Build a test tag for the test
* @param testName Name of the transition(s) being tested
* @param app App being launcher
* @param app2 Second app being launched (if any)
* @param beginRotation Initial screen rotation
* @param endRotation End screen rotation (if any, otherwise use same as initial)
* @param extraInfo Additional information to append to the tag
*
* @return test tag with pattern <NAME>__<APP(S)>__<ROTATION(S)>[__<EXTRA>]
*/
private static String buildTestTag(String testName, IAppHelper app, @Nullable IAppHelper app2,
int beginRotation, int endRotation, String extraInfo) {
StringBuilder testTag = new StringBuilder();
testTag.append(testName)
.append("__")
.append(app.getLauncherName());
if (app2 != null) {
testTag.append("-")
.append(app2.getLauncherName());
}
testTag.append("__")
.append(rotationToString(beginRotation));
if (endRotation != beginRotation) {
testTag.append("-")
.append(rotationToString(endRotation));
}
if (!extraInfo.isEmpty()) {
testTag.append("__")
.append(extraInfo);
}
return testTag.toString();
}
static TransitionBuilder openAppWarm(IAppHelper testApp, UiDevice
device, int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("openAppWarm", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBeforeAll(() -> setRotation(device, beginRotation))
.runBeforeAll(testApp::open)
.runBefore(device::pressHome)
.runBefore(device::waitForIdle)
.runBefore(() -> setRotation(device, beginRotation))
.run(testApp::open)
.runAfterAll(testApp::exit)
.runAfterAll(AutomationUtils::setDefaultWait)
.repeat(ITERATIONS);
}
static TransitionBuilder closeAppWithBackKey(IAppHelper testApp, UiDevice
device, int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("closeAppWithBackKey", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(testApp::open)
.runBefore(device::waitForIdle)
.run(device::pressBack)
.run(device::waitForIdle)
.runAfterAll(testApp::exit)
.runAfterAll(AutomationUtils::setDefaultWait)
.repeat(ITERATIONS);
}
static TransitionBuilder closeAppWithHomeKey(IAppHelper testApp, UiDevice
device, int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("closeAppWithHomeKey", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(testApp::open)
.runBefore(device::waitForIdle)
.run(device::pressHome)
.run(device::waitForIdle)
.runAfterAll(testApp::exit)
.runAfterAll(AutomationUtils::setDefaultWait)
.repeat(ITERATIONS);
}
static TransitionBuilder openAppCold(IAppHelper testApp,
UiDevice device, int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("openAppCold", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(device::pressHome)
.runBeforeAll(() -> setRotation(device, beginRotation))
.runBefore(testApp::exit)
.runBefore(device::waitForIdle)
.run(testApp::open)
.runAfterAll(testApp::exit)
.runAfterAll(() -> setRotation(device, Surface.ROTATION_0))
.repeat(ITERATIONS);
}
static TransitionBuilder changeAppRotation(IAppHelper testApp, UiDevice
device, int beginRotation, int endRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("changeAppRotation", testApp, beginRotation, endRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBeforeAll(testApp::open)
.runBefore(() -> setRotation(device, beginRotation))
.run(() -> setRotation(device, endRotation))
.runAfterAll(testApp::exit)
.runAfterAll(() -> setRotation(device, Surface.ROTATION_0))
.repeat(ITERATIONS);
}
static TransitionBuilder changeAppRotation(Intent intent, String intentId, Context context,
UiDevice device, int beginRotation, int endRotation) {
final String testTag = "changeAppRotation_" + intentId + "_" +
rotationToString(beginRotation) + "_" + rotationToString(endRotation);
return TransitionRunner.newBuilder()
.withTag(testTag)
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBeforeAll(() -> {
context.startActivity(intent);
device.wait(Until.hasObject(By.pkg(intent.getComponent()
.getPackageName()).depth(0)), APP_LAUNCH_TIMEOUT);
}
)
.runBefore(() -> setRotation(device, beginRotation))
.run(() -> setRotation(device, endRotation))
.runAfterAll(() -> stopPackage(context, intent.getComponent().getPackageName()))
.runAfterAll(() -> setRotation(device, Surface.ROTATION_0))
.repeat(ITERATIONS);
}
static TransitionBuilder appToSplitScreen(IAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("appToSplitScreen", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBeforeAll(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.runBefore(device::waitForIdle)
.runBefore(() -> sleep(500))
.run(() -> launchSplitScreen(device))
.runAfter(() -> exitSplitScreen(device))
.runAfterAll(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder splitScreenToLauncher(IAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("splitScreenToLauncher", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBeforeAll(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.runBefore(device::waitForIdle)
.runBefore(() -> launchSplitScreen(device))
.run(() -> exitSplitScreen(device))
.runAfterAll(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder editTextSetFocus(ImeAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("editTextSetFocus", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(device::pressHome)
.runBefore(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.run(() -> testApp.openIME(device))
.runAfterAll(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder resizeSplitScreen(Instrumentation instr, IAppHelper testAppTop,
ImeAppHelper testAppBottom, UiDevice device, int beginRotation, Rational startRatio,
Rational stopRatio) {
String description = startRatio.toString().replace("/", "-") + "_to_"
+ stopRatio.toString().replace("/", "-");
String testTag = buildTestTag("resizeSplitScreen", testAppTop, testAppBottom,
beginRotation, beginRotation, description);
return TransitionRunner.newBuilder()
.withTag(testTag)
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBeforeAll(() -> setRotation(device, beginRotation))
.runBeforeAll(() -> clearRecents(instr))
.runBefore(testAppBottom::open)
.runBefore(device::pressHome)
.runBefore(testAppTop::open)
.runBefore(device::waitForIdle)
.runBefore(() -> launchSplitScreen(device))
.runBefore(() -> {
UiObject2 snapshot = device.findObject(
By.res(device.getLauncherPackageName(), "snapshot"));
snapshot.click();
})
.runBefore(() -> testAppBottom.openIME(device))
.runBefore(device::pressBack)
.runBefore(() -> AutomationUtils.resizeSplitScreen(device, startRatio))
.run(() -> AutomationUtils.resizeSplitScreen(device, stopRatio))
.runAfter(() -> exitSplitScreen(device))
.runAfter(device::pressHome)
.runAfterAll(testAppTop::exit)
.runAfterAll(testAppBottom::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder editTextLoseFocusToHome(ImeAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("editTextLoseFocusToHome", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(device::pressHome)
.runBefore(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.runBefore(() -> testApp.openIME(device))
.run(device::pressHome)
.run(device::waitForIdle)
.runAfterAll(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder editTextLoseFocusToApp(ImeAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("editTextLoseFocusToApp", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(device::pressHome)
.runBefore(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.runBefore(() -> testApp.openIME(device))
.run(device::pressBack)
.run(device::waitForIdle)
.runAfterAll(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder enterPipMode(PipAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("enterPipMode", testApp, beginRotation))
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(device::pressHome)
.runBefore(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.run(() -> testApp.clickEnterPipButton(device))
.runAfter(() -> testApp.closePipWindow(device))
.runAfterAll(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder exitPipModeToHome(PipAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("exitPipModeToHome", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.runBefore(device::pressHome)
.runBefore(() -> setRotation(device, beginRotation))
.runBefore(testApp::open)
.run(() -> testApp.clickEnterPipButton(device))
.run(() -> testApp.closePipWindow(device))
.run(device::waitForIdle)
.run(testApp::exit)
.repeat(ITERATIONS);
}
static TransitionBuilder exitPipModeToApp(PipAppHelper testApp, UiDevice device,
int beginRotation) {
return TransitionRunner.newBuilder()
.withTag(buildTestTag("exitPipModeToApp", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll(AutomationUtils::wakeUpAndGoToHomeScreen)
.run(device::pressHome)
.run(() -> setRotation(device, beginRotation))
.run(testApp::open)
.run(() -> testApp.clickEnterPipButton(device))
.run(() -> expandPipWindow(device))
.run(device::waitForIdle)
.run(testApp::exit)
.repeat(ITERATIONS);
}
}

View File

@@ -0,0 +1,446 @@
/*
* Copyright (C) 2020 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
import android.app.Instrumentation
import android.content.Context
import android.content.Intent
import android.os.RemoteException
import android.os.SystemClock
import android.platform.helpers.IAppHelper
import android.util.Rational
import android.view.Surface
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.AutomationUtils
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.PipAppHelper
/**
* Collection of common transitions which can be used to test different apps or scenarios.
*/
internal object CommonTransitions {
private const val ITERATIONS = 1
private const val APP_LAUNCH_TIMEOUT: Long = 10000
private fun setRotation(device: UiDevice, rotation: Int) {
try {
when (rotation) {
Surface.ROTATION_270 -> device.setOrientationLeft()
Surface.ROTATION_90 -> device.setOrientationRight()
Surface.ROTATION_0 -> device.setOrientationNatural()
else -> device.setOrientationNatural()
}
// Wait for animation to complete
SystemClock.sleep(1000)
} catch (e: RemoteException) {
throw RuntimeException(e)
}
}
/**
* Build a test tag for the test
* @param testName Name of the transition(s) being tested
* @param app App being launcher
* @param rotation Initial screen rotation
*
* @return test tag with pattern <NAME>__<APP>__<ROTATION>
</ROTATION></APP></NAME> */
private fun buildTestTag(testName: String, app: IAppHelper, rotation: Int): String {
return buildTestTag(
testName, app, rotation, rotation, app2 = null, extraInfo = "")
}
/**
* Build a test tag for the test
* @param testName Name of the transition(s) being tested
* @param app App being launcher
* @param beginRotation Initial screen rotation
* @param endRotation End screen rotation (if any, otherwise use same as initial)
*
* @return test tag with pattern <NAME>__<APP>__<BEGIN_ROTATION>-<END_ROTATION>
</END_ROTATION></BEGIN_ROTATION></APP></NAME> */
private fun buildTestTag(
testName: String,
app: IAppHelper,
beginRotation: Int,
endRotation: Int
): String {
return buildTestTag(
testName, app, beginRotation, endRotation, app2 = null, extraInfo = "")
}
/**
* Build a test tag for the test
* @param testName Name of the transition(s) being tested
* @param app App being launcher
* @param app2 Second app being launched (if any)
* @param beginRotation Initial screen rotation
* @param endRotation End screen rotation (if any, otherwise use same as initial)
* @param extraInfo Additional information to append to the tag
*
* @return test tag with pattern <NAME>__<APP></APP>(S)>__<ROTATION></ROTATION>(S)>[__<EXTRA>]
</EXTRA></NAME> */
private fun buildTestTag(
testName: String,
app: IAppHelper,
beginRotation: Int,
endRotation: Int,
app2: IAppHelper?,
extraInfo: String
): String {
val testTag = StringBuilder()
testTag.append(testName)
.append("__")
.append(app.launcherName)
if (app2 != null) {
testTag.append("-")
.append(app2.launcherName)
}
testTag.append("__")
.append(Surface.rotationToString(beginRotation))
if (endRotation != beginRotation) {
testTag.append("-")
.append(Surface.rotationToString(endRotation))
}
if (extraInfo.isNotEmpty()) {
testTag.append("__")
.append(extraInfo)
}
return testTag.toString()
}
fun openAppWarm(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("openAppWarm", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBeforeAll { setRotation(device, beginRotation) }
.runBeforeAll { testApp.open() }
.runBefore { device.pressHome() }
.runBefore { device.waitForIdle() }
.runBefore { setRotation(device, beginRotation) }
.run { testApp.open() }
.runAfterAll { testApp.exit() }
.runAfterAll { AutomationUtils.setDefaultWait() }
.repeat(ITERATIONS)
}
fun closeAppWithBackKey(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("closeAppWithBackKey", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { testApp.open() }
.runBefore { device.waitForIdle() }
.run { device.pressBack() }
.run { device.waitForIdle() }
.runAfterAll { testApp.exit() }
.runAfterAll { AutomationUtils.setDefaultWait() }
.repeat(ITERATIONS)
}
fun closeAppWithHomeKey(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("closeAppWithHomeKey", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { testApp.open() }
.runBefore { device.waitForIdle() }
.run { device.pressHome() }
.run { device.waitForIdle() }
.runAfterAll { testApp.exit() }
.runAfterAll { AutomationUtils.setDefaultWait() }
.repeat(ITERATIONS)
}
fun openAppCold(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("openAppCold", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { device.pressHome() }
.runBeforeAll { setRotation(device, beginRotation) }
.runBefore { testApp.exit() }
.runBefore { device.waitForIdle() }
.run { testApp.open() }
.runAfterAll { testApp.exit() }
.runAfterAll { setRotation(device, Surface.ROTATION_0) }
.repeat(ITERATIONS)
}
fun changeAppRotation(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int,
endRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("changeAppRotation", testApp, beginRotation, endRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBeforeAll { testApp.open() }
.runBefore { setRotation(device, beginRotation) }
.run { setRotation(device, endRotation) }
.runAfterAll { testApp.exit() }
.runAfterAll { setRotation(device, Surface.ROTATION_0) }
.repeat(ITERATIONS)
}
fun changeAppRotation(
intent: Intent,
intentId: String,
context: Context,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int,
endRotation: Int
): TransitionRunner.TransitionBuilder {
val testTag = "changeAppRotation_" + intentId + "_" +
Surface.rotationToString(beginRotation) + "_" +
Surface.rotationToString(endRotation)
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(testTag)
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBeforeAll {
context.startActivity(intent)
device.wait(Until.hasObject(By.pkg(intent.component?.packageName)
.depth(0)), APP_LAUNCH_TIMEOUT)
}
.runBefore { setRotation(device, beginRotation) }
.run { setRotation(device, endRotation) }
.runAfterAll { AutomationUtils.stopPackage(context, intent.component?.packageName) }
.runAfterAll { setRotation(device, Surface.ROTATION_0) }
.repeat(ITERATIONS)
}
fun appToSplitScreen(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("appToSplitScreen", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBeforeAll { setRotation(device, beginRotation) }
.runBefore { testApp.open() }
.runBefore { device.waitForIdle() }
.runBefore { SystemClock.sleep(500) }
.run { AutomationUtils.launchSplitScreen(device) }
.runAfter { AutomationUtils.exitSplitScreen(device) }
.runAfterAll { testApp.exit() }
.repeat(ITERATIONS)
}
fun splitScreenToLauncher(
testApp: IAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("splitScreenToLauncher", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { testApp.open() }
.runBefore { device.waitForIdle() }
.runBefore { AutomationUtils.launchSplitScreen(device) }
.run { AutomationUtils.exitSplitScreen(device) }
.runAfterAll { testApp.exit() }
.repeat(ITERATIONS)
}
fun editTextSetFocus(
testApp: ImeAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("editTextSetFocus", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { device.pressHome() }
.runBefore { setRotation(device, beginRotation) }
.runBefore { testApp.open() }
.run { testApp.openIME(device) }
.runAfterAll { testApp.exit() }
.repeat(ITERATIONS)
}
fun resizeSplitScreen(
testAppTop: IAppHelper,
testAppBottom: ImeAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int,
startRatio: Rational,
stopRatio: Rational
): TransitionRunner.TransitionBuilder {
val description = (startRatio.toString().replace("/", "-") + "_to_" +
stopRatio.toString().replace("/", "-"))
val testTag = buildTestTag("resizeSplitScreen", testAppTop, beginRotation,
beginRotation, testAppBottom, description)
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(testTag)
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBeforeAll { setRotation(device, beginRotation) }
.runBeforeAll { AutomationUtils.clearRecents(instrumentation) }
.runBefore { testAppBottom.open() }
.runBefore { device.pressHome() }
.runBefore { testAppTop.open() }
.runBefore { device.waitForIdle() }
.runBefore { AutomationUtils.launchSplitScreen(device) }
.runBefore {
val snapshot = device.findObject(
By.res(device.launcherPackageName, "snapshot"))
snapshot.click()
}
.runBefore { testAppBottom.openIME(device) }
.runBefore { device.pressBack() }
.runBefore { AutomationUtils.resizeSplitScreen(device, startRatio) }
.run { AutomationUtils.resizeSplitScreen(device, stopRatio) }
.runAfter { AutomationUtils.exitSplitScreen(device) }
.runAfter { device.pressHome() }
.runAfterAll { testAppTop.exit() }
.runAfterAll { testAppBottom.exit() }
.repeat(ITERATIONS)
}
fun editTextLoseFocusToHome(
testApp: ImeAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("editTextLoseFocusToHome", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { device.pressHome() }
.runBefore { setRotation(device, beginRotation) }
.runBefore { testApp.open() }
.runBefore { testApp.openIME(device) }
.run { device.pressHome() }
.run { device.waitForIdle() }
.runAfterAll { testApp.exit() }
.repeat(ITERATIONS)
}
fun editTextLoseFocusToApp(
testApp: ImeAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("editTextLoseFocusToApp", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { device.pressHome() }
.runBefore { setRotation(device, beginRotation) }
.runBefore { testApp.open() }
.runBefore { testApp.openIME(device) }
.run { device.pressBack() }
.run { device.waitForIdle() }
.runAfterAll { testApp.exit() }
.repeat(ITERATIONS)
}
fun enterPipMode(
testApp: PipAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("enterPipMode", testApp, beginRotation))
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { device.pressHome() }
.runBefore { setRotation(device, beginRotation) }
.runBefore { testApp.open() }
.run { testApp.clickEnterPipButton(device) }
.runAfter { testApp.closePipWindow(device) }
.runAfterAll { testApp.exit() }
.repeat(ITERATIONS)
}
fun exitPipModeToHome(
testApp: PipAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("exitPipModeToHome", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.runBefore { device.pressHome() }
.runBefore { setRotation(device, beginRotation) }
.runBefore { testApp.open() }
.run { testApp.clickEnterPipButton(device) }
.run { testApp.closePipWindow(device) }
.run { device.waitForIdle() }
.run { testApp.exit() }
.repeat(ITERATIONS)
}
fun exitPipModeToApp(
testApp: PipAppHelper,
instrumentation: Instrumentation,
device: UiDevice,
beginRotation: Int
): TransitionRunner.TransitionBuilder {
return TransitionRunner.TransitionBuilder(instrumentation)
.withTag(buildTestTag("exitPipModeToApp", testApp, beginRotation))
.recordAllRuns()
.runBeforeAll { AutomationUtils.wakeUpAndGoToHomeScreen() }
.run { device.pressHome() }
.run { setRotation(device, beginRotation) }
.run { testApp.open() }
.run { testApp.clickEnterPipButton(device) }
.run { AutomationUtils.expandPipWindow(device) }
.run { device.waitForIdle() }
.run { testApp.exit() }
.repeat(ITERATIONS)
}
}

View File

@@ -1,193 +0,0 @@
/*
* Copyright (C) 2018 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;
import android.app.Instrumentation;
import android.platform.helpers.IAppHelper;
import android.util.Rational;
import android.view.Surface;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
import com.android.server.wm.flicker.helpers.ImeAppHelper;
import com.android.server.wm.flicker.helpers.PipAppHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
/**
* Tests to help debug individual transitions, capture video recordings and create test cases.
*/
@LargeTest
@Ignore("Used for debugging transitions used in FlickerTests.")
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class DebugTest {
private IAppHelper testApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
private UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
/**
* atest FlickerTests:DebugTest#openAppCold
*/
@Test
public void openAppCold() {
CommonTransitions.openAppCold(testApp, uiDevice, Surface.ROTATION_0)
.recordAllRuns().build().run();
}
/**
* atest FlickerTests:DebugTest#openAppWarm
*/
@Test
public void openAppWarm() {
CommonTransitions.openAppWarm(testApp, uiDevice, Surface.ROTATION_0)
.recordAllRuns().build().run();
}
/**
* atest FlickerTests:DebugTest#changeOrientationFromNaturalToLeft
*/
@Test
public void changeOrientationFromNaturalToLeft() {
CommonTransitions.changeAppRotation(testApp, uiDevice, Surface.ROTATION_0,
Surface.ROTATION_270).recordAllRuns().build().run();
}
/**
* atest FlickerTests:DebugTest#closeAppWithBackKey
*/
@Test
public void closeAppWithBackKey() {
CommonTransitions.closeAppWithBackKey(testApp, uiDevice, Surface.ROTATION_0)
.recordAllRuns().build().run();
}
/**
* atest FlickerTests:DebugTest#closeAppWithHomeKey
*/
@Test
public void closeAppWithHomeKey() {
CommonTransitions.closeAppWithHomeKey(testApp, uiDevice, Surface.ROTATION_0)
.recordAllRuns().build().run();
}
/**
* atest FlickerTests:DebugTest#openAppToSplitScreen
*/
@Test
public void openAppToSplitScreen() {
CommonTransitions.appToSplitScreen(testApp, uiDevice,
Surface.ROTATION_0).includeJankyRuns().recordAllRuns()
.build().run();
}
/**
* atest FlickerTests:DebugTest#splitScreenToLauncher
*/
@Test
public void splitScreenToLauncher() {
CommonTransitions.splitScreenToLauncher(testApp, uiDevice, Surface.ROTATION_0)
.includeJankyRuns().recordAllRuns().build().run();
}
/**
* atest FlickerTests:DebugTest#resizeSplitScreen
*/
@Test
public void resizeSplitScreen() {
Instrumentation instr = InstrumentationRegistry.getInstrumentation();
ImeAppHelper bottomApp = new ImeAppHelper(instr);
CommonTransitions.resizeSplitScreen(instr, testApp, bottomApp, uiDevice, Surface.ROTATION_0,
new Rational(1, 3), new Rational(2, 3))
.includeJankyRuns().build().run();
}
// IME tests
/**
* atest FlickerTests:DebugTest#editTextSetFocus
*/
@Test
public void editTextSetFocus() {
ImeAppHelper testApp = new ImeAppHelper(InstrumentationRegistry.getInstrumentation());
CommonTransitions.editTextSetFocus(testApp, uiDevice, Surface.ROTATION_0)
.includeJankyRuns()
.build().run();
}
/**
* atest FlickerTests:DebugTest#editTextLoseFocusToHome
*/
@Test
public void editTextLoseFocusToHome() {
ImeAppHelper testApp = new ImeAppHelper(InstrumentationRegistry.getInstrumentation());
CommonTransitions.editTextLoseFocusToHome(testApp, uiDevice, Surface.ROTATION_0)
.includeJankyRuns()
.build().run();
}
/**
* atest FlickerTests:DebugTest#editTextLoseFocusToApp
*/
@Test
public void editTextLoseFocusToApp() {
ImeAppHelper testApp = new ImeAppHelper(InstrumentationRegistry.getInstrumentation());
CommonTransitions.editTextLoseFocusToHome(testApp, uiDevice, Surface.ROTATION_0)
.includeJankyRuns()
.build().run();
}
// PIP tests
/**
* atest FlickerTests:DebugTest#enterPipMode
*/
@Test
public void enterPipMode() {
PipAppHelper testApp = new PipAppHelper(InstrumentationRegistry.getInstrumentation());
CommonTransitions.enterPipMode(testApp, uiDevice, Surface.ROTATION_0).includeJankyRuns()
.build().run();
}
/**
* atest FlickerTests:DebugTest#exitPipModeToHome
*/
@Test
public void exitPipModeToHome() {
PipAppHelper testApp = new PipAppHelper(InstrumentationRegistry.getInstrumentation());
CommonTransitions.exitPipModeToHome(testApp, uiDevice, Surface.ROTATION_0)
.includeJankyRuns()
.build().run();
}
/**
* atest FlickerTests:DebugTest#exitPipModeToApp
*/
@Test
public void exitPipModeToApp() {
PipAppHelper testApp = new PipAppHelper(InstrumentationRegistry.getInstrumentation());
CommonTransitions.exitPipModeToApp(testApp, uiDevice, Surface.ROTATION_0).includeJankyRuns()
.build().run();
}
}

View File

@@ -0,0 +1,188 @@
/*
* Copyright (C) 2020 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
import android.platform.helpers.IAppHelper
import android.util.Rational
import android.view.Surface
import androidx.test.InstrumentationRegistry
import androidx.test.filters.LargeTest
import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.UiDevice
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.android.server.wm.flicker.helpers.PipAppHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
/**
* Tests to help debug individual transitions, capture video recordings and create test cases.
*/
@LargeTest
@Ignore("Used for debugging transitions used in FlickerTests.")
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class DebugTest {
private val instrumentation = InstrumentationRegistry.getInstrumentation()
private val testApp: IAppHelper = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
private val uiDevice = UiDevice.getInstance(instrumentation)
/**
* atest FlickerTests:DebugTest#openAppCold
*/
@Test
fun openAppCold() {
CommonTransitions.openAppCold(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
.recordAllRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#openAppWarm
*/
@Test
fun openAppWarm() {
CommonTransitions.openAppWarm(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
.recordAllRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#changeOrientationFromNaturalToLeft
*/
@Test
fun changeOrientationFromNaturalToLeft() {
CommonTransitions.changeAppRotation(testApp, instrumentation, uiDevice, Surface.ROTATION_0,
Surface.ROTATION_270).recordAllRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#closeAppWithBackKey
*/
@Test
fun closeAppWithBackKey() {
CommonTransitions.closeAppWithBackKey(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).recordAllRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#closeAppWithHomeKey
*/
@Test
fun closeAppWithHomeKey() {
CommonTransitions.closeAppWithHomeKey(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).recordAllRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#openAppToSplitScreen
*/
@Test
fun openAppToSplitScreen() {
CommonTransitions.appToSplitScreen(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).includeJankyRuns().recordAllRuns()
.build().run()
}
/**
* atest FlickerTests:DebugTest#splitScreenToLauncher
*/
@Test
fun splitScreenToLauncher() {
CommonTransitions.splitScreenToLauncher(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).includeJankyRuns().recordAllRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#resizeSplitScreen
*/
@Test
fun resizeSplitScreen() {
val bottomApp = ImeAppHelper(instrumentation)
CommonTransitions.resizeSplitScreen(
testApp,
bottomApp,
instrumentation,
uiDevice,
Surface.ROTATION_0,
Rational(1, 3), Rational(2, 3)
).includeJankyRuns().build().run()
}
// IME tests
/**
* atest FlickerTests:DebugTest#editTextSetFocus
*/
@Test
fun editTextSetFocus() {
val testApp = ImeAppHelper(instrumentation)
CommonTransitions.editTextSetFocus(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
.includeJankyRuns()
.build().run()
}
/**
* atest FlickerTests:DebugTest#editTextLoseFocusToHome
*/
@Test
fun editTextLoseFocusToHome() {
val testApp = ImeAppHelper(instrumentation)
CommonTransitions.editTextLoseFocusToHome(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).includeJankyRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#editTextLoseFocusToApp
*/
@Test
fun editTextLoseFocusToApp() {
val testApp = ImeAppHelper(instrumentation)
CommonTransitions.editTextLoseFocusToHome(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).includeJankyRuns().build().run()
}
// PIP tests
/**
* atest FlickerTests:DebugTest#enterPipMode
*/
@Test
fun enterPipMode() {
val testApp = PipAppHelper(instrumentation)
CommonTransitions.enterPipMode(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
.includeJankyRuns().build().run()
}
/**
* atest FlickerTests:DebugTest#exitPipModeToHome
*/
@Test
fun exitPipModeToHome() {
val testApp = PipAppHelper(instrumentation)
CommonTransitions.exitPipModeToHome(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
.includeJankyRuns()
.build().run()
}
/**
* atest FlickerTests:DebugTest#exitPipModeToApp
*/
@Test
fun exitPipModeToApp() {
val testApp = PipAppHelper(instrumentation)
CommonTransitions.exitPipModeToApp(testApp, instrumentation, uiDevice, Surface.ROTATION_0)
.includeJankyRuns().build().run()
}
}

View File

@@ -1,146 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.helpers.AutomationUtils.setDefaultWait;
import static com.google.common.truth.Truth.assertWithMessage;
import android.platform.helpers.IAppHelper;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.uiautomator.UiDevice;
import com.android.server.wm.flicker.TransitionRunner.TransitionResult;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
/**
* Base class of all Flicker test that performs common functions for all flicker tests:
* <p>
* - Caches transitions so that a transition is run once and the transition results are used by
* tests multiple times. This is needed for parameterized tests which call the BeforeClass methods
* multiple times.
* - Keeps track of all test artifacts and deletes ones which do not need to be reviewed.
* - Fails tests if results are not available for any test due to jank.
*/
public abstract class FlickerTestBase {
public static final String TAG = "FLICKER";
static final String SCREENSHOT_LAYER = "RotationLayer";
static final String NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar";
static final String STATUS_BAR_WINDOW_TITLE = "StatusBar";
static final String DOCKED_STACK_DIVIDER = "DockedStackDivider";
private static HashMap<String, List<TransitionResult>> transitionResults =
new HashMap<>();
IAppHelper mTestApp;
UiDevice mUiDevice;
private List<TransitionResult> mResults;
private TransitionResult mLastResult = null;
@Before
public void setUp() {
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
/**
* Teardown any system settings and clean up test artifacts from the file system.
*
* Note: test artifacts for failed tests will remain on the device.
*/
@AfterClass
public static void teardown() {
setDefaultWait();
transitionResults.values().stream()
.flatMap(List::stream)
.forEach(result -> {
if (result.canDelete()) {
result.delete();
} else {
if (result.layersTraceExists()) {
Log.e(TAG, "Layers trace saved to " + result.getLayersTracePath());
}
if (result.windowManagerTraceExists()) {
Log.e(TAG, "WindowManager trace saved to " + result
.getWindowManagerTracePath
());
}
if (result.screenCaptureVideoExists()) {
Log.e(TAG, "Screen capture video saved to " + result
.screenCaptureVideoPath().toString());
}
}
});
}
/**
* Runs a transition, returns a cached result if the transition has run before.
*/
void run(TransitionRunner transition) {
if (transitionResults.containsKey(transition.getTestTag())) {
mResults = transitionResults.get(transition.getTestTag());
return;
}
mResults = transition.run().getResults();
/* Fail if we don't have any results due to jank */
assertWithMessage("No results to test because all transition runs were invalid because "
+ "of Jank").that(mResults).isNotEmpty();
transitionResults.put(transition.getTestTag(), mResults);
}
/**
* Runs a transition, returns a cached result if the transition has run before.
*/
@Before
public void runTransition() {
run(getTransitionToRun());
}
/**
* Gets the transition that will be executed
*/
abstract TransitionRunner getTransitionToRun();
/**
* Goes through a list of transition results and checks assertions on each result.
*/
void checkResults(Consumer<TransitionResult> assertion) {
for (TransitionResult result : mResults) {
mLastResult = result;
assertion.accept(result);
}
mLastResult = null;
}
/**
* Kludge to mark a file for saving. If {@code checkResults} fails, the last result is not
* cleared. This indicates the assertion failed for the result, so mark it for saving.
*/
@After
public void markArtifactsForSaving() {
if (mLastResult != null) {
mLastResult.flagForSaving();
}
}
}

View File

@@ -0,0 +1,137 @@
/*
* Copyright (C) 2020 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
import android.platform.helpers.IAppHelper
import android.util.Log
import androidx.test.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.android.server.wm.flicker.helpers.AutomationUtils
import com.google.common.truth.Truth
import org.junit.After
import org.junit.AfterClass
import org.junit.Before
/**
* Base class of all Flicker test that performs common functions for all flicker tests:
*
*
* - Caches transitions so that a transition is run once and the transition results are used by
* tests multiple times. This is needed for parameterized tests which call the BeforeClass methods
* multiple times.
* - Keeps track of all test artifacts and deletes ones which do not need to be reviewed.
* - Fails tests if results are not available for any test due to jank.
*/
abstract class FlickerTestBase {
lateinit var testApp: IAppHelper
open val instrumentation by lazy {
InstrumentationRegistry.getInstrumentation()
}
val uiDevice by lazy {
UiDevice.getInstance(instrumentation)
}
lateinit var tesults: List<TransitionResult>
private var lastResult: TransitionResult? = null
/**
* Runs a transition, returns a cached result if the transition has run before.
*/
fun run(transition: TransitionRunner) {
if (transitionResults.containsKey(transition.testTag)) {
tesults = transitionResults[transition.testTag]
?: throw IllegalStateException("Results do not contain test tag " +
transition.testTag)
return
}
tesults = transition.run().results
/* Fail if we don't have any results due to jank */
Truth.assertWithMessage("No results to test because all transition runs were invalid " +
"because of Jank").that(tesults).isNotEmpty()
transitionResults[transition.testTag] = tesults
}
/**
* Runs a transition, returns a cached result if the transition has run before.
*/
@Before
fun runTransition() {
run(transitionToRun)
}
/**
* Gets the transition that will be executed
*/
abstract val transitionToRun: TransitionRunner
/**
* Goes through a list of transition results and checks assertions on each result.
*/
fun checkResults(assertion: (TransitionResult) -> Unit) {
for (result in tesults) {
lastResult = result
assertion(result)
}
lastResult = null
}
/**
* Kludge to mark a file for saving. If `checkResults` fails, the last result is not
* cleared. This indicates the assertion failed for the result, so mark it for saving.
*/
@After
fun markArtifactsForSaving() {
lastResult?.flagForSaving()
}
companion object {
const val TAG = "FLICKER"
const val NAVIGATION_BAR_WINDOW_TITLE = "NavigationBar"
const val STATUS_BAR_WINDOW_TITLE = "StatusBar"
const val DOCKED_STACK_DIVIDER = "DockedStackDivider"
private val transitionResults = mutableMapOf<String, List<TransitionResult>>()
/**
* Teardown any system settings and clean up test artifacts from the file system.
*
* Note: test artifacts for failed tests will remain on the device.
*/
@AfterClass
@JvmStatic
fun teardown() {
AutomationUtils.setDefaultWait()
transitionResults.values
.flatten()
.forEach {
if (it.canDelete()) {
it.delete()
} else {
if (it.layersTraceExists()) {
Log.e(TAG, "Layers trace saved to ${it.layersTracePath}")
}
if (it.windowManagerTraceExists()) {
Log.e(TAG,
"WindowManager trace saved to ${it.windowManagerTracePath}")
}
if (it.screenCaptureVideoExists()) {
Log.e(TAG,
"Screen capture video saved to ${it.screenCaptureVideoPath()}")
}
}
}
}
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C) 2019 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;
import static android.view.Surface.rotationToString;
import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
import android.graphics.Rect;
import android.view.Surface;
import androidx.test.filters.FlakyTest;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runners.Parameterized.Parameters;
import java.util.ArrayList;
import java.util.Collection;
public abstract class NonRotationTestBase extends FlickerTestBase {
int mBeginRotation;
public NonRotationTestBase(String beginRotationName, int beginRotation) {
this.mBeginRotation = beginRotation;
}
@Parameters(name = "{0}")
public static Collection<Object[]> getParams() {
int[] supportedRotations =
{Surface.ROTATION_0, Surface.ROTATION_90};
Collection<Object[]> params = new ArrayList<>();
for (int begin : supportedRotations) {
params.add(new Object[]{rotationToString(begin), begin});
}
return params;
}
@FlakyTest(bugId = 141361128)
@Ignore("Waiting bug feedback")
@Test
public void checkCoveredRegion_noUncoveredRegions() {
Rect displayBounds = getDisplayBounds(mBeginRotation);
checkResults(result -> LayersTraceSubject.assertThat(result).coversRegion(
displayBounds).forAllEntries());
}
@FlakyTest(bugId = 141361128)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_navBarLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
}
@FlakyTest(bugId = 141361128)
@Ignore("Waiting bug feedback")
@Test
public void checkVisibility_statusBarLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries());
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2020 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
import android.view.Surface
import androidx.test.filters.FlakyTest
import org.junit.Ignore
import org.junit.Test
import org.junit.runners.Parameterized
abstract class NonRotationTestBase(
beginRotationName: String,
protected val beginRotation: Int
) : FlickerTestBase() {
@FlakyTest(bugId = 141361128)
@Ignore("Waiting bug feedback")
@Test
fun checkCoveredRegion_noUncoveredRegions() {
val displayBounds = WindowUtils.getDisplayBounds(beginRotation)
checkResults {
LayersTraceSubject.assertThat(it).coversRegion(
displayBounds).forAllEntries()
}
}
@FlakyTest(bugId = 141361128)
@Ignore("Waiting bug feedback")
@Test
fun checkVisibility_navBarLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
}
}
@FlakyTest(bugId = 141361128)
@Ignore("Waiting bug feedback")
@Test
fun checkVisibility_statusBarLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries()
}
}
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
val params: MutableCollection<Array<Any>> = ArrayList()
for (begin in supportedRotations) {
params.add(arrayOf(Surface.rotationToString(begin), begin))
}
return params
}
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.openAppCold;
import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test cold launch app from launcher.
* To run this test: {@code atest FlickerTests:OpenAppColdTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OpenAppColdTest extends NonRotationTestBase {
public OpenAppColdTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
this.mTestApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
}
@Override
TransitionRunner getTransitionToRun() {
return openAppCold(mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Test
public void checkVisibility_wallpaperWindowBecomesInvisible() {
checkResults(result -> assertThat(result)
.showsBelowAppWindow("Wallpaper")
.then()
.hidesBelowAppWindow("Wallpaper")
.forAllEntries());
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
public void checkZOrder_appWindowReplacesLauncherAsTopWindow() {
checkResults(result -> assertThat(result)
.showsAppWindowOnTop(
"com.android.launcher3/.Launcher")
.then()
.showsAppWindowOnTop(mTestApp.getPackage())
.forAllEntries());
}
@Test
public void checkVisibility_wallpaperLayerBecomesInvisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer("Wallpaper")
.then()
.replaceVisibleLayer("Wallpaper", mTestApp.getPackage())
.forAllEntries());
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.appToSplitScreen;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test open app to split screen.
* To run this test: {@code atest FlickerTests:OpenAppToSplitScreenTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OpenAppToSplitScreenTest extends NonRotationTestBase {
public OpenAppToSplitScreenTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
this.mTestApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
}
@Override
TransitionRunner getTransitionToRun() {
return appToSplitScreen(mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns()
.build();
}
@Test
public void checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
}
@Test
public void checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
}
@Test
public void checkVisibility_dividerLayerBecomesVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.hidesLayer(DOCKED_STACK_DIVIDER)
.then()
.showsLayer(DOCKED_STACK_DIVIDER)
.forAllEntries());
}
}

View File

@@ -1,84 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.openAppWarm;
import static com.android.server.wm.flicker.WmTraceSubject.assertThat;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test warm launch app.
* To run this test: {@code atest FlickerTests:OpenAppWarmTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OpenAppWarmTest extends NonRotationTestBase {
public OpenAppWarmTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
this.mTestApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
}
@Override
TransitionRunner getTransitionToRun() {
return openAppWarm(mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Test
public void checkVisibility_wallpaperBecomesInvisible() {
checkResults(result -> assertThat(result)
.showsBelowAppWindow("Wallpaper")
.then()
.hidesBelowAppWindow("Wallpaper")
.forAllEntries());
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
public void checkZOrder_appWindowReplacesLauncherAsTopWindow() {
checkResults(result -> assertThat(result)
.showsAppWindowOnTop(
"com.android.launcher3/.Launcher")
.then()
.showsAppWindowOnTop(mTestApp.getPackage())
.forAllEntries());
}
@Test
public void checkVisibility_wallpaperLayerBecomesInvisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer("Wallpaper")
.then()
.replaceVisibleLayer("Wallpaper", mTestApp.getPackage())
.forAllEntries());
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.editTextSetFocus;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.ImeAppHelper;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test IME window opening transitions.
* To run this test: {@code atest FlickerTests:OpenImeWindowTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OpenImeWindowTest extends NonRotationTestBase {
private static final String IME_WINDOW_TITLE = "InputMethod";
public OpenImeWindowTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
mTestApp = new ImeAppHelper(InstrumentationRegistry.getInstrumentation());
}
@Override
TransitionRunner getTransitionToRun() {
return editTextSetFocus((ImeAppHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Test
public void checkVisibility_imeWindowBecomesVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.skipUntilFirstAssertion()
.hidesImeWindow(IME_WINDOW_TITLE)
.then()
.showsImeWindow(IME_WINDOW_TITLE)
.forAllEntries());
}
@Test
public void checkVisibility_imeLayerBecomesVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.hidesLayer(IME_WINDOW_TITLE)
.then()
.showsLayer(IME_WINDOW_TITLE)
.forAllEntries());
}
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (C) 2020 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;
import static com.android.server.wm.flicker.helpers.AutomationUtils.closePipWindow;
import static com.android.server.wm.flicker.helpers.AutomationUtils.hasPipWindow;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.uiautomator.UiDevice;
import com.android.server.wm.flicker.helpers.PipAppHelper;
import org.junit.AfterClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public abstract class PipTestBase extends NonRotationTestBase {
static final String sPipWindowTitle = "PipMenuActivity";
public PipTestBase(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
this.mTestApp = new PipAppHelper(InstrumentationRegistry.getInstrumentation());
}
@AfterClass
public static void teardown() {
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
if (hasPipWindow(device)) {
closePipWindow(device);
}
}
@Test
public void checkVisibility_pipWindowBecomesVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.skipUntilFirstAssertion()
.showsAppWindowOnTop(sPipWindowTitle)
.then()
.hidesAppWindow(sPipWindowTitle)
.forAllEntries());
}
@Test
public void checkVisibility_pipLayerBecomesVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.skipUntilFirstAssertion()
.showsLayer(sPipWindowTitle)
.then()
.hidesLayer(sPipWindowTitle)
.forAllEntries());
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2019 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;
import static com.android.server.wm.flicker.CommonTransitions.exitPipModeToApp;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.PipAppHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test Pip launch.
* To run this test: {@code atest FlickerTests:PipToAppTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
@Ignore("Waiting bug feedback")
public class PipToAppTest extends PipTestBase {
public PipToAppTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
}
@Override
TransitionRunner getTransitionToRun() {
return exitPipModeToApp((PipAppHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Test
public void checkVisibility_backgroundWindowVisibleBehindPipLayer() {
checkResults(result -> WmTraceSubject.assertThat(result)
.skipUntilFirstAssertion()
.showsAppWindowOnTop(sPipWindowTitle)
.then()
.showsBelowAppWindow("Wallpaper")
.then()
.showsAppWindowOnTop(mTestApp.getPackage())
.then()
.hidesAppWindowOnTop(mTestApp.getPackage())
.forAllEntries());
}
}

View File

@@ -1,64 +0,0 @@
/*
* Copyright (C) 2019 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;
import static com.android.server.wm.flicker.CommonTransitions.exitPipModeToHome;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import com.android.server.wm.flicker.helpers.PipAppHelper;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
/**
* Test Pip launch.
* To run this test: {@code atest FlickerTests:PipToHomeTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
@Ignore("Waiting bug feedback")
public class PipToHomeTest extends PipTestBase {
public PipToHomeTest(String beginRotationName, int beginRotation) {
super(beginRotationName, beginRotation);
}
@Override
TransitionRunner getTransitionToRun() {
return exitPipModeToHome((PipAppHelper) mTestApp, mUiDevice, mBeginRotation)
.includeJankyRuns().build();
}
@Ignore
@Test
public void checkVisibility_backgroundWindowVisibleBehindPipLayer() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAppWindowOnTop(sPipWindowTitle)
.then()
.showsBelowAppWindow("Wallpaper")
.then()
.showsAppWindowOnTop("Wallpaper")
.forAllEntries());
}
}

View File

@@ -1,200 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.resizeSplitScreen;
import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
import static com.android.server.wm.flicker.WindowUtils.getDockedStackDividerInset;
import static com.android.server.wm.flicker.WindowUtils.getNavigationBarHeight;
import static com.android.server.wm.flicker.helpers.AutomationUtils.exitSplitScreen;
import static com.android.server.wm.flicker.helpers.AutomationUtils.isInSplitScreen;
import static com.google.common.truth.Truth.assertThat;
import android.app.Instrumentation;
import android.graphics.Rect;
import android.util.Rational;
import android.view.Surface;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
import com.android.server.wm.flicker.helpers.ImeAppHelper;
import org.junit.AfterClass;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
/**
* Test split screen resizing window transitions.
* To run this test: {@code atest FlickerTests:ResizeSplitScreenTest}
*
* Currently it runs only in 0 degrees because of b/156100803
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 159096424)
@Ignore("Waiting bug feedback")
public class ResizeSplitScreenTest extends FlickerTestBase {
private static String sSimpleActivity = "SimpleActivity";
private static String sImeActivity = "ImeActivity";
public ResizeSplitScreenTest() {
this.mTestApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
}
@Override
TransitionRunner getTransitionToRun() {
Instrumentation instr = InstrumentationRegistry.getInstrumentation();
ImeAppHelper bottomApp = new ImeAppHelper(instr);
return resizeSplitScreen(instr, mTestApp, bottomApp, mUiDevice, Surface.ROTATION_0,
new Rational(1, 3), new Rational(2, 3))
.includeJankyRuns().build();
}
@Test
public void checkVisibility_topAppLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(sSimpleActivity)
.forAllEntries());
}
@Test
public void checkVisibility_bottomAppLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(sImeActivity)
.forAllEntries());
}
@Test
public void checkVisibility_dividerLayerIsAlwaysVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(DOCKED_STACK_DIVIDER)
.forAllEntries());
}
@Test
@Ignore("Waiting feedback")
public void checkPosition_appsStartingBounds() {
Rect displayBounds = getDisplayBounds();
checkResults(result -> {
LayersTrace entries = LayersTrace.parseFrom(result.getLayersTrace(),
result.getLayersTracePath(), result.getLayersTraceChecksum());
assertThat(entries.getEntries()).isNotEmpty();
Rect startingDividerBounds = entries.getEntries().get(0).getVisibleBounds
(DOCKED_STACK_DIVIDER);
Rect startingTopAppBounds = new Rect(0, 0, startingDividerBounds.right,
startingDividerBounds.top + getDockedStackDividerInset());
Rect startingBottomAppBounds = new Rect(0,
startingDividerBounds.bottom - getDockedStackDividerInset(),
displayBounds.right,
displayBounds.bottom - getNavigationBarHeight());
LayersTraceSubject.assertThat(result)
.hasVisibleRegion("SimpleActivity", startingTopAppBounds)
.inTheBeginning();
LayersTraceSubject.assertThat(result)
.hasVisibleRegion("ImeActivity", startingBottomAppBounds)
.inTheBeginning();
});
}
@Test
@Ignore("Waiting feedback")
public void checkPosition_appsEndingBounds() {
Rect displayBounds = getDisplayBounds();
checkResults(result -> {
LayersTrace entries = LayersTrace.parseFrom(result.getLayersTrace(),
result.getLayersTracePath(), result.getLayersTraceChecksum());
assertThat(entries.getEntries()).isNotEmpty();
Rect endingDividerBounds = entries.getEntries().get(
entries.getEntries().size() - 1).getVisibleBounds(
DOCKED_STACK_DIVIDER);
Rect startingTopAppBounds = new Rect(0, 0, endingDividerBounds.right,
endingDividerBounds.top + getDockedStackDividerInset());
Rect startingBottomAppBounds = new Rect(0,
endingDividerBounds.bottom - getDockedStackDividerInset(),
displayBounds.right,
displayBounds.bottom - getNavigationBarHeight());
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(sSimpleActivity, startingTopAppBounds)
.atTheEnd();
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(sImeActivity, startingBottomAppBounds)
.atTheEnd();
});
}
@Test
public void checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE)
.forAllEntries());
}
@Test
public void checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE)
.forAllEntries());
}
@Test
@FlakyTest(bugId = 156223549)
@Ignore("Waiting bug feedback")
public void checkVisibility_topAppWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAppWindow(sSimpleActivity)
.forAllEntries());
}
@Test
@FlakyTest(bugId = 156223549)
@Ignore("Waiting bug feedback")
public void checkVisibility_bottomAppWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAppWindow(sImeActivity)
.forAllEntries());
}
@AfterClass
public static void teardown() {
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
if (isInSplitScreen(device)) {
exitSplitScreen(device);
}
}
}

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2020 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
import android.view.Surface
import androidx.test.filters.FlakyTest
import org.junit.Ignore
import org.junit.Test
import org.junit.runners.Parameterized
abstract class RotationTestBase(
beginRotationName: String,
endRotationName: String,
protected val beginRotation: Int,
protected val endRotation: Int
) : FlickerTestBase() {
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
fun checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
}
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
fun checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries()
}
}
@Test
fun checkPosition_navBarLayerRotatesAndScales() {
val startingPos = WindowUtils.getNavigationBarPosition(beginRotation)
val endingPos = WindowUtils.getNavigationBarPosition(endRotation)
if (startingPos == endingPos) {
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
.forAllEntries()
}
} else {
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
.inTheBeginning()
}
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos)
.atTheEnd()
}
}
}
@Test
fun checkPosition_statusBarLayerRotatesScales() {
val startingPos = WindowUtils.getStatusBarPosition(beginRotation)
val endingPos = WindowUtils.getStatusBarPosition(endRotation)
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, startingPos)
.inTheBeginning()
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(STATUS_BAR_WINDOW_TITLE, endingPos).atTheEnd()
}
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
fun checkVisibility_navBarLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
}
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
fun checkVisibility_statusBarLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(STATUS_BAR_WINDOW_TITLE).forAllEntries()
}
}
companion object {
const val SCREENSHOT_LAYER = "RotationLayer"
@Parameterized.Parameters(name = "{0}-{1}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
val params: MutableCollection<Array<Any>> = mutableListOf()
for (begin in supportedRotations) {
for (end in supportedRotations) {
if (begin != end) {
params.add(arrayOf(
Surface.rotationToString(begin),
Surface.rotationToString(end),
begin,
end
))
}
}
}
return params
}
}
}

View File

@@ -1,175 +0,0 @@
/*
* Copyright (C) 2018 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;
import static android.view.Surface.rotationToString;
import static com.android.server.wm.flicker.CommonTransitions.changeAppRotation;
import static com.android.server.wm.flicker.WindowUtils.getAppPosition;
import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
import static com.android.server.wm.flicker.WindowUtils.getNavigationBarPosition;
import static com.android.server.wm.flicker.testapp.ActivityOptions.EXTRA_STARVE_UI_THREAD;
import static com.android.server.wm.flicker.testapp.ActivityOptions.SEAMLESS_ACTIVITY_COMPONENT_NAME;
import android.content.Intent;
import android.graphics.Rect;
import android.view.Surface;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.LargeTest;
import org.junit.FixMethodOrder;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import java.util.ArrayList;
import java.util.Collection;
/**
* Cycle through supported app rotations using seamless rotations.
* To run this test: {@code atest FlickerTests:SeamlessAppRotationTest}
*/
@LargeTest
@RunWith(Parameterized.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 147659548)
@Ignore("Waiting bug feedback")
public class SeamlessAppRotationTest extends FlickerTestBase {
private int mBeginRotation;
private int mEndRotation;
private Intent mIntent;
public SeamlessAppRotationTest(String testId, Intent intent, int beginRotation,
int endRotation) {
this.mIntent = intent;
this.mBeginRotation = beginRotation;
this.mEndRotation = endRotation;
}
@Parameters(name = "{0}")
public static Collection<Object[]> getParams() {
int[] supportedRotations =
{Surface.ROTATION_0, Surface.ROTATION_90};
Collection<Object[]> params = new ArrayList<>();
ArrayList<Intent> testIntents = new ArrayList<>();
// launch test activity that supports seamless rotation
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(SEAMLESS_ACTIVITY_COMPONENT_NAME);
testIntents.add(intent);
// launch test activity that supports seamless rotation with a busy UI thread to miss frames
// when the app is asked to redraw
intent = new Intent(intent);
intent.putExtra(EXTRA_STARVE_UI_THREAD, true);
testIntents.add(intent);
for (Intent testIntent : testIntents) {
for (int begin : supportedRotations) {
for (int end : supportedRotations) {
if (begin != end) {
String testId = rotationToString(begin) + "_" + rotationToString(end);
if (testIntent.getExtras() != null &&
testIntent.getExtras().getBoolean(EXTRA_STARVE_UI_THREAD)) {
testId += "_" + "BUSY_UI_THREAD";
}
params.add(new Object[]{testId, testIntent, begin, end});
}
}
}
}
return params;
}
@Override
TransitionRunner getTransitionToRun() {
String intentId = "";
if (mIntent.getExtras() != null &&
mIntent.getExtras().getBoolean(EXTRA_STARVE_UI_THREAD)) {
intentId = "BUSY_UI_THREAD";
}
return changeAppRotation(mIntent, intentId, InstrumentationRegistry.getContext(),
mUiDevice, mBeginRotation, mEndRotation).build();
}
@Test
public void checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
}
@Test
public void checkPosition_navBarLayerRotatesAndScales() {
Rect startingPos = getNavigationBarPosition(mBeginRotation);
Rect endingPos = getNavigationBarPosition(mEndRotation);
if (startingPos.equals(endingPos)) {
checkResults(result -> LayersTraceSubject.assertThat(result)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
.forAllEntries());
} else {
checkResults(result -> LayersTraceSubject.assertThat(result)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, startingPos)
.inTheBeginning());
checkResults(result -> LayersTraceSubject.assertThat(result)
.hasVisibleRegion(NAVIGATION_BAR_WINDOW_TITLE, endingPos)
.atTheEnd());
}
}
@Test
public void checkPosition_appLayerRotates() {
Rect startingPos = getAppPosition(mBeginRotation);
Rect endingPos = getAppPosition(mEndRotation);
if (startingPos.equals(endingPos)) {
checkResults(result -> LayersTraceSubject.assertThat(result)
.hasVisibleRegion(mIntent.getComponent().getPackageName(), startingPos)
.forAllEntries());
} else {
checkResults(result -> LayersTraceSubject.assertThat(result)
.hasVisibleRegion(mIntent.getComponent().getPackageName(), startingPos)
.then()
.hasVisibleRegion(mIntent.getComponent().getPackageName(), endingPos)
.forAllEntries());
}
}
@Test
public void checkCoveredRegion_noUncoveredRegions() {
Rect startingBounds = getDisplayBounds(mBeginRotation);
Rect endingBounds = getDisplayBounds(mEndRotation);
if (startingBounds.equals(endingBounds)) {
checkResults(result ->
LayersTraceSubject.assertThat(result)
.coversRegion(startingBounds)
.forAllEntries());
} else {
checkResults(result ->
LayersTraceSubject.assertThat(result)
.coversRegion(startingBounds)
.then()
.coversRegion(endingBounds)
.forAllEntries());
}
}
}

View File

@@ -1,102 +0,0 @@
/*
* Copyright (C) 2018 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;
import static com.android.server.wm.flicker.CommonTransitions.splitScreenToLauncher;
import static com.android.server.wm.flicker.WindowUtils.getDisplayBounds;
import static com.android.server.wm.flicker.helpers.AutomationUtils.exitSplitScreen;
import static com.android.server.wm.flicker.helpers.AutomationUtils.isInSplitScreen;
import android.view.Surface;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
import org.junit.AfterClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
/**
* Test open app to split screen.
* To run this test: {@code atest FlickerTests:SplitScreenToLauncherTest}
*/
@LargeTest
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class SplitScreenToLauncherTest extends FlickerTestBase {
public SplitScreenToLauncherTest() {
this.mTestApp = new StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp");
}
@Override
TransitionRunner getTransitionToRun() {
return splitScreenToLauncher(mTestApp, mUiDevice, Surface.ROTATION_0)
.includeJankyRuns().build();
}
@Test
public void checkCoveredRegion_noUncoveredRegions() {
checkResults(result ->
LayersTraceSubject.assertThat(result)
.coversRegion(getDisplayBounds()).forAllEntries());
}
@Test
public void checkVisibility_dividerLayerBecomesInVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(DOCKED_STACK_DIVIDER)
.then()
.hidesLayer(DOCKED_STACK_DIVIDER)
.forAllEntries());
}
@Test
public void checkVisibility_appLayerBecomesInVisible() {
checkResults(result -> LayersTraceSubject.assertThat(result)
.showsLayer(mTestApp.getPackage())
.then()
.hidesLayer(mTestApp.getPackage())
.forAllEntries());
}
@Test
public void checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries());
}
@Test
public void checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults(result -> WmTraceSubject.assertThat(result)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries());
}
@AfterClass
public static void teardown() {
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
if (isInSplitScreen(device)) {
exitSplitScreen(device);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 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.
@@ -14,18 +14,17 @@
* limitations under the License.
*/
package com.android.server.wm.flicker.helpers;
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation;
import android.app.Instrumentation
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.StandardAppHelper;
public abstract class FlickerAppHelper extends StandardAppHelper {
static int sFindTimeout = 10000;
static String sFlickerPackage = "com.android.server.wm.flicker.testapp";
public FlickerAppHelper(Instrumentation instr, String launcherName) {
super(instr, sFlickerPackage, launcherName);
abstract class FlickerAppHelper(
instr: Instrumentation,
launcherName: String
) : StandardAppHelper(instr, sFlickerPackage, launcherName) {
companion object {
var sFindTimeout = 10000
var sFlickerPackage = "com.android.server.wm.flicker.testapp"
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 The Android Open Source Project
* Copyright (C) 2020 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.
@@ -14,19 +14,13 @@
* limitations under the License.
*/
package com.android.server.wm.flicker.helpers;
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation;
import android.app.Instrumentation
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiDevice;
public class ImeAppAutoFocusHelper extends ImeAppHelper {
public ImeAppAutoFocusHelper(Instrumentation instr) {
super(instr, "ImeAppAutoFocus");
}
public void openIME(UiDevice device) {
class ImeAppAutoFocusHelper(instr: Instrumentation) : ImeAppHelper(instr, "ImeAppAutoFocus") {
override fun openIME(device: UiDevice) {
// do nothing (the app is focused automatically)
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright (C) 2019 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.helpers;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import android.app.Instrumentation;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
public class ImeAppHelper extends FlickerAppHelper {
ImeAppHelper(Instrumentation instr, String launcherName) {
super(instr, launcherName);
}
public ImeAppHelper(Instrumentation instr) {
this(instr, "ImeApp");
}
public void openIME(UiDevice device) {
UiObject2 editText = device.wait(
Until.findObject(By.res(getPackage(), "plain_text_input")),
AutomationUtils.FIND_TIMEOUT);
assertNotNull("Text field not found, this usually happens when the device was left "
+ "in an unknown state (e.g. in split screen)", editText);
editText.click();
if (!AutomationUtils.waitForIME(device)) {
fail("IME did not appear");
}
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2020 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.helpers
import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
import org.junit.Assert
open class ImeAppHelper(
instr: Instrumentation,
launcherName: String = "ImeApp"
) : FlickerAppHelper(instr, launcherName) {
open fun openIME(device: UiDevice) {
val editText = device.wait(
Until.findObject(By.res(getPackage(), "plain_text_input")),
AutomationUtils.FIND_TIMEOUT)
Assert.assertNotNull("Text field not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)", editText)
editText.click()
if (!AutomationUtils.waitForIME(device)) {
Assert.fail("IME did not appear")
}
}
}

View File

@@ -1,47 +0,0 @@
/*
* Copyright (C) 2019 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.helpers;
import static com.android.server.wm.flicker.helpers.AutomationUtils.hasPipWindow;
import static org.junit.Assert.assertNotNull;
import android.app.Instrumentation;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
public class PipAppHelper extends FlickerAppHelper {
public PipAppHelper(Instrumentation instr) {
super(instr, "PipApp");
}
public void clickEnterPipButton(UiDevice device) {
UiObject2 enterPipButton = device.findObject(By.res(getPackage(), "enter_pip"));
assertNotNull("Pip button not found, this usually happens when the device was left "
+ "in an unknown state (e.g. in split screen)", enterPipButton);
enterPipButton.click();
hasPipWindow(device);
}
public void closePipWindow(UiDevice device) {
AutomationUtils.closePipWindow(device);
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 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.helpers
import android.app.Instrumentation
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import org.junit.Assert
class PipAppHelper(instr: Instrumentation) : FlickerAppHelper(instr, "PipApp") {
fun clickEnterPipButton(device: UiDevice) {
val enterPipButton = device.findObject(By.res(getPackage(), "enter_pip"))
Assert.assertNotNull("Pip button not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)", enterPipButton)
enterPipButton.click()
AutomationUtils.hasPipWindow(device)
}
fun closePipWindow(device: UiDevice) {
AutomationUtils.closePipWindow(device)
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2020 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.ime
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test IME window closing back to app window transitions.
* To run this test: `atest FlickerTests:CloseImeWindowToAppTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class CloseImeAutoOpenWindowToAppTest(
beginRotationName: String,
beginRotation: Int
) : CloseImeWindowToAppTest(beginRotationName, beginRotation) {
init {
testApp = ImeAppAutoFocusHelper(instrumentation)
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.editTextLoseFocusToApp(testApp as ImeAppAutoFocusHelper,
instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
override fun checkVisibility_imeLayerBecomesInvisible() {
super.checkVisibility_imeLayerBecomesInvisible()
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
override fun checkVisibility_imeAppLayerIsAlwaysVisible() {
super.checkVisibility_imeAppLayerIsAlwaysVisible()
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
override fun checkVisibility_imeAppWindowIsAlwaysVisible() {
super.checkVisibility_imeAppWindowIsAlwaysVisible()
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2020 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.ime
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test IME window closing back to app window transitions.
* To run this test: `atest FlickerTests:CloseImeWindowToAppTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class CloseImeAutoOpenWindowToHomeTest(
beginRotationName: String,
beginRotation: Int
) : CloseImeWindowToHomeTest(beginRotationName, beginRotation) {
init {
testApp = ImeAppAutoFocusHelper(instrumentation)
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.editTextLoseFocusToHome(testApp as ImeAppAutoFocusHelper,
instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
override fun checkVisibility_imeWindowBecomesInvisible() {
super.checkVisibility_imeWindowBecomesInvisible()
}
@FlakyTest(bugId = 141458352)
@Ignore("Waiting bug feedback")
@Test
override fun checkVisibility_imeLayerBecomesInvisible() {
super.checkVisibility_imeLayerBecomesInvisible()
}
@FlakyTest(bugId = 157449248)
@Ignore("Waiting bug feedback")
@Test
override fun checkVisibility_imeAppWindowBecomesInvisible() {
super.checkVisibility_imeAppWindowBecomesInvisible()
}
}

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2020 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.ime
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.ImeAppHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test IME window closing back to app window transitions.
* To run this test: `atest FlickerTests:CloseImeWindowToAppTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class CloseImeWindowToAppTest(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = ImeAppHelper(instrumentation)
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.editTextLoseFocusToApp(testApp as ImeAppHelper,
instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@Ignore("Flaky. Pending debug")
@Test
open fun checkVisibility_imeLayerBecomesInvisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(IME_WINDOW_TITLE)
.then()
.hidesLayer(IME_WINDOW_TITLE)
.forAllEntries()
}
}
@Test
open fun checkVisibility_imeAppLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(testApp.getPackage())
.forAllEntries()
}
}
@Test
open fun checkVisibility_imeAppWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindowOnTop(testApp.getPackage())
.forAllEntries()
}
}
companion object {
const val IME_WINDOW_TITLE = "InputMethod"
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2020 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.ime
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.ImeAppHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test IME window closing to home transitions.
* To run this test: `atest FlickerTests:CloseImeWindowToHomeTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class CloseImeWindowToHomeTest(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = ImeAppHelper(instrumentation)
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.editTextLoseFocusToHome(testApp as ImeAppHelper,
instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@Test
open fun checkVisibility_imeWindowBecomesInvisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsImeWindow(IME_WINDOW_TITLE)
.then()
.hidesImeWindow(IME_WINDOW_TITLE)
.forAllEntries()
}
}
@FlakyTest(bugId = 153739621)
@Ignore
@Test
open fun checkVisibility_imeLayerBecomesInvisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.skipUntilFirstAssertion()
.showsLayer(IME_WINDOW_TITLE)
.then()
.hidesLayer(IME_WINDOW_TITLE)
.forAllEntries()
}
}
@FlakyTest(bugId = 153739621)
@Ignore
@Test
fun checkVisibility_imeAppLayerBecomesInvisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.skipUntilFirstAssertion()
.showsLayer(testApp.getPackage())
.then()
.hidesLayer(testApp.getPackage())
.forAllEntries()
}
}
@Test
open fun checkVisibility_imeAppWindowBecomesInvisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindowOnTop(testApp.getPackage())
.then()
.hidesAppWindowOnTop(testApp.getPackage())
.forAllEntries()
}
}
companion object {
const val IME_WINDOW_TITLE: String = "InputMethod"
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2020 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.ime
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.ImeAppHelper
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test IME window opening transitions.
* To run this test: `atest FlickerTests:OpenImeWindowTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenImeWindowTest(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = ImeAppHelper(instrumentation)
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.editTextSetFocus(testApp as ImeAppHelper,
instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@Test
fun checkVisibility_imeWindowBecomesVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.skipUntilFirstAssertion()
.hidesImeWindow(IME_WINDOW_TITLE)
.then()
.showsImeWindow(IME_WINDOW_TITLE)
.forAllEntries()
}
}
@Test
fun checkVisibility_imeLayerBecomesVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.hidesLayer(IME_WINDOW_TITLE)
.then()
.showsLayer(IME_WINDOW_TITLE)
.forAllEntries()
}
}
companion object {
private const val IME_WINDOW_TITLE = "InputMethod"
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 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.launch
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test cold launch app from launcher.
* To run this test: `atest FlickerTests:OpenAppColdTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenAppColdTest(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.openAppCold(testApp, instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@Test
fun checkVisibility_wallpaperWindowBecomesInvisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsBelowAppWindow("Wallpaper")
.then()
.hidesBelowAppWindow("Wallpaper")
.forAllEntries()
}
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
fun checkZOrder_appWindowReplacesLauncherAsTopWindow() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindowOnTop(
"com.android.launcher3/.Launcher")
.then()
.showsAppWindowOnTop(testApp.getPackage())
.forAllEntries()
}
}
@Test
fun checkVisibility_wallpaperLayerBecomesInvisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer("Wallpaper")
.then()
.replaceVisibleLayer("Wallpaper", testApp.getPackage())
.forAllEntries()
}
}
}

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2020 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.launch
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test warm launch app.
* To run this test: `atest FlickerTests:OpenAppWarmTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenAppWarmTest(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.openAppWarm(testApp, instrumentation, uiDevice, beginRotation)
.includeJankyRuns().build()
@Test
fun checkVisibility_wallpaperBecomesInvisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsBelowAppWindow("Wallpaper")
.then()
.hidesBelowAppWindow("Wallpaper")
.forAllEntries()
}
}
@FlakyTest(bugId = 140855415)
@Ignore("Waiting bug feedback")
@Test
fun checkZOrder_appWindowReplacesLauncherAsTopWindow() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindowOnTop(
"com.android.launcher3/.Launcher")
.then()
.showsAppWindowOnTop(testApp.getPackage())
.forAllEntries()
}
}
@Test
fun checkVisibility_wallpaperLayerBecomesInvisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer("Wallpaper")
.then()
.replaceVisibleLayer("Wallpaper", testApp.getPackage())
.forAllEntries()
}
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2020 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.pip
import androidx.test.InstrumentationRegistry
import androidx.test.filters.LargeTest
import androidx.test.uiautomator.UiDevice
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.AutomationUtils
import com.android.server.wm.flicker.helpers.PipAppHelper
import org.junit.AfterClass
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
abstract class PipTestBase(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = PipAppHelper(instrumentation)
}
@Test
fun checkVisibility_pipWindowBecomesVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.skipUntilFirstAssertion()
.showsAppWindowOnTop(sPipWindowTitle)
.then()
.hidesAppWindow(sPipWindowTitle)
.forAllEntries()
}
}
@Test
fun checkVisibility_pipLayerBecomesVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.skipUntilFirstAssertion()
.showsLayer(sPipWindowTitle)
.then()
.hidesLayer(sPipWindowTitle)
.forAllEntries()
}
}
companion object {
const val sPipWindowTitle = "PipMenuActivity"
@AfterClass
@JvmStatic
fun teardown() {
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
if (AutomationUtils.hasPipWindow(device)) {
AutomationUtils.closePipWindow(device)
}
}
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2020 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.pip
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.PipAppHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test Pip launch.
* To run this test: `atest FlickerTests:PipToAppTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
@Ignore("Waiting bug feedback")
class PipToAppTest(
beginRotationName: String,
beginRotation: Int
) : PipTestBase(beginRotationName, beginRotation) {
override val transitionToRun: TransitionRunner
get() = CommonTransitions.exitPipModeToApp(testApp as PipAppHelper, instrumentation,
uiDevice, beginRotation)
.includeJankyRuns().build()
@Test
fun checkVisibility_backgroundWindowVisibleBehindPipLayer() {
checkResults {
WmTraceSubject.assertThat(it)
.skipUntilFirstAssertion()
.showsAppWindowOnTop(sPipWindowTitle)
.then()
.showsBelowAppWindow("Wallpaper")
.then()
.showsAppWindowOnTop(testApp.getPackage())
.then()
.hidesAppWindowOnTop(testApp.getPackage())
.forAllEntries()
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 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.pip
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.PipAppHelper
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test Pip launch.
* To run this test: `atest FlickerTests:PipToHomeTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 152738416)
@Ignore("Waiting bug feedback")
class PipToHomeTest(
beginRotationName: String,
beginRotation: Int
) : PipTestBase(beginRotationName, beginRotation) {
override val transitionToRun: TransitionRunner
get() = CommonTransitions.exitPipModeToHome(testApp as PipAppHelper, instrumentation,
uiDevice, beginRotation)
.includeJankyRuns().build()
@Ignore
@Test
fun checkVisibility_backgroundWindowVisibleBehindPipLayer() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindowOnTop(sPipWindowTitle)
.then()
.showsBelowAppWindow("Wallpaper")
.then()
.showsAppWindowOnTop("Wallpaper")
.forAllEntries()
}
}
}

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2020 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.rotation
import android.util.Log
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.RotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WindowUtils
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Cycle through supported app rotations.
* To run this test: `atest FlickerTest:ChangeAppRotationTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class ChangeAppRotationTest(
beginRotationName: String,
endRotationName: String,
beginRotation: Int,
endRotation: Int
) : RotationTestBase(beginRotationName, endRotationName, beginRotation, endRotation) {
init {
testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.changeAppRotation(testApp, instrumentation, uiDevice,
beginRotation, endRotation)
.includeJankyRuns().build()
@Test
fun checkPosition_appLayerRotates() {
val startingPos = WindowUtils.getAppPosition(beginRotation)
val endingPos = WindowUtils.getAppPosition(endRotation)
Log.e(TAG, "startingPos=$startingPos endingPos=$endingPos")
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(testApp.getPackage(), startingPos).inTheBeginning()
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(testApp.getPackage(), endingPos).atTheEnd()
}
}
@Ignore("Flaky. Pending debug")
@Test
fun checkVisibility_screenshotLayerBecomesInvisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(testApp.getPackage())
.then()
.replaceVisibleLayer(testApp.getPackage(), SCREENSHOT_LAYER)
.then()
.showsLayer(testApp.getPackage()).and().showsLayer(SCREENSHOT_LAYER)
.then()
.replaceVisibleLayer(SCREENSHOT_LAYER, testApp.getPackage())
.forAllEntries()
}
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright (C) 2020 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.rotation
import android.content.Intent
import android.view.Surface
import androidx.test.InstrumentationRegistry
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.RotationTestBase
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WindowUtils
import com.android.server.wm.flicker.testapp.ActivityOptions
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Cycle through supported app rotations using seamless rotations.
* To run this test: `atest FlickerTests:SeamlessAppRotationTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 147659548)
@Ignore("Waiting bug feedback")
class SeamlessAppRotationTest(
private val intent: Intent,
beginRotationName: String,
endRotationName: String,
beginRotation: Int,
endRotation: Int
) : RotationTestBase(beginRotationName, endRotationName, beginRotation, endRotation) {
override val transitionToRun: TransitionRunner
get() {
var intentId = ""
if (intent.extras?.getBoolean(ActivityOptions.EXTRA_STARVE_UI_THREAD) == true) {
intentId = "BUSY_UI_THREAD"
}
return CommonTransitions.changeAppRotation(intent, intentId,
InstrumentationRegistry.getContext(), instrumentation, uiDevice,
beginRotation, endRotation).build()
}
@Test
fun checkPosition_appLayerRotates() {
val startingPos = WindowUtils.getAppPosition(beginRotation)
val endingPos = WindowUtils.getAppPosition(endRotation)
if (startingPos == endingPos) {
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(intent.component?.packageName ?: "", startingPos)
.forAllEntries()
}
} else {
checkResults {
LayersTraceSubject.assertThat(it)
.hasVisibleRegion(intent.component?.packageName ?: "", startingPos)
.then()
.hasVisibleRegion(intent.component?.packageName ?: "", endingPos)
.forAllEntries()
}
}
}
@Test
fun checkCoveredRegion_noUncoveredRegions() {
val startingBounds = WindowUtils.getDisplayBounds(beginRotation)
val endingBounds = WindowUtils.getDisplayBounds(endRotation)
if (startingBounds == endingBounds) {
checkResults {
LayersTraceSubject.assertThat(it)
.coversRegion(startingBounds)
.forAllEntries()
}
} else {
checkResults {
LayersTraceSubject.assertThat(it)
.coversRegion(startingBounds)
.then()
.coversRegion(endingBounds)
.forAllEntries()
}
}
}
companion object {
// launch test activity that supports seamless rotation
// launch test activity that supports seamless rotation with a busy UI thread to miss frames
// when the app is asked to redraw
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<Array<Any>> {
val supportedRotations = intArrayOf(Surface.ROTATION_0, Surface.ROTATION_90)
val params: MutableCollection<Array<Any>> = ArrayList()
val testIntents = ArrayList<Intent>()
// launch test activity that supports seamless rotation
var intent = Intent(Intent.ACTION_MAIN)
intent.component = ActivityOptions.SEAMLESS_ACTIVITY_COMPONENT_NAME
testIntents.add(intent)
// launch test activity that supports seamless rotation with a busy UI thread to miss frames
// when the app is asked to redraw
intent = Intent(intent)
intent.putExtra(ActivityOptions.EXTRA_STARVE_UI_THREAD, true)
testIntents.add(intent)
for (testIntent in testIntents) {
for (begin in supportedRotations) {
for (end in supportedRotations) {
if (begin != end) {
var testId: String = Surface.rotationToString(begin) +
"_" + Surface.rotationToString(end)
if (testIntent.extras?.getBoolean(
ActivityOptions.EXTRA_STARVE_UI_THREAD) == true) {
testId += "_" + "BUSY_UI_THREAD"
}
params.add(arrayOf(testId, testIntent, begin, end))
}
}
}
}
return params
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2020 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.splitscreen
import androidx.test.filters.LargeTest
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.NonRotationTestBase
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WmTraceSubject
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
* Test open app to split screen.
* To run this test: `atest FlickerTests:OpenAppToSplitScreenTest`
*/
@LargeTest
@RunWith(Parameterized::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class OpenAppToSplitScreenTest(
beginRotationName: String,
beginRotation: Int
) : NonRotationTestBase(beginRotationName, beginRotation) {
init {
testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.appToSplitScreen(testApp, instrumentation, uiDevice,
beginRotation).includeJankyRuns().build()
@Test
fun checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
}
}
@Test
fun checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries()
}
}
@Test
fun checkVisibility_dividerLayerBecomesVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.hidesLayer(DOCKED_STACK_DIVIDER)
.then()
.showsLayer(DOCKED_STACK_DIVIDER)
.forAllEntries()
}
}
}

View File

@@ -0,0 +1,202 @@
/*
* Copyright (C) 2020 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.splitscreen
import android.graphics.Region
import android.util.Rational
import android.view.Surface
import androidx.test.InstrumentationRegistry
import androidx.test.filters.FlakyTest
import androidx.test.filters.LargeTest
import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.UiDevice
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.FlickerTestBase
import com.android.server.wm.flicker.LayersTrace
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.TransitionResult
import com.android.server.wm.flicker.WindowUtils
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.AutomationUtils
import com.android.server.wm.flicker.helpers.ImeAppHelper
import com.google.common.truth.Truth
import org.junit.AfterClass
import org.junit.FixMethodOrder
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
/**
* Test split screen resizing window transitions.
* To run this test: `atest FlickerTests:ResizeSplitScreenTest`
*
* Currently it runs only in 0 degrees because of b/156100803
*/
@LargeTest
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 159096424)
@Ignore("Waiting bug feedback")
class ResizeSplitScreenTest : FlickerTestBase() {
init {
testApp = StandardAppHelper(instrumentation,
"com.android.server.wm.flicker.testapp", "SimpleApp")
}
override val transitionToRun: TransitionRunner
get() {
val bottomApp = ImeAppHelper(instrumentation)
return CommonTransitions.resizeSplitScreen(testApp, bottomApp, instrumentation,
uiDevice, Surface.ROTATION_0,
Rational(1, 3), Rational(2, 3))
.includeJankyRuns().build()
}
@Test
fun checkVisibility_topAppLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(sSimpleActivity)
.forAllEntries()
}
}
@Test
fun checkVisibility_bottomAppLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(sImeActivity)
.forAllEntries()
}
}
@Test
fun checkVisibility_dividerLayerIsAlwaysVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(DOCKED_STACK_DIVIDER)
.forAllEntries()
}
}
@Test
@Ignore("Waiting feedback")
fun checkPosition_appsStartingBounds() {
val displayBounds = WindowUtils.getDisplayBounds()
checkResults { result: TransitionResult ->
val entries = LayersTrace.parseFrom(result.layersTrace,
result.layersTracePath, result.layersTraceChecksum)
Truth.assertThat(entries.entries).isNotEmpty()
val startingDividerBounds = entries.entries[0].getVisibleBounds(
DOCKED_STACK_DIVIDER).bounds
val startingTopAppBounds = Region(0, 0, startingDividerBounds.right,
startingDividerBounds.top + WindowUtils.getDockedStackDividerInset())
val startingBottomAppBounds = Region(0,
startingDividerBounds.bottom - WindowUtils.getDockedStackDividerInset(),
displayBounds.right,
displayBounds.bottom - WindowUtils.getNavigationBarHeight())
LayersTraceSubject.assertThat(result)
.hasVisibleRegion("SimpleActivity", startingTopAppBounds)
.inTheBeginning()
LayersTraceSubject.assertThat(result)
.hasVisibleRegion("ImeActivity", startingBottomAppBounds)
.inTheBeginning()
}
}
@Test
@Ignore("Waiting feedback")
fun checkPosition_appsEndingBounds() {
val displayBounds = WindowUtils.getDisplayBounds()
checkResults { result: TransitionResult ->
val entries = LayersTrace.parseFrom(result.layersTrace,
result.layersTracePath, result.layersTraceChecksum)
Truth.assertThat(entries.entries).isNotEmpty()
val endingDividerBounds = entries.entries[entries.entries.size - 1].getVisibleBounds(
DOCKED_STACK_DIVIDER).bounds
val startingTopAppBounds = Region(0, 0, endingDividerBounds.right,
endingDividerBounds.top + WindowUtils.getDockedStackDividerInset())
val startingBottomAppBounds = Region(0,
endingDividerBounds.bottom - WindowUtils.getDockedStackDividerInset(),
displayBounds.right,
displayBounds.bottom - WindowUtils.getNavigationBarHeight())
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(sSimpleActivity, startingTopAppBounds)
.atTheEnd()
LayersTraceSubject.assertThat(result)
.hasVisibleRegion(sImeActivity, startingBottomAppBounds)
.atTheEnd()
}
}
@Test
fun checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE)
.forAllEntries()
}
}
@Test
fun checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE)
.forAllEntries()
}
}
@Test
@FlakyTest(bugId = 156223549)
@Ignore("Waiting bug feedback")
fun checkVisibility_topAppWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindow(sSimpleActivity)
.forAllEntries()
}
}
@Test
@FlakyTest(bugId = 156223549)
@Ignore("Waiting bug feedback")
fun checkVisibility_bottomAppWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAppWindow(sImeActivity)
.forAllEntries()
}
}
companion object {
private const val sSimpleActivity = "SimpleActivity"
private const val sImeActivity = "ImeActivity"
@AfterClass
@JvmStatic
fun teardown() {
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
if (AutomationUtils.isInSplitScreen(device)) {
AutomationUtils.exitSplitScreen(device)
}
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (C) 2020 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.splitscreen
import android.view.Surface
import androidx.test.InstrumentationRegistry
import androidx.test.filters.LargeTest
import androidx.test.runner.AndroidJUnit4
import androidx.test.uiautomator.UiDevice
import com.android.server.wm.flicker.CommonTransitions
import com.android.server.wm.flicker.FlickerTestBase
import com.android.server.wm.flicker.LayersTraceSubject
import com.android.server.wm.flicker.StandardAppHelper
import com.android.server.wm.flicker.TransitionRunner
import com.android.server.wm.flicker.WindowUtils
import com.android.server.wm.flicker.WmTraceSubject
import com.android.server.wm.flicker.helpers.AutomationUtils
import org.junit.AfterClass
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
/**
* Test open app to split screen.
* To run this test: `atest FlickerTests:SplitScreenToLauncherTest`
*/
@LargeTest
@RunWith(AndroidJUnit4::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class SplitScreenToLauncherTest : FlickerTestBase() {
init {
testApp = StandardAppHelper(InstrumentationRegistry.getInstrumentation(),
"com.android.server.wm.flicker.testapp", "SimpleApp")
}
override val transitionToRun: TransitionRunner
get() = CommonTransitions.splitScreenToLauncher(testApp, instrumentation, uiDevice,
Surface.ROTATION_0).includeJankyRuns().build()
@Test
fun checkCoveredRegion_noUncoveredRegions() {
checkResults {
LayersTraceSubject.assertThat(it)
.coversRegion(WindowUtils.getDisplayBounds()).forAllEntries()
}
}
@Test
fun checkVisibility_dividerLayerBecomesInVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(DOCKED_STACK_DIVIDER)
.then()
.hidesLayer(DOCKED_STACK_DIVIDER)
.forAllEntries()
}
}
@Test
fun checkVisibility_appLayerBecomesInVisible() {
checkResults {
LayersTraceSubject.assertThat(it)
.showsLayer(testApp.getPackage())
.then()
.hidesLayer(testApp.getPackage())
.forAllEntries()
}
}
@Test
fun checkVisibility_navBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(NAVIGATION_BAR_WINDOW_TITLE).forAllEntries()
}
}
@Test
fun checkVisibility_statusBarWindowIsAlwaysVisible() {
checkResults {
WmTraceSubject.assertThat(it)
.showsAboveAppWindow(STATUS_BAR_WINDOW_TITLE).forAllEntries()
}
}
companion object {
@AfterClass
@JvmStatic
fun teardown() {
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
if (AutomationUtils.isInSplitScreen(device)) {
AutomationUtils.exitSplitScreen(device)
}
}
}
}