mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-03-21 01:59:13 +00:00
Merge 1fd8a14ca9e7d4d7cd176b6a6d5aaa1b8a30f2d5 into ee7c04a5688be6ad16105ec62f9d394feffad1d9
This commit is contained in:
commit
627066224a
BIN
wlauto/common/android/BaseUiAutomation$1.class
Normal file
BIN
wlauto/common/android/BaseUiAutomation$1.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/BaseUiAutomation$ActionLogger.class
Normal file
BIN
wlauto/common/android/BaseUiAutomation$ActionLogger.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/BaseUiAutomation$Direction.class
Normal file
BIN
wlauto/common/android/BaseUiAutomation$Direction.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/BaseUiAutomation$FindByCriteria.class
Normal file
BIN
wlauto/common/android/BaseUiAutomation$FindByCriteria.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/BaseUiAutomation$PinchType.class
Normal file
BIN
wlauto/common/android/BaseUiAutomation$PinchType.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/BaseUiAutomation$ScreenOrientation.class
Normal file
BIN
wlauto/common/android/BaseUiAutomation$ScreenOrientation.class
Normal file
Binary file not shown.
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$1.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$1.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$ActionLogger.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$ActionLogger.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$Direction.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$Direction.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$GestureTestParams.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$GestureTestParams.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$GestureType.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$GestureType.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$PinchType.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$PinchType.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$SurfaceLogger.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$SurfaceLogger.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$Timer.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$Timer.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation$UxPerfLogger.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation$UxPerfLogger.class
Normal file
Binary file not shown.
BIN
wlauto/common/android/UxPerfUiAutomation.class
Normal file
BIN
wlauto/common/android/UxPerfUiAutomation.class
Normal file
Binary file not shown.
8
wlauto/external/uiauto/build.sh
vendored
8
wlauto/external/uiauto/build.sh
vendored
@ -16,6 +16,12 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Build and return appropriate exit code if failed
|
||||||
ant build
|
ant build
|
||||||
|
exit_code=$?
|
||||||
|
if [ $exit_code -ne 0 ]; then
|
||||||
|
echo "ERROR: 'ant build' exited with code $exit_code"
|
||||||
|
exit $exit_code
|
||||||
|
fi
|
||||||
|
|
||||||
cp bin/classes/com/arm/wlauto/uiauto/BaseUiAutomation.class ../../common/android
|
cp bin/classes/com/arm/wlauto/uiauto/*.class ../../common/android
|
||||||
|
2
wlauto/external/uiauto/project.properties
vendored
2
wlauto/external/uiauto/project.properties
vendored
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -20,6 +20,7 @@ import java.io.File;
|
|||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@ -27,6 +28,9 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.graphics.Point;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
// Import the uiautomator libraries
|
// Import the uiautomator libraries
|
||||||
@ -34,9 +38,25 @@ import com.android.uiautomator.core.UiObject;
|
|||||||
import com.android.uiautomator.core.UiObjectNotFoundException;
|
import com.android.uiautomator.core.UiObjectNotFoundException;
|
||||||
import com.android.uiautomator.core.UiScrollable;
|
import com.android.uiautomator.core.UiScrollable;
|
||||||
import com.android.uiautomator.core.UiSelector;
|
import com.android.uiautomator.core.UiSelector;
|
||||||
|
import com.android.uiautomator.core.UiDevice;
|
||||||
|
import com.android.uiautomator.core.UiWatcher;
|
||||||
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
|
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
|
||||||
|
|
||||||
public class BaseUiAutomation extends UiAutomatorTestCase {
|
public class BaseUiAutomation extends UiAutomatorTestCase {
|
||||||
|
|
||||||
|
public long uiAutoTimeout = TimeUnit.SECONDS.toMillis(4);
|
||||||
|
|
||||||
|
public enum ScreenOrientation { RIGHT, NATURAL, LEFT };
|
||||||
|
public enum Direction { UP, DOWN, LEFT, RIGHT, NULL };
|
||||||
|
public enum PinchType { IN, OUT, NULL };
|
||||||
|
|
||||||
|
public static final int CLICK_REPEAT_INTERVAL_MINIMUM = 5;
|
||||||
|
public static final int CLICK_REPEAT_INTERVAL_DEFAULT = 50;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Used by clickUiObject() methods in order to provide a consistent API
|
||||||
|
*/
|
||||||
|
public enum FindByCriteria { BY_ID, BY_TEXT, BY_DESC; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic marker API for workloads to generate start and end markers for
|
* Basic marker API for workloads to generate start and end markers for
|
||||||
@ -86,11 +106,11 @@ public class BaseUiAutomation extends UiAutomatorTestCase {
|
|||||||
|
|
||||||
public boolean takeScreenshot(String name) {
|
public boolean takeScreenshot(String name) {
|
||||||
Bundle params = getParams();
|
Bundle params = getParams();
|
||||||
String png_dir = params.getString("workdir");
|
String pngDir = params.getString("workdir");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return getUiDevice().takeScreenshot(new File(png_dir, name + ".png"));
|
return getUiDevice().takeScreenshot(new File(pngDir, name + ".png"));
|
||||||
} catch(NoSuchMethodError e) {
|
} catch (NoSuchMethodError e) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,9 +121,9 @@ public class BaseUiAutomation extends UiAutomatorTestCase {
|
|||||||
|
|
||||||
public void waitText(String text, int second) throws UiObjectNotFoundException {
|
public void waitText(String text, int second) throws UiObjectNotFoundException {
|
||||||
UiSelector selector = new UiSelector();
|
UiSelector selector = new UiSelector();
|
||||||
UiObject text_obj = new UiObject(selector.text(text)
|
UiObject textObj = new UiObject(selector.text(text)
|
||||||
.className("android.widget.TextView"));
|
.className("android.widget.TextView"));
|
||||||
waitObject(text_obj, second);
|
waitObject(textObj, second);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitObject(UiObject obj) throws UiObjectNotFoundException {
|
public void waitObject(UiObject obj) throws UiObjectNotFoundException {
|
||||||
@ -111,7 +131,7 @@ public class BaseUiAutomation extends UiAutomatorTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void waitObject(UiObject obj, int second) throws UiObjectNotFoundException {
|
public void waitObject(UiObject obj, int second) throws UiObjectNotFoundException {
|
||||||
if (! obj.waitForExists(second * 1000)){
|
if (!obj.waitForExists(second * 1000)) {
|
||||||
throw new UiObjectNotFoundException("UiObject is not found: "
|
throw new UiObjectNotFoundException("UiObject is not found: "
|
||||||
+ obj.getSelector().toString());
|
+ obj.getSelector().toString());
|
||||||
}
|
}
|
||||||
@ -133,10 +153,10 @@ public class BaseUiAutomation extends UiAutomatorTestCase {
|
|||||||
|
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
while ((currentTime - startTime) < timeout){
|
while ((currentTime - startTime) < timeout) {
|
||||||
sleep(2); // poll every two seconds
|
sleep(2); // poll every two seconds
|
||||||
|
|
||||||
while((line=reader.readLine())!=null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
if (line.contains(searchText)) {
|
if (line.contains(searchText)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@ -152,7 +172,8 @@ public class BaseUiAutomation extends UiAutomatorTestCase {
|
|||||||
process.destroy();
|
process.destroy();
|
||||||
|
|
||||||
if ((currentTime - startTime) >= timeout) {
|
if ((currentTime - startTime) >= timeout) {
|
||||||
throw new TimeoutException("Timed out waiting for Logcat text \"%s\"".format(searchText));
|
throw new TimeoutException(String.format("Timed out waiting for Logcat text \"%s\"",
|
||||||
|
searchText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,5 +211,367 @@ public class BaseUiAutomation extends UiAutomatorTestCase {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public void registerWatcher(String name, UiWatcher watcher) {
|
||||||
|
UiDevice.getInstance().registerWatcher(name, watcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void runWatchers() {
|
||||||
|
UiDevice.getInstance().runWatchers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeWatcher(String name) {
|
||||||
|
UiDevice.getInstance().removeWatcher(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressEnter() {
|
||||||
|
UiDevice.getInstance().pressEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressBack() {
|
||||||
|
UiDevice.getInstance().pressBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressDPadUp() {
|
||||||
|
UiDevice.getInstance().pressDPadUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressDPadDown() {
|
||||||
|
UiDevice.getInstance().pressDPadDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressDPadLeft() {
|
||||||
|
UiDevice.getInstance().pressDPadLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pressDPadRight() {
|
||||||
|
UiDevice.getInstance().pressDPadRight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayHeight() {
|
||||||
|
return UiDevice.getInstance().getDisplayHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayWidth() {
|
||||||
|
return UiDevice.getInstance().getDisplayWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayCentreWidth() {
|
||||||
|
return getDisplayWidth() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDisplayCentreHeight() {
|
||||||
|
return getDisplayHeight() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tapDisplayCentre() {
|
||||||
|
tapDisplay(getDisplayCentreWidth(), getDisplayCentreHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tapDisplay(int x, int y) {
|
||||||
|
UiDevice.getInstance().click(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipeUp(int steps) {
|
||||||
|
UiDevice.getInstance().swipe(
|
||||||
|
getDisplayCentreWidth(),
|
||||||
|
(getDisplayCentreHeight() / 2),
|
||||||
|
getDisplayCentreWidth(),
|
||||||
|
(getDisplayCentreHeight() + (getDisplayCentreHeight() / 2)),
|
||||||
|
steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipeDown(int steps) {
|
||||||
|
UiDevice.getInstance().swipe(
|
||||||
|
getDisplayCentreWidth(),
|
||||||
|
(getDisplayCentreHeight() + (getDisplayCentreHeight() / 2)),
|
||||||
|
getDisplayCentreWidth(),
|
||||||
|
(getDisplayCentreHeight() / 2),
|
||||||
|
steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipeLeft(int steps) {
|
||||||
|
UiDevice.getInstance().swipe(
|
||||||
|
(getDisplayCentreWidth() + (getDisplayCentreWidth() / 2)),
|
||||||
|
getDisplayCentreHeight(),
|
||||||
|
(getDisplayCentreWidth() / 2),
|
||||||
|
getDisplayCentreHeight(),
|
||||||
|
steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipeRight(int steps) {
|
||||||
|
UiDevice.getInstance().swipe(
|
||||||
|
(getDisplayCentreWidth() / 2),
|
||||||
|
getDisplayCentreHeight(),
|
||||||
|
(getDisplayCentreWidth() + (getDisplayCentreWidth() / 2)),
|
||||||
|
getDisplayCentreHeight(),
|
||||||
|
steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipe(Direction direction, int steps) throws Exception {
|
||||||
|
switch (direction) {
|
||||||
|
case UP:
|
||||||
|
uiDeviceSwipeUp(steps);
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
uiDeviceSwipeDown(steps);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
uiDeviceSwipeLeft(steps);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
uiDeviceSwipeRight(steps);
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
throw new Exception("No direction specified");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiObjectSwipe(UiObject view, Direction direction, int steps) throws Exception {
|
||||||
|
switch (direction) {
|
||||||
|
case UP:
|
||||||
|
view.swipeUp(steps);
|
||||||
|
break;
|
||||||
|
case DOWN:
|
||||||
|
view.swipeDown(steps);
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
view.swipeLeft(steps);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
view.swipeRight(steps);
|
||||||
|
break;
|
||||||
|
case NULL:
|
||||||
|
throw new Exception("No direction specified");
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiObjectVertPinchIn(UiObject view, int steps, int percent) throws Exception {
|
||||||
|
final int FINGER_TOUCH_HALF_WIDTH = 20;
|
||||||
|
|
||||||
|
// Make value between 1 and 100
|
||||||
|
int nPercent = (percent < 0) ? 1 : (percent > 100) ? 100 : percent;
|
||||||
|
float percentage = nPercent / 100f;
|
||||||
|
|
||||||
|
Rect rect = view.getVisibleBounds();
|
||||||
|
|
||||||
|
if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2) {
|
||||||
|
throw new IllegalStateException("Object width is too small for operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start at the top-center and bottom-center of the control
|
||||||
|
Point startPoint1 = new Point(rect.centerX(), rect.centerY()
|
||||||
|
+ (int) ((rect.height() / 2) * percentage));
|
||||||
|
Point startPoint2 = new Point(rect.centerX(), rect.centerY()
|
||||||
|
- (int) ((rect.height() / 2) * percentage));
|
||||||
|
|
||||||
|
// End at the same point at the center of the control
|
||||||
|
Point endPoint1 = new Point(rect.centerX(), rect.centerY() + FINGER_TOUCH_HALF_WIDTH);
|
||||||
|
Point endPoint2 = new Point(rect.centerX(), rect.centerY() - FINGER_TOUCH_HALF_WIDTH);
|
||||||
|
|
||||||
|
view.performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiObjectVertPinchOut(UiObject view, int steps, int percent) throws Exception {
|
||||||
|
final int FINGER_TOUCH_HALF_WIDTH = 20;
|
||||||
|
|
||||||
|
// Make value between 1 and 100
|
||||||
|
int nPercent = (percent < 0) ? 1 : (percent > 100) ? 100 : percent;
|
||||||
|
float percentage = nPercent / 100f;
|
||||||
|
|
||||||
|
Rect rect = view.getVisibleBounds();
|
||||||
|
|
||||||
|
if (rect.width() <= FINGER_TOUCH_HALF_WIDTH * 2) {
|
||||||
|
throw new IllegalStateException("Object width is too small for operation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start from the same point at the center of the control
|
||||||
|
Point startPoint1 = new Point(rect.centerX(), rect.centerY() + FINGER_TOUCH_HALF_WIDTH);
|
||||||
|
Point startPoint2 = new Point(rect.centerX(), rect.centerY() - FINGER_TOUCH_HALF_WIDTH);
|
||||||
|
|
||||||
|
// End at the top-center and bottom-center of the control
|
||||||
|
Point endPoint1 = new Point(rect.centerX(), rect.centerY()
|
||||||
|
+ (int) ((rect.height() / 2) * percentage));
|
||||||
|
Point endPoint2 = new Point(rect.centerX(), rect.centerY()
|
||||||
|
- (int) ((rect.height() / 2) * percentage));
|
||||||
|
|
||||||
|
view.performTwoPointerGesture(startPoint1, startPoint2, endPoint1, endPoint2, steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScreenOrientation(ScreenOrientation orientation) throws Exception {
|
||||||
|
switch (orientation) {
|
||||||
|
case RIGHT:
|
||||||
|
getUiDevice().setOrientationRight();
|
||||||
|
break;
|
||||||
|
case NATURAL:
|
||||||
|
getUiDevice().setOrientationNatural();
|
||||||
|
break;
|
||||||
|
case LEFT:
|
||||||
|
getUiDevice().setOrientationLeft();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("No orientation specified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unsetScreenOrientation() throws Exception {
|
||||||
|
getUiDevice().unfreezeRotation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiObjectPerformLongClick(UiObject view, int steps) throws Exception {
|
||||||
|
Rect rect = view.getBounds();
|
||||||
|
UiDevice.getInstance().swipe(rect.centerX(), rect.centerY(),
|
||||||
|
rect.centerX(), rect.centerY(), steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipeVertical(int startY, int endY, int xCoordinate, int steps) {
|
||||||
|
getUiDevice().swipe(startY, xCoordinate, endY, xCoordinate, steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiDeviceSwipeHorizontal(int startX, int endX, int yCoordinate, int steps) {
|
||||||
|
getUiDevice().swipe(startX, yCoordinate, endX, yCoordinate, steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiObjectPinch(UiObject view, PinchType direction, int steps,
|
||||||
|
int percent) throws Exception {
|
||||||
|
if (direction.equals(PinchType.IN)) {
|
||||||
|
view.pinchIn(percent, steps);
|
||||||
|
} else if (direction.equals(PinchType.OUT)) {
|
||||||
|
view.pinchOut(percent, steps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void uiObjectVertPinch(UiObject view, PinchType direction,
|
||||||
|
int steps, int percent) throws Exception {
|
||||||
|
if (direction.equals(PinchType.IN)) {
|
||||||
|
uiObjectVertPinchIn(view, steps, percent);
|
||||||
|
} else if (direction.equals(PinchType.OUT)) {
|
||||||
|
uiObjectVertPinchOut(view, steps, percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void repeatClickUiObject(UiObject view, int repeatCount, int intervalInMillis) throws Exception {
|
||||||
|
int repeatInterval = intervalInMillis > CLICK_REPEAT_INTERVAL_MINIMUM
|
||||||
|
? intervalInMillis : CLICK_REPEAT_INTERVAL_DEFAULT;
|
||||||
|
if (repeatCount < 1 || !view.isClickable()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < repeatCount; ++i) {
|
||||||
|
view.click();
|
||||||
|
SystemClock.sleep(repeatInterval); // in order to register as separate click
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject clickUiObject(FindByCriteria criteria, String matching) throws Exception {
|
||||||
|
return clickUiObject(criteria, matching, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject clickUiObject(FindByCriteria criteria, String matching, boolean wait) throws Exception {
|
||||||
|
return clickUiObject(criteria, matching, null, wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject clickUiObject(FindByCriteria criteria, String matching, String clazz) throws Exception {
|
||||||
|
return clickUiObject(criteria, matching, clazz, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject clickUiObject(FindByCriteria criteria, String matching, String clazz, boolean wait) throws Exception {
|
||||||
|
UiObject view;
|
||||||
|
|
||||||
|
switch (criteria) {
|
||||||
|
case BY_ID:
|
||||||
|
view = (clazz == null)
|
||||||
|
? getUiObjectByResourceId(matching) : getUiObjectByResourceId(matching, clazz);
|
||||||
|
break;
|
||||||
|
case BY_DESC:
|
||||||
|
view = (clazz == null)
|
||||||
|
? getUiObjectByDescription(matching) : getUiObjectByDescription(matching, clazz);
|
||||||
|
break;
|
||||||
|
case BY_TEXT:
|
||||||
|
default:
|
||||||
|
view = (clazz == null)
|
||||||
|
? getUiObjectByText(matching) : getUiObjectByText(matching, clazz);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait) {
|
||||||
|
view.clickAndWaitForNewWindow();
|
||||||
|
} else {
|
||||||
|
view.click();
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByResourceId(String resourceId, String className) throws Exception {
|
||||||
|
return getUiObjectByResourceId(resourceId, className, uiAutoTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByResourceId(String resourceId, String className, long timeout) throws Exception {
|
||||||
|
UiObject object = new UiObject(new UiSelector().resourceId(resourceId)
|
||||||
|
.className(className));
|
||||||
|
if (!object.waitForExists(timeout)) {
|
||||||
|
throw new UiObjectNotFoundException(String.format("Could not find \"%s\" \"%s\"",
|
||||||
|
resourceId, className));
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByResourceId(String id) throws Exception {
|
||||||
|
UiObject object = new UiObject(new UiSelector().resourceId(id));
|
||||||
|
|
||||||
|
if (!object.waitForExists(uiAutoTimeout)) {
|
||||||
|
throw new UiObjectNotFoundException("Could not find view with resource ID: " + id);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByDescription(String description, String className) throws Exception {
|
||||||
|
return getUiObjectByDescription(description, className, uiAutoTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByDescription(String description, String className, long timeout) throws Exception {
|
||||||
|
UiObject object = new UiObject(new UiSelector().descriptionContains(description)
|
||||||
|
.className(className));
|
||||||
|
if (!object.waitForExists(timeout)) {
|
||||||
|
throw new UiObjectNotFoundException(String.format("Could not find \"%s\" \"%s\"",
|
||||||
|
description, className));
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByDescription(String desc) throws Exception {
|
||||||
|
UiObject object = new UiObject(new UiSelector().descriptionContains(desc));
|
||||||
|
|
||||||
|
if (!object.waitForExists(uiAutoTimeout)) {
|
||||||
|
throw new UiObjectNotFoundException("Could not find view with description: " + desc);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByText(String text, String className) throws Exception {
|
||||||
|
return getUiObjectByText(text, className, uiAutoTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByText(String text, String className, long timeout) throws Exception {
|
||||||
|
UiObject object = new UiObject(new UiSelector().textContains(text)
|
||||||
|
.className(className));
|
||||||
|
if (!object.waitForExists(timeout)) {
|
||||||
|
throw new UiObjectNotFoundException(String.format("Could not find \"%s\" \"%s\"",
|
||||||
|
text, className));
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UiObject getUiObjectByText(String text) throws Exception {
|
||||||
|
UiObject object = new UiObject(new UiSelector().textContains(text));
|
||||||
|
|
||||||
|
if (!object.waitForExists(uiAutoTimeout)) {
|
||||||
|
throw new UiObjectNotFoundException("Could not find view with text: " + text);
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
49
wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UxPerfUiAutomation.java
vendored
Normal file
49
wlauto/external/uiauto/src/com/arm/wlauto/uiauto/UxPerfUiAutomation.java
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/* Copyright 2013-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* 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.arm.wlauto.uiauto;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class UxPerfUiAutomation extends BaseUiAutomation {
|
||||||
|
|
||||||
|
private Logger logger = Logger.getLogger(UxPerfUiAutomation.class.getName());
|
||||||
|
|
||||||
|
public enum GestureType { UIDEVICE_SWIPE, UIOBJECT_SWIPE, PINCH };
|
||||||
|
|
||||||
|
public static class GestureTestParams {
|
||||||
|
public GestureType gestureType;
|
||||||
|
public Direction gestureDirection;
|
||||||
|
public PinchType pinchType;
|
||||||
|
public int percent;
|
||||||
|
public int steps;
|
||||||
|
|
||||||
|
public GestureTestParams(GestureType gesture, Direction direction, int steps) {
|
||||||
|
this.gestureType = gesture;
|
||||||
|
this.gestureDirection = direction;
|
||||||
|
this.pinchType = PinchType.NULL;
|
||||||
|
this.steps = steps;
|
||||||
|
this.percent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GestureTestParams(GestureType gesture, PinchType pinchType, int steps, int percent) {
|
||||||
|
this.gestureType = gesture;
|
||||||
|
this.gestureDirection = Direction.NULL;
|
||||||
|
this.pinchType = pinchType;
|
||||||
|
this.steps = steps;
|
||||||
|
this.percent = percent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
131
wlauto/workloads/googlephotos/__init__.py
Executable file
131
wlauto/workloads/googlephotos/__init__.py
Executable file
@ -0,0 +1,131 @@
|
|||||||
|
# Copyright 2014-2016 ARM Limited
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
import wlauto.common.resources
|
||||||
|
|
||||||
|
from wlauto import AndroidUiAutoBenchmark, Parameter
|
||||||
|
from wlauto.exceptions import ValidationError
|
||||||
|
from wlauto.utils.types import list_of_strings
|
||||||
|
|
||||||
|
__version__ = '0.1.1'
|
||||||
|
|
||||||
|
|
||||||
|
class Googlephotos(AndroidUiAutoBenchmark):
|
||||||
|
|
||||||
|
name = 'googlephotos'
|
||||||
|
package = 'com.google.android.apps.photos'
|
||||||
|
activity = 'com.google.android.apps.photos.home.HomeActivity'
|
||||||
|
view = [package + '/com.google.android.apps.consumerphotoeditor.fragments.ConsumerPhotoEditorActivity',
|
||||||
|
package + '/com.google.android.apps.photos.home.HomeActivity',
|
||||||
|
package + '/com.google.android.apps.photos.localmedia.ui.LocalPhotosActivity',
|
||||||
|
package + '/com.google.android.apps.photos.onboarding.AccountPickerActivity',
|
||||||
|
package + '/com.google.android.apps.photos.onboarding.IntroActivity']
|
||||||
|
description = """
|
||||||
|
A workload to perform standard productivity tasks with Google Photos. The workload carries out
|
||||||
|
various tasks, such as browsing images, performing zooms, post-processing and saving a selected
|
||||||
|
image to file.
|
||||||
|
|
||||||
|
Test description:
|
||||||
|
1. Four images are copied to the device
|
||||||
|
2. The application is started in offline access mode
|
||||||
|
3. Gestures are performed to swipe between images and pinch zoom in and out of the selected
|
||||||
|
image
|
||||||
|
4. The Colour of a selected image is edited by selecting the colour menu, incrementing the
|
||||||
|
colour, resetting the colour and decrementing the colour using the seek bar.
|
||||||
|
5. A Crop test is performed on a selected image. UiAutomator does not allow the selection of
|
||||||
|
the crop markers so the image is tilted positively, reset and then negatively to get a
|
||||||
|
similar cropping effect.
|
||||||
|
6. A Rotate test is performed on a selected image, rotating anticlockwise 90 degrees, 180
|
||||||
|
degrees and 270 degrees.
|
||||||
|
"""
|
||||||
|
|
||||||
|
default_test_images = [
|
||||||
|
'uxperf_1200x1600.png', 'uxperf_1600x1200.jpg',
|
||||||
|
'uxperf_2448x3264.png', 'uxperf_3264x2448.jpg',
|
||||||
|
]
|
||||||
|
|
||||||
|
parameters = [
|
||||||
|
Parameter('dumpsys_enabled', kind=bool, default=True,
|
||||||
|
description="""
|
||||||
|
If ``True`` turns on the action logger which outputs
|
||||||
|
timestamps to logcat for actions recorded in the workload.
|
||||||
|
"""),
|
||||||
|
Parameter('test_images', kind=list_of_strings, default=default_test_images,
|
||||||
|
description="""
|
||||||
|
A list of four image files to be pushed to the device.
|
||||||
|
Absolute file paths may be used but tilde expansion is not supported.
|
||||||
|
"""),
|
||||||
|
]
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
super(Googlephotos, self).validate()
|
||||||
|
self.uiauto_params['package'] = self.package
|
||||||
|
self.uiauto_params['output_dir'] = self.device.working_directory
|
||||||
|
self.uiauto_params['dumpsys_enabled'] = self.dumpsys_enabled
|
||||||
|
|
||||||
|
self._check_image_numbers()
|
||||||
|
self._check_image_extensions()
|
||||||
|
self._check_image_duplicates()
|
||||||
|
self._info_image_used()
|
||||||
|
|
||||||
|
def initialize(self, context):
|
||||||
|
super(Googlephotos, self).initialize(context)
|
||||||
|
for image in self.test_images:
|
||||||
|
if os.path.exists(image):
|
||||||
|
image_path = image
|
||||||
|
else:
|
||||||
|
image_path = context.resolver.get(wlauto.common.resources.File(self, image))
|
||||||
|
self.device.push_file(image_path, self.device.working_directory, timeout=300)
|
||||||
|
|
||||||
|
# Force a re-index of the mediaserver cache to pick up new files
|
||||||
|
self.device.execute('am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///sdcard')
|
||||||
|
|
||||||
|
def teardown(self, context):
|
||||||
|
super(Googlephotos, self).teardown(context)
|
||||||
|
self.device.execute('am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///sdcard')
|
||||||
|
|
||||||
|
def finalize(self, context):
|
||||||
|
super(Googlephotos, self).finalize(context)
|
||||||
|
|
||||||
|
for entry in self.device.listdir(self.device.working_directory):
|
||||||
|
if entry in self.test_images:
|
||||||
|
self.device.delete_file(self.device.path.join(self.device.working_directory, entry))
|
||||||
|
|
||||||
|
self.device.execute('am broadcast -a android.intent.action.MEDIA_MOUNTED -d file:///sdcard')
|
||||||
|
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
# Internal methods
|
||||||
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def _check_image_extensions(self):
|
||||||
|
for image in self.test_images:
|
||||||
|
if not image.endswith(('jpg', 'jpeg', 'png')):
|
||||||
|
raise ValidationError('{} must be a jpeg or png file'.format(image))
|
||||||
|
|
||||||
|
def _check_image_numbers(self):
|
||||||
|
if len(self.test_images) != 4:
|
||||||
|
message = "This workload requires four test images - only {} specified"
|
||||||
|
raise ValidationError(message.format(len(self.test_images)))
|
||||||
|
|
||||||
|
def _check_image_duplicates(self):
|
||||||
|
if len(self.test_images) != len(set(self.test_images)):
|
||||||
|
raise ValidationError('Duplicate image names not allowed')
|
||||||
|
|
||||||
|
def _info_image_used(self):
|
||||||
|
if set(self.test_images) & set(self.default_test_images):
|
||||||
|
self.logger.info('Using default test images')
|
||||||
|
else:
|
||||||
|
self.logger.warning('Using custom test images')
|
Binary file not shown.
39
wlauto/workloads/googlephotos/uiauto/build.sh
Executable file
39
wlauto/workloads/googlephotos/uiauto/build.sh
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# CD into build dir if possible - allows building from any directory
|
||||||
|
script_path='.'
|
||||||
|
if `readlink -f $0 &>/dev/null`; then
|
||||||
|
script_path=`readlink -f $0 2>/dev/null`
|
||||||
|
fi
|
||||||
|
script_dir=`dirname $script_path`
|
||||||
|
cd $script_dir
|
||||||
|
|
||||||
|
# Ensure build.xml exists before starting
|
||||||
|
if [[ ! -f build.xml ]]; then
|
||||||
|
echo 'Ant build.xml file not found! Check that you are in the right directory.'
|
||||||
|
exit 9
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Copy base classes from wlauto dist
|
||||||
|
class_dir=bin/classes/com/arm/wlauto/uiauto
|
||||||
|
base_classes=`python -c "import os, wlauto; print os.path.join(os.path.dirname(wlauto.__file__), 'common', 'android', '*.class')"`
|
||||||
|
mkdir -p $class_dir
|
||||||
|
cp $base_classes $class_dir
|
||||||
|
|
||||||
|
# Build and return appropriate exit code if failed
|
||||||
|
ant build
|
||||||
|
exit_code=$?
|
||||||
|
if [[ $exit_code -ne 0 ]]; then
|
||||||
|
echo "ERROR: 'ant build' exited with code $exit_code"
|
||||||
|
exit $exit_code
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If successful move JAR file to workload folder (overwrite previous)
|
||||||
|
package=com.arm.wlauto.uiauto.googlephotos.jar
|
||||||
|
rm -f ../$package
|
||||||
|
if [[ -f bin/$package ]]; then
|
||||||
|
cp bin/$package ..
|
||||||
|
else
|
||||||
|
echo 'ERROR: UiAutomator JAR could not be found!'
|
||||||
|
exit 9
|
||||||
|
fi
|
92
wlauto/workloads/googlephotos/uiauto/build.xml
Normal file
92
wlauto/workloads/googlephotos/uiauto/build.xml
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="com.arm.wlauto.uiauto.googlephotos" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||||
|
It contains the path to the SDK. It should *NOT* be checked into
|
||||||
|
Version Control Systems. -->
|
||||||
|
<property file="local.properties" />
|
||||||
|
|
||||||
|
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||||
|
'android' tool to add properties to it.
|
||||||
|
This is the place to change some Ant specific build properties.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
source.dir
|
||||||
|
The name of the source directory. Default is 'src'.
|
||||||
|
out.dir
|
||||||
|
The name of the output directory. Default is 'bin'.
|
||||||
|
|
||||||
|
For other overridable properties, look at the beginning of the rules
|
||||||
|
files in the SDK, at tools/ant/build.xml
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should
|
||||||
|
be updated using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="ant.properties" />
|
||||||
|
|
||||||
|
<!-- if sdk.dir was not set from one of the property file, then
|
||||||
|
get it from the ANDROID_HOME env var.
|
||||||
|
This must be done before we load project.properties since
|
||||||
|
the proguard config can use sdk.dir -->
|
||||||
|
<property environment="env" />
|
||||||
|
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||||
|
<isset property="env.ANDROID_HOME" />
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<!-- The project.properties file is created and updated by the 'android'
|
||||||
|
tool, as well as ADT.
|
||||||
|
|
||||||
|
This contains project specific properties such as project target, and library
|
||||||
|
dependencies. Lower level build properties are stored in ant.properties
|
||||||
|
(or in .classpath for Eclipse projects).
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems. -->
|
||||||
|
<loadproperties srcFile="project.properties" />
|
||||||
|
|
||||||
|
<!-- quick check on sdk.dir -->
|
||||||
|
<fail
|
||||||
|
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||||
|
unless="sdk.dir"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Import per project custom build rules if present at the root of the project.
|
||||||
|
This is the place to put custom intermediary targets such as:
|
||||||
|
-pre-build
|
||||||
|
-pre-compile
|
||||||
|
-post-compile (This is typically used for code obfuscation.
|
||||||
|
Compiled code location: ${out.classes.absolute.dir}
|
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||||
|
-post-package
|
||||||
|
-post-build
|
||||||
|
-pre-clean
|
||||||
|
-->
|
||||||
|
<import file="custom_rules.xml" optional="true" />
|
||||||
|
|
||||||
|
<!-- Import the actual build file.
|
||||||
|
|
||||||
|
To customize existing targets, there are two options:
|
||||||
|
- Customize only one target:
|
||||||
|
- copy/paste the target into this file, *before* the
|
||||||
|
<import> task.
|
||||||
|
- customize it to your needs.
|
||||||
|
- Customize the whole content of build.xml
|
||||||
|
- copy/paste the content of the rules files (minus the top node)
|
||||||
|
into this file, replacing the <import> task.
|
||||||
|
- customize to your needs.
|
||||||
|
|
||||||
|
***********************
|
||||||
|
****** IMPORTANT ******
|
||||||
|
***********************
|
||||||
|
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||||
|
in order to avoid having your file be overridden by tools such as "android update project"
|
||||||
|
-->
|
||||||
|
<!-- version-tag: VERSION_TAG -->
|
||||||
|
<import file="${sdk.dir}/tools/ant/uibuild.xml" />
|
||||||
|
|
||||||
|
</project>
|
14
wlauto/workloads/googlephotos/uiauto/project.properties
Normal file
14
wlauto/workloads/googlephotos/uiauto/project.properties
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# This file is automatically generated by Android Tools.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file must be checked in Version Control Systems.
|
||||||
|
#
|
||||||
|
# To customize properties used by the Ant build system edit
|
||||||
|
# "ant.properties", and override values to adapt the script to your
|
||||||
|
# project structure.
|
||||||
|
#
|
||||||
|
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
|
||||||
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
|
# Project target.
|
||||||
|
target=android-18
|
440
wlauto/workloads/googlephotos/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
Executable file
440
wlauto/workloads/googlephotos/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java
Executable file
@ -0,0 +1,440 @@
|
|||||||
|
/* Copyright 2014-2016 ARM Limited
|
||||||
|
*
|
||||||
|
* 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.arm.wlauto.uiauto.googlephotos;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
|
||||||
|
// Import the uiautomator libraries
|
||||||
|
import com.android.uiautomator.core.UiObject;
|
||||||
|
import com.android.uiautomator.core.UiObjectNotFoundException;
|
||||||
|
import com.android.uiautomator.core.UiSelector;
|
||||||
|
import com.android.uiautomator.core.UiScrollable;
|
||||||
|
|
||||||
|
import com.arm.wlauto.uiauto.UxPerfUiAutomation;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
public class UiAutomation extends UxPerfUiAutomation {
|
||||||
|
|
||||||
|
public static String TAG = "uxperf_googlephotos";
|
||||||
|
|
||||||
|
public Bundle parameters;
|
||||||
|
private int viewTimeoutSecs = 10;
|
||||||
|
private long viewTimeout = TimeUnit.SECONDS.toMillis(viewTimeoutSecs);
|
||||||
|
|
||||||
|
public void runUiAutomation() throws Exception {
|
||||||
|
parameters = getParams();
|
||||||
|
|
||||||
|
pauseForSplashScreen();
|
||||||
|
setScreenOrientation(ScreenOrientation.NATURAL);
|
||||||
|
dismissWelcomeView();
|
||||||
|
closePromotionPopUp();
|
||||||
|
selectWorkingGallery();
|
||||||
|
gesturesTest();
|
||||||
|
editPhotoColorTest();
|
||||||
|
cropPhotoTest();
|
||||||
|
rotatePhotoTest();
|
||||||
|
unsetScreenOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pauseForSplashScreen() {
|
||||||
|
sleep(5); // Pause while splash screen loads
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dismissWelcomeView() throws Exception {
|
||||||
|
|
||||||
|
// Click through the first two pages and make sure that we don't sign
|
||||||
|
// in to our google account. This ensures the same set of photographs
|
||||||
|
// are placed in the camera directory for each run.
|
||||||
|
|
||||||
|
UiObject getStartedButton =
|
||||||
|
new UiObject(new UiSelector().textContains("Get started")
|
||||||
|
.className("android.widget.Button"));
|
||||||
|
|
||||||
|
waitObject(getStartedButton, viewTimeoutSecs);
|
||||||
|
getStartedButton.click();
|
||||||
|
|
||||||
|
// A network connection is not required for this workload. However,
|
||||||
|
// when the Google Photos app is invoked from the multiapp workload a
|
||||||
|
// connection is required for sharing content. Handle the different UI
|
||||||
|
// pathways when dismissing welcome views here.
|
||||||
|
UiObject doNotSignInButton =
|
||||||
|
new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/dont_sign_in_button"));
|
||||||
|
|
||||||
|
if (doNotSignInButton.exists()) {
|
||||||
|
doNotSignInButton.click();
|
||||||
|
} else {
|
||||||
|
UiObject welcomeButton =
|
||||||
|
getUiObjectByResourceId("com.google.android.apps.photos:id/name",
|
||||||
|
"android.widget.TextView");
|
||||||
|
welcomeButton.click();
|
||||||
|
|
||||||
|
UiObject useWithoutAccount =
|
||||||
|
getUiObjectByText("Use without an account", "android.widget.TextView");
|
||||||
|
useWithoutAccount.clickAndWaitForNewWindow();
|
||||||
|
|
||||||
|
// Dismiss welcome views promoting app features
|
||||||
|
sleep(1);
|
||||||
|
uiDeviceSwipeLeft(10);
|
||||||
|
sleep(1);
|
||||||
|
uiDeviceSwipeLeft(10);
|
||||||
|
sleep(1);
|
||||||
|
uiDeviceSwipeLeft(10);
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
UiObject nextButton =
|
||||||
|
new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/next_button")
|
||||||
|
.className("android.widget.ImageView"));
|
||||||
|
|
||||||
|
if (nextButton.exists()) {
|
||||||
|
nextButton.clickAndWaitForNewWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
UiObject workingFolder = new UiObject(new UiSelector().text("wa-working"));
|
||||||
|
waitObject(workingFolder, viewTimeoutSecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gesturesTest() throws Exception {
|
||||||
|
String testTag = "gestures";
|
||||||
|
|
||||||
|
// Perform a range of swipe tests while browsing photo gallery
|
||||||
|
LinkedHashMap<String, GestureTestParams> testParams = new LinkedHashMap<String, GestureTestParams>();
|
||||||
|
testParams.put("swipe_left", new GestureTestParams(GestureType.UIDEVICE_SWIPE, Direction.LEFT, 10));
|
||||||
|
testParams.put("pinch_out", new GestureTestParams(GestureType.PINCH, PinchType.OUT, 100, 50));
|
||||||
|
testParams.put("pinch_in", new GestureTestParams(GestureType.PINCH, PinchType.IN, 100, 50));
|
||||||
|
testParams.put("swipe_right", new GestureTestParams(GestureType.UIDEVICE_SWIPE, Direction.RIGHT, 10));
|
||||||
|
|
||||||
|
Iterator<Entry<String, GestureTestParams>> it = testParams.entrySet().iterator();
|
||||||
|
|
||||||
|
// Select first photograph
|
||||||
|
selectPhoto(1);
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Map.Entry<String, GestureTestParams> pair = it.next();
|
||||||
|
GestureType type = pair.getValue().gestureType;
|
||||||
|
Direction dir = pair.getValue().gestureDirection;
|
||||||
|
PinchType pinch = pair.getValue().pinchType;
|
||||||
|
int steps = pair.getValue().steps;
|
||||||
|
int percent = pair.getValue().percent;
|
||||||
|
|
||||||
|
UiObject view = new UiObject(new UiSelector().enabled(true));
|
||||||
|
|
||||||
|
if (!view.waitForExists(viewTimeout)) {
|
||||||
|
throw new UiObjectNotFoundException("Could not find \"photo view\".");
|
||||||
|
}
|
||||||
|
|
||||||
|
String runName = String.format(testTag + "_" + pair.getKey());
|
||||||
|
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||||
|
logger.start();
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case UIDEVICE_SWIPE:
|
||||||
|
uiDeviceSwipe(dir, steps);
|
||||||
|
break;
|
||||||
|
case UIOBJECT_SWIPE:
|
||||||
|
uiObjectSwipe(view, dir, steps);
|
||||||
|
break;
|
||||||
|
case PINCH:
|
||||||
|
uiObjectVertPinch(view, pinch, steps, percent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
UiObject navigateUpButton =
|
||||||
|
getUiObjectByDescription("Navigate Up", "android.widget.ImageButton");
|
||||||
|
navigateUpButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Position { LEFT, RIGHT, CENTRE };
|
||||||
|
|
||||||
|
private class SeekBarTestParams {
|
||||||
|
|
||||||
|
private Position seekBarPosition;
|
||||||
|
private int percent;
|
||||||
|
private int steps;
|
||||||
|
|
||||||
|
SeekBarTestParams(final Position position, final int steps, final int percent) {
|
||||||
|
this.seekBarPosition = position;
|
||||||
|
this.steps = steps;
|
||||||
|
this.percent = percent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void editPhotoColorTest() throws Exception {
|
||||||
|
String testTag = "edit_photo";
|
||||||
|
|
||||||
|
// Perform a range of swipe tests while browsing photo gallery
|
||||||
|
LinkedHashMap<String, SeekBarTestParams> testParams = new LinkedHashMap<String, SeekBarTestParams>();
|
||||||
|
testParams.put("increment_color", new SeekBarTestParams(Position.RIGHT, 10, 20));
|
||||||
|
testParams.put("reset_color", new SeekBarTestParams(Position.CENTRE, 0, 0));
|
||||||
|
testParams.put("decrement_color", new SeekBarTestParams(Position.LEFT, 10, 20));
|
||||||
|
|
||||||
|
Iterator<Entry<String, SeekBarTestParams>> it = testParams.entrySet().iterator();
|
||||||
|
|
||||||
|
// Select second photograph
|
||||||
|
selectPhoto(2);
|
||||||
|
UiObject editView = getUiObjectByResourceId("com.google.android.apps.photos:id/edit",
|
||||||
|
"android.widget.ImageView");
|
||||||
|
editView.click();
|
||||||
|
|
||||||
|
// Manage potential different spelling of UI element
|
||||||
|
UiObject editColor = new UiObject(new UiSelector().text("Color"));
|
||||||
|
UiObject editColour = new UiObject(new UiSelector().text("Colour"));
|
||||||
|
|
||||||
|
if (editColor.exists()) {
|
||||||
|
editColor.click();
|
||||||
|
} else if (editColour.exists()) {
|
||||||
|
editColour.click();
|
||||||
|
} else {
|
||||||
|
throw new UiObjectNotFoundException(String.format("Could not find \"%s\" \"%s\"",
|
||||||
|
"Color/Colour", "android.widget.RadioButton"));
|
||||||
|
}
|
||||||
|
|
||||||
|
UiObject seekBar = getUiObjectByResourceId("com.google.android.apps.photos:id/cpe_strength_seek_bar",
|
||||||
|
"android.widget.SeekBar");
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Map.Entry<String, SeekBarTestParams> pair = it.next();
|
||||||
|
Position pos = pair.getValue().seekBarPosition;
|
||||||
|
int steps = pair.getValue().steps;
|
||||||
|
int percent = pair.getValue().percent;
|
||||||
|
|
||||||
|
String runName = String.format(testTag + "_" + pair.getKey());
|
||||||
|
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||||
|
|
||||||
|
logger.start();
|
||||||
|
seekBarTest(seekBar, pos, steps);
|
||||||
|
logger.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAndReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cropPhotoTest() throws Exception {
|
||||||
|
String testTag = "crop_photo";
|
||||||
|
|
||||||
|
// To improve travel accuracy perform the slide bar operation slowly
|
||||||
|
final int steps = 500;
|
||||||
|
|
||||||
|
// Perform a range of swipe tests while browsing photo gallery
|
||||||
|
LinkedHashMap<String, Position> testParams = new LinkedHashMap<String, Position>();
|
||||||
|
testParams.put("tilt_positive", Position.LEFT);
|
||||||
|
testParams.put("tilt_reset", Position.RIGHT);
|
||||||
|
testParams.put("tilt_negative", Position.RIGHT);
|
||||||
|
|
||||||
|
Iterator<Entry<String, Position>> it = testParams.entrySet().iterator();
|
||||||
|
|
||||||
|
// Select third photograph
|
||||||
|
selectPhoto(3);
|
||||||
|
UiObject editView = getUiObjectByResourceId("com.google.android.apps.photos:id/edit",
|
||||||
|
"android.widget.ImageView");
|
||||||
|
editView.click();
|
||||||
|
|
||||||
|
UiObject cropTool = getUiObjectByResourceId("com.google.android.apps.photos:id/cpe_crop_tool",
|
||||||
|
"android.widget.ImageView");
|
||||||
|
cropTool.click();
|
||||||
|
|
||||||
|
UiObject straightenSlider = getUiObjectByResourceId("com.google.android.apps.photos:id/cpe_straighten_slider",
|
||||||
|
"android.view.View");
|
||||||
|
|
||||||
|
while (it.hasNext()) {
|
||||||
|
Map.Entry<String, Position> pair = it.next();
|
||||||
|
Position pos = pair.getValue();
|
||||||
|
|
||||||
|
String runName = String.format(testTag + "_" + pair.getKey());
|
||||||
|
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||||
|
|
||||||
|
logger.start();
|
||||||
|
slideBarTest(straightenSlider, pos, steps);
|
||||||
|
logger.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAndReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rotatePhotoTest() throws Exception {
|
||||||
|
String testTag = "rotate_photo";
|
||||||
|
|
||||||
|
String[] subTests = {"anticlockwise_90", "anticlockwise_180", "anticlockwise_270"};
|
||||||
|
|
||||||
|
// Select fourth photograph
|
||||||
|
selectPhoto(4);
|
||||||
|
UiObject editView = getUiObjectByResourceId("com.google.android.apps.photos:id/edit",
|
||||||
|
"android.widget.ImageView");
|
||||||
|
editView.click();
|
||||||
|
|
||||||
|
UiObject cropTool = getUiObjectByResourceId("com.google.android.apps.photos:id/cpe_crop_tool",
|
||||||
|
"android.widget.ImageView");
|
||||||
|
cropTool.click();
|
||||||
|
|
||||||
|
UiObject rotate = getUiObjectByResourceId("com.google.android.apps.photos:id/cpe_rotate_90",
|
||||||
|
"android.widget.ImageView");
|
||||||
|
|
||||||
|
for (String subTest : subTests) {
|
||||||
|
String runName = String.format(testTag + "_" + subTest);
|
||||||
|
ActionLogger logger = new ActionLogger(runName, parameters);
|
||||||
|
|
||||||
|
logger.start();
|
||||||
|
rotate.click();
|
||||||
|
logger.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
closeAndReturn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to slide the seekbar during photo edit.
|
||||||
|
private void seekBarTest(final UiObject view, final Position pos, final int steps) throws Exception {
|
||||||
|
final int SWIPE_MARGIN_LIMIT = 5;
|
||||||
|
Rect rect = view.getVisibleBounds();
|
||||||
|
|
||||||
|
switch (pos) {
|
||||||
|
case LEFT:
|
||||||
|
getUiDevice().click(rect.left + SWIPE_MARGIN_LIMIT, rect.centerY());
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
getUiDevice().click(rect.right - SWIPE_MARGIN_LIMIT, rect.centerY());
|
||||||
|
break;
|
||||||
|
case CENTRE:
|
||||||
|
view.click();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to slide the slidebar during photo edit.
|
||||||
|
private void slideBarTest(final UiObject view, final Position pos, final int steps) throws Exception {
|
||||||
|
final int SWIPE_MARGIN_LIMIT = 5;
|
||||||
|
Rect rect = view.getBounds();
|
||||||
|
|
||||||
|
switch (pos) {
|
||||||
|
case LEFT:
|
||||||
|
getUiDevice().drag(rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(),
|
||||||
|
rect.left + rect.width() / 4, rect.centerY(),
|
||||||
|
steps);
|
||||||
|
break;
|
||||||
|
case RIGHT:
|
||||||
|
getUiDevice().drag(rect.right - SWIPE_MARGIN_LIMIT, rect.centerY(),
|
||||||
|
rect.right - rect.width() / 4, rect.centerY(),
|
||||||
|
steps);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closePromotionPopUp() throws Exception {
|
||||||
|
UiObject promoCloseButton =
|
||||||
|
new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/promo_close_button"));
|
||||||
|
|
||||||
|
if (promoCloseButton.exists()) {
|
||||||
|
promoCloseButton.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to click on the wa-working gallery.
|
||||||
|
public void selectWorkingGallery() throws Exception {
|
||||||
|
UiObject workdir = new UiObject(new UiSelector().text("wa-working")
|
||||||
|
.className("android.widget.TextView"));
|
||||||
|
|
||||||
|
UiScrollable scrollView = new UiScrollable(new UiSelector().scrollable(true));
|
||||||
|
|
||||||
|
while (!workdir.exists()) {
|
||||||
|
scrollView.scrollForward();
|
||||||
|
}
|
||||||
|
|
||||||
|
workdir.clickAndWaitForNewWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to click on an individual photograph based on index in wa-working gallery.
|
||||||
|
public void selectPhoto(final int index) throws Exception {
|
||||||
|
UiObject photo =
|
||||||
|
new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/recycler_view")
|
||||||
|
.childSelector(new UiSelector()
|
||||||
|
.index(index)));
|
||||||
|
|
||||||
|
// On some versions of the app a non-zero index is used for the
|
||||||
|
// photographs position while on other versions a zero index is used.
|
||||||
|
// Try both possiblities before throwing an exception.
|
||||||
|
if (photo.exists()) {
|
||||||
|
photo.click();
|
||||||
|
} else {
|
||||||
|
photo = new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/recycler_view")
|
||||||
|
.childSelector(new UiSelector()
|
||||||
|
.index(index - 1)));
|
||||||
|
photo.click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper that accepts, closes and navigates back to application home screen after an edit operation.
|
||||||
|
// dontsave - True will discard the image. False will save the image
|
||||||
|
public void closeAndReturn(final boolean dontsave) throws Exception {
|
||||||
|
|
||||||
|
UiObject accept = getUiObjectByDescription("Accept", "android.widget.ImageView");
|
||||||
|
accept.click();
|
||||||
|
|
||||||
|
if (dontsave) {
|
||||||
|
UiObject close = getUiObjectByDescription("Close editor", "android.widget.ImageView");
|
||||||
|
close.click();
|
||||||
|
|
||||||
|
UiObject discard = getUiObjectByText("DISCARD", "android.widget.Button");
|
||||||
|
discard.waitForExists(viewTimeout);
|
||||||
|
discard.click();
|
||||||
|
} else {
|
||||||
|
UiObject save = getUiObjectByText("SAVE", "android.widget.TextView");
|
||||||
|
save.waitForExists(viewTimeout);
|
||||||
|
save.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
UiObject navigateUpButton =
|
||||||
|
new UiObject(new UiSelector().descriptionContains("Navigate Up")
|
||||||
|
.className("android.widget.ImageButton"));
|
||||||
|
navigateUpButton.waitForExists(viewTimeout);
|
||||||
|
navigateUpButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to tag an individual photograph based on the index in wa-working
|
||||||
|
// gallery. After long clicking it tags the photograph with a tick in the
|
||||||
|
// corner of the image to indicate that the photograph has been selected
|
||||||
|
public void tagPhoto(final int index) throws Exception {
|
||||||
|
UiObject photo =
|
||||||
|
new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/recycler_view")
|
||||||
|
.childSelector(new UiSelector()
|
||||||
|
.index(index)));
|
||||||
|
|
||||||
|
// On some versions of the app a non-zero index is used for the
|
||||||
|
// photographs position while on other versions a zero index is used.
|
||||||
|
// Try both possiblities before throwing an exception.
|
||||||
|
if (photo.exists()) {
|
||||||
|
uiObjectPerformLongClick(photo, 100);
|
||||||
|
} else {
|
||||||
|
photo = new UiObject(new UiSelector().resourceId("com.google.android.apps.photos:id/recycler_view")
|
||||||
|
.childSelector(new UiSelector()
|
||||||
|
.index(index - 1)));
|
||||||
|
uiObjectPerformLongClick(photo, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
@ -11,4 +11,4 @@
|
|||||||
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
|
||||||
|
|
||||||
# Project target.
|
# Project target.
|
||||||
target=android-17
|
target=android-18
|
||||||
|
Loading…
x
Reference in New Issue
Block a user