diff --git a/wlauto/common/android/BaseUiAutomation.class b/wlauto/common/android/BaseUiAutomation.class index 2683f453..353201f6 100644 Binary files a/wlauto/common/android/BaseUiAutomation.class and b/wlauto/common/android/BaseUiAutomation.class differ diff --git a/wlauto/common/android/workload.py b/wlauto/common/android/workload.py index 61b6d290..97650d15 100644 --- a/wlauto/common/android/workload.py +++ b/wlauto/common/android/workload.py @@ -87,7 +87,7 @@ class UiAutomatorWorkload(Workload): params_dict['workdir'] = self.device.working_directory params = '' for k, v in self.uiauto_params.iteritems(): - params += ' -e {} {}'.format(k, v) + params += ' -e {} "{}"'.format(k, v) self.command = 'uiautomator runtest {}{} -c {}'.format(self.device_uiauto_file, params, method_string) self.device.push_file(self.uiauto_file, self.device_uiauto_file) self.device.killall('uiautomator') diff --git a/wlauto/external/uiauto/build.sh b/wlauto/external/uiauto/build.sh index 96b8b7f2..074f245a 100755 --- a/wlauto/external/uiauto/build.sh +++ b/wlauto/external/uiauto/build.sh @@ -18,4 +18,4 @@ ant build -cp bin/classes/com/arm/wlauto/uiauto/BaseUiAutomation.class ../../common +cp bin/classes/com/arm/wlauto/uiauto/BaseUiAutomation.class ../../common/android diff --git a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java index 4d26100b..8fd35df6 100644 --- a/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java +++ b/wlauto/external/uiauto/src/com/arm/wlauto/uiauto/BaseUiAutomation.java @@ -20,6 +20,10 @@ import java.io.File; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.concurrent.TimeoutException; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import android.app.Activity; import android.os.Bundle; @@ -109,5 +113,40 @@ public class BaseUiAutomation extends UiAutomatorTestCase { throw new TimeoutException("Timed out waiting for Logcat text \"%s\"".format(searchText)); } } + + public Integer[] splitVersion(String versionString) { + String pattern = "(\\d+).(\\d+).(\\d+)"; + Pattern r = Pattern.compile(pattern); + ArrayList result = new ArrayList(); + + Matcher m = r.matcher(versionString); + if (m.find() && m.groupCount() > 0) { + for(int i=1; i<=m.groupCount(); i++) { + result.add(Integer.parseInt(m.group(i))); + } + } else { + throw new IllegalArgumentException(versionString + " - unknown format"); + } + return result.toArray(new Integer[result.size()]); + } + + //Return values: + // -1 = a lower than b + // 0 = a and b equal + // 1 = a greater than b + public int compareVersions(Integer[] a, Integer[] b) { + if (a.length != b.length) { + String msg = "Versions do not match format:\n %1$s\n %1$s"; + msg = String.format(msg, Arrays.toString(a), Arrays.toString(b)); + throw new IllegalArgumentException(msg); + } + for(int i=0; i b[i]) + return 1; + else if(a[i] < b[i]) + return -1; + } + return 0; + } } diff --git a/wlauto/utils/types.py b/wlauto/utils/types.py index 419fcb0c..e9a49fb9 100644 --- a/wlauto/utils/types.py +++ b/wlauto/utils/types.py @@ -111,7 +111,6 @@ def list_of_numbers(value): """ Value must be iterable. All elements will be converted to numbers (either ``ints`` or ``float``\ s depending on the elements). - """ if not isiterable(value): raise ValueError(value) @@ -300,3 +299,32 @@ class arguments(list): def __str__(self): return ' '.join(self) + +class range_dict(dict): + """ + This dict allows you to specify mappings with a range. + + If a key is not in the dict it will search downward until + the next key and return its value. E.g: + + If: + a[5] = "Hello" + a[10] = "There" + + Then: + a[2] == None + a[7] == "Hello" + a[999] == "There" + + """ + def __getitem__(self, i): + key = int(i) + while key not in self and key > 0: + key -= 1 + if key <= 0: + raise KeyError(i) + return dict.__getitem__(self, key) + + def __setitem__(self, i, v): + i = int(i) + super(range_dict, self).__setitem__(i, v) diff --git a/wlauto/workloads/cameracapture/__init__.py b/wlauto/workloads/cameracapture/__init__.py index de72acea..7e7e2aab 100644 --- a/wlauto/workloads/cameracapture/__init__.py +++ b/wlauto/workloads/cameracapture/__init__.py @@ -16,6 +16,7 @@ # pylint: disable=E1101 from wlauto import UiAutomatorWorkload, Parameter +from wlauto.utils.types import range_dict class Cameracapture(UiAutomatorWorkload): @@ -28,6 +29,10 @@ class Cameracapture(UiAutomatorWorkload): package = 'com.google.android.gallery3d' activity = 'com.android.camera.CameraActivity' + api_packages = range_dict() + api_packages[1] = 'com.google.android.gallery3d' + api_packages[23] = 'com.google.android.GoogleCamera' + parameters = [ Parameter('no_of_captures', kind=int, default=5, description='Number of photos to be taken.'), @@ -40,12 +45,18 @@ class Cameracapture(UiAutomatorWorkload): self.uiauto_params['no_of_captures'] = self.no_of_captures self.uiauto_params['time_between_captures'] = self.time_between_captures + def initialize(self, context): + api = self.device.get_sdk_version() + self.uiauto_params['api_level'] = api + self.package = self.api_packages[api] + version = self.device.get_installed_package_version(self.package) + version = version.replace(' ', '_') + self.uiauto_params['version'] = version + def setup(self, context): super(Cameracapture, self).setup(context) self.device.execute('am start -n {}/{}'.format(self.package, self.activity)) - def update_result(self, context): - pass - def teardown(self, context): + self.device.execute('am force-stop {}'.format(self.package)) super(Cameracapture, self).teardown(context) diff --git a/wlauto/workloads/cameracapture/com.arm.wlauto.uiauto.cameracapture.jar b/wlauto/workloads/cameracapture/com.arm.wlauto.uiauto.cameracapture.jar index 0d37d0b2..52bf4b49 100644 Binary files a/wlauto/workloads/cameracapture/com.arm.wlauto.uiauto.cameracapture.jar and b/wlauto/workloads/cameracapture/com.arm.wlauto.uiauto.cameracapture.jar differ diff --git a/wlauto/workloads/cameracapture/uiauto/project.properties b/wlauto/workloads/cameracapture/uiauto/project.properties index a3ee5ab6..ce39f2d0 100644 --- a/wlauto/workloads/cameracapture/uiauto/project.properties +++ b/wlauto/workloads/cameracapture/uiauto/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-17 +target=android-18 diff --git a/wlauto/workloads/cameracapture/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/cameracapture/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java index a5497468..9c9a2dea 100644 --- a/wlauto/workloads/cameracapture/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java +++ b/wlauto/workloads/cameracapture/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -16,6 +16,8 @@ package com.arm.wlauto.uiauto.cameracapture; +import java.util.concurrent.TimeUnit; + import android.app.Activity; import android.os.Bundle; import android.util.Log; @@ -32,37 +34,98 @@ import com.arm.wlauto.uiauto.BaseUiAutomation; public class UiAutomation extends BaseUiAutomation { public static String TAG = "cameracapture"; + int timeDurationBetweenEachCapture = 0; + int sleepTime = 2; + int iterations = 0; + int api = 0; + Integer[] version = {0,0,0}; public void runUiAutomation() throws Exception { - int timeDurationBetweenEachCapture = 0; - int sleepTime = 2; - Bundle parameters = getParams(); - String noOfCaptures = ""; - int iterations = 0; + Bundle parameters = getParams(); + if (parameters.size() > 0) { + iterations = Integer.parseInt(parameters + .getString("no_of_captures")); + timeDurationBetweenEachCapture = Integer.parseInt(parameters + .getString("time_between_captures")); + api = Integer.parseInt(parameters.getString("api_level")); + String versionString = parameters.getString("version"); + version = splitVersion(versionString); + } + + // Pre Android M UI + if(api < 23) + takePhotosAosp(); + else + { + if(compareVersions(version, new Integer[]{3,2,0}) >= 0) + takePhotosGoogleV3_2(); + else + takePhotosGoogle(); + } + } - if (parameters.size() > 0) { - iterations = Integer.parseInt(parameters - .getString("no_of_captures")); - timeDurationBetweenEachCapture = Integer.parseInt(parameters - .getString("time_between_captures")); - } - // switch to camera capture mode - UiObject clickModes = new UiObject(new UiSelector().descriptionMatches("Camera, video or panorama selector")); - clickModes.click(); - sleep(sleepTime); + private void takePhotosAosp() throws Exception + { + // switch to camera capture mode + UiObject clickModes = new UiObject(new UiSelector().descriptionMatches("Camera, video or panorama selector")); + clickModes.click(); + sleep(sleepTime); - UiObject changeModeToCapture = new UiObject(new UiSelector().descriptionMatches("Switch to photo")); + UiObject changeModeToCapture = new UiObject(new UiSelector().descriptionMatches("Switch to photo")); - changeModeToCapture.click(); - sleep(sleepTime); + changeModeToCapture.click(); + sleep(sleepTime); - // click to capture photos - UiObject clickCaptureButton = new UiObject(new UiSelector().descriptionMatches("Shutter button")); + // click to capture photos + UiObject clickCaptureButton = new UiObject(new UiSelector().descriptionMatches("Shutter button")); - for (int i = 0; i < iterations; i++) { - clickCaptureButton.longClick(); - sleep(timeDurationBetweenEachCapture); - } - getUiDevice().pressBack(); + for (int i = 0; i < iterations; i++) { + clickCaptureButton.longClick(); + sleep(timeDurationBetweenEachCapture); + } + getUiDevice().pressBack(); + } + + private void takePhotosGoogleV3_2() throws Exception + { + // clear tutorial if needed + UiObject tutorialText = new UiObject(new UiSelector().resourceId("com.android.camera2:id/photoVideoSwipeTutorialText")); + if (tutorialText.waitForExists(TimeUnit.SECONDS.toMillis(5))) { + tutorialText.swipeLeft(5); + sleep(sleepTime); + tutorialText.swipeRight(5); + } + + // ensure we are in photo mode + UiObject viewFinder = new UiObject(new UiSelector().resourceId("com.android.camera2:id/viewfinder_frame")); + viewFinder.swipeRight(5); + + // click to capture photos + UiObject clickCaptureButton = new UiObject(new UiSelector().resourceId("com.android.camera2:id/photo_video_button")); + + for (int i = 0; i < iterations; i++) { + clickCaptureButton.longClick(); + sleep(timeDurationBetweenEachCapture); + } + } + + private void takePhotosGoogle() throws Exception + { + // open mode select menu + UiObject swipeScreen = new UiObject(new UiSelector().resourceId("com.android.camera2:id/mode_options_overlay")); + swipeScreen.swipeRight(5); + + // switch to video mode + UiObject changeModeToCapture = new UiObject(new UiSelector().descriptionMatches("Switch to Camera Mode")); + changeModeToCapture.click(); + sleep(sleepTime); + + // click to capture photos + UiObject clickCaptureButton = new UiObject(new UiSelector().descriptionMatches("Shutter")); + + for (int i = 0; i < iterations; i++) { + clickCaptureButton.longClick(); + sleep(timeDurationBetweenEachCapture); + } } } diff --git a/wlauto/workloads/camerarecord/__init__.py b/wlauto/workloads/camerarecord/__init__.py index 7f237f2f..b39ab143 100644 --- a/wlauto/workloads/camerarecord/__init__.py +++ b/wlauto/workloads/camerarecord/__init__.py @@ -14,6 +14,7 @@ # from wlauto import UiAutomatorWorkload, Parameter +from wlauto.utils.types import range_dict class Camerarecord(UiAutomatorWorkload): @@ -28,6 +29,10 @@ class Camerarecord(UiAutomatorWorkload): activity = 'com.android.camera.CameraActivity' run_timeout = 0 + api_packages = range_dict() + api_packages[1] = 'com.google.android.gallery3d' + api_packages[23] = 'com.google.android.GoogleCamera' + parameters = [ Parameter('recording_time', kind=int, default=60, description='The video recording time in seconds.'), @@ -36,8 +41,17 @@ class Camerarecord(UiAutomatorWorkload): def __init__(self, device, **kwargs): super(Camerarecord, self).__init__(device) self.uiauto_params['recording_time'] = self.recording_time # pylint: disable=E1101 + self.uiauto_params['version'] = "button" self.run_timeout = 3 * self.uiauto_params['recording_time'] + def initialize(self, context): + api = self.device.get_sdk_version() + self.uiauto_params['api_level'] = api + self.package = self.api_packages[api] + version = self.device.get_installed_package_version(self.package) + version = version.replace(' ', '_') + self.uiauto_params['version'] = version + def setup(self, context): super(Camerarecord, self).setup(context) self.device.execute('am start -n {}/{}'.format(self.package, self.activity)) diff --git a/wlauto/workloads/camerarecord/com.arm.wlauto.uiauto.camerarecord.jar b/wlauto/workloads/camerarecord/com.arm.wlauto.uiauto.camerarecord.jar index 7de7cfcf..d52f2d4d 100644 Binary files a/wlauto/workloads/camerarecord/com.arm.wlauto.uiauto.camerarecord.jar and b/wlauto/workloads/camerarecord/com.arm.wlauto.uiauto.camerarecord.jar differ diff --git a/wlauto/workloads/camerarecord/uiauto/project.properties b/wlauto/workloads/camerarecord/uiauto/project.properties index a3ee5ab6..ce39f2d0 100644 --- a/wlauto/workloads/camerarecord/uiauto/project.properties +++ b/wlauto/workloads/camerarecord/uiauto/project.properties @@ -11,4 +11,4 @@ #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt # Project target. -target=android-17 +target=android-18 diff --git a/wlauto/workloads/camerarecord/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/camerarecord/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java index c030a078..4b504460 100644 --- a/wlauto/workloads/camerarecord/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java +++ b/wlauto/workloads/camerarecord/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -16,6 +16,8 @@ package com.arm.wlauto.uiauto.camerarecord; +import java.util.concurrent.TimeUnit; + import android.app.Activity; import android.os.Bundle; import android.util.Log; @@ -32,18 +34,36 @@ import com.arm.wlauto.uiauto.BaseUiAutomation; public class UiAutomation extends BaseUiAutomation { public static String TAG = "camerarecord"; + int timeToRecord = 0; + int timeout = 4; + int sleepTime = 2; + int recordingTime = 0; + int api = 0; + Integer[] version = {0,0,0}; public void runUiAutomation() throws Exception { Bundle parameters = getParams(); - int timeToRecord = 0; - int timeout = 4; - int sleepTime = 2; - int recordingTime = 0; if (parameters.size() > 0) { recordingTime = Integer.parseInt(parameters .getString("recording_time")); + api = Integer.parseInt(parameters.getString("api_level")); + String versionString = parameters.getString("version"); + version = splitVersion(versionString); } + //Pre Android M UI + if (api < 23) + recordVideoAosp(); + else + { + if(compareVersions(version, new Integer[]{3,2,0}) >= 0) + recordVideoGoogleV3_2(); + else + recordVideoGoogle(); + } + } + + void recordVideoAosp() throws Exception { // switch to camera capture mode UiObject clickModes = new UiObject(new UiSelector().descriptionMatches("Camera, video or panorama selector")); clickModes.click(); @@ -62,4 +82,44 @@ public class UiAutomation extends BaseUiAutomation { getUiDevice().pressBack(); } + void recordVideoGoogleV3_2() throws Exception { + // clear tutorial if needed + UiObject tutorialText = new UiObject(new UiSelector().resourceId("com.android.camera2:id/photoVideoSwipeTutorialText")); + if (tutorialText.waitForExists(TimeUnit.SECONDS.toMillis(5))) { + tutorialText.swipeLeft(5); + sleep(sleepTime); + tutorialText.swipeRight(5); + } + + // ensure we are in video mode + UiObject viewFinder = new UiObject(new UiSelector().resourceId("com.android.camera2:id/viewfinder_frame")); + viewFinder.swipeLeft(5); + + // click to capture photos + UiObject clickCaptureButton = new UiObject(new UiSelector().resourceId("com.android.camera2:id/photo_video_button")); + clickCaptureButton.longClick(); + sleep(recordingTime); + + // stop video recording + clickCaptureButton.longClick(); + } + + void recordVideoGoogle() throws Exception { + // Open mode select menu + UiObject swipeScreen = new UiObject(new UiSelector().resourceId("com.android.camera2:id/mode_options_overlay")); + swipeScreen.swipeRight(5); + + // Switch to video mode + UiObject changeModeToCapture = new UiObject(new UiSelector().descriptionMatches("Switch to Video Camera")); + changeModeToCapture.click(); + sleep(sleepTime); + + UiObject clickRecordingButton = new UiObject(new UiSelector().descriptionMatches("Shutter")); + clickRecordingButton.longClick(); + sleep(recordingTime); + + // Stop video recording + clickRecordingButton.longClick(); + } } +