blob: b5c02f1f0c400b71eaaf31258e1f73ed923ede54 [file] [log] [blame]
/*
* Copyright (C) 2017 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 android.preference2.cts;
import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.app.UiModeManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import com.android.compatibility.common.util.SystemUtil;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Collection of helper utils for preferences testing.
*/
public class TestUtils {
final UiDevice device;
private final Instrumentation mInstrumentation;
private final UiAutomation mAutomation;
private int mStatusBarHeight = -1;
TestUtils() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
device = UiDevice.getInstance(mInstrumentation);
mAutomation = mInstrumentation.getUiAutomation();
}
Bitmap takeScreenshot() {
// Only take screenshot once the screen is stable enough.
device.waitForIdle();
Bitmap bt = mAutomation.takeScreenshot();
// Crop-out the top bar where current time is displayed since any time change would
// introduce flakiness (we are cutting 5% of the screen height or status_bar_height).
int yToCut = Math.max(bt.getHeight() / 20, getStatusBarHeight());
// Crop the right side for scrollbar which might or might not be visible. But on
// watch, the scroll bar is a curve and occupies 20% of the screen on the right
// hand side.
int xToCut = isOnWatchUiMode() ? bt.getWidth() / 5 : bt.getWidth() / 20;
bt = Bitmap.createBitmap(
bt, 0, yToCut, bt.getWidth() - xToCut, bt.getHeight() - yToCut);
return bt;
}
void tapOnViewWithText(String searchText) {
if (searchText == null) {
return;
}
try {
// If the current UI has shown text, just click on it.
UiObject text = new UiObject(new UiSelector().text(searchText));
if (text.exists() || text.waitForExists(1000)) {
text.click();
return;
}
// Otherwise, if it is scrollable, scroll to where the text is and tap.
UiScrollable textScroll = new UiScrollable(new UiSelector().scrollable(true));
textScroll.scrollIntoView(new UiSelector().text(searchText));
text = new UiObject(new UiSelector().text(searchText));
text.click();
} catch (UiObjectNotFoundException e) {
throw new AssertionError("View with text '" + searchText + "' was not found!", e);
}
}
boolean isTextShown(String searchText) {
if (searchText == null) {
return false;
}
UiObject text = new UiObject(new UiSelector().text(searchText));
if (text.exists() || text.waitForExists(1000)) {
return true;
}
UiScrollable textScroll = new UiScrollable(new UiSelector().scrollable(true));
try {
return textScroll.scrollIntoView(new UiSelector().text(searchText));
} catch (UiObjectNotFoundException e) {
return false;
}
}
boolean isTextHidden(String text) {
UiObject obj = device.findObject(new UiSelector().textMatches(text));
if (!obj.exists()) {
return true;
}
return obj.waitUntilGone(1000);
}
boolean isTextFocused(String text) {
UiObject obj = device.findObject(new UiSelector().textMatches(text));
try {
return obj.isFocused();
} catch(UiObjectNotFoundException e) {
return false;
}
}
boolean isOnWatchUiMode() {
Context context = mInstrumentation.getTargetContext();
UiModeManager uiModeManager = context.getSystemService(UiModeManager.class);
return uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_WATCH;
}
void getMultiWindowFocus(Context context) {
// Get window focus (otherwise back press would close multi-window instead of firing to the
// Activity and also the automator would fail to find objects on the screen.
// We want to click slightly below status bar in the 1/3 of width of the screen.
int x = device.getDisplayWidth() / 3;
int resourceId =
context.getResources().getIdentifier("status_bar_height", "dimen", "android");
int statusBarHeight =
(resourceId > 0) ? context.getResources().getDimensionPixelSize(resourceId) : 0;
device.click(x, 2 * statusBarHeight);
}
// Multi-window helpers taken from ActivityManagerDockedStackTests.java
void enterMultiWindow(Activity activity) {
try {
int id = getActivityTaskId(activity);
runShellCommand("am stack move-task " + id + " 3 true");
} catch (IOException e) {
throw new RuntimeException("Failed to get activity task id!", e);
}
SystemClock.sleep(5000);
}
void leaveMultiWindow(Activity activity) {
try {
int id = getActivityTaskId(activity);
runShellCommand("am stack move-task "+ id +" 1 true");
} catch (IOException e) {
throw new RuntimeException("Failed to get activity task id!", e);
}
SystemClock.sleep(5000);
}
private int getActivityTaskId(Activity activity) throws IOException {
// Taken from ActivityManagerTestBase.java
final String output = runShellCommand("am stack list");
final Pattern activityPattern =
Pattern.compile("(.*) " + getWindowName(activity) + " (.*)");
for (String line : output.split("\\n")) {
Matcher matcher = activityPattern.matcher(line);
if (matcher.matches()) {
for (String word : line.split("\\s+")) {
if (word.startsWith("taskId")) {
final String withColon = word.split("=")[1];
return Integer.parseInt(withColon.substring(0, withColon.length() - 1));
}
}
}
}
return -1;
}
private String getWindowName(Activity activity) {
String componentName = activity.getPackageName();
String baseWindowName = componentName + "/" + componentName + ".";
return baseWindowName + activity.getClass().getSimpleName();
}
private int getStatusBarHeight() {
// Cache the result to keep it fast.
if (mStatusBarHeight >= 0) {
return mStatusBarHeight;
}
int result = 0;
int resourceId = mInstrumentation.getTargetContext().getResources()
.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = mInstrumentation.getTargetContext().getResources()
.getDimensionPixelSize(resourceId);
}
mStatusBarHeight = result;
return result;
}
private String runShellCommand(String cmd) {
try {
return SystemUtil.runShellCommand(mInstrumentation, cmd);
} catch (IOException e) {
throw new RuntimeException("Failed to run command: " + cmd, e);
}
}
}