summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHyungtae Tim Kim <hyungtaekim@google.com>2016-09-20 20:43:42 +0900
committerHyungtae Tim Kim <hyungtaekim@google.com>2016-09-26 12:00:36 +0900
commit079833855b826fde1661f52ec26cd813d466787d (patch)
treed92d541584120cf586a9e6efb8724062ed797d23
parent72eae3aa0a7ff570a12613b5a47ac3c8d7288a71 (diff)
downloadplatform_testing-079833855b826fde1661f52ec26cd813d466787d.tar.gz
Create dpad util for TV functional tests
Adds dpad util to inject key events so that it can be used by system/app helpers Bug: 31635441 Change-Id: I47a533055927541d0516a7e4a5f6c21046bf2e92
-rw-r--r--libraries/base-app-helpers/Android.mk2
-rw-r--r--libraries/base-app-helpers/src/android/platform/test/helpers/AbstractLeanbackAppHelper.java11
-rw-r--r--libraries/launcher-helper/Android.mk1
-rw-r--r--libraries/launcher-helper/src/android/support/test/launcherhelper/LeanbackLauncherStrategy.java60
-rw-r--r--utils/dpad/Android.mk27
-rw-r--r--utils/dpad/src/android/platform/test/utils/DPadUtil.java169
6 files changed, 228 insertions, 42 deletions
diff --git a/libraries/base-app-helpers/Android.mk b/libraries/base-app-helpers/Android.mk
index 938ee4cba..ce06cc53e 100644
--- a/libraries/base-app-helpers/Android.mk
+++ b/libraries/base-app-helpers/Android.mk
@@ -17,7 +17,7 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := base-app-helpers
-LOCAL_STATIC_JAVA_LIBRARIES := account-util
+LOCAL_STATIC_JAVA_LIBRARIES := account-util dpad-util
LOCAL_JAVA_LIBRARIES := ub-uiautomator launcher-helper-lib
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractLeanbackAppHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractLeanbackAppHelper.java
index 7d7b1b467..afe3c04b7 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractLeanbackAppHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractLeanbackAppHelper.java
@@ -19,6 +19,7 @@ package android.platform.test.helpers;
import android.app.Instrumentation;
import android.platform.test.helpers.exceptions.UiTimeoutException;
import android.platform.test.helpers.exceptions.UnknownUiException;
+import android.platform.test.utils.DPadUtil;
import android.support.test.launcherhelper.ILeanbackLauncherStrategy;
import android.support.test.launcherhelper.LauncherStrategyFactory;
import android.support.test.uiautomator.By;
@@ -53,12 +54,16 @@ public abstract class AbstractLeanbackAppHelper extends AbstractStandardAppHelpe
ERROR_FRAGMENT
}
+ protected DPadUtil mDPadUtil;
+ // TODO: Delete DPadHelper once migrated to using DPadUtil
protected DPadHelper mDPadHelper;
public ILeanbackLauncherStrategy mLauncherStrategy;
public AbstractLeanbackAppHelper(Instrumentation instr) {
super(instr);
+ mDPadUtil = new DPadUtil(instr);
+ // TODO: Delete DPadHelper once migrated to using DPadUtil
mDPadHelper = DPadHelper.getInstance(instr);
mLauncherStrategy = LauncherStrategyFactory.getInstance(
mDevice).getLeanbackLauncherStrategy();
@@ -218,10 +223,10 @@ public abstract class AbstractLeanbackAppHelper extends AbstractStandardAppHelpe
}
while (!focus.hasObject(target)) {
UiObject2 prev = focus;
- mDPadHelper.pressDPad(direction);
+ mDPadUtil.pressDPad(direction);
focus = container.findObject(By.focused(true));
if (focus == null) {
- mDPadHelper.pressDPad(Direction.reverse(direction));
+ mDPadUtil.pressDPad(Direction.reverse(direction));
focus = container.findObject(By.focused(true));
}
if (focus.equals(prev)) {
@@ -321,7 +326,7 @@ public abstract class AbstractLeanbackAppHelper extends AbstractStandardAppHelpe
throw new IllegalStateException("Failed to find a card in row content " + title);
}
}
- mDPadHelper.pressDPadCenter();
+ mDPadUtil.pressDPadCenter();
mDevice.wait(Until.gone(By.res(getPackage(), "title_text").text(title)),
SELECT_WAIT_TIME_MS);
}
diff --git a/libraries/launcher-helper/Android.mk b/libraries/launcher-helper/Android.mk
index 60c499be5..bd9d62f1c 100644
--- a/libraries/launcher-helper/Android.mk
+++ b/libraries/launcher-helper/Android.mk
@@ -19,6 +19,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := launcher-helper-lib
LOCAL_JAVA_LIBRARIES := ub-uiautomator
+LOCAL_STATIC_JAVA_LIBRARIES := dpad-util
LOCAL_SDK_VERSION := 21
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/LeanbackLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/LeanbackLauncherStrategy.java
index 16c6b3b2a..59084ae3f 100644
--- a/libraries/launcher-helper/src/android/support/test/launcherhelper/LeanbackLauncherStrategy.java
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/LeanbackLauncherStrategy.java
@@ -19,6 +19,7 @@ package android.support.test.launcherhelper;
import android.graphics.Point;
import android.os.RemoteException;
import android.os.SystemClock;
+import android.platform.test.utils.DPadUtil;
import android.support.test.uiautomator.*;
import android.util.Log;
@@ -37,6 +38,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
private static final int NOTIFICATION_WAIT_TIME = 30000;
protected UiDevice mDevice;
+ protected DPadUtil mDPadUtil = new DPadUtil();
/**
@@ -62,7 +64,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
public void open() {
// if we see main list view, assume at home screen already
if (!mDevice.hasObject(getWorkspaceSelector())) {
- mDevice.pressHome();
+ mDPadUtil.pressHome();
// ensure launcher is shown
if (!mDevice.wait(Until.hasObject(getWorkspaceSelector()), SHORT_WAIT_TIME)) {
// HACK: dump hierarchy to logcat
@@ -205,12 +207,12 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
throw new RuntimeException("Could not find keyboard orb.");
}
if (orbButton.isFocused()) {
- mDevice.pressDPadCenter();
+ mDPadUtil.pressDPadCenter();
} else {
// Move the focus to keyboard orb by DPad button.
- mDevice.pressDPadRight();
+ mDPadUtil.pressDPadRight();
if (orbButton.isFocused()) {
- mDevice.pressDPadCenter();
+ mDPadUtil.pressDPadCenter();
}
}
mDevice.wait(Until.gone(keyboardOrb), SHORT_WAIT_TIME);
@@ -225,7 +227,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
SystemClock.sleep(SHORT_WAIT_TIME);
// Note that Enter key is pressed instead of DPad keys to dismiss leanback IME
- mDevice.pressEnter();
+ mDPadUtil.pressEnter();
mDevice.wait(Until.gone(searchEditor), SHORT_WAIT_TIME);
}
@@ -239,7 +241,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
public UiObject2 selectNotificationRow() {
if (!isNotificationRowSelected()) {
open();
- mDevice.pressHome(); // Home key to move to the first card in the Notification row
+ mDPadUtil.pressHome(); // Home key to move to the first card in the Notification row
}
return mDevice.wait(Until.findObject(
getNotificationRowSelector().hasDescendant(By.focused(true), 3)), SHORT_WAIT_TIME);
@@ -252,7 +254,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
public UiObject2 selectSearchRow() {
if (!isSearchRowSelected()) {
selectNotificationRow();
- mDevice.pressDPadUp();
+ mDPadUtil.pressDPadUp();
}
return mDevice.wait(Until.findObject(
getSearchRowSelector().hasDescendant(By.focused(true))), SHORT_WAIT_TIME);
@@ -392,19 +394,19 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
// The sequence of moving should be kept in the following order so as not to
// be stuck in case that the apps row are not even.
if (dx < -MARGIN) {
- mDevice.pressDPadLeft();
+ mDPadUtil.pressDPadLeft();
continue;
}
if (dy < -MARGIN) {
- mDevice.pressDPadUp();
+ mDPadUtil.pressDPadUp();
continue;
}
if (dx > MARGIN) {
- mDevice.pressDPadRight();
+ mDPadUtil.pressDPadRight();
continue;
}
if (dy > MARGIN) {
- mDevice.pressDPadDown();
+ mDPadUtil.pressDPadDown();
continue;
}
throw new RuntimeException(
@@ -419,7 +421,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
// The app icon is already found and focused.
long ready = SystemClock.uptimeMillis();
- mDevice.pressDPadCenter();
+ mDPadUtil.pressDPadCenter();
if (!mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), APP_LAUNCH_TIMEOUT)) {
Log.w(LOG_TAG, "no new window detected after app launch attempt.");
return ILauncherStrategy.LAUNCH_FAILED_TIMESTAMP;
@@ -467,12 +469,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
appName, card.getContentDescription()));
// Click and wait until the Notification card opens
- return mDevice.performActionAndWait(new Runnable() {
- @Override
- public void run() {
- mDevice.pressDPadCenter();
- }
- }, Until.newWindow(), APP_LAUNCH_TIMEOUT);
+ return mDPadUtil.pressDPadCenterAndWait(Until.newWindow(), APP_LAUNCH_TIMEOUT);
}
protected boolean isSearchRowSelected() {
@@ -539,7 +536,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
protected UiObject2 findNotificationCard(BySelector selector) {
// Move to the first notification, Search to the right
- mDevice.pressHome();
+ mDPadUtil.pressHome();
// Find if a focused card matches a given selector
UiObject2 currentFocus = mDevice.findObject(getNotificationRowSelector())
@@ -549,7 +546,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
if (currentFocus.hasObject(selector)) {
return currentFocus; // Found
}
- mDevice.pressDPadRight();
+ mDPadUtil.pressDPadRight();
previousFocus = currentFocus;
currentFocus = mDevice.findObject(getNotificationRowSelector())
.findObject(By.res(getSupportedLauncherPackage(), "card").focused(true));
@@ -565,7 +562,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
String prevText = focusedIcon.getContentDescription();
String nextText;
do {
- mDevice.pressDPadLeft();
+ mDPadUtil.pressDPadLeft();
appIcon = container.findObject(app);
if (appIcon != null) {
return appIcon;
@@ -577,7 +574,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
// If we haven't found it yet, search by going right
do {
- mDevice.pressDPadRight();
+ mDPadUtil.pressDPadRight();
appIcon = container.findObject(app);
if (appIcon != null) {
return appIcon;
@@ -609,11 +606,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
return rowObject; // Found
}
- if (direction == Direction.DOWN) {
- mDevice.pressDPadDown();
- } else if (direction == Direction.UP) {
- mDevice.pressDPadUp();
- }
+ mDPadUtil.pressDPad(direction);
prevFocused = currentFocused;
currentFocused = mDevice.findObject(By.focused(true));
}
@@ -641,12 +634,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
if (button == null) {
throw new IllegalStateException("Restricted Profile not found on launcher");
}
- mDevice.performActionAndWait(new Runnable() {
- @Override
- public void run() {
- mDevice.pressDPadCenter();
- }
- }, Until.newWindow(), APP_LAUNCH_TIMEOUT);
+ mDPadUtil.pressDPadCenterAndWait(Until.newWindow(), APP_LAUNCH_TIMEOUT);
}
protected UiObject2 findSettingInRow(BySelector selector, Direction direction) {
@@ -665,11 +653,7 @@ public class LeanbackLauncherStrategy implements ILeanbackLauncherStrategy {
return setting;
}
- if (direction == Direction.RIGHT) {
- mDevice.pressDPadRight();
- } else if (direction == Direction.LEFT) {
- mDevice.pressDPadLeft();
- }
+ mDPadUtil.pressDPad(direction);
mDevice.waitForIdle();
prevFocused = currentFocused;
currentFocused = mDevice.findObject(By.focused(true));
diff --git a/utils/dpad/Android.mk b/utils/dpad/Android.mk
new file mode 100644
index 000000000..f211bc798
--- /dev/null
+++ b/utils/dpad/Android.mk
@@ -0,0 +1,27 @@
+#
+# Copyright (C) 2016 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# -----------------------------------------------------------------------
+# The static library that platform/app helpers can link against
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := dpad-util
+LOCAL_JAVA_LIBRARIES := ub-uiautomator android-support-test
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/utils/dpad/src/android/platform/test/utils/DPadUtil.java b/utils/dpad/src/android/platform/test/utils/DPadUtil.java
new file mode 100644
index 000000000..dfd7fdf3b
--- /dev/null
+++ b/utils/dpad/src/android/platform/test/utils/DPadUtil.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2016 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.platform.test.utils;
+
+import android.app.Instrumentation;
+import android.os.SystemClock;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.EventCondition;
+import android.support.test.uiautomator.UiDevice;
+import android.util.Log;
+import android.view.KeyEvent;
+
+import java.io.IOException;
+
+
+public class DPadUtil {
+
+ private static final String TAG = DPadUtil.class.getSimpleName();
+ private static final long DPAD_DEFAULT_WAIT_TIME_MS = 1000; // 1 sec
+ private UiDevice mDevice;
+
+
+ public DPadUtil() {
+ mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ }
+
+ public DPadUtil(Instrumentation instrumentation) {
+ mDevice = UiDevice.getInstance(instrumentation);
+ }
+
+ public boolean pressDPad(Direction direction) {
+ return pressDPad(direction, 1, DPAD_DEFAULT_WAIT_TIME_MS);
+ }
+
+ public void pressDPad(Direction direction, long repeat) {
+ pressDPad(direction, repeat, DPAD_DEFAULT_WAIT_TIME_MS);
+ }
+
+ /**
+ * Presses DPad button of the same direction for the count times.
+ * It sleeps between each press for DPAD_DEFAULT_WAIT_TIME_MS.
+ *
+ * @param direction the direction of the button to press.
+ * @param repeat the number of times to press the button.
+ * @param timeout the timeout for the wait.
+ * @return true if the last key simulation is successful, else return false
+ */
+ public boolean pressDPad(Direction direction, long repeat, long timeout) {
+ int iteration = 0;
+ boolean result = false;
+ while (iteration++ < repeat) {
+ switch (direction) {
+ case LEFT:
+ result = mDevice.pressDPadLeft();
+ break;
+ case RIGHT:
+ result = mDevice.pressDPadRight();
+ break;
+ case UP:
+ result = mDevice.pressDPadUp();
+ break;
+ case DOWN:
+ result = mDevice.pressDPadDown();
+ break;
+ }
+ SystemClock.sleep(timeout);
+ }
+ return result;
+ }
+
+ public boolean pressDPadLeft() {
+ return mDevice.pressDPadLeft();
+ }
+
+ public boolean pressDPadRight() {
+ return mDevice.pressDPadRight();
+ }
+
+ public boolean pressDPadUp() {
+ return mDevice.pressDPadUp();
+ }
+
+ public boolean pressDPadDown() {
+ return mDevice.pressDPadDown();
+ }
+
+ public boolean pressHome() {
+ return mDevice.pressHome();
+ }
+
+ public boolean pressBack() {
+ return mDevice.pressBack();
+ }
+
+ public boolean pressDPadCenter() {
+ return mDevice.pressDPadCenter();
+ }
+
+ public boolean pressEnter() {
+ return mDevice.pressEnter();
+ }
+
+ public boolean pressPipKey() {
+ return mDevice.pressKeyCode(KeyEvent.KEYCODE_WINDOW);
+ }
+
+ public boolean pressKeyCode(int keyCode) {
+ return mDevice.pressKeyCode(keyCode);
+ }
+
+ public boolean longPressKeyCode(int keyCode) {
+ try {
+ mDevice.executeShellCommand(String.format("input keyevent --longpress %d", keyCode));
+ return true;
+ } catch (IOException e) {
+ // Ignore
+ Log.w(TAG, String.format("Failed to long press the key code: %d", keyCode));
+ return false;
+ }
+ }
+
+ /**
+ * Press the key code, and waits for the given condition to become true.
+ * @param condition
+ * @param keyCode
+ * @param timeout
+ * @param <R>
+ * @return
+ */
+ public <R> R pressKeyCodeAndWait(int keyCode, EventCondition<R> condition, long timeout) {
+ return mDevice.performActionAndWait(new KeyEventRunnable(keyCode), condition, timeout);
+ }
+
+ public <R> R pressDPadCenterAndWait(EventCondition<R> condition, long timeout) {
+ return mDevice.performActionAndWait(new KeyEventRunnable(KeyEvent.KEYCODE_DPAD_CENTER),
+ condition, timeout);
+ }
+
+ public <R> R pressEnterAndWait(EventCondition<R> condition, long timeout) {
+ return mDevice.performActionAndWait(new KeyEventRunnable(KeyEvent.KEYCODE_ENTER),
+ condition, timeout);
+ }
+
+ private class KeyEventRunnable implements Runnable {
+ private int mKeyCode;
+ public KeyEventRunnable(int keyCode) {
+ mKeyCode = keyCode;
+ }
+ @Override
+ public void run() {
+ mDevice.pressKeyCode(mKeyCode);
+ }
+ }
+}