Merge "Increase timeout for testDeselectTrackForSubtitleTracks." into nyc-dev
diff --git a/OldCtsTestCaseList.mk b/OldCtsTestCaseList.mk
index 68130f3..aff9f3c 100644
--- a/OldCtsTestCaseList.mk
+++ b/OldCtsTestCaseList.mk
@@ -109,6 +109,8 @@
CtsDeviceTaskSwitchingAppA \
CtsDeviceTaskSwitchingAppB \
CtsDeviceTaskSwitchingControl \
+ CtsDragAndDropSourceApp \
+ CtsDragAndDropTargetApp \
CtsExternalServiceService \
CtsHostsideNetworkTestsApp \
CtsHostsideNetworkTestsApp2 \
@@ -266,6 +268,7 @@
CtsAtraceHostTestCases \
CtsCppToolsTestCases \
CtsDevicePolicyManagerTestCases \
+ CtsDragAndDropHostTestCases \
CtsDumpsysHostTestCases \
CtsHostsideNetworkTests \
CtsJdwpSecurityHostTestCases \
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index 4777f97..54bd0ad 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -58,6 +58,10 @@
# Seconds timeout on each socket operation.
SOCK_TIMEOUT = 10.0
+ # Additional timeout in seconds when ITS service is doing more complicated
+ # operations, for example: issuing warmup requests before actual capture.
+ EXTRA_SOCK_TIMEOUT = 5.0
+
SEC_TO_NSEC = 1000*1000*1000.0
PACKAGE = 'com.android.cts.verifier.camera.its'
@@ -327,9 +331,12 @@
cmd = {}
cmd["cmdName"] = "getSensorEvents"
self.sock.send(json.dumps(cmd) + "\n")
+ timeout = self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT
+ self.sock.settimeout(timeout)
data,_ = self.__read_response_from_socket()
if data['tag'] != 'sensorEvents':
raise its.error.Error('Invalid command response')
+ self.sock.settimeout(self.SOCK_TIMEOUT)
return data['objValue']
def get_camera_ids(self):
@@ -674,6 +681,8 @@
extended_timeout = longest_exp_time / self.SEC_TO_NSEC + \
self.SOCK_TIMEOUT
+ if repeat_request:
+ extended_timeout += self.EXTRA_SOCK_TIMEOUT
self.sock.settimeout(extended_timeout)
print "Capturing %d frame%s with %d format%s [%s]" % (
diff --git a/apps/CameraITS/tests/scene1/test_locked_burst.py b/apps/CameraITS/tests/scene1/test_locked_burst.py
index 6552c73..daefb6b 100644
--- a/apps/CameraITS/tests/scene1/test_locked_burst.py
+++ b/apps/CameraITS/tests/scene1/test_locked_burst.py
@@ -32,7 +32,7 @@
NAME = os.path.basename(__file__).split(".")[0]
BURST_LEN = 8
- SPREAD_THRESH_MANUAL_SENSOR = 0.005
+ SPREAD_THRESH_MANUAL_SENSOR = 0.01
SPREAD_THRESH = 0.03
FPS_MAX_DIFF = 2.0
diff --git a/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py b/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py
index 20558d7..61b431c 100644
--- a/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py
+++ b/apps/CameraITS/tests/scene1/test_post_raw_sensitivity_boost.py
@@ -30,7 +30,10 @@
NAME = os.path.basename(__file__).split(".")[0]
# Each raw image
- RATIO_THRESHOLD = 0.05
+ RATIO_THRESHOLD = 0.1
+ # Waive the check if raw pixel value is below this level (signal too small
+ # that small black level error converts to huge error in percentage)
+ RAW_PIXEL_VAL_THRESHOLD = 0.03
with its.device.ItsSession() as cam:
props = cam.get_camera_properties()
@@ -135,6 +138,8 @@
raw_rgb_means[step - 1][rgb],
raw_rgb_means[step][rgb],
ratio, raw_thres_min, raw_thres_max)
+ if (raw_rgb_means[step][rgb] <= RAW_PIXEL_VAL_THRESHOLD):
+ continue
assert(raw_thres_min < ratio < raw_thres_max)
# Test that each yuv step is about the same bright as their mean
@@ -142,9 +147,12 @@
yuv_thres_max = 1 + RATIO_THRESHOLD
for rgb in range(3):
vals = [val[rgb] for val in yuv_rgb_means]
+ for step in range(len(reqs)):
+ if (raw_rgb_means[step][rgb] <= RAW_PIXEL_VAL_THRESHOLD):
+ vals = vals[:step]
mean = sum(vals) / len(vals)
print "%s channel vals %s mean %f"%(rgb_str[rgb], vals, mean)
- for step in range(len(reqs)):
+ for step in range(len(vals)):
ratio = vals[step] / mean
assert(yuv_thres_min < ratio < yuv_thres_max)
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index e6fe4c2..c4f9b84 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -15,6 +15,7 @@
import its.image
import its.device
import its.objects
+import its.caps
import time
import math
import pylab
@@ -58,6 +59,11 @@
THRESH_MAX_SHIFT_MS = 2
THRESH_MIN_ROT = 0.001
+# lens facing
+FACING_FRONT = 0
+FACING_BACK = 1
+FACING_EXTERNAL = 2
+
def main():
"""Test if image and motion sensor events are well synchronized.
@@ -98,7 +104,7 @@
# Compute the camera rotation displacements (rad) between each pair of
# adjacent frames.
- cam_rots = get_cam_rotations(frames)
+ cam_rots = get_cam_rotations(frames, events["facing"])
if max(abs(cam_rots)) < THRESH_MIN_ROT:
print "Device wasn't moved enough"
assert(0)
@@ -240,7 +246,7 @@
gyro_rots = numpy.array(gyro_rots)
return gyro_rots
-def get_cam_rotations(frames):
+def get_cam_rotations(frames, facing):
"""Get the rotations of the camera between each pair of frames.
Takes N frames and returns N-1 angular displacements corresponding to the
@@ -264,8 +270,13 @@
p1,st,_ = cv2.calcOpticalFlowPyrLK(gframe0, gframe1, p0, None,
**LK_PARAMS)
tform = procrustes_rotation(p0[st==1], p1[st==1])
- # TODO: Choose the sign for the rotation so the cam matches the gyro
- rot = -math.atan2(tform[0, 1], tform[0, 0])
+ if facing == FACING_BACK:
+ rot = -math.atan2(tform[0, 1], tform[0, 0])
+ elif facing == FACING_FRONT:
+ rot = math.atan2(tform[0, 1], tform[0, 0])
+ else:
+ print "Unknown lens facing", facing
+ assert(0)
rots.append(rot)
if i == 1:
# Save a debug visualization of the features that are being
@@ -323,16 +334,25 @@
frames: List of RGB images as numpy arrays.
"""
with its.device.ItsSession() as cam:
+ props = cam.get_camera_properties()
+ its.caps.skip_unless(its.caps.sensor_fusion(props) and
+ its.caps.manual_sensor(props) and
+ props['android.lens.facing'] != FACING_EXTERNAL)
+
print "Starting sensor event collection"
cam.start_sensor_events()
# Sleep a few seconds for gyro events to stabilize.
- time.sleep(5)
+ time.sleep(2)
# TODO: Ensure that OIS is disabled; set to DISABLE and wait some time.
# Capture the frames.
- props = cam.get_camera_properties()
+ facing = props['android.lens.facing']
+ if facing != FACING_FRONT and facing != FACING_BACK:
+ print "Unknown lens facing", facing
+ assert(0)
+
fmt = {"format":"yuv", "width":W, "height":H}
s,e,_,_,_ = cam.do_3a(get_results=True)
req = its.objects.manual_capture_request(s, e)
@@ -350,7 +370,8 @@
exptimes = [c["metadata"]["android.sensor.exposureTime"] for c in caps]
readouts = [c["metadata"]["android.sensor.rollingShutterSkew"]
for c in caps]
- events = {"gyro": gyro, "cam": zip(starts,exptimes,readouts)}
+ events = {"gyro": gyro, "cam": zip(starts,exptimes,readouts),
+ "facing": facing}
with open("%s_events.txt"%(NAME), "w") as f:
f.write(json.dumps(events))
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index 7239c9a..52780eb 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -45,12 +45,15 @@
"scene2":[],
"scene3":[],
"scene4":[],
- "scene5":[]
+ "scene5":[],
+ "sensor_fusion":[]
}
# Get all the scene0 and scene1 tests, which can be run using the same
# physical setup.
- scenes = ["scene0", "scene1", "scene2", "scene3", "scene4", "scene5"]
+ scenes = ["scene0", "scene1", "scene2", "scene3", "scene4", "scene5",
+ "sensor_fusion"]
+
scene_req = {
"scene0" : None,
"scene1" : "A grey card covering at least the middle 30% of the scene",
@@ -60,7 +63,14 @@
"middle 50% of the scene. See CameraITS.pdf section 2.3.4 "
"for more details",
"scene5" : "Capture images with a diffuser attached to the camera. See "
- "CameraITS.pdf section 2.3.4 for more details"
+ "CameraITS.pdf section 2.3.4 for more details",
+ "sensor_fusion" : "Rotating checkboard pattern. See "
+ "sensor_fusion/SensorFusion.pdf for detailed "
+ "instructions. Note that this test will be skipped "
+ "on devices not supporting REALTIME camera timestamp."
+ "If that is the case, no scene setup is required and "
+ "you can just answer Y when being asked if the scene "
+ "is okay"
}
scene_extra_args = {
"scene5" : ["doAF=False"]
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 73557c8..603a80b 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -979,7 +979,7 @@
\n\n4. Run the full ITS test suite on all possible camera Ids.
(cd CameraITS; python tools/run_all_tests.py). Once all
of the tests have been run, the \'PASS\' button will be enabled if all of the tests have
- succeeded. Please note that these tests can take 20+ minutes to run.
+ succeeded. Please note that these tests can take more than 2 hours to run on some devices.
</string>
<string name="no_camera_manager">
No camera manager exists! This test device is in a bad state.
@@ -1814,8 +1814,8 @@
Navigate to Device administrators and confirm that:\n
\n
- Device administrators outside of the work profile (if any) appear in the list, and the managed profile administrators are badged correctly.\n
- - \"CTS Verifier\" exists under the Work category, and is activated.\n
- - Attempting to uncheck badged \"CTS Verifier\" shows an alert dialog informing you that this admin can be deactivated only if you remove the managed profile.\n
+ - A badged \"CTS Verifier\" exists, and is activated.\n
+ - Attempting to uncheck the badged \"CTS Verifier\" shows a page allowing the user to remove the managed profile.\n
\n
Use the Back button to return to this page.
</string>
@@ -1850,19 +1850,6 @@
Then use the Back button to return to this test and mark accordingly.
</string>
- <string name="provisioning_byod_battery_settings">Profile-aware battery settings</string>
- <string name="provisioning_byod_battery_settings_instruction">
- Please press the Go button to open Battery page in settings.\n
- \n
- Verify that Battery page shows both badged and unbadged apps in the usage list.\n
- \n
- Note that the usage list only displays usage since last charge,
- so you may need to unplug your device and use a badged and unbadged app
- for a little while before they will appear in the list.\n
- \n
- Then use the Back button to return to this test and mark accordingly.
- </string>
-
<string name="provisioning_byod_wifi_data_usage_settings">Profile-aware data usage settings (Wi-Fi)</string>
<string name="provisioning_byod_wifi_data_usage_settings_instruction">
Please press the Go button to open the Settings page.\n
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index d528604..793c332 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -97,6 +97,9 @@
private static final int TIMEOUT_CALLBACK = 10;
private static final int TIMEOUT_3A = 10;
+ // Timeout for doCapture command polling
+ private static final int TIMEOUT_POLL_MS = 500;
+
// Time given for background requests to warm up pipeline
private static final long PIPELINE_WARMUP_TIME_MS = 2000;
@@ -564,6 +567,7 @@
// Each command is a serialized JSON object.
try {
JSONObject cmdObj = new JSONObject(cmd);
+ Logt.i(TAG, "Start processing command" + cmdObj.getString("cmdName"));
if ("open".equals(cmdObj.getString("cmdName"))) {
int cameraId = cmdObj.getInt("cameraId");
openCameraDevice(cameraId);
@@ -588,6 +592,7 @@
} else {
throw new ItsException("Unknown command: " + cmd);
}
+ Logt.i(TAG, "Finish processing command" + cmdObj.getString("cmdName"));
} catch (org.json.JSONException e) {
Logt.e(TAG, "Invalid command: ", e);
}
@@ -642,6 +647,7 @@
public void sendResponse(LinkedList<MySensorEvent> events)
throws ItsException {
+ Logt.i(TAG, "Sending " + events.size() + " sensor events");
try {
JSONArray accels = new JSONArray();
JSONArray mags = new JSONArray();
@@ -668,6 +674,7 @@
} catch (org.json.JSONException e) {
throw new ItsException("JSON error: ", e);
}
+ Logt.i(TAG, "Sent sensor events");
}
public void sendResponse(CameraCharacteristics props)
@@ -1273,16 +1280,20 @@
// Make sure all callbacks have been hit (wait until captures are done).
// If no timeouts are received after a timeout, then fail.
int currentCount = mCountCallbacksRemaining.get();
+ long totalSleep = 0;
while (currentCount > 0) {
try {
- Thread.sleep(timeout);
+ Thread.sleep(TIMEOUT_POLL_MS);
} catch (InterruptedException e) {
throw new ItsException("Timeout failure", e);
}
+ totalSleep += TIMEOUT_POLL_MS;
int newCount = mCountCallbacksRemaining.get();
- if (newCount == currentCount) {
+ if (newCount == currentCount && totalSleep > timeout) {
throw new ItsException(
"No callback received within timeout");
+ } else if (newCount < currentCount) {
+ totalSleep = 0;
}
currentCount = newCount;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index 5a20936..6aacea8 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -71,7 +71,6 @@
private DialogTestListItem mWorkStatusBarToastTest;
private DialogTestListItem mAppSettingsVisibleTest;
private DialogTestListItem mLocationSettingsVisibleTest;
- private DialogTestListItem mBatterySettingsVisibleTest;
private DialogTestListItem mWiFiDataUsageSettingsVisibleTest;
private DialogTestListItem mCellularDataUsageSettingsVisibleTest;
private DialogTestListItem mCredSettingsVisibleTest;
@@ -266,12 +265,6 @@
R.string.provisioning_byod_location_settings_instruction,
new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
- mBatterySettingsVisibleTest = new DialogTestListItem(this,
- R.string.provisioning_byod_battery_settings,
- "BYOD_BatterySettingsVisibleTest",
- R.string.provisioning_byod_battery_settings_instruction,
- new Intent(Intent.ACTION_POWER_USAGE_SUMMARY));
-
mWiFiDataUsageSettingsVisibleTest = new DialogTestListItem(this,
R.string.provisioning_byod_wifi_data_usage_settings,
"BYOD_WiFiDataUsageSettingsVisibleTest",
@@ -406,7 +399,6 @@
adapter.add(mCredSettingsVisibleTest);
adapter.add(mAppSettingsVisibleTest);
adapter.add(mLocationSettingsVisibleTest);
- adapter.add(mBatterySettingsVisibleTest);
adapter.add(mWiFiDataUsageSettingsVisibleTest);
adapter.add(mCellularDataUsageSettingsVisibleTest);
adapter.add(mPrintSettingsVisibleTest);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java
index fa89b71..28d5d1c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVCameraPreview.java
@@ -26,6 +26,7 @@
import android.view.ViewGroup;
import java.io.IOException;
+import java.lang.Math;
/** Camera preview class */
public class RVCVCameraPreview extends SurfaceView implements SurfaceHolder.Callback {
@@ -94,10 +95,10 @@
ViewGroup.LayoutParams layout = getLayoutParams();
if ( (float)v_height/v_width >
mAspect) {
- layout.height = (int)(v_width * mAspect);
+ layout.height = (int)Math.round(v_width * mAspect);
layout.width = v_width;
}else {
- layout.width = (int)(v_height / mAspect);
+ layout.width = (int)Math.round(v_height / mAspect);
layout.height = v_height;
}
Log.d(TAG, String.format("Layout (%d, %d) -> (%d, %d)", v_width, v_height,
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java
index 1ef87bd..21afe0d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/sensors/RVCVRecordActivity.java
@@ -451,6 +451,7 @@
}
}
if (profile != null) {
+ param = mCamera.getParameters(); //acquire proper fov after change the picture size
float fovW = param.getHorizontalViewAngle();
float fovH = param.getVerticalViewAngle();
writeVideoMetaInfo(profile.videoFrameWidth, profile.videoFrameHeight,
diff --git a/build/test_host_java_library.mk b/build/test_host_java_library.mk
index 7fdefb5..abf6829 100644
--- a/build/test_host_java_library.mk
+++ b/build/test_host_java_library.mk
@@ -17,6 +17,8 @@
# package XML needed by CTS.
#
+LOCAL_STATIC_JAVA_LIBRARIES += platform-test-annotations-host
+
include $(BUILD_HOST_JAVA_LIBRARY)
include $(BUILD_CTS_MODULE_TEST_CONFIG)
diff --git a/build/test_package.mk b/build/test_package.mk
index c6b0865..690e2e9 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -22,6 +22,7 @@
# Disable by default so "m cts" will work in emulator builds
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_STATIC_JAVA_LIBRARIES += platform-test-annotations
include $(BUILD_CTS_SUPPORT_PACKAGE)
include $(BUILD_CTS_MODULE_TEST_CONFIG)
diff --git a/build/test_target_java_library.mk b/build/test_target_java_library.mk
index 525abb5..c2a93d4 100644
--- a/build/test_target_java_library.mk
+++ b/build/test_target_java_library.mk
@@ -18,6 +18,7 @@
#
# Disable by default so "m cts" will work in emulator builds
LOCAL_DEX_PREOPT := false
+LOCAL_STATIC_JAVA_LIBRARIES += platform-test-annotations
include $(BUILD_JAVA_LIBRARY)
include $(BUILD_CTS_MODULE_TEST_CONFIG)
diff --git a/build/test_target_testng_package.mk b/build/test_target_testng_package.mk
index 0621109..d038917 100644
--- a/build/test_target_testng_package.mk
+++ b/build/test_target_testng_package.mk
@@ -18,6 +18,7 @@
#
# Disable by default so "m cts" will work in emulator builds
LOCAL_DEX_PREOPT := false
+LOCAL_STATIC_JAVA_LIBRARIES += platform-test-annotations
include $(BUILD_JAVA_LIBRARY)
include $(BUILD_CTS_MODULE_TEST_CONFIG)
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
index 204466a..8bdd0bd 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/DeviceReportLog.java
@@ -279,4 +279,18 @@
instrumentation.sendStatus(INST_STATUS_ERROR, null);
}
}
+
+ /**
+ * Closes report file. Static functions that do not have access to instrumentation can
+ * use this to close report logs. Summary, if present, is not reported to instrumentation, hence
+ * does not appear in the result XML.
+ */
+ public void submit() {
+ Log.i(TAG, "Submit");
+ try {
+ store.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Submit Failed", e);
+ }
+ }
}
diff --git a/common/host-side/tradefed/res/config/common-compatibility-config.xml b/common/host-side/tradefed/res/config/common-compatibility-config.xml
index 7ffbea5..0006203 100644
--- a/common/host-side/tradefed/res/config/common-compatibility-config.xml
+++ b/common/host-side/tradefed/res/config/common-compatibility-config.xml
@@ -17,6 +17,8 @@
<device_recovery class="com.android.tradefed.device.WaitDeviceRecovery" />
<build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
<test class="com.android.compatibility.common.tradefed.testtype.CompatibilityTest" />
+ <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:rerun-from-file:true" />
+ <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:fallback-to-serial-rerun:false" />
<logger class="com.android.tradefed.log.FileLogger">
<option name="log-level-display" value="WARN" />
</logger>
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
index e21f98e..522d372 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelper.java
@@ -21,6 +21,8 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -37,8 +39,11 @@
private static final String SUITE_VERSION = "SUITE_VERSION";
private static final String SUITE_PLAN = "SUITE_PLAN";
private static final String RESULT_DIR = "RESULT_DIR";
+ private static final String START_TIME_MS = "START_TIME_MS";
private static final String CONFIG_PATH_PREFIX = "DYNAMIC_CONFIG_FILE:";
private static final String DYNAMIC_CONFIG_OVERRIDE_URL = "DYNAMIC_CONFIG_OVERRIDE_URL";
+ private static final String COMMAND_LINE_ARGS = "command_line_args";
+ private static final String RETRY_COMMAND_LINE_ARGS = "retry_command_line_args";
private final IBuildInfo mBuildInfo;
private boolean mInitialized = false;
@@ -50,9 +55,17 @@
}
/**
- * Initializes the {@link IBuildInfo} from the manifest.
+ * Initializes the {@link IBuildInfo} from the manifest with the current time
+ * as the start time.
*/
public void init(String suitePlan, String dynamicConfigUrl) {
+ init(suitePlan, dynamicConfigUrl, System.currentTimeMillis());
+ }
+
+ /**
+ * Initializes the {@link IBuildInfo} from the manifest.
+ */
+ public void init(String suitePlan, String dynamicConfigUrl, long startTimeMs) {
if (mInitialized) {
return;
}
@@ -62,6 +75,8 @@
mBuildInfo.addBuildAttribute(SUITE_FULL_NAME, SuiteInfo.FULLNAME);
mBuildInfo.addBuildAttribute(SUITE_VERSION, SuiteInfo.VERSION);
mBuildInfo.addBuildAttribute(SUITE_PLAN, suitePlan);
+ mBuildInfo.addBuildAttribute(START_TIME_MS, Long.toString(startTimeMs));
+ mBuildInfo.addBuildAttribute(RESULT_DIR, getDirSuffix(startTimeMs));
String rootDirPath = null;
if (mBuildInfo instanceof IFolderBuildInfo) {
File rootDir = ((IFolderBuildInfo) mBuildInfo).getRootDir();
@@ -86,6 +101,24 @@
}
}
+ public IBuildInfo getBuildInfo() {
+ return mBuildInfo;
+ }
+
+ public void setRetryCommandLineArgs(String commandLineArgs) {
+ mBuildInfo.addBuildAttribute(RETRY_COMMAND_LINE_ARGS, commandLineArgs);
+ }
+
+ public String getCommandLineArgs() {
+ if (mBuildInfo.getBuildAttributes().containsKey(RETRY_COMMAND_LINE_ARGS)) {
+ return mBuildInfo.getBuildAttributes().get(RETRY_COMMAND_LINE_ARGS);
+ } else {
+ // NOTE: this is a temporary workaround set in TestInvocation#invoke in tradefed.
+ // This will be moved to a separate method in a new invocation metadata class.
+ return mBuildInfo.getBuildAttributes().get(COMMAND_LINE_ARGS);
+ }
+ }
+
public String getSuiteBuild() {
return mBuildInfo.getBuildAttributes().get(SUITE_BUILD);
}
@@ -110,6 +143,10 @@
return mBuildInfo.getBuildAttributes().get(DYNAMIC_CONFIG_OVERRIDE_URL);
}
+ public long getStartTime() {
+ return Long.parseLong(mBuildInfo.getBuildAttributes().get(START_TIME_MS));
+ }
+
public void addDynamicConfigFile(String moduleName, File configFile) {
mBuildInfo.addBuildAttribute(CONFIG_PATH_PREFIX + moduleName, configFile.getAbsolutePath());
}
@@ -172,18 +209,12 @@
}
/**
- * Sets the name of the current invocation's result directory.
- */
- public void setResultDir(String resultDir) {
- mBuildInfo.addBuildAttribute(RESULT_DIR, resultDir);
- }
-
- /**
* @return a {@link File} representing the result directory of the current invocation.
* @throws FileNotFoundException if the directory structure is not valid.
*/
public File getResultDir() throws FileNotFoundException {
- return new File(getResultsDir(), mBuildInfo.getBuildAttributes().get(RESULT_DIR));
+ return new File(getResultsDir(),
+ getDirSuffix(Long.parseLong(mBuildInfo.getBuildAttributes().get(START_TIME_MS))));
}
/**
@@ -208,4 +239,10 @@
return testsDir;
}
+ /**
+ * @return a {@link String} to use for directory suffixes created from the given time.
+ */
+ public static String getDirSuffix(long millis) {
+ return new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss").format(new Date(millis));
+ }
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/MasterBuildInfo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/MasterBuildInfo.java
deleted file mode 100644
index fdcb634..0000000
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/build/MasterBuildInfo.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 com.android.compatibility.common.tradefed.build;
-
-import com.android.tradefed.build.IBuildInfo;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Singleton class containing a master {@link IBuildInfo} to be persisted across sharded
- * invocations.
- */
-public class MasterBuildInfo {
-
- private static Map<String, String> mBuild = new HashMap<String, String>();
-
- private MasterBuildInfo() { }
-
- public static Map<String, String> getBuild() {
- return mBuild;
- }
-
- /**
- *
- * @param buildInfo
- */
- public static void addBuildInfo(Map<String, String> buildInfo) {
- mBuild.putAll(buildInfo);
- }
-
- public static void clear() {
- mBuild.clear();
- }
-}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
index e79659b..9daf9e4 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/command/CompatibilityConsole.java
@@ -65,7 +65,6 @@
MODULE_SPLIT_EXCLUSIONS.add("CtsDeqpTestCases");
}
private CompatibilityBuildHelper mBuildHelper;
- private static final int TIMESTAMP_COLUMN = 4;
/**
* {@inheritDoc}
@@ -171,7 +170,7 @@
helpBuilder.append("Options:\n");
helpBuilder.append(" --serial/-s <device_id>: The device to run the test on.\n");
helpBuilder.append(" --abi/-a <abi>: The ABI to run the test against.\n");
- helpBuilder.append(" --shard <shards>: Shards a run into the given number of independant");
+ helpBuilder.append(" --shards <shards>: Shards a run into the given number of independant");
helpBuilder.append(" chunks, to run on multiple devices in parallel.\n");
helpBuilder.append(" --logcat-on-failure: Capture logcat when a test fails.\n");
helpBuilder.append(" --bugreport-on-failure: Capture a bugreport when a test fails.\n");
@@ -323,13 +322,13 @@
if (testResultRepo != null && results.size() > 0) {
for (int i = 0; i < results.size(); i++) {
IInvocationResult result = results.get(i);
- Map<String, String> buildInfo = result.getBuildInfo();
+ Map<String, String> invocationInfo = result.getInvocationInfo();
- // build attributes are not always present (e.g. in the case of halted test runs)
+ // invocation attributes are not always present (e.g. in the case of halted runs)
// replace null entries with the string "Unknown"
- for (Map.Entry<String, String> entry : buildInfo.entrySet()) {
+ for (Map.Entry<String, String> entry : invocationInfo.entrySet()) {
if (entry.getValue() == null) {
- buildInfo.put(entry.getKey(), "Unknown");
+ invocationInfo.put(entry.getKey(), "Unknown");
}
}
@@ -338,24 +337,17 @@
Integer.toString(result.countResults(TestStatus.PASS)),
Integer.toString(result.countResults(TestStatus.FAIL)),
Integer.toString(result.countResults(TestStatus.NOT_EXECUTED)),
- TimeUtil.formatTimeStamp(result.getStartTime()),
+ CompatibilityBuildHelper.getDirSuffix(result.getStartTime()),
result.getTestPlan(),
ArrayUtil.join(", ", result.getDeviceSerials()),
- buildInfo.get("build_id"),
- buildInfo.get("build_product")
+ invocationInfo.get("build_id"),
+ invocationInfo.get("build_product")
));
-
- // sort the table entries on each entry's formatted timestamp
- Collections.sort(table, new Comparator<List<String>>() {
- public int compare(List<String> firstList, List<String> secondList) {
- return firstList.get(TIMESTAMP_COLUMN)
- .compareTo(secondList.get(TIMESTAMP_COLUMN));
- }
- });
}
+
// add the table header to the beginning of the list
- table.add(0, Arrays.asList("Session", "Pass", "Fail", "Not Executed", "Start Time",
+ table.add(0, Arrays.asList("Session", "Pass", "Fail", "Not Executed", "Result Directory",
"Test Plan", "Device serial(s)", "Build ID", "Product"));
tableFormatter.displayTable(table, new PrintWriter(System.out, true));
} else {
@@ -367,7 +359,8 @@
if (mBuildHelper == null) {
CompatibilityBuildProvider buildProvider = new CompatibilityBuildProvider();
mBuildHelper = new CompatibilityBuildHelper(buildProvider.getBuild());
- mBuildHelper.init("" /* suite plan */, "" /* dynamic config url */);
+ mBuildHelper.init(
+ "" /* suite plan */, "" /* dynamic config url */, -1 /*startTimeMs*/);
}
return mBuildHelper;
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java
index 19adb3f..8728f4f 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ConsoleReporter.java
@@ -43,6 +43,10 @@
private String mDeviceSerial = UNKNOWN_DEVICE;
private boolean mTestFailed;
private String mModuleId;
+ private int mCurrentTestNum;
+ private int mTotalTestsInModule;
+ private int mPassedTests;
+ private int mFailedTests;
/**
* {@inheritDoc}
@@ -53,7 +57,7 @@
CLog.w("buildInfo should not be null");
return;
}
-
+ // Escape any "%" signs in the device serial.
mDeviceSerial = buildInfo.getDeviceSerial().replace("%", "%%");
}
@@ -62,8 +66,21 @@
*/
@Override
public void testRunStarted(String id, int numTests) {
- mModuleId = id;
- log("Starting %s with %d test%s", id, numTests, (numTests > 1) ? "s" : "");
+ if (mModuleId == null || !mModuleId.equals(id)) {
+ mModuleId = id;
+ mTotalTestsInModule = numTests;
+ // Reset counters
+ mCurrentTestNum = 0;
+ mPassedTests = 0;
+ mFailedTests = 0;
+ mTestFailed = false;
+ logMessage("Starting %s with %d test%s",
+ id, mTotalTestsInModule, (mTotalTestsInModule > 1) ? "s" : "");
+ } else {
+ mTotalTestsInModule += numTests;
+ logMessage("Continuing %s with %d test%s",
+ id, mTotalTestsInModule, (mTotalTestsInModule > 1) ? "s" : "");
+ }
}
/**
@@ -72,6 +89,7 @@
@Override
public void testStarted(TestIdentifier test) {
mTestFailed = false;
+ mCurrentTestNum++;
}
/**
@@ -79,8 +97,9 @@
*/
@Override
public void testFailed(TestIdentifier test, String trace) {
- log("%s fail: %s", test, trace);
+ logProgress("%s fail: %s", test, trace);
mTestFailed = true;
+ mFailedTests++;
}
/**
@@ -88,7 +107,7 @@
*/
@Override
public void testIgnored(TestIdentifier test) {
- log("%s ignore", test);
+ logProgress("%s ignore", test);
}
/**
@@ -96,7 +115,7 @@
*/
@Override
public void testAssumptionFailure(TestIdentifier test, String trace) {
- log("%s failed assumption: %s", test, trace);
+ logProgress("%s failed assumption: %s", test, trace);
}
/**
@@ -105,7 +124,8 @@
@Override
public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
if (!mTestFailed) {
- log("%s pass", test);
+ logProgress("%s pass", test);
+ mPassedTests++;
}
}
@@ -114,7 +134,24 @@
*/
@Override
public void testRunFailed(String errorMessage) {
- log(errorMessage);
+ logMessage(errorMessage);
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
+ int notExecuted = mTotalTestsInModule - mCurrentTestNum;
+ String status = notExecuted > 0 ? "failed" : "completed";
+ logMessage("%s %s in %s. %d passed, %d failed, %d not executed",
+ mModuleId,
+ status,
+ TimeUtil.formatElapsedTime(elapsedTime),
+ mPassedTests,
+ mFailedTests,
+ notExecuted);
}
/**
@@ -122,16 +159,29 @@
*/
@Override
public void testRunStopped(long elapsedTime) {
- log("%s stopped (%s)", mModuleId, TimeUtil.formatElapsedTime(elapsedTime));
+ logMessage("%s stopped (%s)", mModuleId, TimeUtil.formatElapsedTime(elapsedTime));
+ }
+
+ /**
+ * Print out message with test execution status.
+ */
+ private void logProgress(String format, Object... args) {
+ format = String.format("[%s %s %s] %s", progress(), mModuleId, mDeviceSerial, format);
+ log(format, args);
+ }
+
+ /**
+ * Print out message to the console
+ */
+ private void logMessage(String format, Object... args) {
+ format = String.format("[%s] %s", mDeviceSerial, format);
+ log(format, args);
}
/**
* Print out to the console or log silently when mQuietOutput is true.
*/
private void log(String format, Object... args) {
- // Escape any "%" signs in the device serial.
- format = String.format("[%s] %s", mDeviceSerial, format);
-
if (mQuietOutput) {
CLog.i(format, args);
} else {
@@ -148,4 +198,39 @@
OptionCopier.copyOptionsNoThrow(this, clone);
return clone;
}
+
+ /**
+ * Return a string containing the percentage complete of module test execution.
+ */
+ private String progress() {
+ return String.format("%d/%d", mCurrentTestNum, mTotalTestsInModule);
+ }
+
+ String getDeviceSerial() {
+ return mDeviceSerial;
+ }
+
+ boolean getTestFailed() {
+ return mTestFailed;
+ }
+
+ String getModuleId() {
+ return mModuleId;
+ }
+
+ int getCurrentTestNum() {
+ return mCurrentTestNum;
+ }
+
+ int getTotalTestsInModule() {
+ return mTotalTestsInModule;
+ }
+
+ int getPassedTests() {
+ return mPassedTests;
+ }
+
+ int getFailedTests() {
+ return mFailedTests;
+ }
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
index ae74c26..b5a7929 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/result/ResultReporter.java
@@ -16,7 +16,6 @@
package com.android.compatibility.common.tradefed.result;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.compatibility.common.tradefed.build.MasterBuildInfo;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
import com.android.compatibility.common.util.ICaseResult;
import com.android.compatibility.common.util.IInvocationResult;
@@ -35,9 +34,11 @@
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.config.OptionClass;
+import com.android.tradefed.config.OptionCopier;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.result.ILogSaver;
import com.android.tradefed.result.ILogSaverListener;
+import com.android.tradefed.result.IShardableListener;
import com.android.tradefed.result.ITestInvocationListener;
import com.android.tradefed.result.ITestSummaryListener;
import com.android.tradefed.result.InputStreamSource;
@@ -59,17 +60,20 @@
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
/**
* Collect test results for an entire invocation and output test results to disk.
*/
@OptionClass(alias="result-reporter")
public class ResultReporter implements ILogSaverListener, ITestInvocationListener,
- ITestSummaryListener {
+ ITestSummaryListener, IShardableListener {
+ private static final String UNKNOWN_DEVICE = "unknown_device";
private static final String RESULT_KEY = "COMPATIBILITY_TEST_RESULT";
private static final String CTS_PREFIX = "cts:";
private static final String BUILD_INFO = CTS_PREFIX + "build_";
@@ -97,100 +101,138 @@
@Option(name = "use-log-saver", description = "Also saves generated result with log saver")
private boolean mUseLogSaver = false;
- private String mDeviceSerial;
-
- private IInvocationResult mResult;
+ private CompatibilityBuildHelper mBuildHelper;
private File mResultDir = null;
private File mLogDir = null;
- private long mStartTime;
private ResultUploader mUploader;
private String mReferenceUrl;
+ private ILogSaver mLogSaver;
+ private int invocationEndedCount = 0;
+
+ private IInvocationResult mResult = new InvocationResult();
private IModuleResult mCurrentModuleResult;
private ICaseResult mCurrentCaseResult;
private ITestResult mCurrentResult;
- private IBuildInfo mBuild;
- private CompatibilityBuildHelper mBuildHelper;
- private ILogSaver mLogSaver;
- private boolean mReloadBuildInfo = false;
+ private String mDeviceSerial = UNKNOWN_DEVICE;
+ private Set<String> mMasterDeviceSerials = new HashSet<>();
+ private Set<IBuildInfo> mMasterBuildInfos = new HashSet<>();
+
+ // Nullable. If null, "this" is considered the master and must handle
+ // result aggregation and reporting. When not null, it should forward events
+ // to the master.
+ private final ResultReporter mMasterResultReporter;
+
+ /**
+ * Default constructor.
+ */
+ public ResultReporter() {
+ this(null);
+ }
+
+ /**
+ * Construct a shard ResultReporter that forwards module results to the
+ * masterResultReporter.
+ */
+ public ResultReporter(ResultReporter masterResultReporter) {
+ mMasterResultReporter = masterResultReporter;
+ }
/**
* {@inheritDoc}
*/
@Override
public void invocationStarted(IBuildInfo buildInfo) {
- mBuild = buildInfo;
- mBuildHelper = new CompatibilityBuildHelper(mBuild);
- mDeviceSerial = buildInfo.getDeviceSerial();
- if (mDeviceSerial == null) {
- mDeviceSerial = "unknown_device";
- mReloadBuildInfo = true;
+ synchronized(this) {
+ if (mBuildHelper == null) {
+ mBuildHelper = new CompatibilityBuildHelper(buildInfo);
+ }
+ if (mDeviceSerial == null && buildInfo.getDeviceSerial() != null) {
+ mDeviceSerial = buildInfo.getDeviceSerial();
+ }
}
- long time = System.currentTimeMillis();
- String dirSuffix = getDirSuffix(time);
- if (mRetrySessionId != null) {
- CLog.d("[%s] Retrying session %d", mDeviceSerial, mRetrySessionId);
- List<IInvocationResult> results = null;
- try {
- results = ResultHandler.getResults(mBuildHelper.getResultsDir());
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- if (results != null && mRetrySessionId >= 0 && mRetrySessionId < results.size()) {
- mResult = results.get(mRetrySessionId);
- } else {
- throw new IllegalArgumentException(
- String.format("Could not find session %d",mRetrySessionId));
- }
- mStartTime = mResult.getStartTime();
- mResultDir = mResult.getResultDir();
- } else {
- mStartTime = time;
- try {
- mResultDir = new File(mBuildHelper.getResultsDir(), dirSuffix);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- if (mResultDir != null && mResultDir.mkdirs()) {
- info("Created result dir %s", mResultDir.getAbsolutePath());
- } else {
- throw new IllegalArgumentException(String.format("Could not create result dir %s",
- mResultDir.getAbsolutePath()));
- }
- mResult = new InvocationResult(mStartTime, mResultDir);
+
+ if (isShardResultReporter()) {
+ // Shard ResultReporters forward invocationStarted to the mMasterResultReporter
+ mMasterResultReporter.invocationStarted(buildInfo);
+ return;
}
- mBuildHelper.setResultDir(mResultDir.getName());
+
+ // NOTE: Everything after this line only applies to the master ResultReporter.
+
+ synchronized(this) {
+ if (buildInfo.getDeviceSerial() != null) {
+ // The master ResultReporter collects all device serials being used
+ // for the current implementation.
+ mMasterDeviceSerials.add(buildInfo.getDeviceSerial());
+ }
+
+ // The master ResultReporter collects all buildInfos.
+ mMasterBuildInfos.add(buildInfo);
+
+ if (mResultDir == null) {
+ // For the non-sharding case, invocationStarted is only called once,
+ // but for the sharding case, this might be called multiple times.
+ // Logic used to initialize the result directory should not be
+ // invoked twice during the same invocation.
+ initializeResultDirectories();
+ }
+ }
+ }
+
+ /**
+ * Create directory structure where results and logs will be written.
+ */
+ private void initializeResultDirectories() {
+ info("Initializing result directory");
+
+ try {
+ // Initialize the result directory. Either a new directory or reusing
+ // an existing session.
+ if (mRetrySessionId != null) {
+ // Overwrite the mResult with the test results of the previous session
+ mResult = ResultHandler.findResult(mBuildHelper.getResultsDir(), mRetrySessionId);
+ }
+ mResult.setStartTime(mBuildHelper.getStartTime());
+ mResultDir = mBuildHelper.getResultDir();
+ if (mResultDir != null) {
+ mResultDir.mkdirs();
+ }
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ if (mResultDir == null) {
+ throw new RuntimeException("Result Directory was not created");
+ }
+ if (!mResultDir.exists()) {
+ throw new RuntimeException("Result Directory was not created: " +
+ mResultDir.getAbsolutePath());
+ }
+
+ info("Results Directory: " + mResultDir.getAbsolutePath());
+
mUploader = new ResultUploader(mResultServer, mBuildHelper.getSuiteName());
try {
- mLogDir = new File(mBuildHelper.getLogsDir(), dirSuffix);
+ mLogDir = new File(mBuildHelper.getLogsDir(),
+ CompatibilityBuildHelper.getDirSuffix(mBuildHelper.getStartTime()));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (mLogDir != null && mLogDir.mkdirs()) {
info("Created log dir %s", mLogDir.getAbsolutePath());
- } else {
+ }
+ if (mLogDir == null || !mLogDir.exists()) {
throw new IllegalArgumentException(String.format("Could not create log dir %s",
mLogDir.getAbsolutePath()));
}
}
/**
- * @return a {@link String} to use for directory suffixes created from the given time.
- */
- private String getDirSuffix(long time) {
- return new SimpleDateFormat("yyyy.MM.dd_HH.mm.ss").format(new Date(time));
- }
-
- /**
* {@inheritDoc}
*/
@Override
public void testRunStarted(String id, int numTests) {
mCurrentModuleResult = mResult.getOrCreateModule(id);
- if (mDeviceSerial == null || mDeviceSerial.equals("unknown_device")) {
- mResult.addDeviceSerial(mBuild.getDeviceSerial());
- } else {
- mResult.addDeviceSerial(mDeviceSerial);
- }
}
/**
@@ -270,20 +312,25 @@
*/
@Override
public void testRunEnded(long elapsedTime, Map<String, String> metrics) {
- // Get device info from build attributes
- for (Entry<String, String> entry : mBuild.getBuildAttributes().entrySet()) {
- String key = entry.getKey();
- if (key.startsWith(BUILD_INFO)) {
- mResult.addBuildInfo(key.substring(CTS_PREFIX.length()), entry.getValue());
- }
- }
mCurrentModuleResult.addRuntime(elapsedTime);
- info("%s completed in %s. %d passed, %d failed, %d not executed",
- mCurrentModuleResult.getId(),
- TimeUtil.formatElapsedTime(elapsedTime),
- mCurrentModuleResult.countResults(TestStatus.PASS),
- mCurrentModuleResult.countResults(TestStatus.FAIL),
- mCurrentModuleResult.countResults(TestStatus.NOT_EXECUTED));
+
+ if (isShardResultReporter()) {
+ // Forward module results to the master.
+ mMasterResultReporter.mergeModuleResult(mCurrentModuleResult);
+ }
+ }
+
+ /**
+ * Directly add a module result. Note: this method is meant to be used by
+ * a shard ResultReporter.
+ */
+ private void mergeModuleResult(IModuleResult moduleResult) {
+ // This merges the results in moduleResult to any existing results already
+ // contained in mResult. This is useful for retries and allows the final
+ // report from a retry to contain all test results.
+ synchronized(this) {
+ mResult.mergeModuleResult(moduleResult);
+ }
}
/**
@@ -308,6 +355,8 @@
*/
@Override
public void putSummary(List<TestSummary> summaries) {
+ // This is safe to be invoked on either the master or a shard ResultReporter,
+ // but the value added to the report will be that of the master ResultReporter.
if (summaries.size() > 0) {
mReferenceUrl = summaries.get(0).getSummary().getString();
}
@@ -318,65 +367,68 @@
*/
@Override
public void invocationEnded(long elapsedTime) {
+ if (isShardResultReporter()) {
+ // Shard ResultReporters report
+ mMasterResultReporter.invocationEnded(elapsedTime);
+ return;
+ }
+
+ // NOTE: Everything after this line only applies to the master ResultReporter.
+
+
+ synchronized(this) {
+ // The master ResultReporter tracks the progress of all invocations across
+ // shard ResultReporters. Writing results should not proceed until all
+ // ResultReporters have completed.
+ if (++invocationEndedCount < mMasterBuildInfos.size()) {
+ return;
+ }
+ finalizeResultDirectories(elapsedTime);
+ }
+ }
+
+ private void finalizeResultDirectories(long elapsedTime) {
info("Invocation completed in %s. %d passed, %d failed, %d not executed",
TimeUtil.formatElapsedTime(elapsedTime),
mResult.countResults(TestStatus.PASS),
mResult.countResults(TestStatus.FAIL),
mResult.countResults(TestStatus.NOT_EXECUTED));
- try {
- // invocationStarted picked up an unfinished IBuildInfo, so repopulate it now from
- // the master
- if (mReloadBuildInfo) {
- for (Map.Entry<String, String> e : MasterBuildInfo.getBuild().entrySet()) {
- mResult.addBuildInfo(e.getKey(), e.getValue());
+
+ // Add all device serials into the result to be serialized
+ for (String deviceSerial : mMasterDeviceSerials) {
+ mResult.addDeviceSerial(deviceSerial);
+ }
+
+ // Add all build info to the result to be serialized
+ for (IBuildInfo buildInfo : mMasterBuildInfos) {
+ for (Map.Entry<String, String> entry : buildInfo.getBuildAttributes().entrySet()) {
+ String key = entry.getKey();
+ if (key.startsWith(BUILD_INFO)) {
+ mResult.addInvocationInfo(key.substring(CTS_PREFIX.length()), entry.getValue());
}
}
+ }
+ long startTime = mResult.getStartTime();
+ try {
File resultFile = ResultHandler.writeResults(mBuildHelper.getSuiteName(),
mBuildHelper.getSuiteVersion(), mBuildHelper.getSuitePlan(),
- mBuildHelper.getSuiteBuild(), mResult, mResultDir, mStartTime,
- elapsedTime + mStartTime, mReferenceUrl);
+ mBuildHelper.getSuiteBuild(), mResult, mResultDir, startTime,
+ elapsedTime + startTime, mReferenceUrl, mBuildHelper.getCommandLineArgs());
info("Test Result: %s", resultFile.getCanonicalPath());
+
+ // Zip the full test results directory.
copyDynamicConfigFiles(mBuildHelper.getDynamicConfigFiles(), mResultDir);
copyFormattingFiles(mResultDir);
- // Zip the full test results directory.
File zippedResults = zipResults(mResultDir);
info("Full Result: %s", zippedResults.getCanonicalPath());
- // Save the test result XML.
- if (mUseLogSaver) {
- FileInputStream fis = null;
- try {
- fis = new FileInputStream(resultFile);
- mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
- } catch (IOException ioe) {
- CLog.e("[%s] error saving XML with log saver", mDeviceSerial);
- CLog.e(ioe);
- } finally {
- StreamUtil.close(fis);
- }
- // Save the full results folder.
- if (zippedResults != null) {
- FileInputStream zipResultStream = null;
- try {
- zipResultStream = new FileInputStream(zippedResults);
- mLogSaver.saveLogData("results", LogDataType.ZIP, zipResultStream);
- } finally {
- StreamUtil.close(zipResultStream);
- }
- }
- }
- if (mResultServer != null && !mResultServer.trim().isEmpty() && !mDisableResultPosting) {
- try {
- info("Result Server: %d", mUploader.uploadResult(resultFile, mReferenceUrl));
- } catch (IOException ioe) {
- CLog.e("[%s] IOException while uploading result.", mDeviceSerial);
- CLog.e(ioe);
- }
- }
+
+ saveLog(resultFile, zippedResults);
+
+ uploadResult(resultFile);
+
} catch (IOException | XmlPullParserException e) {
CLog.e("[%s] Exception while saving result XML.", mDeviceSerial);
CLog.e(e);
- } finally {
- MasterBuildInfo.clear();
}
}
@@ -393,6 +445,7 @@
*/
@Override
public void testLog(String name, LogDataType type, InputStreamSource stream) {
+ // This is safe to be invoked on either the master or a shard ResultReporter
try {
LogFileSaver saver = new LogFileSaver(mLogDir);
File logFile = saver.saveAndZipLogData(name, type, stream.createInputStream());
@@ -409,8 +462,10 @@
@Override
public void testLogSaved(String dataName, LogDataType dataType, InputStreamSource dataStream,
LogFile logFile) {
+ // This is safe to be invoked on either the master or a shard ResultReporter
if (mIncludeTestLogTags && mCurrentResult != null
&& dataName.startsWith(mCurrentResult.getFullName())) {
+
if (dataType == LogDataType.BUGREPORT) {
mCurrentResult.setBugReport(logFile.getUrl());
} else if (dataType == LogDataType.LOGCAT) {
@@ -426,10 +481,70 @@
*/
@Override
public void setLogSaver(ILogSaver saver) {
+ // This is safe to be invoked on either the master or a shard ResultReporter
mLogSaver = saver;
}
/**
+ * When enabled, save log data using log saver
+ */
+ private void saveLog(File resultFile, File zippedResults) throws IOException {
+ if (!mUseLogSaver) {
+ return;
+ }
+
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(resultFile);
+ mLogSaver.saveLogData("log-result", LogDataType.XML, fis);
+ } catch (IOException ioe) {
+ CLog.e("[%s] error saving XML with log saver", mDeviceSerial);
+ CLog.e(ioe);
+ } finally {
+ StreamUtil.close(fis);
+ }
+ // Save the full results folder.
+ if (zippedResults != null) {
+ FileInputStream zipResultStream = null;
+ try {
+ zipResultStream = new FileInputStream(zippedResults);
+ mLogSaver.saveLogData("results", LogDataType.ZIP, zipResultStream);
+ } finally {
+ StreamUtil.close(zipResultStream);
+ }
+ }
+ }
+
+ @Override
+ public IShardableListener clone() {
+ ResultReporter clone = new ResultReporter(this);
+ OptionCopier.copyOptionsNoThrow(this, clone);
+ return clone;
+ }
+
+ /**
+ * Return true if this instance is a shard ResultReporter and should propagate
+ * certain events to the master.
+ */
+ private boolean isShardResultReporter() {
+ return mMasterResultReporter != null;
+ }
+
+ /**
+ * When enabled, upload the result to a server.
+ */
+ private void uploadResult(File resultFile) throws IOException {
+ if (mResultServer != null && !mResultServer.trim().isEmpty() && !mDisableResultPosting) {
+ try {
+ info("Result Server: %d", mUploader.uploadResult(resultFile, mReferenceUrl));
+ } catch (IOException ioe) {
+ CLog.e("[%s] IOException while uploading result.", mDeviceSerial);
+ CLog.e(ioe);
+ }
+ }
+ }
+
+ /**
* Copy the xml formatting files stored in this jar to the results directory
*
* @param resultsDir
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
index bae4e02..b6cd48f 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/DeviceInfoCollector.java
@@ -17,7 +17,6 @@
package com.android.compatibility.common.tradefed.targetprep;
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.compatibility.common.tradefed.build.MasterBuildInfo;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTest;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
@@ -85,7 +84,6 @@
buildInfo.addBuildAttribute(entry.getKey(),
ArrayUtil.join(",", device.getProperty(entry.getValue())));
}
- MasterBuildInfo.addBuildInfo(buildInfo.getBuildAttributes());
if (mSkipDeviceInfo) {
return;
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
index e620f19..a1c8a4a 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/ReportLogCollector.java
@@ -27,11 +27,18 @@
import com.android.tradefed.targetprep.TargetSetupError;
import com.android.tradefed.util.FileUtil;
+import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* An {@link ITargetCleaner} that prepares and pulls report logs.
@@ -97,6 +104,7 @@
return;
}
pull(device, mSrcDir, hostReportDir, resultDir);
+ reformatRepeatedStreams(resultDir);
} catch (Exception exception) {
exception.printStackTrace();
}
@@ -122,4 +130,66 @@
CLog.e(e);
}
}
+
+ private void reformatRepeatedStreams(File resultDir) throws IOException, FileNotFoundException {
+ File[] reportLogs = resultDir.listFiles();
+ // Sometimes report logs are in a sub-directory.
+ if (reportLogs.length == 1 && reportLogs[0].isDirectory()) {
+ reportLogs = reportLogs[0].listFiles();
+ }
+ for (File reportLog : reportLogs) {
+ try (BufferedReader metricsReader = new BufferedReader(new FileReader(reportLog))) {
+ // Get metrics as string.
+ StringBuilder metricBuilder = new StringBuilder();
+ String line;
+ while ((line = metricsReader.readLine()) != null) {
+ metricBuilder.append(line);
+ }
+ String metrics = metricBuilder.toString();
+ // Create map of stream names and metrics.
+ HashMap<String, List<String>> metricsMap = new HashMap<>();
+ String pattern = "\\\"([a-z0-9_]*)\\\":(\\{[^{}]*\\})";
+ Pattern p = Pattern.compile(pattern);
+ Matcher m = p.matcher(metrics);
+ while (m.find()) {
+ String key = m.group(1);
+ String value = m.group(2);
+ if (!metricsMap.containsKey(key)) {
+ metricsMap.put(key, new ArrayList<String>());
+ }
+ metricsMap.get(key).add(value);
+ }
+ // Rewrite metrics as arrays.
+ StringBuilder newMetricsBuilder = new StringBuilder();
+ newMetricsBuilder.append("{");
+ boolean firstLine = true;
+ for (String key: metricsMap.keySet()) {
+ if (!firstLine) {
+ newMetricsBuilder.append(",");
+ } else {
+ firstLine = false;
+ }
+ newMetricsBuilder.append("\"").append(key).append("\":[");
+ boolean firstValue = true;
+ for (String stream : metricsMap.get(key)) {
+ if (!firstValue) {
+ newMetricsBuilder.append(",");
+ }
+ else {
+ firstValue = false;
+ }
+ newMetricsBuilder.append(stream);
+ }
+ newMetricsBuilder.append("]");
+ }
+ newMetricsBuilder.append("}");
+ reportLog.createNewFile();
+ try (BufferedWriter metricsWriter = new BufferedWriter(new
+ FileWriter(reportLog))) {
+ String newMetrics = newMetricsBuilder.toString();
+ metricsWriter.write(newMetrics, 0, newMetrics.length());
+ }
+ }
+ }
+ }
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
index 48b7d3b..16986fb 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/CompatibilityTest.java
@@ -20,16 +20,20 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
import com.android.compatibility.common.tradefed.result.IInvocationResultRepo;
import com.android.compatibility.common.tradefed.result.InvocationResultRepo;
+import com.android.compatibility.common.tradefed.util.OptionHelper;
import com.android.compatibility.common.util.AbiUtils;
import com.android.compatibility.common.util.ICaseResult;
import com.android.compatibility.common.util.IInvocationResult;
import com.android.compatibility.common.util.IModuleResult;
import com.android.compatibility.common.util.ITestResult;
import com.android.compatibility.common.util.MonitoringUtils;
+import com.android.compatibility.common.util.ResultHandler;
import com.android.compatibility.common.util.TestFilter;
import com.android.compatibility.common.util.TestStatus;
import com.android.ddmlib.Log.LogLevel;
import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.ArgsOptionParser;
+import com.android.tradefed.config.ConfigurationException;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.Option.Importance;
import com.android.tradefed.config.OptionClass;
@@ -57,6 +61,8 @@
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
/**
@@ -194,7 +200,6 @@
private int mTotalShards;
private IModuleRepo mModuleRepo;
private ITestDevice mDevice;
- private IBuildInfo mBuild;
private CompatibilityBuildHelper mBuildHelper;
/**
@@ -239,9 +244,12 @@
*/
@Override
public void setBuild(IBuildInfo buildInfo) {
- mBuild = buildInfo;
- mBuildHelper = new CompatibilityBuildHelper(mBuild);
- mBuildHelper.init(mSuitePlan, mURL);
+ mBuildHelper = new CompatibilityBuildHelper(buildInfo);
+ // Initializing the mBuildHelper also updates properties in buildInfo.
+ // TODO(nicksauer): Keeping invocation properties around via buildInfo
+ // is confusing and would be better done in an "InvocationInfo".
+ // Note, the current time is used to generated the result directory.
+ mBuildHelper.init(mSuitePlan, mURL, System.currentTimeMillis());
}
/**
@@ -255,12 +263,15 @@
synchronized (mModuleRepo) {
if (!mModuleRepo.isInitialized()) {
setupFilters();
+ // Set retry mode for module repo
+ mModuleRepo.setRetryMode(mRetrySessionId != null);
// Initialize the repository, {@link CompatibilityBuildHelper#getTestsDir} can
// throw a {@link FileNotFoundException}
mModuleRepo.initialize(mTotalShards, mBuildHelper.getTestsDir(), getAbis(),
mDeviceTokens, mTestArgs, mModuleArgs, mIncludeFilters,
- mExcludeFilters, mBuild);
+ mExcludeFilters, mBuildHelper.getBuildInfo());
}
+
}
// Get the tests to run in this shard
List<IModuleDef> modules = mModuleRepo.getModules(getDevice().getSerialNumber());
@@ -281,7 +292,7 @@
// Set values and run preconditions
for (int i = 0; i < moduleCount; i++) {
IModuleDef module = modules.get(i);
- module.setBuild(mBuild);
+ module.setBuild(mBuildHelper.getBuildInfo());
module.setDevice(mDevice);
module.setPreparerWhitelist(mPreparerWhitelist);
module.prepare(mSkipPreconditions);
@@ -381,18 +392,31 @@
mModuleName = null;
mTestName = null;
// Load the invocation result
- IInvocationResultRepo repo;
IInvocationResult result = null;
try {
- repo = new InvocationResultRepo(mBuildHelper.getResultsDir());
- result = repo.getResult(mRetrySessionId);
+ result = ResultHandler.findResult(mBuildHelper.getResultsDir(), mRetrySessionId);
} catch (FileNotFoundException e) {
- e.printStackTrace();
+ throw new RuntimeException(e);
}
if (result == null) {
throw new IllegalArgumentException(String.format(
"Could not find session with id %d", mRetrySessionId));
}
+ CLog.logAndDisplay(LogLevel.INFO, "Retrying session from: %s",
+ CompatibilityBuildHelper.getDirSuffix(result.getStartTime()));
+
+ String retryCommandLineArgs = result.getCommandLineArgs();
+ if (retryCommandLineArgs != null) {
+ // Copy the original command into the build helper so it can be serialized later
+ mBuildHelper.setRetryCommandLineArgs(retryCommandLineArgs);
+ try {
+ // parse the command-line string from the result file and set options
+ ArgsOptionParser parser = new ArgsOptionParser(this);
+ parser.parse(OptionHelper.getValidCliArgs(retryCommandLineArgs, this));
+ } catch (ConfigurationException e) {
+ throw new RuntimeException(e);
+ }
+ }
// Append each test that failed or was not executed to the filters
for (IModuleResult module : result.getModules()) {
for (ICaseResult testResultList : module.getResults()) {
@@ -404,7 +428,8 @@
}
}
}
- } else if (mModuleName != null) {
+ }
+ if (mModuleName != null) {
mIncludeFilters.clear();
try {
List<String> modules = ModuleRepo.getModuleNamesMatching(
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
index f18bfc8..4491fb3 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleDef.java
@@ -21,14 +21,16 @@
import com.android.tradefed.testtype.IDeviceTest;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IRuntimeHintProvider;
+import com.android.tradefed.testtype.ITestFileFilterReceiver;
+import java.io.File;
import java.util.Set;
/**
* Container for Compatibility test info.
*/
public interface IModuleDef extends Comparable<IModuleDef>, IBuildReceiver, IDeviceTest,
- IRemoteTest, IRuntimeHintProvider {
+ IRemoteTest, IRuntimeHintProvider, ITestFileFilterReceiver {
/**
* @return The name of this module.
@@ -72,6 +74,11 @@
void addExcludeFilter(String name);
/**
+ * @return true if the IModuleDef can handle files of include and exclude filters
+ */
+ boolean isFileFilterReceiver();
+
+ /**
* Set a list of preparers to allow to run before or after a test.
* If this list is empty, then all configured preparers will run.
*
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java
index 24e1dec..7f32c10 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/IModuleRepo.java
@@ -41,6 +41,11 @@
List<String> mExcludeFilters, IBuildInfo buildInfo);
/**
+ * Set the retry mode of the module repo.
+ */
+ void setRetryMode(boolean isRetry);
+
+ /**
* @return a {@link Map} of all modules to run on the device referenced by the given serial.
*/
List<IModuleDef> getModules(String serial);
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
index 8d0490b..ae940a5 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleDef.java
@@ -38,8 +38,10 @@
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IRuntimeHintProvider;
import com.android.tradefed.testtype.ITestCollector;
+import com.android.tradefed.testtype.ITestFileFilterReceiver;
import com.android.tradefed.testtype.ITestFilterReceiver;
+import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@@ -191,6 +193,40 @@
* {@inheritDoc}
*/
@Override
+ public void setIncludeTestFile(File testFile) {
+ if (!isFileFilterReceiver()) {
+ throw new IllegalArgumentException(
+ String.format("%s does not implement interface ITestFileFilterReceiver,"
+ + " cannot setExcludeFile for %s", mTest, mName));
+ }
+ ((ITestFileFilterReceiver)mTest).setIncludeTestFile(testFile);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setExcludeTestFile(File testFile) {
+ if (!isFileFilterReceiver()) {
+ throw new IllegalArgumentException(
+ String.format("%s does not implement interface ITestFileFilterReceiver,"
+ + " cannot setExcludeFile for %s", mTest, mName));
+ }
+ ((ITestFileFilterReceiver)mTest).setExcludeTestFile(testFile);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isFileFilterReceiver() {
+ return (mTest instanceof ITestFileFilterReceiver);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public void setPreparerWhitelist(Set<String> preparerWhitelist) {
mPreparerWhitelist.addAll(preparerWhitelist);
}
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
index 8e984cb..41a5407 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/testtype/ModuleRepo.java
@@ -28,10 +28,13 @@
import com.android.tradefed.testtype.IBuildReceiver;
import com.android.tradefed.testtype.IRemoteTest;
import com.android.tradefed.testtype.IShardableTest;
+import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.TimeUtil;
import java.io.File;
import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -63,6 +66,7 @@
private int mMediumModulesPerShard;
private int mLargeModulesPerShard;
private int mModuleCount = 0;
+ private boolean mIsRetry = false;
private Set<String> mSerials = new HashSet<>();
private Map<String, Set<String>> mDeviceTokens = new HashMap<>();
private Map<String, Map<String, String>> mTestArgs = new HashMap<>();
@@ -175,6 +179,11 @@
return mInitialized;
}
+ @Override
+ public void setRetryMode(boolean isRetry) {
+ mIsRetry = isRetry;
+ }
+
/**
* {@inheritDoc}
*/
@@ -333,40 +342,95 @@
private void addModuleDef(IModuleDef moduleDef) {
String id = moduleDef.getId();
- boolean includeModule = mIncludeAll;
- for (TestFilter include : getFilter(mIncludeFilters, id)) {
- String test = include.getTest();
- if (test != null) {
- // We're including a subset of tests
- moduleDef.addIncludeFilter(test);
- }
- includeModule = true;
+ List<TestFilter> mdIncludes = getFilter(mIncludeFilters, id);
+ List<TestFilter> mdExcludes = getFilter(mExcludeFilters, id);
+ if ((!mIncludeAll && mdIncludes.isEmpty()) || containsModuleExclude(mdExcludes)) {
+ // if only including some modules, and no includes exist for this module, do not add
+ // this module. Or if an exclude applies to this entire module, do not add this module.
+ return;
}
- for (TestFilter exclude : getFilter(mExcludeFilters, id)) {
- String test = exclude.getTest();
- if (test != null) {
- // Excluding a subset of tests, so keep module but give filter
- moduleDef.addExcludeFilter(test);
- } else {
- // Excluding all tests in the module so just remove the whole thing
- includeModule = false;
+ if (!mdIncludes.isEmpty()) {
+ addModuleIncludes(moduleDef, mdIncludes);
+ }
+ if (!mdExcludes.isEmpty()) {
+ addModuleExcludes(moduleDef, mdExcludes);
+ }
+
+ Set<String> tokens = moduleDef.getTokens();
+ if (tokens != null && !tokens.isEmpty()) {
+ mTokenModules.add(moduleDef);
+ } else if (moduleDef.getRuntimeHint() < SMALL_TEST) {
+ mSmallModules.add(moduleDef);
+ } else if (moduleDef.getRuntimeHint() < MEDIUM_TEST) {
+ mMediumModules.add(moduleDef);
+ } else {
+ mLargeModules.add(moduleDef);
+ }
+ mModuleCount++;
+ }
+
+ private void addModuleIncludes(IModuleDef moduleDef, List<TestFilter> includes) {
+ if (mIsRetry && moduleDef.isFileFilterReceiver()) {
+ File includeFile = createFilterFile(moduleDef.getName(), ".include", includes);
+ moduleDef.setIncludeTestFile(includeFile);
+ } else {
+ // add module includes one at a time
+ for (TestFilter include : includes) {
+ String test = include.getTest();
+ if (test != null) {
+ moduleDef.addIncludeFilter(test);
+ }
}
}
- if (includeModule) {
- Set<String> tokens = moduleDef.getTokens();
- if (tokens != null && !tokens.isEmpty()) {
- mTokenModules.add(moduleDef);
- } else if (moduleDef.getRuntimeHint() < SMALL_TEST) {
- mSmallModules.add(moduleDef);
- } else if (moduleDef.getRuntimeHint() < MEDIUM_TEST) {
- mMediumModules.add(moduleDef);
- } else {
- mLargeModules.add(moduleDef);
+ }
+
+ private void addModuleExcludes(IModuleDef moduleDef, List<TestFilter> excludes) {
+ if (mIsRetry && moduleDef.isFileFilterReceiver()) {
+ File excludeFile = createFilterFile(moduleDef.getName(), ".exclude", excludes);
+ moduleDef.setExcludeTestFile(excludeFile);
+ } else {
+ // add module excludes one at a time
+ for (TestFilter exclude : excludes) {
+ moduleDef.addExcludeFilter(exclude.getTest());
}
- mModuleCount++;
}
}
+ private File createFilterFile(String prefix, String suffix, List<TestFilter> filters) {
+ File filterFile = null;
+ PrintWriter out = null;
+ try {
+ filterFile = FileUtil.createTempFile(prefix, suffix);
+ out = new PrintWriter(filterFile);
+ for (TestFilter filter : filters) {
+ String filterTest = filter.getTest();
+ if (filterTest != null) {
+ out.println(filterTest);
+ }
+ }
+ out.flush();
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to create filter file");
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ return filterFile;
+ }
+
+ /*
+ * Returns true iff one or more test filters in excludes apply to the entire module.
+ */
+ private boolean containsModuleExclude(Collection<TestFilter> excludes) {
+ for (TestFilter exclude : excludes) {
+ if (exclude.getTest() == null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* A {@link FilenameFilter} to find all the config files in a directory.
*/
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/OptionHelper.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/OptionHelper.java
new file mode 100644
index 0000000..23832a2
--- /dev/null
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/util/OptionHelper.java
@@ -0,0 +1,127 @@
+/*
+ * 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 com.android.compatibility.common.tradefed.util;
+
+import com.android.tradefed.config.Option;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Helper class for manipulating fields with @option annotations.
+ */
+public final class OptionHelper {
+
+ private OptionHelper() {}
+
+ /**
+ * Return the {@link List} of {@link Field} entries on the given object
+ * that have the {@link Option} annotation.
+ *
+ * @param object An object with @option-annotated fields.
+ */
+ private static List<Field> getFields(Object object) {
+ Field[] classFields = object.getClass().getDeclaredFields();
+ List<Field> optionFields = new ArrayList<Field>();
+
+ for (Field declaredField : classFields) {
+ // allow access to protected and private fields
+ declaredField.setAccessible(true);
+
+ // store type and values only in annotated fields
+ if (declaredField.isAnnotationPresent(Option.class)) {
+ optionFields.add(declaredField);
+ }
+ }
+ return optionFields;
+ }
+
+ /**
+ * Retrieve a {@link Set} of {@link Option} names present on the given
+ * object.
+ *
+ * @param object An object with @option-annotated fields.
+ */
+ static Set<String> getOptionNames(Object object) {
+ Set<String> options = new HashSet<String>();
+ List<Field> optionFields = getFields(object);
+
+ for (Field declaredField : optionFields) {
+ Option option = declaredField.getAnnotation(Option.class);
+ options.add(option.name());
+ }
+ return options;
+ }
+
+ /**
+ * Retrieve a {@link Set} of {@link Option} short names present on the given
+ * object.
+ *
+ * @param object An object with @option-annotated fields.
+ */
+ static Set<String> getOptionShortNames(Object object) {
+ Set<String> shortNames = new HashSet<String>();
+ List<Field> optionFields = getFields(object);
+
+ for (Field declaredField : optionFields) {
+ Option option = declaredField.getAnnotation(Option.class);
+ if (option.shortName() != Option.NO_SHORT_NAME) {
+ shortNames.add(String.valueOf(option.shortName()));
+ }
+ }
+ return shortNames;
+ }
+
+ /**
+ * Retrieve a {@link List} of {@link String} entries of the valid
+ * command-line options for the given {@link Object} from the given
+ * input {@link String}.
+ */
+ public static List<String> getValidCliArgs(String commandString, Object object) {
+ Set<String> optionNames = OptionHelper.getOptionNames(object);
+ Set<String> optionShortNames = OptionHelper.getOptionShortNames(object);
+ List<String> validCliArgs = new ArrayList<String>();
+
+ // get "-option/--option value" pairs from the command-line string
+ Pattern cliPattern = Pattern.compile("-[-\\w]+[ =]\\S+");
+ Matcher matcher = cliPattern.matcher(commandString);
+
+ while (matcher.find()) {
+ String match = matcher.group();
+ // split between the option name and value
+ String[] tokens = match.split("[ =]");
+ // remove initial hyphens from option args
+ String keyName = tokens[0].replaceFirst("^--?", "");
+
+ // add substrings only when the options are recognized
+ if (optionShortNames.contains(keyName) || optionNames.contains(keyName)) {
+ if (match.contains(" ")) {
+ // ArgsOptionParser expect stand-alone entity or a key=value format, no spaces.
+ validCliArgs.add(match.split(" ")[0]);
+ validCliArgs.add(match.split(" ")[1]);
+ } else {
+ validCliArgs.add(match);
+ }
+ }
+ }
+ return validCliArgs;
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
index 318960c..b710128 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/UnitTests.java
@@ -17,12 +17,14 @@
import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelperTest;
import com.android.compatibility.common.tradefed.command.CompatibilityConsoleTest;
+import com.android.compatibility.common.tradefed.result.ConsoleReporterTest;
import com.android.compatibility.common.tradefed.result.ResultReporterTest;
import com.android.compatibility.common.tradefed.targetprep.PropertyCheckTest;
import com.android.compatibility.common.tradefed.targetprep.SettingsPreparerTest;
import com.android.compatibility.common.tradefed.testtype.CompatibilityTestTest;
import com.android.compatibility.common.tradefed.testtype.ModuleDefTest;
import com.android.compatibility.common.tradefed.testtype.ModuleRepoTest;
+import com.android.compatibility.common.tradefed.util.OptionHelperTest;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -38,8 +40,11 @@
super();
addTestSuite(CompatibilityBuildHelperTest.class);
addTestSuite(CompatibilityConsoleTest.class);
+ addTestSuite(CompatibilityTestTest.class);
+ addTestSuite(ConsoleReporterTest.class);
addTestSuite(ResultReporterTest.class);
addTestSuite(CompatibilityTestTest.class);
+ addTestSuite(OptionHelperTest.class);
addTestSuite(ModuleDefTest.class);
addTestSuite(ModuleRepoTest.class);
addTestSuite(PropertyCheckTest.class);
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java
index 55d15dd..503c529 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/build/CompatibilityBuildHelperTest.java
@@ -36,6 +36,8 @@
private static final String ROOT_DIR_NAME = "root";
private static final String BASE_DIR_NAME = "android-tests";
private static final String TESTCASES = "testcases";
+ private static final String COMMAND_LINE_ARGS = "cts -m CtsModuleTestCases";
+ private static final long START_TIME = 123456L;
private File mRoot = null;
private File mBase = null;
@@ -69,7 +71,7 @@
public void testSuiteInfoLoad() throws Exception {
setProperty(mRoot.getAbsolutePath());
- mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
assertEquals("Incorrect suite build number", BUILD_NUMBER, mHelper.getSuiteBuild());
assertEquals("Incorrect suite name", SUITE_NAME, mHelper.getSuiteName());
assertEquals("Incorrect suite full name", SUITE_FULL_NAME, mHelper.getSuiteFullName());
@@ -82,19 +84,19 @@
CompatibilityBuildHelper helper = new CompatibilityBuildHelper(provider.getBuild());
try {
// Should fail with root unset
- helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
fail("Expected fail for unset root property");
} catch (IllegalArgumentException e) {
/* expected */
}
setProperty(mRoot.getAbsolutePath());
// Shouldn't fail with root set
- helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
}
public void testValidation() throws Exception {
setProperty(mRoot.getAbsolutePath());
- mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
try {
mHelper.getDir();
fail("Build helper validation succeeded on an invalid installation");
@@ -112,7 +114,7 @@
public void testDirs() throws Exception {
setProperty(mRoot.getAbsolutePath());
- mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ mHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
createDirStructure();
assertNotNull(mRoot);
assertNotNull(mBuild);
@@ -129,6 +131,16 @@
mHelper.getResultsDir().getAbsolutePath());
}
+ public void testGetCommandLineArgs() {
+ assertNull(mHelper.getCommandLineArgs());
+ mBuild.addBuildAttribute("command_line_args", COMMAND_LINE_ARGS);
+ assertEquals(COMMAND_LINE_ARGS, mHelper.getCommandLineArgs());
+
+ mBuild.addBuildAttribute("command_line_args", "cts --retry 0");
+ mHelper.setRetryCommandLineArgs(COMMAND_LINE_ARGS);
+ assertEquals(COMMAND_LINE_ARGS, mHelper.getCommandLineArgs());
+ }
+
/**
* Sets the *_ROOT property of the build's installation location.
*
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java
new file mode 100644
index 0000000..38fb1db
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ConsoleReporterTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compatibility.common.tradefed.result;
+
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.AbiUtils;
+import com.android.compatibility.common.util.ICaseResult;
+import com.android.compatibility.common.util.IInvocationResult;
+import com.android.compatibility.common.util.IModuleResult;
+import com.android.compatibility.common.util.ITestResult;
+import com.android.compatibility.common.util.TestStatus;
+import com.android.ddmlib.testrunner.TestIdentifier;
+import com.android.tradefed.build.BuildInfo;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.config.OptionSetter;
+import com.android.tradefed.util.FileUtil;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.HashMap;
+import java.util.List;
+
+public class ConsoleReporterTest extends TestCase {
+
+ private static final String TESTCASES = "testcases";
+ private static final String NAME = "ModuleName";
+ private static final String NAME2 = "ModuleName2";
+ private static final String ABI = "mips64";
+ private static final String ID = AbiUtils.createId(ABI, NAME);
+ private static final String ID2 = AbiUtils.createId(ABI, NAME2);
+ private static final String CLASS = "android.test.FoorBar";
+ private static final String METHOD_1 = "testBlah1";
+ private static final String METHOD_2 = "testBlah2";
+ private static final String METHOD_3 = "testBlah3";
+ private static final String TEST_1 = String.format("%s#%s", CLASS, METHOD_1);
+ private static final String TEST_2 = String.format("%s#%s", CLASS, METHOD_2);
+ private static final String TEST_3 = String.format("%s#%s", CLASS, METHOD_3);
+ private static final String STACK_TRACE = "Something small is not alright\n " +
+ "at four.big.insects.Marley.sing(Marley.java:10)";
+
+ private ConsoleReporter mReporter;
+ private IBuildInfo mBuildInfo;
+ private CompatibilityBuildHelper mBuildHelper;
+
+ private File mRoot = null;
+ private File mBase = null;
+ private File mTests = null;
+
+ @Override
+ public void setUp() throws Exception {
+ mReporter = new ConsoleReporter();
+ OptionSetter setter = new OptionSetter(mReporter);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ mReporter = null;
+ }
+
+ public void testResultReporting_singleModule() throws Exception {
+ mReporter.invocationStarted(mBuildInfo);
+ mReporter.testRunStarted(ID, 3);
+ runTests();
+
+ mReporter.testRunEnded(10, new HashMap<String, String>());
+ mReporter.invocationEnded(10);
+
+ assertEquals(ID, mReporter.getModuleId());
+ assertEquals(2, mReporter.getFailedTests());
+ assertEquals(1, mReporter.getPassedTests());
+ assertEquals(3, mReporter.getCurrentTestNum());
+ assertEquals(3, mReporter.getTotalTestsInModule());
+ }
+
+ public void testResultReporting_multipleModules() throws Exception {
+ mReporter.invocationStarted(mBuildInfo);
+ mReporter.testRunStarted(ID, 3);
+ runTests();
+
+ assertEquals(ID, mReporter.getModuleId());
+ assertEquals(2, mReporter.getFailedTests());
+ assertEquals(1, mReporter.getPassedTests());
+ assertEquals(3, mReporter.getCurrentTestNum());
+ assertEquals(3, mReporter.getTotalTestsInModule());
+
+ // Should reset counters
+ mReporter.testRunStarted(ID2, 3);
+ assertEquals(ID2, mReporter.getModuleId());
+ assertEquals(0, mReporter.getFailedTests());
+ assertEquals(0, mReporter.getPassedTests());
+ assertEquals(0, mReporter.getCurrentTestNum());
+ assertEquals(3, mReporter.getTotalTestsInModule());
+
+ runTests();
+ // Same id, should not reset test counters, but aggregate total tests
+ mReporter.testRunStarted(ID2, 5);
+ assertEquals(ID2, mReporter.getModuleId());
+ assertEquals(2, mReporter.getFailedTests());
+ assertEquals(1, mReporter.getPassedTests());
+ assertEquals(3, mReporter.getCurrentTestNum());
+ assertEquals(8, mReporter.getTotalTestsInModule());
+ }
+
+ private void runTests() {
+ TestIdentifier test1 = new TestIdentifier(CLASS, METHOD_1);
+ mReporter.testStarted(test1);
+ mReporter.testEnded(test1, new HashMap<String, String>());
+ assertFalse(mReporter.getTestFailed());
+
+ TestIdentifier test2 = new TestIdentifier(CLASS, METHOD_2);
+ mReporter.testStarted(test2);
+ assertFalse(mReporter.getTestFailed());
+ mReporter.testFailed(test2, STACK_TRACE);
+ assertTrue(mReporter.getTestFailed());
+
+ TestIdentifier test3 = new TestIdentifier(CLASS, METHOD_3);
+ mReporter.testStarted(test3);
+ assertFalse(mReporter.getTestFailed());
+ mReporter.testFailed(test3, STACK_TRACE);
+ assertTrue(mReporter.getTestFailed());
+ }
+}
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
index 6228cd7..60c48b3 100644
--- a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/result/ResultReporterTest.java
@@ -63,6 +63,7 @@
"compatibility_result.xsd",
"compatibility_result.xsl",
"logo.png"};
+ private static final long START_TIME = 123456L;
private ResultReporter mReporter;
private IBuildInfo mBuildInfo;
@@ -76,7 +77,6 @@
public void setUp() throws Exception {
mReporter = new ResultReporter();
OptionSetter setter = new OptionSetter(mReporter);
- setter.setOptionValue("quiet-output", "true");
mRoot = FileUtil.createTempDir(ROOT_DIR_NAME);
mBase = new File(mRoot, BASE_DIR_NAME);
mBase.mkdirs();
@@ -85,7 +85,7 @@
System.setProperty(ROOT_PROPERTY, mRoot.getAbsolutePath());
mBuildInfo = new BuildInfo(BUILD_NUMBER, "", "");
mBuildHelper = new CompatibilityBuildHelper(mBuildInfo);
- mBuildHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ mBuildHelper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
}
@Override
diff --git a/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/OptionHelperTest.java b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/OptionHelperTest.java
new file mode 100644
index 0000000..4f3d48f
--- /dev/null
+++ b/common/host-side/tradefed/tests/src/com/android/compatibility/common/tradefed/util/OptionHelperTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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 com.android.compatibility.common.tradefed.util;
+
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+
+import junit.framework.TestCase;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Unit tests for {@link OptionHelper}
+ */
+public class OptionHelperTest extends TestCase {
+
+ private static final String TEST_CLASS = "test-class";
+ private static final String TEST_CLASS_SHORTNAME = "c";
+ private static final String TEST_NAME = "test-name";
+ private static final String TEST_SUITE = "test-suite";
+ private static final String TEST_SUITE_SHORTNAME = "s";
+
+ @Option(name = TEST_CLASS,
+ shortName = 'c',
+ importance = Importance.ALWAYS)
+ private String mTestClass = null;
+
+ @Option(name = TEST_NAME,
+ importance = Importance.ALWAYS)
+ private String mTestName = null;
+
+ @Option(name = TEST_SUITE,
+ shortName = 's',
+ importance = Importance.ALWAYS)
+ private String mTestSuite = null;
+
+ public void testGetOptionNames() throws Exception {
+ Set<String> optionNames = OptionHelper.getOptionNames(this);
+ List<String> expectedNames = Arrays.asList(TEST_CLASS, TEST_NAME, TEST_SUITE);
+ assertEquals("Missing option names", true, optionNames.containsAll(expectedNames));
+ assertEquals("Expected three elements", 3, optionNames.size());
+ }
+
+ public void testGetOptionShortNames() throws Exception {
+ Set<String> optionShortNames = OptionHelper.getOptionShortNames(this);
+ List<String> expectedShortNames = Arrays.asList(TEST_CLASS_SHORTNAME, TEST_SUITE_SHORTNAME);
+ assertEquals("Missing option shortnames", true,
+ optionShortNames.containsAll(expectedShortNames));
+ assertEquals("Expected two elements", 2, optionShortNames.size());
+ }
+
+ public void testGetValidCliArgs() throws Exception {
+ List<String> noValidNames = new ArrayList<String>();
+ List<String> validSubset = Arrays.asList("--" + TEST_CLASS, "fooclass",
+ "-" + TEST_SUITE_SHORTNAME, "foosuite");
+ List<String> allValidNames = Arrays.asList("--" + TEST_CLASS, "fooclass",
+ "-" + TEST_SUITE_SHORTNAME, "foosuite", "--" + TEST_NAME, "footest");
+
+ assertEquals("Expected no valid names", noValidNames,
+ OptionHelper.getValidCliArgs("test --foo -b", this));
+ assertEquals("Expected one long name and one short name", validSubset,
+ OptionHelper.getValidCliArgs("test --" + TEST_CLASS + " fooclass -b fake"
+ + " -s foosuite", this));
+ assertEquals("Expected two long names and one short name", allValidNames,
+ OptionHelper.getValidCliArgs("test --" + TEST_CLASS + " fooclass -b fake"
+ + " -s foosuite " + "--" + TEST_NAME + " footest", this));
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/CaseResult.java b/common/util/src/com/android/compatibility/common/util/CaseResult.java
index e16ad1f..36f77d7 100644
--- a/common/util/src/com/android/compatibility/common/util/CaseResult.java
+++ b/common/util/src/com/android/compatibility/common/util/CaseResult.java
@@ -112,4 +112,20 @@
return getName().compareTo(another.getName());
}
-}
\ No newline at end of file
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void mergeFrom(ICaseResult otherCaseResult) {
+ if (!otherCaseResult.getName().equals(getName())) {
+ throw new IllegalArgumentException(String.format(
+ "Cannot merge case result with mismatched name. Expected %s, Found %d",
+ otherCaseResult.getName(), getName()));
+ }
+
+ for (ITestResult otherTestResult : otherCaseResult.getResults()) {
+ mResults.put(otherTestResult.getName(), otherTestResult);
+ }
+ }
+
+}
diff --git a/common/util/src/com/android/compatibility/common/util/ICaseResult.java b/common/util/src/com/android/compatibility/common/util/ICaseResult.java
index 99e646a0..5904d69 100644
--- a/common/util/src/com/android/compatibility/common/util/ICaseResult.java
+++ b/common/util/src/com/android/compatibility/common/util/ICaseResult.java
@@ -55,4 +55,8 @@
*/
int countResults(TestStatus status);
+ /**
+ * Merge the case results from otherCaseResult into this caseResult.
+ */
+ void mergeFrom(ICaseResult otherCaseResult);
}
diff --git a/common/util/src/com/android/compatibility/common/util/IInvocationResult.java b/common/util/src/com/android/compatibility/common/util/IInvocationResult.java
index c1e5d28..3e73ede 100644
--- a/common/util/src/com/android/compatibility/common/util/IInvocationResult.java
+++ b/common/util/src/com/android/compatibility/common/util/IInvocationResult.java
@@ -71,17 +71,27 @@
List<IModuleResult> getModules();
/**
- * @return the directory containing this result.
+ * Merges a module result to the invocation result.
*/
- File getResultDir();
+ void mergeModuleResult(IModuleResult moduleResult);
/**
- * Adds the given build info to the result.
+ * Adds the given invocation info to the result.
*/
- void addBuildInfo(String key, String value);
+ void addInvocationInfo(String key, String value);
/**
- * Gets the {@link Map} of build info collected.
+ * Gets the {@link Map} of invocation info collected.
*/
- Map<String, String> getBuildInfo();
+ Map<String, String> getInvocationInfo();
+
+ /**
+ * Set the string containing the command line arguments to the run command.
+ */
+ void setCommandLineArgs(String setCommandLineArgs);
+
+ /**
+ * Retrieve the command line arguments to the run command.
+ */
+ String getCommandLineArgs();
}
diff --git a/common/util/src/com/android/compatibility/common/util/IModuleResult.java b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
index 6d4efa1..f861b51 100644
--- a/common/util/src/com/android/compatibility/common/util/IModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/IModuleResult.java
@@ -58,4 +58,8 @@
*/
int countResults(TestStatus status);
+ /**
+ * Merge the module results from otherModuleResult into this moduleResult.
+ */
+ void mergeFrom(IModuleResult otherModuleResult);
}
diff --git a/common/util/src/com/android/compatibility/common/util/InvocationResult.java b/common/util/src/com/android/compatibility/common/util/InvocationResult.java
index b499bc1..a94dea8 100644
--- a/common/util/src/com/android/compatibility/common/util/InvocationResult.java
+++ b/common/util/src/com/android/compatibility/common/util/InvocationResult.java
@@ -15,7 +15,6 @@
*/
package com.android.compatibility.common.util;
-import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -32,26 +31,10 @@
private long mTimestamp;
private Map<String, IModuleResult> mModuleResults = new LinkedHashMap<>();
- private Map<String, String> mBuildInfo = new HashMap<>();
+ private Map<String, String> mInvocationInfo = new HashMap<>();
private Set<String> mSerials = new HashSet<>();
private String mTestPlan;
- private File mResultDir;
-
- /**
- * @param resultDir
- */
- public InvocationResult(File resultDir) {
- this(System.currentTimeMillis(), resultDir);
- }
-
- /**
- * @param timestamp
- * @param resultDir
- */
- public InvocationResult(long timestamp, File resultDir) {
- setStartTime(timestamp);
- mResultDir = resultDir;
- }
+ private String mCommandLineArgs;
/**
* {@inheritDoc}
@@ -92,16 +75,26 @@
* {@inheritDoc}
*/
@Override
- public void addBuildInfo(String key, String value) {
- mBuildInfo.put(key, value);
+ public void mergeModuleResult(IModuleResult moduleResult) {
+ // Merge the moduleResult with any existing module result
+ IModuleResult existingModuleResult = getOrCreateModule(moduleResult.getId());
+ existingModuleResult.mergeFrom(moduleResult);
}
/**
* {@inheritDoc}
*/
@Override
- public Map<String, String> getBuildInfo() {
- return mBuildInfo;
+ public void addInvocationInfo(String key, String value) {
+ mInvocationInfo.put(key, value);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Map<String, String> getInvocationInfo() {
+ return mInvocationInfo;
}
/**
@@ -156,8 +149,15 @@
* {@inheritDoc}
*/
@Override
- public File getResultDir() {
- return mResultDir;
+ public void setCommandLineArgs(String commandLineArgs) {
+ mCommandLineArgs = commandLineArgs;
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getCommandLineArgs() {
+ return mCommandLineArgs;
+ }
}
diff --git a/common/util/src/com/android/compatibility/common/util/ModuleResult.java b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
index 1f277f7..7e93824 100644
--- a/common/util/src/com/android/compatibility/common/util/ModuleResult.java
+++ b/common/util/src/com/android/compatibility/common/util/ModuleResult.java
@@ -130,4 +130,21 @@
return getId().compareTo(another.getId());
}
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void mergeFrom(IModuleResult otherModuleResult) {
+ if (!otherModuleResult.getId().equals(getId())) {
+ throw new IllegalArgumentException(String.format(
+ "Cannot merge module result with mismatched id. Expected %s, Found %s",
+ otherModuleResult.getId(), getId()));
+ }
+
+ this.mRuntime += otherModuleResult.getRuntime();
+ for (ICaseResult otherCaseResult : otherModuleResult.getResults()) {
+ ICaseResult caseResult = getOrCreateResult(otherCaseResult.getName());
+ caseResult.mergeFrom(otherCaseResult);
+ }
+ }
}
diff --git a/common/util/src/com/android/compatibility/common/util/ResultHandler.java b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
index 8e435d8..c56ff1a 100644
--- a/common/util/src/com/android/compatibility/common/util/ResultHandler.java
+++ b/common/util/src/com/android/compatibility/common/util/ResultHandler.java
@@ -30,6 +30,8 @@
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;
@@ -53,6 +55,7 @@
private static final String BUILD_PRODUCT = "build_product";
private static final String BUILD_TAG = "Build";
private static final String CASE_TAG = "TestCase";
+ private static final String COMMAND_LINE_ARGS = "command_line_args";
private static final String DEVICES_ATTR = "devices";
private static final String END_DISPLAY_TIME_ATTR = "end_display";
private static final String END_TIME_ATTR = "end";
@@ -105,7 +108,7 @@
if (!resultFile.exists()) {
continue;
}
- IInvocationResult invocation = new InvocationResult(resultDir);
+ IInvocationResult invocation = new InvocationResult();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
parser.setInput(new FileReader(resultFile));
@@ -115,6 +118,7 @@
invocation.setStartTime(Long.valueOf(
parser.getAttributeValue(NS, START_TIME_ATTR)));
invocation.setTestPlan(parser.getAttributeValue(NS, SUITE_PLAN_ATTR));
+ invocation.setCommandLineArgs(parser.getAttributeValue(NS, COMMAND_LINE_ARGS));
String deviceList = parser.getAttributeValue(NS, DEVICES_ATTR);
for (String device : deviceList.split(",")) {
invocation.addDeviceSerial(device);
@@ -122,8 +126,9 @@
parser.nextTag();
parser.require(XmlPullParser.START_TAG, NS, BUILD_TAG);
- invocation.addBuildInfo(BUILD_ID, parser.getAttributeValue(NS, BUILD_ID));
- invocation.addBuildInfo(BUILD_PRODUCT, parser.getAttributeValue(NS, BUILD_PRODUCT));
+ invocation.addInvocationInfo(BUILD_ID, parser.getAttributeValue(NS, BUILD_ID));
+ invocation.addInvocationInfo(BUILD_PRODUCT, parser.getAttributeValue(NS,
+ BUILD_PRODUCT));
// TODO(stuartscott): may want to reload these incase the retry was done with
// --skip-device-info flag
@@ -190,6 +195,12 @@
e.printStackTrace();
}
}
+ // Sort the table entries on each entry's timestamp.
+ Collections.sort(results, new Comparator<IInvocationResult>() {
+ public int compare(IInvocationResult result1, IInvocationResult result2) {
+ return Long.compare(result1.getStartTime(), result2.getStartTime());
+ }
+ });
return results;
}
@@ -198,13 +209,14 @@
* @param resultDir
* @param startTime
* @param referenceUrl A nullable string that can contain a URL to a related data
+ * @param commandLineArgs A string containing the arguments to the run command
* @return The result file created.
* @throws IOException
* @throws XmlPullParserException
*/
public static File writeResults(String suiteName, String suiteVersion, String suitePlan,
String suiteBuild, IInvocationResult result, File resultDir,
- long startTime, long endTime, String referenceUrl)
+ long startTime, long endTime, String referenceUrl, String commandLineArgs)
throws IOException, XmlPullParserException {
int passed = result.countResults(TestStatus.PASS);
int failed = result.countResults(TestStatus.FAIL);
@@ -228,6 +240,8 @@
serializer.attribute(NS, SUITE_PLAN_ATTR, suitePlan);
serializer.attribute(NS, SUITE_BUILD_ATTR, suiteBuild);
serializer.attribute(NS, REPORT_VERSION_ATTR, RESULT_FILE_VERSION);
+ serializer.attribute(NS, COMMAND_LINE_ARGS, nullToEmpty(commandLineArgs));
+
if (referenceUrl != null) {
serializer.attribute(NS, REFERENCE_URL_ATTR, referenceUrl);
}
@@ -260,7 +274,7 @@
// Build Info
serializer.startTag(NS, BUILD_TAG);
- for (Entry<String, String> entry : result.getBuildInfo().entrySet()) {
+ for (Entry<String, String> entry : result.getInvocationInfo().entrySet()) {
serializer.attribute(NS, entry.getKey(), entry.getValue());
}
serializer.endTag(NS, BUILD_TAG);
@@ -330,6 +344,23 @@
}
/**
+ * Find the IInvocationResult for the given sessionId.
+ */
+ public static IInvocationResult findResult(File resultsDir, Integer sessionId)
+ throws FileNotFoundException {
+ if (sessionId < 0) {
+ throw new IllegalArgumentException(
+ String.format("Invalid session id [%d] ", sessionId));
+ }
+
+ List<IInvocationResult> results = getResults(resultsDir);
+ if (results == null || sessionId >= results.size()) {
+ throw new RuntimeException(String.format("Could not find session [%d]", sessionId));
+ }
+ return results.get(sessionId);
+ }
+
+ /**
* Return the given time as a {@link String} suitable for displaying.
* <p/>
* Example: Fri Aug 20 15:13:03 PDT 2010
@@ -340,4 +371,11 @@
SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
return dateFormat.format(new Date(time));
}
+
+ /**
+ * When nullable is null, return an empty string. Otherwise, return the value in nullable.
+ */
+ private static String nullToEmpty(String nullable) {
+ return nullable == null ? "" : nullable;
+ }
}
diff --git a/common/util/src/com/android/compatibility/common/util/TestFilter.java b/common/util/src/com/android/compatibility/common/util/TestFilter.java
index 47ed9ec..460e34f 100644
--- a/common/util/src/com/android/compatibility/common/util/TestFilter.java
+++ b/common/util/src/com/android/compatibility/common/util/TestFilter.java
@@ -94,15 +94,15 @@
public String toString() {
StringBuilder sb = new StringBuilder();
if (mAbi != null) {
- sb.append(mAbi);
+ sb.append(mAbi.trim());
sb.append(" ");
}
if (mName != null) {
- sb.append(mName);
+ sb.append(mName.trim());
}
if (mTest != null) {
sb.append(" ");
- sb.append(mTest);
+ sb.append(mTest.trim());
}
return sb.toString();
}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java b/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
index ae29597..c8b74c0 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/CaseResultTest.java
@@ -76,4 +76,45 @@
assertEquals("Expected two failures", 2, mResult.countResults(TestStatus.FAIL));
assertEquals("Expected one pass", 1, mResult.countResults(TestStatus.PASS));
}
-}
\ No newline at end of file
+
+ public void testMergeCase() throws Exception {
+ mResult.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+ mResult.getOrCreateResult(METHOD_2).passed(null);
+
+ // Same case another test and passing results in method 2
+ CaseResult otherResult = new CaseResult(CLASS);
+ otherResult.getOrCreateResult(METHOD_1).passed(null);
+ otherResult.getOrCreateResult(METHOD_2).passed(null);
+ otherResult.getOrCreateResult(METHOD_3).failed(STACK_TRACE);
+
+ mResult.mergeFrom(otherResult);
+ assertEquals("Expected one result", 3, mResult.getResults().size());
+ assertEquals("Expected one failures", 1, mResult.countResults(TestStatus.FAIL));
+ assertEquals("Expected two pass", 2, mResult.countResults(TestStatus.PASS));
+ }
+
+ public void testMergeCase_passToFail() throws Exception {
+ mResult.getOrCreateResult(METHOD_1).passed(null);
+
+ // Same case another test and passing results in method 2
+ CaseResult otherResult = new CaseResult(CLASS);
+ otherResult.getOrCreateResult(METHOD_1).passed(null);
+ otherResult.getOrCreateResult(METHOD_2).passed(null);
+ otherResult.getOrCreateResult(METHOD_3).failed(STACK_TRACE);
+
+ mResult.mergeFrom(otherResult);
+
+ assertEquals("Expected one result", 3, mResult.getResults().size());
+ assertEquals("Expected one failures", 1, mResult.countResults(TestStatus.FAIL));
+ assertEquals("Expected two pass", 2, mResult.countResults(TestStatus.PASS));
+ }
+
+ public void testMergeCase_mismatchedModuleName() throws Exception {
+
+ CaseResult otherResult = new CaseResult(CLASS + "foo");
+ try {
+ mResult.mergeFrom(otherResult);
+ fail("Expected IlleglArgumentException");
+ } catch (IllegalArgumentException expected) {}
+ }
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java b/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java
index 2239ac8..497623c 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ModuleResultTest.java
@@ -24,9 +24,12 @@
public class ModuleResultTest extends TestCase {
private static final String NAME = "ModuleName";
+ private static final String NAME_2 = "ModuleName2";
private static final String ABI = "mips64";
private static final String ID = AbiUtils.createId(ABI, NAME);
+ private static final String ID_2 = AbiUtils.createId(ABI, NAME_2);
private static final String CLASS = "android.test.FoorBar";
+ private static final String CLASS_2 = "android.test.FoorBar2";
private static final String METHOD_1 = "testBlah1";
private static final String METHOD_2 = "testBlah2";
private static final String METHOD_3 = "testBlah3";
@@ -69,4 +72,40 @@
assertEquals("Expected two failures", 2, mResult.countResults(TestStatus.FAIL));
assertEquals("Expected one pass", 1, mResult.countResults(TestStatus.PASS));
}
-}
\ No newline at end of file
+
+ public void testMergeModule() throws Exception {
+ ICaseResult caseResult = mResult.getOrCreateResult(CLASS);
+ caseResult.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+ caseResult.getOrCreateResult(METHOD_3).passed(null);
+
+ ICaseResult caseResult2 = mResult.getOrCreateResult(CLASS_2);
+ caseResult2.getOrCreateResult(METHOD_1).failed(STACK_TRACE);
+ caseResult2.getOrCreateResult(METHOD_3).passed(null);
+
+ assertEquals("Expected two results", 2, mResult.getResults().size());
+ assertTrue("Expected test result", mResult.getResults().contains(caseResult));
+ assertTrue("Expected test result", mResult.getResults().contains(caseResult2));
+
+ ModuleResult otherResult = new ModuleResult(ID);
+ // Same class but all passing tests
+ ICaseResult otherCaseResult = otherResult.getOrCreateResult(CLASS);
+ otherCaseResult.getOrCreateResult(METHOD_1).passed(null);
+ otherCaseResult.getOrCreateResult(METHOD_2).passed(null);
+ otherCaseResult.getOrCreateResult(METHOD_3).passed(null);
+
+ mResult.mergeFrom(otherResult);
+
+ assertEquals("Expected two results", 2, mResult.getResults().size());
+ assertTrue("Expected test result", mResult.getResults().contains(caseResult));
+ assertTrue("Expected test result", mResult.getResults().contains(caseResult2));
+ }
+
+ public void testMergeModule_mismatchedModuleId() throws Exception {
+
+ ModuleResult otherResult = new ModuleResult(ID_2);
+ try {
+ mResult.mergeFrom(otherResult);
+ fail("Expected IlleglArgumentException");
+ } catch (IllegalArgumentException expected) {}
+ }
+}
diff --git a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
index 3009ec4..b03e8c7 100644
--- a/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
+++ b/common/util/tests/src/com/android/compatibility/common/util/ResultHandlerTest.java
@@ -80,6 +80,7 @@
private static final String END_DISPLAY = "Fri Aug 20 15:13:04 PDT 2010";
private static final String REFERENCE_URL="http://android.com";
+ private static final String COMMAND_LINE_ARGS = "cts -m CtsMyModuleTestCases";
private static final String JOIN = "%s%s";
private static final String XML_BASE =
"<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" +
@@ -89,7 +90,7 @@
"suite_plan=\"%s\" suite_build_number=\"%s\" report_version=\"%s\" " +
"devices=\"%s\" host_name=\"%s\"" +
"os_name=\"%s\" os_version=\"%s\" os_arch=\"%s\" java_vendor=\"%s\"" +
- "java_version=\"%s\" reference_url=\"%s\">\n" +
+ "java_version=\"%s\" reference_url=\"%s\" command_line_args=\"%s\">\n" +
"%s%s%s" +
"</Result>";
private static final String XML_BUILD_INFO =
@@ -140,13 +141,13 @@
}
public void testSerialization() throws Exception {
- IInvocationResult result = new InvocationResult(resultDir);
+ IInvocationResult result = new InvocationResult();
result.setStartTime(START_MS);
result.setTestPlan(SUITE_PLAN);
result.addDeviceSerial(DEVICE_A);
result.addDeviceSerial(DEVICE_B);
- result.addBuildInfo(BUILD_ID, EXAMPLE_BUILD_ID);
- result.addBuildInfo(BUILD_PRODUCT, EXAMPLE_BUILD_PRODUCT);
+ result.addInvocationInfo(BUILD_ID, EXAMPLE_BUILD_ID);
+ result.addInvocationInfo(BUILD_PRODUCT, EXAMPLE_BUILD_PRODUCT);
IModuleResult moduleA = result.getOrCreateModule(ID_A);
ICaseResult moduleACase = moduleA.getOrCreateResult(CLASS_A);
ITestResult moduleATest1 = moduleACase.getOrCreateResult(METHOD_1);
@@ -170,7 +171,7 @@
// Serialize to file
ResultHandler.writeResults(SUITE_NAME, SUITE_VERSION, SUITE_PLAN, SUITE_BUILD,
- result, resultDir, START_MS, END_MS, REFERENCE_URL);
+ result, resultDir, START_MS, END_MS, REFERENCE_URL, COMMAND_LINE_ARGS);
// Parse the results and assert correctness
checkResult(ResultHandler.getResults(resultsDir), resultDir);
@@ -211,7 +212,7 @@
String output = String.format(XML_BASE, START_MS, END_MS, START_DISPLAY, END_DISPLAY,
SUITE_NAME, SUITE_VERSION, SUITE_PLAN, SUITE_BUILD, REPORT_VERSION, DEVICES,
hostName, OS_NAME, OS_VERSION, OS_ARCH, JAVA_VENDOR,
- JAVA_VERSION, REFERENCE_URL, buildInfo, summary, modules);
+ JAVA_VERSION, REFERENCE_URL, COMMAND_LINE_ARGS, buildInfo, summary, modules);
writer.write(output);
writer.flush();
@@ -227,13 +228,11 @@
private void checkResult(List<IInvocationResult> results, File resultDir) throws Exception {
assertEquals("Expected 1 result", 1, results.size());
IInvocationResult result = results.get(0);
- assertEquals("Incorrect result dir", resultDir.getAbsolutePath(),
- result.getResultDir().getAbsolutePath());
assertEquals("Expected 2 passes", 2, result.countResults(TestStatus.PASS));
assertEquals("Expected 1 failure", 1, result.countResults(TestStatus.FAIL));
assertEquals("Expected 1 not executed", 1, result.countResults(TestStatus.NOT_EXECUTED));
- Map<String, String> buildInfo = result.getBuildInfo();
+ Map<String, String> buildInfo = result.getInvocationInfo();
assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID));
assertEquals("Incorrect Build Product",
EXAMPLE_BUILD_PRODUCT, buildInfo.get(BUILD_PRODUCT));
diff --git a/hostsidetests/appsecurity/res/pkgsigverify/v1-only-pkcs7-cert-bag-first-cert-not-used.apk b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-pkcs7-cert-bag-first-cert-not-used.apk
new file mode 100644
index 0000000..0ebd01f
--- /dev/null
+++ b/hostsidetests/appsecurity/res/pkgsigverify/v1-only-pkcs7-cert-bag-first-cert-not-used.apk
Binary files differ
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
index 254dda8..6a47676 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/PkgInstallSignatureVerificationTest.java
@@ -340,6 +340,21 @@
assertInstallFailsWithError("v2-only-missing-classes.dex.apk", "code is missing");
}
+ public void testCorrectCertUsedFromPkcs7SignedDataCertsSet() throws Exception {
+ // Obtained by prepending the rsa-1024 certificate to the PKCS#7 SignedData certificates set
+ // of v1-only-with-rsa-pkcs1-sha1-2048.apk META-INF/CERT.RSA. The certs (in the order of
+ // appearance in the file) are thus: rsa-1024, rsa-2048. The package's signing cert is
+ // rsa-2048.
+ assertInstallSucceeds("v1-only-pkcs7-cert-bag-first-cert-not-used.apk");
+
+ // Check that rsa-1024 was not used as the previously installed package's signing cert.
+ assertInstallFailsWithError(
+ "v1-only-with-rsa-pkcs1-sha1-1024.apk", "signatures do not match");
+
+ // Check that rsa-2048 was used as the previously installed package's signing cert.
+ assertInstallSucceeds("v1-only-with-rsa-pkcs1-sha1-2048.apk");
+ }
+
private void assertInstallSucceeds(String apkFilenameInResources) throws Exception {
String installResult = installPackageFromResource(apkFilenameInResources);
if (installResult != null) {
diff --git a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk
index c71163d..18771de 100644
--- a/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk
+++ b/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp/CtsShimPrivUpgrade.apk
Binary files differ
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
index 391ef15..6def711 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/CreateAndManageUserTest.java
@@ -34,240 +34,241 @@
import java.lang.reflect.Field;
-/**
- * Test {@link DevicePolicyManager#createAndManageUser}.
- */
-public class CreateAndManageUserTest extends BaseDeviceOwnerTest {
-
- private static final String BROADCAST_EXTRA = "broadcastExtra";
- private static final String ACTION_EXTRA = "actionExtra";
- private static final String SERIAL_EXTRA = "serialExtra";
- private static final String PROFILE_OWNER_EXTRA = "profileOwnerExtra";
- private static final String SETUP_COMPLETE_EXTRA = "setupCompleteExtra";
- private static final int BROADCAST_TIMEOUT = 15_000;
- private static final int USER_SWITCH_DELAY = 10_000;
- private PackageManager mPackageManager;
- private ActivityManager mActivityManager;
- private volatile boolean mReceived;
- private volatile boolean mTestProfileOwnerWasUsed;
- private volatile boolean mSetupComplete;
- private UserHandle mUserHandle;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mPackageManager = mContext.getPackageManager();
- mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
- mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
- // Remove user in case of failed test.
- if (mUserHandle != null) {
- mDevicePolicyManager.removeUser(getWho(), mUserHandle);
- mUserHandle = null;
- }
- super.tearDown();
- }
-
- // This class is used by createAndManageUserTest as profile owner for the new user. When
- // enabled, it sends a broadcast to signal success.
- public static class TestProfileOwner extends DeviceAdminReceiver {
- @Override
- public void onEnabled(Context context, Intent intent) {
- if (intent.getBooleanExtra(BROADCAST_EXTRA, false)) {
- Intent i = new Intent(intent.getStringExtra(ACTION_EXTRA));
- UserManager userManager = (UserManager)
- context.getSystemService(Context.USER_SERVICE);
- long serial = intent.getLongExtra(SERIAL_EXTRA, 0);
- UserHandle handle = userManager.getUserForSerialNumber(serial);
- i.putExtra(PROFILE_OWNER_EXTRA, true);
- // find value of user_setup_complete on new user, and send the result back
- try {
- boolean setupComplete = (Settings.Secure.getInt(context.getContentResolver(),
- "user_setup_complete") == 1);
- i.putExtra(SETUP_COMPLETE_EXTRA, setupComplete);
- } catch (Settings.SettingNotFoundException e) {
- fail("Did not find settings user_setup_complete");
- }
-
- context.sendBroadcastAsUser(i, handle);
- }
- }
-
- public static ComponentName getComponentName() {
- return new ComponentName(CreateAndManageUserTest.class.getPackage().getName(),
- TestProfileOwner.class.getName());
- }
- }
-
- private void waitForBroadcastLocked() {
- // Wait for broadcast. Time is measured in a while loop because of spurious wakeups.
- final long initTime = System.currentTimeMillis();
- while (!mReceived) {
- try {
- wait(BROADCAST_TIMEOUT - (System.currentTimeMillis() - initTime));
- } catch (InterruptedException e) {
- fail("InterruptedException: " + e.getMessage());
- }
- if (!mReceived && System.currentTimeMillis() - initTime > BROADCAST_TIMEOUT) {
- fail("Timeout while waiting for broadcast after createAndManageUser.");
- }
- }
- }
-
- // This test will create a user that will get passed a bundle that we specify. The bundle will
- // contain an action and a serial (for user handle) to broadcast to notify the test that the
- // configuration was triggered.
- private void createAndManageUserTest(final int flags) {
- // This test sets a profile owner on the user, which requires the managed_users feature.
- if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)) {
- return;
- }
-
- final boolean expectedSetupComplete = (flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0;
- UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-
- UserHandle firstUser = Process.myUserHandle();
- final String testUserName = "TestUser_" + System.currentTimeMillis();
- String action = "com.android.cts.TEST_USER_ACTION";
- PersistableBundle bundle = new PersistableBundle();
- bundle.putBoolean(BROADCAST_EXTRA, true);
- bundle.putLong(SERIAL_EXTRA, userManager.getSerialNumberForUser(firstUser));
- bundle.putString(ACTION_EXTRA, action);
-
- mReceived = false;
- mTestProfileOwnerWasUsed = false;
- mSetupComplete = !expectedSetupComplete;
- BroadcastReceiver receiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mReceived = true;
- if (intent.getBooleanExtra(PROFILE_OWNER_EXTRA, false)) {
- mTestProfileOwnerWasUsed = true;
- }
- mSetupComplete = intent.getBooleanExtra(SETUP_COMPLETE_EXTRA,
- !expectedSetupComplete);
- synchronized (CreateAndManageUserTest.this) {
- CreateAndManageUserTest.this.notify();
- }
- }
- };
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(action);
- mContext.registerReceiver(receiver, filter);
-
- synchronized (this) {
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), testUserName,
- TestProfileOwner.getComponentName(), bundle, flags);
- assertNotNull(mUserHandle);
-
- mDevicePolicyManager.switchUser(getWho(), mUserHandle);
- try {
- wait(USER_SWITCH_DELAY);
- } catch (InterruptedException e) {
- fail("InterruptedException: " + e.getMessage());
- }
- mDevicePolicyManager.switchUser(getWho(), firstUser);
-
- waitForBroadcastLocked();
-
- assertTrue(mReceived);
- assertTrue(mTestProfileOwnerWasUsed);
- assertEquals(expectedSetupComplete, mSetupComplete);
-
- assertTrue(mDevicePolicyManager.removeUser(getWho(), mUserHandle));
-
- mUserHandle = null;
- }
-
- mContext.unregisterReceiver(receiver);
- }
-
- /**
- * Test creating an ephemeral user using the {@link DevicePolicyManager#createAndManageUser}
- * method.
- *
- * <p>The test creates a user by calling to {@link DevicePolicyManager#createAndManageUser}. It
- * doesn't remove the user afterwards, so its properties can be queried and tested by host-side
- * tests.
- * <p>The user's flags will be checked from the corresponding host-side test.
- */
- public void testCreateAndManageEphemeralUser() throws Exception {
- String testUserName = "TestUser_" + System.currentTimeMillis();
-
- // Use reflection to get the value of the hidden flag to make the new user ephemeral.
- Field field = DevicePolicyManager.class.getField("MAKE_USER_EPHEMERAL");
- int makeEphemeralFlag = field.getInt(null);
-
- // Do not assign return value to mUserHandle, so it is not removed in tearDown.
- mDevicePolicyManager.createAndManageUser(
- getWho(),
- testUserName,
- getWho(),
- null,
- makeEphemeralFlag);
- }
-
- /**
- * Test creating an ephemeral user using the {@link DevicePolicyManager#createAndManageUser}
- * method fails on systems without the split system user.
- *
- * <p>To be used by host-side test on systems without the split system user.
- */
- public void testCreateAndManageEphemeralUserFails() throws Exception {
- String testUserName = "TestUser_" + System.currentTimeMillis();
-
- // Use reflection to get the value of the hidden flag to make the new user ephemeral.
- Field field = DevicePolicyManager.class.getField("MAKE_USER_EPHEMERAL");
- int makeEphemeralFlag = field.getInt(null);
-
- try {
- mDevicePolicyManager.createAndManageUser(
- getWho(),
- testUserName,
- getWho(),
- null,
- makeEphemeralFlag);
- } catch (IllegalArgumentException e) {
- // Success, the expected exception was thrown.
- return;
- }
- fail("createAndManageUser should have thrown IllegalArgumentException");
- }
-
- public void testCreateAndManageUser_SkipSetupWizard() {
- createAndManageUserTest(DevicePolicyManager.SKIP_SETUP_WIZARD);
- }
-
- public void testCreateAndManageUser_DontSkipSetupWizard() {
- if (!mActivityManager.isRunningInTestHarness()) {
- // In test harness, the setup wizard will be disabled by default, so this test is always
- // failing.
- createAndManageUserTest(0);
- }
- }
-
- // createAndManageUser should circumvent the DISALLOW_ADD_USER restriction
- public void testCreateAndManageUser_AddRestrictionSet() {
- mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
-
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
- null, 0);
- assertNotNull(mUserHandle);
- }
-
- public void testCreateAndManageUser_RemoveRestrictionSet() {
- mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
-
- mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
- null, 0);
- assertNotNull(mUserHandle);
-
- boolean removed = mDevicePolicyManager.removeUser(getWho(), mUserHandle);
- assertFalse(removed);
- }
-}
+// Disabled due to b/29072728
+///**
+// * Test {@link DevicePolicyManager#createAndManageUser}.
+// */
+//public class CreateAndManageUserTest extends BaseDeviceOwnerTest {
+//
+// private static final String BROADCAST_EXTRA = "broadcastExtra";
+// private static final String ACTION_EXTRA = "actionExtra";
+// private static final String SERIAL_EXTRA = "serialExtra";
+// private static final String PROFILE_OWNER_EXTRA = "profileOwnerExtra";
+// private static final String SETUP_COMPLETE_EXTRA = "setupCompleteExtra";
+// private static final int BROADCAST_TIMEOUT = 15_000;
+// private static final int USER_SWITCH_DELAY = 10_000;
+// private PackageManager mPackageManager;
+// private ActivityManager mActivityManager;
+// private volatile boolean mReceived;
+// private volatile boolean mTestProfileOwnerWasUsed;
+// private volatile boolean mSetupComplete;
+// private UserHandle mUserHandle;
+//
+// @Override
+// protected void setUp() throws Exception {
+// super.setUp();
+// mPackageManager = mContext.getPackageManager();
+// mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+// }
+//
+// @Override
+// protected void tearDown() throws Exception {
+// mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
+// mDevicePolicyManager.clearUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
+// // Remove user in case of failed test.
+// if (mUserHandle != null) {
+// mDevicePolicyManager.removeUser(getWho(), mUserHandle);
+// mUserHandle = null;
+// }
+// super.tearDown();
+// }
+//
+// // This class is used by createAndManageUserTest as profile owner for the new user. When
+// // enabled, it sends a broadcast to signal success.
+// public static class TestProfileOwner extends DeviceAdminReceiver {
+// @Override
+// public void onEnabled(Context context, Intent intent) {
+// if (intent.getBooleanExtra(BROADCAST_EXTRA, false)) {
+// Intent i = new Intent(intent.getStringExtra(ACTION_EXTRA));
+// UserManager userManager = (UserManager)
+// context.getSystemService(Context.USER_SERVICE);
+// long serial = intent.getLongExtra(SERIAL_EXTRA, 0);
+// UserHandle handle = userManager.getUserForSerialNumber(serial);
+// i.putExtra(PROFILE_OWNER_EXTRA, true);
+// // find value of user_setup_complete on new user, and send the result back
+// try {
+// boolean setupComplete = (Settings.Secure.getInt(context.getContentResolver(),
+// "user_setup_complete") == 1);
+// i.putExtra(SETUP_COMPLETE_EXTRA, setupComplete);
+// } catch (Settings.SettingNotFoundException e) {
+// fail("Did not find settings user_setup_complete");
+// }
+//
+// context.sendBroadcastAsUser(i, handle);
+// }
+// }
+//
+// public static ComponentName getComponentName() {
+// return new ComponentName(CreateAndManageUserTest.class.getPackage().getName(),
+// TestProfileOwner.class.getName());
+// }
+// }
+//
+// private void waitForBroadcastLocked() {
+// // Wait for broadcast. Time is measured in a while loop because of spurious wakeups.
+// final long initTime = System.currentTimeMillis();
+// while (!mReceived) {
+// try {
+// wait(BROADCAST_TIMEOUT - (System.currentTimeMillis() - initTime));
+// } catch (InterruptedException e) {
+// fail("InterruptedException: " + e.getMessage());
+// }
+// if (!mReceived && System.currentTimeMillis() - initTime > BROADCAST_TIMEOUT) {
+// fail("Timeout while waiting for broadcast after createAndManageUser.");
+// }
+// }
+// }
+//
+// // This test will create a user that will get passed a bundle that we specify. The bundle will
+// // contain an action and a serial (for user handle) to broadcast to notify the test that the
+// // configuration was triggered.
+// private void createAndManageUserTest(final int flags) {
+// // This test sets a profile owner on the user, which requires the managed_users feature.
+// if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)) {
+// return;
+// }
+//
+// final boolean expectedSetupComplete = (flags & DevicePolicyManager.SKIP_SETUP_WIZARD) != 0;
+// UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+//
+// UserHandle firstUser = Process.myUserHandle();
+// final String testUserName = "TestUser_" + System.currentTimeMillis();
+// String action = "com.android.cts.TEST_USER_ACTION";
+// PersistableBundle bundle = new PersistableBundle();
+// bundle.putBoolean(BROADCAST_EXTRA, true);
+// bundle.putLong(SERIAL_EXTRA, userManager.getSerialNumberForUser(firstUser));
+// bundle.putString(ACTION_EXTRA, action);
+//
+// mReceived = false;
+// mTestProfileOwnerWasUsed = false;
+// mSetupComplete = !expectedSetupComplete;
+// BroadcastReceiver receiver = new BroadcastReceiver() {
+// @Override
+// public void onReceive(Context context, Intent intent) {
+// mReceived = true;
+// if (intent.getBooleanExtra(PROFILE_OWNER_EXTRA, false)) {
+// mTestProfileOwnerWasUsed = true;
+// }
+// mSetupComplete = intent.getBooleanExtra(SETUP_COMPLETE_EXTRA,
+// !expectedSetupComplete);
+// synchronized (CreateAndManageUserTest.this) {
+// CreateAndManageUserTest.this.notify();
+// }
+// }
+// };
+//
+// IntentFilter filter = new IntentFilter();
+// filter.addAction(action);
+// mContext.registerReceiver(receiver, filter);
+//
+// synchronized (this) {
+// mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), testUserName,
+// TestProfileOwner.getComponentName(), bundle, flags);
+// assertNotNull(mUserHandle);
+//
+// mDevicePolicyManager.switchUser(getWho(), mUserHandle);
+// try {
+// wait(USER_SWITCH_DELAY);
+// } catch (InterruptedException e) {
+// fail("InterruptedException: " + e.getMessage());
+// }
+// mDevicePolicyManager.switchUser(getWho(), firstUser);
+//
+// waitForBroadcastLocked();
+//
+// assertTrue(mReceived);
+// assertTrue(mTestProfileOwnerWasUsed);
+// assertEquals(expectedSetupComplete, mSetupComplete);
+//
+// assertTrue(mDevicePolicyManager.removeUser(getWho(), mUserHandle));
+//
+// mUserHandle = null;
+// }
+//
+// mContext.unregisterReceiver(receiver);
+// }
+//
+// /**
+// * Test creating an ephemeral user using the {@link DevicePolicyManager#createAndManageUser}
+// * method.
+// *
+// * <p>The test creates a user by calling to {@link DevicePolicyManager#createAndManageUser}. It
+// * doesn't remove the user afterwards, so its properties can be queried and tested by host-side
+// * tests.
+// * <p>The user's flags will be checked from the corresponding host-side test.
+// */
+// public void testCreateAndManageEphemeralUser() throws Exception {
+// String testUserName = "TestUser_" + System.currentTimeMillis();
+//
+// // Use reflection to get the value of the hidden flag to make the new user ephemeral.
+// Field field = DevicePolicyManager.class.getField("MAKE_USER_EPHEMERAL");
+// int makeEphemeralFlag = field.getInt(null);
+//
+// // Do not assign return value to mUserHandle, so it is not removed in tearDown.
+// mDevicePolicyManager.createAndManageUser(
+// getWho(),
+// testUserName,
+// getWho(),
+// null,
+// makeEphemeralFlag);
+// }
+//
+// /**
+// * Test creating an ephemeral user using the {@link DevicePolicyManager#createAndManageUser}
+// * method fails on systems without the split system user.
+// *
+// * <p>To be used by host-side test on systems without the split system user.
+// */
+// public void testCreateAndManageEphemeralUserFails() throws Exception {
+// String testUserName = "TestUser_" + System.currentTimeMillis();
+//
+// // Use reflection to get the value of the hidden flag to make the new user ephemeral.
+// Field field = DevicePolicyManager.class.getField("MAKE_USER_EPHEMERAL");
+// int makeEphemeralFlag = field.getInt(null);
+//
+// try {
+// mDevicePolicyManager.createAndManageUser(
+// getWho(),
+// testUserName,
+// getWho(),
+// null,
+// makeEphemeralFlag);
+// } catch (IllegalArgumentException e) {
+// // Success, the expected exception was thrown.
+// return;
+// }
+// fail("createAndManageUser should have thrown IllegalArgumentException");
+// }
+//
+// public void testCreateAndManageUser_SkipSetupWizard() {
+// createAndManageUserTest(DevicePolicyManager.SKIP_SETUP_WIZARD);
+// }
+//
+// public void testCreateAndManageUser_DontSkipSetupWizard() {
+// if (!mActivityManager.isRunningInTestHarness()) {
+// // In test harness, the setup wizard will be disabled by default, so this test is always
+// // failing.
+// createAndManageUserTest(0);
+// }
+// }
+//
+// // createAndManageUser should circumvent the DISALLOW_ADD_USER restriction
+// public void testCreateAndManageUser_AddRestrictionSet() {
+// mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_ADD_USER);
+//
+// mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
+// null, 0);
+// assertNotNull(mUserHandle);
+// }
+//
+// public void testCreateAndManageUser_RemoveRestrictionSet() {
+// mDevicePolicyManager.addUserRestriction(getWho(), UserManager.DISALLOW_REMOVE_USER);
+//
+// mUserHandle = mDevicePolicyManager.createAndManageUser(getWho(), "Test User", getWho(),
+// null, 0);
+// assertNotNull(mUserHandle);
+//
+// boolean removed = mDevicePolicyManager.removeUser(getWho(), mUserHandle);
+// assertFalse(removed);
+// }
+//}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index 39d7f22..c7a84cf 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -215,75 +215,76 @@
assertTrue("User must be ephemeral", 0 != (getUserFlags(userId) & FLAG_EPHEMERAL));
}
- /**
- * Test creating an epehemeral user using the DevicePolicyManager's createAndManageUser method.
- */
- public void testCreateAndManageEphemeralUser() throws Exception {
- if (!mHasEphemeralUserFeature) {
- return;
- }
-
- ArrayList<Integer> originalUsers = listUsers();
- executeDeviceTestMethod(".CreateAndManageUserTest", "testCreateAndManageEphemeralUser");
-
- ArrayList<Integer> newUsers = listUsers();
-
- // Check that exactly one new user was created.
- assertEquals(
- "One user should have been created", originalUsers.size() + 1, newUsers.size());
-
- // Get the id of the newly created user.
- int newUserId = -1;
- for (int userId : newUsers) {
- if (!originalUsers.contains(userId)) {
- newUserId = userId;
- break;
- }
- }
-
- // Get the flags of the new user and check the user is ephemeral.
- int flags = getUserFlags(newUserId);
- assertEquals("Ephemeral flag must be set", FLAG_EPHEMERAL, flags & FLAG_EPHEMERAL);
- }
-
- /**
- * Test that creating an epehemeral user using the DevicePolicyManager's createAndManageUser
- * method fails on systems without the split system user.
- */
- public void testCreateAndManageEphemeralUserFailsWithoutSplitSystemUser() throws Exception {
- if (mHasDisabledEphemeralUserFeature) {
- executeDeviceTestMethod(
- ".CreateAndManageUserTest", "testCreateAndManageEphemeralUserFails");
- }
- }
-
- public void testCreateAndManageUser_SkipSetupWizard() throws Exception {
- if (mHasCreateAndManageUserFeature) {
- executeDeviceTestMethod(".CreateAndManageUserTest",
- "testCreateAndManageUser_SkipSetupWizard");
- }
- }
-
- public void testCreateAndManageUser_DontSkipSetupWizard() throws Exception {
- if (mHasCreateAndManageUserFeature) {
- executeDeviceTestMethod(".CreateAndManageUserTest",
- "testCreateAndManageUser_DontSkipSetupWizard");
- }
- }
-
- public void testCreateAndManageUser_AddRestrictionSet() throws Exception {
- if (mHasCreateAndManageUserFeature) {
- executeDeviceTestMethod(".CreateAndManageUserTest",
- "testCreateAndManageUser_AddRestrictionSet");
- }
- }
-
- public void testCreateAndManageUser_RemoveRestrictionSet() throws Exception {
- if (mHasCreateAndManageUserFeature) {
- executeDeviceTestMethod(".CreateAndManageUserTest",
- "testCreateAndManageUser_RemoveRestrictionSet");
- }
- }
+// Disabled due to b/29072728
+// /**
+// * Test creating an epehemeral user using the DevicePolicyManager's createAndManageUser method.
+// */
+// public void testCreateAndManageEphemeralUser() throws Exception {
+// if (!mHasEphemeralUserFeature) {
+// return;
+// }
+//
+// ArrayList<Integer> originalUsers = listUsers();
+// executeDeviceTestMethod(".CreateAndManageUserTest", "testCreateAndManageEphemeralUser");
+//
+// ArrayList<Integer> newUsers = listUsers();
+//
+// // Check that exactly one new user was created.
+// assertEquals(
+// "One user should have been created", originalUsers.size() + 1, newUsers.size());
+//
+// // Get the id of the newly created user.
+// int newUserId = -1;
+// for (int userId : newUsers) {
+// if (!originalUsers.contains(userId)) {
+// newUserId = userId;
+// break;
+// }
+// }
+//
+// // Get the flags of the new user and check the user is ephemeral.
+// int flags = getUserFlags(newUserId);
+// assertEquals("Ephemeral flag must be set", FLAG_EPHEMERAL, flags & FLAG_EPHEMERAL);
+// }
+//
+// /**
+// * Test that creating an epehemeral user using the DevicePolicyManager's createAndManageUser
+// * method fails on systems without the split system user.
+// */
+// public void testCreateAndManageEphemeralUserFailsWithoutSplitSystemUser() throws Exception {
+// if (mHasDisabledEphemeralUserFeature) {
+// executeDeviceTestMethod(
+// ".CreateAndManageUserTest", "testCreateAndManageEphemeralUserFails");
+// }
+// }
+//
+// public void testCreateAndManageUser_SkipSetupWizard() throws Exception {
+// if (mHasCreateAndManageUserFeature) {
+// executeDeviceTestMethod(".CreateAndManageUserTest",
+// "testCreateAndManageUser_SkipSetupWizard");
+// }
+// }
+//
+// public void testCreateAndManageUser_DontSkipSetupWizard() throws Exception {
+// if (mHasCreateAndManageUserFeature) {
+// executeDeviceTestMethod(".CreateAndManageUserTest",
+// "testCreateAndManageUser_DontSkipSetupWizard");
+// }
+// }
+//
+// public void testCreateAndManageUser_AddRestrictionSet() throws Exception {
+// if (mHasCreateAndManageUserFeature) {
+// executeDeviceTestMethod(".CreateAndManageUserTest",
+// "testCreateAndManageUser_AddRestrictionSet");
+// }
+// }
+//
+// public void testCreateAndManageUser_RemoveRestrictionSet() throws Exception {
+// if (mHasCreateAndManageUserFeature) {
+// executeDeviceTestMethod(".CreateAndManageUserTest",
+// "testCreateAndManageUser_RemoveRestrictionSet");
+// }
+// }
public void testSecurityLoggingWithTwoUsers() throws Exception {
if (!mHasFeature || getMaxNumberOfUsersSupported() < 2) {
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
index 13ce6ce..ba56665 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractAppIdleTestCase.java
@@ -16,6 +16,8 @@
package com.android.cts.net.hostside;
+import android.util.Log;
+
/**
* Base class for metered and non-metered tests on idle apps.
*/
@@ -25,6 +27,8 @@
protected final void setUp() throws Exception {
super.setUp();
+ if (!isSupported()) return;
+
// Set initial state.
setUpMeteredNetwork();
removePowerSaveModeWhitelist(TEST_APP2_PKG);
@@ -38,6 +42,8 @@
protected final void tearDown() throws Exception {
super.tearDown();
+ if (!isSupported()) return;
+
try {
tearDownMeteredNetwork();
} finally {
@@ -46,6 +52,16 @@
}
}
+ @Override
+ protected boolean isSupported() throws Exception {
+ boolean supported = isDozeModeEnabled();
+ if (!supported) {
+ Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ + "() because device does not support Doze Mode");
+ }
+ return supported;
+ }
+
/**
* Sets the initial (non) metered network state.
*
@@ -63,6 +79,8 @@
}
public void testBackgroundNetworkAccess_enabled() throws Exception {
+ if (!isSupported()) return;
+
setAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -92,6 +110,8 @@
}
public void testBackgroundNetworkAccess_whitelisted() throws Exception {
+ if (!isSupported()) return;
+
setAppIdle(true);
assertBackgroundNetworkAccess(false);
@@ -111,6 +131,8 @@
}
public void testBackgroundNetworkAccess_disabled() throws Exception {
+ if (!isSupported()) return;
+
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
index 2acc670..c1c91da 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractBatterySaverModeTestCase.java
@@ -16,6 +16,8 @@
package com.android.cts.net.hostside;
+import android.util.Log;
+
/**
* Base class for metered and non-metered Battery Saver Mode tests.
*/
@@ -25,6 +27,8 @@
protected final void setUp() throws Exception {
super.setUp();
+ if (!isSupported()) return;
+
// Set initial state.
setUpMeteredNetwork();
removePowerSaveModeWhitelist(TEST_APP2_PKG);
@@ -37,6 +41,8 @@
protected final void tearDown() throws Exception {
super.tearDown();
+ if (!isSupported()) return;
+
try {
tearDownMeteredNetwork();
} finally {
@@ -44,6 +50,16 @@
}
}
+ @Override
+ protected boolean isSupported() throws Exception {
+ boolean supported = isDozeModeEnabled();
+ if (!supported) {
+ Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ + "() because device does not support Doze Mode");
+ }
+ return supported;
+ }
+
/**
* Sets the initial (non) metered network state.
*
@@ -61,6 +77,8 @@
}
public void testBackgroundNetworkAccess_enabled() throws Exception {
+ if (!isSupported()) return;
+
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
@@ -87,6 +105,8 @@
}
public void testBackgroundNetworkAccess_whitelisted() throws Exception {
+ if (!isSupported()) return;
+
setBatterySaverMode(true);
assertBackgroundNetworkAccess(false);
@@ -101,6 +121,8 @@
}
public void testBackgroundNetworkAccess_disabled() throws Exception {
+ if (!isSupported()) return;
+
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
index e0ba76b8..b89cf93 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractDozeModeTestCase.java
@@ -17,6 +17,7 @@
package com.android.cts.net.hostside;
import android.os.SystemClock;
+import android.util.Log;
/**
* Base class for metered and non-metered Doze Mode tests.
@@ -27,6 +28,8 @@
protected final void setUp() throws Exception {
super.setUp();
+ if (!isSupported()) return;
+
// Set initial state.
setUpMeteredNetwork();
removePowerSaveModeWhitelist(TEST_APP2_PKG);
@@ -39,6 +42,8 @@
protected final void tearDown() throws Exception {
super.tearDown();
+ if (!isSupported()) return;
+
try {
tearDownMeteredNetwork();
} finally {
@@ -46,6 +51,16 @@
}
}
+ @Override
+ protected boolean isSupported() throws Exception {
+ boolean supported = isDozeModeEnabled();
+ if (!supported) {
+ Log.i(TAG, "Skipping " + getClass() + "." + getName()
+ + "() because device does not support Doze Mode");
+ }
+ return supported;
+ }
+
/**
* Sets the initial (non) metered network state.
*
@@ -63,6 +78,8 @@
}
public void testBackgroundNetworkAccess_enabled() throws Exception {
+ if (!isSupported()) return;
+
setDozeMode(true);
assertBackgroundNetworkAccess(false);
@@ -81,6 +98,8 @@
}
public void testBackgroundNetworkAccess_whitelisted() throws Exception {
+ if (!isSupported()) return;
+
setDozeMode(true);
assertBackgroundNetworkAccess(false);
@@ -95,6 +114,8 @@
}
public void testBackgroundNetworkAccess_disabled() throws Exception {
+ if (!isSupported()) return;
+
assertBackgroundNetworkAccess(true);
assertsForegroundAlwaysHasNetworkAccess();
@@ -103,6 +124,8 @@
public void testBackgroundNetworkAccess_enabledButWhitelistedOnNotificationAction()
throws Exception {
+ if (!isSupported()) return;
+
setPendingIntentWhitelistDuration(NETWORK_TIMEOUT_MS);
try {
registerNotificationListenerService();
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
index ba383a8..439fbbe 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/AbstractRestrictBackgroundNetworkTestCase.java
@@ -188,6 +188,22 @@
}
/**
+ * Whether this device suport this type of test.
+ *
+ * <p>Should be overridden when necessary, and explicitly used before each test. Example:
+ *
+ * <pre><code>
+ * public void testSomething() {
+ * if (!isSupported()) return;
+ * </code></pre>
+ *
+ * @return {@code true} by default.
+ */
+ protected boolean isSupported() throws Exception {
+ return true;
+ }
+
+ /**
* Asserts that an app always have access while on foreground or running a foreground service.
*
* <p>This method will launch an activity and a foreground service to make the assertion, but
@@ -269,8 +285,6 @@
private void assertNetworkAccess(boolean expectAvailable) throws Exception {
final Intent intent = new Intent(ACTION_CHECK_NETWORK);
- // When the network info state change, it's possible the app still get the previous value,
- // so we need to retry a couple times.
final int maxTries = 5;
String resultData = null;
for (int i = 1; i <= maxTries; i++) {
@@ -287,8 +301,14 @@
final String networkInfo = parts[4];
if (expectAvailable) {
- assertTrue("should be connected: " + connectionCheckDetails
- + " (network info: " + networkInfo + ")", connected);
+ if (!connected) {
+ // Since it's establishing a connection to an external site, it could be flaky.
+ Log.w(TAG, "Failed to connect to an external site on attempt #" + i +
+ " (error: " + connectionCheckDetails + ", NetworkInfo: " + networkInfo
+ + "); sleeping " + NETWORK_TIMEOUT_MS + "ms before trying again");
+ SystemClock.sleep(NETWORK_TIMEOUT_MS);
+ continue;
+ }
if (state != State.CONNECTED) {
Log.d(TAG, "State (" + state + ") not set to CONNECTED on attempt #" + i
+ "; sleeping 1s before trying again");
@@ -303,6 +323,8 @@
assertFalse("should not be connected: " + connectionCheckDetails
+ " (network info: " + networkInfo + ")", connected);
if (state != State.DISCONNECTED) {
+ // When the network info state change, it's possible the app still get the
+ // previous value, so we need to retry a couple times.
Log.d(TAG, "State (" + state + ") not set to DISCONNECTED on attempt #" + i
+ "; sleeping 1s before trying again");
SystemClock.sleep(SECOND_IN_MS);
@@ -313,7 +335,8 @@
}
}
}
- fail("Invalid state after " + maxTries + " attempts. Last data: " + resultData);
+ fail("Invalid state for expectAvailable=" + expectAvailable + " after " + maxTries
+ + " attempts. Last data: " + resultData);
}
protected String executeShellCommand(String command) throws Exception {
@@ -591,6 +614,9 @@
}
protected void setDozeMode(boolean enabled) throws Exception {
+ // Sanity check, since tests should check beforehand....
+ assertTrue("Device does not support Doze Mode", isDozeModeEnabled());
+
Log.i(TAG, "Setting Doze Mode to " + enabled);
if (enabled) {
turnBatteryOff();
@@ -609,6 +635,11 @@
assertDelayedShellCommand("dumpsys deviceidle get deep", enabled ? "IDLE" : "ACTIVE");
}
+ protected boolean isDozeModeEnabled() throws Exception {
+ final String result = executeShellCommand("cmd deviceidle enabled deep").trim();
+ return result.equals("1");
+ }
+
protected void setAppIdle(boolean enabled) throws Exception {
Log.i(TAG, "Setting app idle to " + enabled);
executeSilentShellCommand("am set-inactive " + TEST_APP2_PKG + " " + enabled );
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
index 1895156..3e6bd33 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/DataSaverModeTest.java
@@ -30,6 +30,8 @@
public void setUp() throws Exception {
super.setUp();
+ if (!isSupported()) return;
+
// Set initial state.
setMeteredNetwork();
setRestrictBackground(false);
@@ -44,6 +46,8 @@
protected void tearDown() throws Exception {
super.tearDown();
+ if (!isSupported()) return;
+
try {
resetMeteredNetwork();
} finally {
@@ -52,6 +56,8 @@
}
public void testGetRestrictBackgroundStatus_disabled() throws Exception {
+ if (!isSupported()) return;
+
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_DISABLED);
// Sanity check: make sure status is always disabled, never whitelisted
@@ -64,6 +70,8 @@
}
public void testGetRestrictBackgroundStatus_whitelisted() throws Exception {
+ if (!isSupported()) return;
+
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(1);
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
@@ -81,6 +89,8 @@
}
public void testGetRestrictBackgroundStatus_enabled() throws Exception {
+ if (!isSupported()) return;
+
setRestrictBackground(true);
assertRestrictBackgroundChangedReceived(1);
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
@@ -108,6 +118,8 @@
}
public void testGetRestrictBackgroundStatus_blacklisted() throws Exception {
+ if (!isSupported()) return;
+
addRestrictBackgroundBlacklist(mUid);
assertRestrictBackgroundChangedReceived(1);
assertDataSaverStatusOnBackground(RESTRICT_BACKGROUND_STATUS_ENABLED);
@@ -136,6 +148,8 @@
}
public void testGetRestrictBackgroundStatus_requiredWhitelistedPackages() throws Exception {
+ if (!isSupported()) return;
+
final StringBuilder error = new StringBuilder();
for (String packageName : REQUIRED_WHITELISTED_PACKAGES) {
int uid = -1;
diff --git a/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java b/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
index c97a0f9..af52eee 100644
--- a/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
+++ b/hostsidetests/net/app/src/com/android/cts/net/hostside/MixedModesTest.java
@@ -32,6 +32,8 @@
public void setUp() throws Exception {
super.setUp();
+ if (!isSupported()) return;
+
// Set initial state.
removeRestrictBackgroundWhitelist(mUid);
removeRestrictBackgroundBlacklist(mUid);
@@ -44,6 +46,8 @@
protected void tearDown() throws Exception {
super.tearDown();
+ if (!isSupported()) return;
+
try {
setRestrictBackground(false);
} finally {
@@ -55,6 +59,14 @@
* Tests all DS ON and BS ON scenarios from network-policy-restrictions.md on metered networks.
*/
public void testDataAndBatterySaverModes_meteredNetwork() throws Exception {
+ if (!isSupported()) return;
+
+ if (!isDozeModeEnabled()) {
+ Log.w(TAG, "testDataAndBatterySaverModes_meteredNetwork() skipped because "
+ + "device does not support Doze Mode");
+ return;
+ }
+
Log.i(TAG, "testDataAndBatterySaverModes_meteredNetwork() tests");
setMeteredNetwork();
@@ -119,6 +131,14 @@
* networks.
*/
public void testDataAndBatterySaverModes_nonMeteredNetwork() throws Exception {
+ if (!isSupported()) return;
+
+ if (!isDozeModeEnabled()) {
+ Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because "
+ + "device does not support Doze Mode");
+ return;
+ }
+
if (mCm.isActiveNetworkMetered()) {
Log.w(TAG, "testDataAndBatterySaverModes_nonMeteredNetwork() skipped because network"
+ " is metered");
diff --git a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
index c741b12..7d5f817 100644
--- a/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
+++ b/hostsidetests/net/src/com/android/cts/net/HostsideRestrictBackgroundNetworkTests.java
@@ -101,6 +101,12 @@
}
public void testBatterySaverMode_reinstall() throws Exception {
+ if (!isDozeModeEnabled()) {
+ Log.w(TAG, "testBatterySaverMode_reinstall() skipped because device does not support "
+ + "Doze Mode");
+ return;
+ }
+
addPowerSaveModeWhitelist(TEST_APP2_PKG);
uninstallPackage(TEST_APP2_PKG, true);
@@ -287,4 +293,9 @@
runCommand("dumpsys deviceidle whitelist +" + packageName);
assertPowerSaveModeWhitelist(packageName, true); // Sanity check
}
+
+ protected boolean isDozeModeEnabled() throws Exception {
+ final String result = runCommand("cmd deviceidle enabled deep").trim();
+ return result.equals("1");
+ }
}
diff --git a/hostsidetests/numberblocking/src/com/android/cts/numberblocking/hostside/NumberBlockingTest.java b/hostsidetests/numberblocking/src/com/android/cts/numberblocking/hostside/NumberBlockingTest.java
index eae6d86..11455a0 100644
--- a/hostsidetests/numberblocking/src/com/android/cts/numberblocking/hostside/NumberBlockingTest.java
+++ b/hostsidetests/numberblocking/src/com/android/cts/numberblocking/hostside/NumberBlockingTest.java
@@ -45,18 +45,25 @@
private static final String NUMBER_BLOCKING_APP_TEST_CLASS_NAME = "NumberBlockingAppTest";
private static final String TEST_APP_CONNECTION_SERVICE_NAME = "DummyConnectionService";
private static final String SECONDARY_USER_NAME = "NumberBlockingTest SecondaryUser";
+ private static final String FEATURE_TELEPHONY = "android.hardware.telephony";
+ private static final String FEATURE_CONNECTION_SERVICE = "android.software.connectionservice";
private int mSecondaryUserId;
private int mPrimaryUserSerialNumber;
private int mSecondaryUserSerialNumber;
private IBuildInfo mCtsBuild;
+ private boolean mHasFeature;
@Override
protected void setUp() throws Exception {
super.setUp();
- if (!getDevice().isMultiUserSupported()) {
+ mHasFeature = getDevice().isMultiUserSupported()
+ && getDevice().hasFeature(FEATURE_TELEPHONY)
+ && getDevice().hasFeature(FEATURE_CONNECTION_SERVICE);
+
+ if (!mHasFeature) {
return;
}
@@ -70,7 +77,7 @@
@Override
protected void tearDown() throws Exception {
- if (getDevice().isMultiUserSupported()) {
+ if (mHasFeature) {
getDevice().removeUser(mSecondaryUserId);
}
@@ -83,7 +90,9 @@
}
public void testNumberBlocking() throws Exception {
- if (!getDevice().isMultiUserSupported()) {
+ if (!mHasFeature) {
+ LogUtil.CLog.logAndDisplay(Log.LogLevel.INFO,
+ "Skipping number blocking test as the feature is not supported.");
return;
}
diff --git a/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java b/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
index 808899a..5730ee0 100644
--- a/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
+++ b/hostsidetests/sample/src/android/sample/cts/SampleHostResultTest.java
@@ -44,6 +44,11 @@
private static final String TAG = SampleHostResultTest.class.getSimpleName();
/**
+ * Name of the report log to store test metrics.
+ */
+ private static final String REPORT_LOG_NAME = "SampleHostTestMetrics";
+
+ /**
* The number of times to repeat the test.
*/
private static final int REPEAT = 5;
@@ -132,15 +137,14 @@
// Compute the stats.
Stat.StatResult stat = Stat.getStat(result);
// Get the report for this test and add the results to record.
- String reportLogName = "SampleHostTestMetrics";
String streamName = "test_transfer_time_metrics";
MetricsReportLog report = new MetricsReportLog(mDevice.getSerialNumber(), mAbi.getName(),
String.format("%s#testTransferTime", getClass().getCanonicalName()),
- reportLogName, streamName);
+ REPORT_LOG_NAME, streamName);
report.addValues("times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
report.addValue("min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
report.addValue("max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
- // Every report must have a summary,
+ // Set a summary.
report.setSummary("average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
// Send the report to Tradefed.
report.submit();
diff --git a/tests/tests/draganddrop/Android.mk b/hostsidetests/services/windowmanager/Android.mk
similarity index 62%
rename from tests/tests/draganddrop/Android.mk
rename to hostsidetests/services/windowmanager/Android.mk
index 5042624..eeac27b 100644
--- a/tests/tests/draganddrop/Android.mk
+++ b/hostsidetests/services/windowmanager/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (C) 2016 The Android Open Source Project
+# Copyright (C) 2015 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.
@@ -12,30 +12,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-# Don't include this package in any target
LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
+# Must match the package name in OldCtsTestCaseList.mk
+LOCAL_MODULE := CtsDragAndDropHostTestCases
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator android-support-test
+LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+
+LOCAL_CTS_TEST_PACKAGE := android.wm.cts
+
+LOCAL_CTS_MODULE_CONFIG := $(LOCAL_PATH)/Old$(CTS_MODULE_TEST_CONFIG)
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_PACKAGE_NAME := CtsDragAndDropTestCases
+include $(BUILD_CTS_HOST_JAVA_LIBRARY)
-LOCAL_SDK_VERSION := test_current
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
+# Build the test APKs using their own makefiles
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/tests/draganddrop/AndroidTest.xml b/hostsidetests/services/windowmanager/AndroidTest.xml
similarity index 63%
rename from tests/tests/draganddrop/AndroidTest.xml
rename to hostsidetests/services/windowmanager/AndroidTest.xml
index ef2f491..5e305cf 100644
--- a/tests/tests/draganddrop/AndroidTest.xml
+++ b/hostsidetests/services/windowmanager/AndroidTest.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
+<!-- Copyright (C) 2015 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.
@@ -13,15 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<configuration description="Config for the CTS Drag and Drop tests">
+<configuration description="Config for CTS drag and drop host test cases">
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.ApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsDragSourceApp.apk" />
- <option name="test-file-name" value="CtsDropTargetApp.apk" />
- <option name="test-file-name" value="CtsDragAndDropTestCases.apk" />
+ <option name="test-file-name" value="CtsDragAndDropSourceApp.apk" />
+ <option name="test-file-name" value="CtsDragAndDropTargetApp.apk" />
</target_preparer>
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.dnd.cts" />
+ <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
+ <option name="jar" value="CtsDragAndDropHostTestCases.jar" />
</test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/tests/tests/draganddrop/droptarget/res/values/strings.xml b/hostsidetests/services/windowmanager/OldAndroidTest.xml
similarity index 61%
rename from tests/tests/draganddrop/droptarget/res/values/strings.xml
rename to hostsidetests/services/windowmanager/OldAndroidTest.xml
index ea0cc34..844bca3 100644
--- a/tests/tests/draganddrop/droptarget/res/values/strings.xml
+++ b/hostsidetests/services/windowmanager/OldAndroidTest.xml
@@ -13,7 +13,9 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
-<resources>
- <string name="not_available_label">N/A</string>
-</resources>
+<configuration description="CTS package preparer for install/uninstall of the apk used as a test operation target">
+ <include name="common-config" />
+ <!-- This will tell tradefed to install the test apk. -->
+ <option name="cts-apk-installer:test-file-name" value="CtsDragAndDropSourceApp.apk" />
+ <option name="cts-apk-installer:test-file-name" value="CtsDragAndDropTargetApp.apk" />
+</configuration>
diff --git a/tests/tests/draganddrop/dragsource/Android.mk b/hostsidetests/services/windowmanager/dndsourceapp/Android.mk
similarity index 75%
rename from tests/tests/draganddrop/dragsource/Android.mk
rename to hostsidetests/services/windowmanager/dndsourceapp/Android.mk
index 066759d..1ec751c 100644
--- a/tests/tests/draganddrop/dragsource/Android.mk
+++ b/hostsidetests/services/windowmanager/dndsourceapp/Android.mk
@@ -16,22 +16,16 @@
include $(CLEAR_VARS)
-# Don't include this package in any target
+# Don't include this package in any target.
LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_PACKAGE_NAME := CtsDragSourceApp
+LOCAL_PACKAGE_NAME := CtsDragAndDropSourceApp
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/draganddrop/dragsource/AndroidManifest.xml b/hostsidetests/services/windowmanager/dndsourceapp/AndroidManifest.xml
similarity index 75%
rename from tests/tests/draganddrop/dragsource/AndroidManifest.xml
rename to hostsidetests/services/windowmanager/dndsourceapp/AndroidManifest.xml
index d7c9011..296a979 100644
--- a/tests/tests/draganddrop/dragsource/AndroidManifest.xml
+++ b/hostsidetests/services/windowmanager/dndsourceapp/AndroidManifest.xml
@@ -15,16 +15,17 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.dnd.cts.dragsource">
- <application android:label="DragSource">
- <activity android:name="android.dnd.cts.dragsource.DragSource">
+ package="android.wm.cts.dndsourceapp">
+ <application android:label="CtsDnDSource">
+ <activity android:name="android.wm.cts.dndsourceapp.DragSource">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
- <provider android:name=".DragSourceContentProvider"
- android:authorities="android.dnd.cts.dragsource.contentprovider"
+
+ <provider android:name="android.wm.cts.dndsourceapp.DragSourceContentProvider"
+ android:authorities="android.wm.cts.dndsource.contentprovider"
android:grantUriPermissions="true"/>
</application>
</manifest>
diff --git a/tests/tests/draganddrop/dragsource/res/layout/main_activity.xml b/hostsidetests/services/windowmanager/dndsourceapp/res/layout/source_activity.xml
similarity index 85%
rename from tests/tests/draganddrop/dragsource/res/layout/main_activity.xml
rename to hostsidetests/services/windowmanager/dndsourceapp/res/layout/source_activity.xml
index 98c8202..673994c 100644
--- a/tests/tests/draganddrop/dragsource/res/layout/main_activity.xml
+++ b/hostsidetests/services/windowmanager/dndsourceapp/res/layout/source_activity.xml
@@ -19,13 +19,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
-
<TextView
- android:id="@+id/source"
+ android:id="@+id/drag_source"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:background="#ddd">
+ android:layout_height="match_parent"
+ android:gravity="center">
</TextView>
-
</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java b/hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSource.java
similarity index 85%
rename from tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java
rename to hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSource.java
index df93852..ff92656 100644
--- a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSource.java
+++ b/hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSource.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.dnd.cts.dragsource;
+package android.wm.cts.dndsourceapp;
import android.app.Activity;
import android.content.ClipData;
@@ -23,6 +23,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.PersistableBundle;
+import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
@@ -31,13 +32,13 @@
"content://" + DragSourceContentProvider.AUTHORITY + "/data";
private static final String MAGIC_VALUE = "42";
- public static final long TIMEOUT_CANCEL = 150;
+ private static final long TIMEOUT_CANCEL = 150;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- View view = getLayoutInflater().inflate(R.layout.main_activity, null);
+ View view = getLayoutInflater().inflate(R.layout.source_activity, null);
setContentView(view);
final Uri plainUri = Uri.parse(URI_PREFIX + "/" + MAGIC_VALUE);
@@ -45,7 +46,7 @@
setUpDragSource("disallow_global", plainUri, 0);
setUpDragSource("cancel_soon", plainUri, View.DRAG_FLAG_GLOBAL);
- setUpDragSource("dont_grant", plainUri, View.DRAG_FLAG_GLOBAL);
+ setUpDragSource("grant_none", plainUri, View.DRAG_FLAG_GLOBAL);
setUpDragSource("grant_read", plainUri,
View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ);
setUpDragSource("grant_write", plainUri,
@@ -61,18 +62,20 @@
View.DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION);
setUpDragSource("grant_read_noprefix", prefixUri,
View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ);
-
}
private void setUpDragSource(String mode, final Uri uri, final int flags) {
if (!mode.equals(getIntent().getStringExtra("mode"))) {
return;
}
- final View source = findViewById(R.id.source);
+ final View source = findViewById(R.id.drag_source);
((TextView) source).setText(mode);
- source.setOnLongClickListener(new View.OnLongClickListener() {
+ source.setOnTouchListener(new View.OnTouchListener() {
@Override
- public boolean onLongClick(final View v) {
+ public boolean onTouch(View v, MotionEvent event) {
+ if (event.getAction() != MotionEvent.ACTION_DOWN) {
+ return false;
+ }
final ClipDescription clipDescription = new ClipDescription("", new String[] {
ClipDescription.MIMETYPE_TEXT_URILIST });
PersistableBundle extras = new PersistableBundle(1);
@@ -92,7 +95,7 @@
}
}, TIMEOUT_CANCEL);
}
- return false;
+ return true;
}
});
}
diff --git a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSourceContentProvider.java b/hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSourceContentProvider.java
similarity index 93%
rename from tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSourceContentProvider.java
rename to hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSourceContentProvider.java
index 5b93832..06a94aa 100644
--- a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSourceContentProvider.java
+++ b/hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSourceContentProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.dnd.cts.dragsource;
+package android.wm.cts.dndsourceapp;
import android.content.ContentProvider;
import android.content.ContentValues;
@@ -24,7 +24,7 @@
public class DragSourceContentProvider extends ContentProvider {
- public static final String AUTHORITY = "android.dnd.cts.dragsource.contentprovider";
+ public static final String AUTHORITY = "android.wm.cts.dndsource.contentprovider";
private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
diff --git a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSourceCursor.java b/hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSourceCursor.java
similarity index 97%
rename from tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSourceCursor.java
rename to hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSourceCursor.java
index aa036fb..c54df65 100644
--- a/tests/tests/draganddrop/dragsource/src/android/dnd/cts/dragsource/DragSourceCursor.java
+++ b/hostsidetests/services/windowmanager/dndsourceapp/src/android/wm/cts/dndsourceapp/DragSourceCursor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.dnd.cts.dragsource;
+package android.wm.cts.dndsourceapp;
import android.database.AbstractCursor;
diff --git a/tests/tests/draganddrop/dragsource/Android.mk b/hostsidetests/services/windowmanager/dndtargetapp/Android.mk
similarity index 75%
copy from tests/tests/draganddrop/dragsource/Android.mk
copy to hostsidetests/services/windowmanager/dndtargetapp/Android.mk
index 066759d..7dc512c 100644
--- a/tests/tests/draganddrop/dragsource/Android.mk
+++ b/hostsidetests/services/windowmanager/dndtargetapp/Android.mk
@@ -16,22 +16,16 @@
include $(CLEAR_VARS)
-# Don't include this package in any target
+# Don't include this package in any target.
LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := current
+
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
-LOCAL_PACKAGE_NAME := CtsDragSourceApp
+LOCAL_PACKAGE_NAME := CtsDragAndDropTargetApp
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
+include $(BUILD_CTS_SUPPORT_PACKAGE)
diff --git a/tests/tests/draganddrop/droptarget/AndroidManifest.xml b/hostsidetests/services/windowmanager/dndtargetapp/AndroidManifest.xml
similarity index 85%
rename from tests/tests/draganddrop/droptarget/AndroidManifest.xml
rename to hostsidetests/services/windowmanager/dndtargetapp/AndroidManifest.xml
index 83d7005..ed7b9c2 100644
--- a/tests/tests/draganddrop/droptarget/AndroidManifest.xml
+++ b/hostsidetests/services/windowmanager/dndtargetapp/AndroidManifest.xml
@@ -15,9 +15,9 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.dnd.cts.droptarget">
- <application android:label="DropTarget">
- <activity android:name="android.dnd.cts.droptarget.DropTarget">
+ package="android.wm.cts.dndtargetapp">
+ <application android:label="CtsDnDTarget">
+ <activity android:name="android.wm.cts.dndtargetapp.DropTarget">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
diff --git a/tests/tests/draganddrop/dragsource/res/layout/main_activity.xml b/hostsidetests/services/windowmanager/dndtargetapp/res/layout/target_activity.xml
similarity index 85%
copy from tests/tests/draganddrop/dragsource/res/layout/main_activity.xml
copy to hostsidetests/services/windowmanager/dndtargetapp/res/layout/target_activity.xml
index 98c8202..ddcdf33 100644
--- a/tests/tests/draganddrop/dragsource/res/layout/main_activity.xml
+++ b/hostsidetests/services/windowmanager/dndtargetapp/res/layout/target_activity.xml
@@ -19,13 +19,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
-
<TextView
- android:id="@+id/source"
+ android:id="@+id/drag_target"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:background="#ddd">
+ android:layout_height="match_parent"
+ android:gravity="center">
</TextView>
-
</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java b/hostsidetests/services/windowmanager/dndtargetapp/src/android/wm/cts/dndtargetapp/DropTarget.java
similarity index 81%
rename from tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java
rename to hostsidetests/services/windowmanager/dndtargetapp/src/android/wm/cts/dndtargetapp/DropTarget.java
index 62c7d16..904a422 100644
--- a/tests/tests/draganddrop/droptarget/src/android/dnd/cts/droptarget/DropTarget.java
+++ b/hostsidetests/services/windowmanager/dndtargetapp/src/android/wm/cts/dndtargetapp/DropTarget.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.dnd.cts.droptarget;
+package android.wm.cts.dndtargetapp;
import android.app.Activity;
import android.content.ClipData;
@@ -23,24 +23,35 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.util.Log;
import android.view.DragAndDropPermissions;
import android.view.DragEvent;
import android.view.View;
import android.widget.TextView;
public class DropTarget extends Activity {
+ public static final String LOG_TAG = "DropTarget";
- private static final String MAGIC_VALUE = "42";
+ private static final String RESULT_KEY_DRAG_STARTED = "DRAG_STARTED";
+ private static final String RESULT_KEY_EXTRAS = "EXTRAS";
+ private static final String RESULT_KEY_DROP_RESULT = "DROP";
+ private static final String RESULT_KEY_DETAILS = "DETAILS";
+
public static final String RESULT_OK = "OK";
+ public static final String RESULT_EXCEPTION = "Exception";
+
+ protected static final String MAGIC_VALUE = "42";
+
+ private TextView mTextView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- View view = getLayoutInflater().inflate(R.layout.main_activity, null);
+ View view = getLayoutInflater().inflate(R.layout.target_activity, null);
setContentView(view);
- setUpDropTarget("dont_request", new OnDragUriReadListener(false));
+ setUpDropTarget("request_none", new OnDragUriReadListener(false));
setUpDropTarget("request_read", new OnDragUriReadListener());
setUpDropTarget("request_write", new OnDragUriWriteListener());
setUpDropTarget("request_read_nested", new OnDragUriReadPrefixListener());
@@ -51,9 +62,9 @@
if (!mode.equals(getIntent().getStringExtra("mode"))) {
return;
}
- final View target = findViewById(R.id.target);
- ((TextView) target).setText(mode);
- target.setOnDragListener(listener);
+ mTextView = (TextView)findViewById(R.id.drag_target);
+ mTextView.setText(mode);
+ mTextView.setOnDragListener(listener);
}
private String checkExtraValue(DragEvent event) {
@@ -69,6 +80,11 @@
return value;
}
+ private void logResult(String key, String value) {
+ Log.i(LOG_TAG, key + "=" + value);
+ mTextView.setText(mTextView.getText() + "\n" + key + "=" + value);
+ }
+
private abstract class OnDragUriListener implements View.OnDragListener {
private final boolean requestPermissions;
@@ -80,8 +96,8 @@
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
- ((TextView) findViewById(R.id.drag_started)).setText("DRAG_STARTED");
- ((TextView) findViewById(R.id.extra_value)).setText(checkExtraValue(event));
+ logResult(RESULT_KEY_DRAG_STARTED, RESULT_OK);
+ logResult(RESULT_KEY_EXTRAS, checkExtraValue(event));
return true;
case DragEvent.ACTION_DRAG_ENTERED:
@@ -98,10 +114,10 @@
try {
result = processDrop(event, requestPermissions);
} catch (Exception e) {
- result = "Exception";
- ((TextView) findViewById(R.id.details)).setText(e.getMessage());
+ result = RESULT_EXCEPTION;
+ logResult(RESULT_KEY_DETAILS, e.getMessage());
}
- ((TextView) findViewById(R.id.result)).setText(result);
+ logResult(RESULT_KEY_DROP_RESULT, result);
return true;
case DragEvent.ACTION_DRAG_ENDED:
@@ -150,11 +166,11 @@
}
private class OnDragUriReadListener extends OnDragUriListener {
- public OnDragUriReadListener(boolean requestPermissions) {
+ OnDragUriReadListener(boolean requestPermissions) {
super(requestPermissions);
}
- public OnDragUriReadListener() {
+ OnDragUriReadListener() {
super(true);
}
@@ -184,7 +200,7 @@
}
private class OnDragUriWriteListener extends OnDragUriListener {
- public OnDragUriWriteListener() {
+ OnDragUriWriteListener() {
super(true);
}
@@ -217,7 +233,7 @@
}
private class OnDragUriTakePersistableListener extends OnDragUriListener {
- public OnDragUriTakePersistableListener() {
+ OnDragUriTakePersistableListener() {
super(true);
}
diff --git a/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
new file mode 100644
index 0000000..5dc789a
--- /dev/null
+++ b/hostsidetests/services/windowmanager/src/android/wm/cts/CrossAppDragAndDropTests.java
@@ -0,0 +1,334 @@
+/*
+ * 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.wm.cts;
+
+import com.android.tradefed.device.CollectingOutputReceiver;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class CrossAppDragAndDropTests extends DeviceTestCase {
+ // Constants copied from ActivityManager.StackId. If they are changed there, these must be
+ // updated.
+ /** ID of stack where fullscreen activities are normally launched into. */
+ private static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
+
+ /** ID of stack where freeform/resized activities are normally launched into. */
+ private static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;
+
+ /** ID of stack that occupies a dedicated region of the screen. */
+ private static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;
+
+ private static final String AM_FORCE_STOP = "am force-stop ";
+ private static final String AM_MOVE_TASK = "am stack movetask ";
+ private static final String AM_START_N = "am start -n ";
+ private static final String AM_STACK_LIST = "am stack list";
+ private static final String INPUT_MOUSE_SWIPE = "input mouse swipe ";
+
+ private static final String TASK_ID_PREFIX = "taskId";
+
+ private static final int SWIPE_DURATION_MS = 500;
+
+ private static final String SOURCE_PACKAGE_NAME = "android.wm.cts.dndsourceapp";
+ private static final String TARGET_PACKAGE_NAME = "android.wm.cts.dndtargetapp";
+
+ private static final String SOURCE_ACTIVITY_NAME = "DragSource";
+ private static final String TARGET_ACTIVITY_NAME = "DropTarget";
+
+ private static final String DISALLOW_GLOBAL = "disallow_global";
+ private static final String CANCEL_SOON = "cancel_soon";
+ private static final String GRANT_NONE = "grant_none";
+ private static final String GRANT_READ = "grant_read";
+ private static final String GRANT_WRITE = "grant_write";
+ private static final String GRANT_READ_PREFIX = "grant_read_prefix";
+ private static final String GRANT_READ_NOPREFIX = "grant_read_noprefix";
+ private static final String GRANT_READ_PERSISTABLE = "grant_read_persistable";
+
+ private static final String REQUEST_NONE = "request_none";
+ private static final String REQUEST_READ = "request_read";
+ private static final String REQUEST_READ_NESTED = "request_read_nested";
+ private static final String REQUEST_TAKE_PERSISTABLE = "request_take_persistable";
+ private static final String REQUEST_WRITE = "request_write";
+
+ private static final String TARGET_LOG_TAG = "DropTarget";
+
+ private static final String RESULT_KEY_DRAG_STARTED = "DRAG_STARTED";
+ private static final String RESULT_KEY_EXTRAS = "EXTRAS";
+ private static final String RESULT_KEY_DROP_RESULT = "DROP";
+
+ private static final String RESULT_OK = "OK";
+ private static final String RESULT_EXCEPTION = "Exception";
+ private static final String RESULT_NULL_DROP_PERMISSIONS = "Null DragAndDropPermissions";
+
+ private ITestDevice mDevice;
+
+ private Map<String, String> mResults;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ mDevice.executeShellCommand(AM_FORCE_STOP + SOURCE_PACKAGE_NAME);
+ mDevice.executeShellCommand(AM_FORCE_STOP + TARGET_PACKAGE_NAME);
+ }
+
+ private String adbShell(String command) throws DeviceNotAvailableException {
+ return mDevice.executeShellCommand(command);
+ }
+
+ private void clearLogs() throws DeviceNotAvailableException {
+ adbShell("logcat -c");
+ }
+
+ private String getStartCommand(String componentName, String modeExtra) {
+ return AM_START_N + componentName + " -e mode " + modeExtra;
+ }
+
+ private String getMoveTaskCommand(int taskId, int stackId) throws Exception {
+ return AM_MOVE_TASK + taskId + " " + stackId + " true";
+ }
+
+ private String getComponentName(String packageName, String activityName) {
+ return packageName + "/" + packageName + "." + activityName;
+ }
+
+ private void launchDockedActivity(String packageName, String activityName, String mode)
+ throws Exception {
+ clearLogs();
+ final String componentName = getComponentName(packageName, activityName);
+ adbShell(getStartCommand(componentName, mode));
+ final int taskId = getActivityTaskId(componentName);
+ adbShell(getMoveTaskCommand(taskId, DOCKED_STACK_ID));
+ waitForResume(packageName, activityName);
+ }
+
+ private void launchFreeformActivity(String packageName, String activityName, String mode)
+ throws Exception {
+ clearLogs();
+ final String componentName = getComponentName(packageName, activityName);
+ adbShell(getStartCommand(componentName, mode) + " --stack " + FREEFORM_WORKSPACE_STACK_ID);
+ waitForResume(packageName, activityName);
+ }
+
+ private void waitForResume(String packageName, String activityName) throws Exception {
+ final String fullActivityName = packageName + "." + activityName;
+ int retryCount = 3;
+ do {
+ String logs = adbShell("logcat -d -b events");
+ for (String line : logs.split("\\n")) {
+ if(line.contains("am_on_resume_called") && line.contains(fullActivityName)) {
+ return;
+ }
+ }
+ } while (retryCount-- > 0);
+
+ throw new Exception(fullActivityName + " has failed to start");
+ }
+
+ private void injectInput(Point from, Point to, int durationMs) throws Exception {
+ adbShell(INPUT_MOUSE_SWIPE + from.x + " " + from.y + " " + to.x + " " + to.y + " " +
+ durationMs);
+ }
+
+ static class Point {
+ public int x, y;
+
+ public Point(int _x, int _y) {
+ x=_x;
+ y=_y;
+ }
+
+ public Point() {}
+ }
+
+ private String findTaskInfo(String name) throws Exception {
+ CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
+ mDevice.executeShellCommand(AM_STACK_LIST, outputReceiver);
+ final String output = outputReceiver.getOutput();
+ for (String line : output.split("\\n")) {
+ if (line.contains(name)) {
+ return line;
+ }
+ }
+ return "";
+ }
+
+ private boolean getWindowBounds(String name, Point from, Point to) throws Exception {
+ final String taskInfo = findTaskInfo(name);
+ final String[] sections = taskInfo.split("\\[");
+ if (sections.length > 2) {
+ try {
+ parsePoint(sections[1], from);
+ parsePoint(sections[2], to);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private int getActivityTaskId(String name) throws Exception {
+ final String taskInfo = findTaskInfo(name);
+ for (String word : taskInfo.split("\\s+")) {
+ if (word.startsWith(TASK_ID_PREFIX)) {
+ final String withColon = word.split("=")[1];
+ return Integer.parseInt(withColon.substring(0, withColon.length() - 1));
+ }
+ }
+ return -1;
+ }
+
+ private Point getWindowCenter(String name) throws Exception {
+ Point p1 = new Point();
+ Point p2 = new Point();
+ if (getWindowBounds(name, p1, p2)) {
+ return new Point((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);
+ }
+ return null;
+ }
+
+ private void parsePoint(String string, Point point) {
+ final String[] parts = string.split("[,|\\]]");
+ point.x = Integer.parseInt(parts[0]);
+ point.y = Integer.parseInt(parts[1]);
+ }
+
+ private Map<String, String> getLogResults(String className) throws Exception {
+ int retryCount = 3;
+ Map<String, String> output = new HashMap<String, String>();
+ do {
+
+ String logs = adbShell("logcat -v brief -d " + className + ":I" + " *:S");
+ for (String line : logs.split("\\n")) {
+ if (line.startsWith("I/" + className)) {
+ String payload = line.split(":")[1].trim();
+ final String[] split = payload.split("=");
+ if (split.length > 1) {
+ output.put(split[0], split[1]);
+ }
+ }
+ }
+ if (output.containsKey(RESULT_KEY_DROP_RESULT)) {
+ return output;
+ }
+ } while (retryCount-- > 0);
+ return output;
+ }
+
+ private void doTestDragAndDrop(String sourceMode, String targetMode, String expectedDropResult)
+ throws Exception {
+
+ launchDockedActivity(SOURCE_PACKAGE_NAME, SOURCE_ACTIVITY_NAME, sourceMode);
+ launchFreeformActivity(TARGET_PACKAGE_NAME, TARGET_ACTIVITY_NAME, targetMode);
+
+ clearLogs();
+
+ injectInput(
+ getWindowCenter(getComponentName(SOURCE_PACKAGE_NAME, SOURCE_ACTIVITY_NAME)),
+ getWindowCenter(getComponentName(TARGET_PACKAGE_NAME, TARGET_ACTIVITY_NAME)),
+ SWIPE_DURATION_MS);
+
+ mResults = getLogResults(TARGET_LOG_TAG);
+ assertResult(RESULT_KEY_DROP_RESULT, expectedDropResult);
+ }
+
+
+ private void assertResult(String resultKey, String expectedResult) {
+ if (expectedResult == null) {
+ if (mResults.containsKey(resultKey)) {
+ fail("Unexpected " + resultKey + "=" + mResults.get(resultKey));
+ }
+ } else {
+ assertTrue("Missing " + resultKey, mResults.containsKey(resultKey));
+ assertEquals(expectedResult, mResults.get(resultKey));
+ }
+ }
+
+ public void testCancelSoon() throws Exception {
+ doTestDragAndDrop(CANCEL_SOON, REQUEST_NONE, null);
+ assertResult(RESULT_KEY_DRAG_STARTED, RESULT_OK);
+ assertResult(RESULT_KEY_EXTRAS, RESULT_OK);
+ }
+
+ public void testDisallowGlobal() throws Exception {
+ doTestDragAndDrop(DISALLOW_GLOBAL, REQUEST_NONE, null);
+ assertResult(RESULT_KEY_DRAG_STARTED, null);
+ }
+
+ public void testGrantNoneRequestNone() throws Exception {
+ doTestDragAndDrop(GRANT_NONE, REQUEST_NONE, RESULT_EXCEPTION);
+ assertResult(RESULT_KEY_DRAG_STARTED, RESULT_OK);
+ assertResult(RESULT_KEY_EXTRAS, RESULT_OK);
+ }
+
+ public void testGrantNoneRequestRead() throws Exception {
+ doTestDragAndDrop(GRANT_NONE, REQUEST_READ, RESULT_NULL_DROP_PERMISSIONS);
+ }
+
+ public void testGrantNoneRequestWrite() throws Exception {
+ doTestDragAndDrop(GRANT_NONE, REQUEST_WRITE, RESULT_NULL_DROP_PERMISSIONS);
+ }
+
+ public void testGrantReadRequestNone() throws Exception {
+ doTestDragAndDrop(GRANT_READ, REQUEST_NONE, RESULT_EXCEPTION);
+ }
+
+ public void testGrantReadRequestRead() throws Exception {
+ doTestDragAndDrop(GRANT_READ, REQUEST_READ, RESULT_OK);
+ }
+
+ public void testGrantReadRequestWrite() throws Exception {
+ doTestDragAndDrop(GRANT_READ, REQUEST_WRITE, RESULT_EXCEPTION);
+ }
+
+ public void testGrantReadNoPrefixRequestReadNested() throws Exception {
+ doTestDragAndDrop(GRANT_READ_NOPREFIX, REQUEST_READ_NESTED, RESULT_EXCEPTION);
+ }
+
+ public void testGrantReadPrefixRequestReadNested() throws Exception {
+ doTestDragAndDrop(GRANT_READ_PREFIX, REQUEST_READ_NESTED, RESULT_OK);
+ }
+
+ public void testGrantPersistableRequestTakePersistable() throws Exception {
+ doTestDragAndDrop(GRANT_READ_PERSISTABLE, REQUEST_TAKE_PERSISTABLE, RESULT_OK);
+ }
+
+ public void testGrantReadRequestTakePersistable() throws Exception {
+ doTestDragAndDrop(GRANT_READ, REQUEST_TAKE_PERSISTABLE, RESULT_EXCEPTION);
+ }
+
+ public void testGrantWriteRequestNone() throws Exception {
+ doTestDragAndDrop(GRANT_WRITE, REQUEST_NONE, RESULT_EXCEPTION);
+ }
+
+ public void testGrantWriteRequestRead() throws Exception {
+ doTestDragAndDrop(GRANT_WRITE, REQUEST_READ, RESULT_EXCEPTION);
+ }
+
+ public void testGrantWriteRequestWrite() throws Exception {
+ doTestDragAndDrop(GRANT_WRITE, REQUEST_WRITE, RESULT_OK);
+ }
+}
diff --git a/hostsidetests/theme/README b/hostsidetests/theme/README
index bce711a..d585db3 100644
--- a/hostsidetests/theme/README
+++ b/hostsidetests/theme/README
@@ -42,11 +42,15 @@
reference images are saved in assets/<api>/<dpi>.zip and will overwrite
any existing sets. Image generation may be started using:
- .cts/hostsidetests/theme/generate_images.sh
+ ./cts/hostsidetests/theme/generate_images.sh
A complete collection of reference images for a given API revision must include
a set for each possible DPI bucket (tvdpi, xxhdpi, etc.) that may be tested.
+For a list of devices and their DPI buckets, see Device Metrics:
+
+ https://design.google.com/devices/
+
II. Building theme tests
@@ -68,6 +72,8 @@
2. Run the theme tests using cts-tradefed:
- cts-tradefed run cts -c android.theme.cts.ThemeHostTest
+ cts-tradefed run singleCommand cts --skip-device-info --skip-preconditions \
+ --skip-connectivity-check --module CtsThemeHostTestCases \
+ --test android.theme.cts.ThemeHostTest
3. Wait for the tests to complete. This should take less than five minutes.
diff --git a/hostsidetests/theme/android_device.py b/hostsidetests/theme/android_device.py
index 97b5fdd..6687494 100644
--- a/hostsidetests/theme/android_device.py
+++ b/hostsidetests/theme/android_device.py
@@ -31,7 +31,7 @@
def runAdbCommand(self, cmd):
self.waitForAdbDevice()
adbCmd = "adb -s %s %s" %(self._adbDevice, cmd)
- adbProcess = subprocess.Popen(adbCmd.split(" "), bufsize = -1, stdout = subprocess.PIPE)
+ adbProcess = subprocess.Popen(adbCmd.split(" "), bufsize = -1, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
return adbProcess.communicate()
def runShellCommand(self, cmd):
@@ -58,12 +58,12 @@
def installApk(self, apkPath):
(out, err) = self.runAdbCommand("install -r -d -g " + apkPath)
- result = out.split()
+ result = err.split()
return (out, err, "Success" in result)
def uninstallApk(self, package):
(out, err) = self.runAdbCommand("uninstall " + package)
- result = out.split()
+ result = err.split()
return "Success" in result
def runInstrumentationTest(self, option):
diff --git a/hostsidetests/theme/app/AndroidManifest.xml b/hostsidetests/theme/app/AndroidManifest.xml
index 4e81ab0..2a1b59b 100755
--- a/hostsidetests/theme/app/AndroidManifest.xml
+++ b/hostsidetests/theme/app/AndroidManifest.xml
@@ -31,13 +31,6 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
- <activity android:name=".DisplayInfoActivity"
- android:label="@string/display_info">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
<activity android:name=".GenerateImagesActivity"
android:exported="true" />
</application>
diff --git a/hostsidetests/theme/app/res/drawable-400dpi/display_info.png b/hostsidetests/theme/app/res/drawable-400dpi/display_info.png
deleted file mode 100644
index e5f1f96..0000000
--- a/hostsidetests/theme/app/res/drawable-400dpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-560dpi/display_info.png b/hostsidetests/theme/app/res/drawable-560dpi/display_info.png
deleted file mode 100644
index babe0da..0000000
--- a/hostsidetests/theme/app/res/drawable-560dpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-hdpi/display_info.png b/hostsidetests/theme/app/res/drawable-hdpi/display_info.png
deleted file mode 100644
index 10b3950..0000000
--- a/hostsidetests/theme/app/res/drawable-hdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-ldpi/display_info.png b/hostsidetests/theme/app/res/drawable-ldpi/display_info.png
deleted file mode 100644
index af1fda5..0000000
--- a/hostsidetests/theme/app/res/drawable-ldpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-mdpi/display_info.png b/hostsidetests/theme/app/res/drawable-mdpi/display_info.png
deleted file mode 100644
index 4378b14..0000000
--- a/hostsidetests/theme/app/res/drawable-mdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-tvdpi/display_info.png b/hostsidetests/theme/app/res/drawable-tvdpi/display_info.png
deleted file mode 100644
index d9825fb..0000000
--- a/hostsidetests/theme/app/res/drawable-tvdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-xhdpi/display_info.png b/hostsidetests/theme/app/res/drawable-xhdpi/display_info.png
deleted file mode 100644
index 585af2f..0000000
--- a/hostsidetests/theme/app/res/drawable-xhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-xxhdpi/display_info.png b/hostsidetests/theme/app/res/drawable-xxhdpi/display_info.png
deleted file mode 100644
index 255c28f..0000000
--- a/hostsidetests/theme/app/res/drawable-xxhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/drawable-xxxhdpi/display_info.png b/hostsidetests/theme/app/res/drawable-xxxhdpi/display_info.png
deleted file mode 100644
index 095382c..0000000
--- a/hostsidetests/theme/app/res/drawable-xxxhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/hostsidetests/theme/app/res/layout/display_info.xml b/hostsidetests/theme/app/res/layout/display_info.xml
deleted file mode 100644
index 167d935..0000000
--- a/hostsidetests/theme/app/res/layout/display_info.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <ImageView
- android:src="@drawable/display_info"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- />
- <TextView
- android:id="@+id/text"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- />
-</LinearLayout>
-
diff --git a/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java b/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java
deleted file mode 100644
index 530675d..0000000
--- a/hostsidetests/theme/app/src/android/theme/app/DisplayInfoActivity.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2014 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.theme.app;
-
-import android.app.Activity;
-import android.theme.app.R;
-import android.os.Bundle;
-import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.WindowManager;
-import android.widget.TextView;
-
-/**
- * An activity to display information about the device, including density
- * bucket and dimensions.
- */
-public class DisplayInfoActivity extends Activity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.display_info);
-
- WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- DisplayMetrics metrics = new DisplayMetrics();
- display.getMetrics(metrics);
-
- DisplayMetrics dm = getResources().getDisplayMetrics();
- int width = Math.round(dm.widthPixels / dm.density);
- int height = Math.round(dm.heightPixels / dm.density);
-
- TextView text = (TextView) findViewById(R.id.text);
- text.setText(getString(R.string.display_info_text, metrics.densityDpi,
- getScreenDensityBucket(metrics), width, height));
- }
-
- private static String getScreenDensityBucket(DisplayMetrics metrics) {
- switch (metrics.densityDpi) {
- case DisplayMetrics.DENSITY_LOW:
- return "ldpi";
-
- case DisplayMetrics.DENSITY_MEDIUM:
- return "mdpi";
-
- case DisplayMetrics.DENSITY_HIGH:
- return "hdpi";
-
- case DisplayMetrics.DENSITY_XHIGH:
- return "xhdpi";
-
- case DisplayMetrics.DENSITY_360:
- return "360dpi";
-
- case DisplayMetrics.DENSITY_400:
- return "400dpi";
-
- case DisplayMetrics.DENSITY_420:
- return "420dpi";
-
- case DisplayMetrics.DENSITY_XXHIGH:
- return "xxhdpi";
-
- case DisplayMetrics.DENSITY_560:
- return "560dpi";
-
- case DisplayMetrics.DENSITY_XXXHIGH:
- return "xxxhdpi";
-
- case DisplayMetrics.DENSITY_TV:
- return "tvdpi";
-
- default:
- return "" + metrics.densityDpi;
- }
- }
-}
diff --git a/hostsidetests/theme/app/src/android/theme/app/ThemeDeviceActivity.java b/hostsidetests/theme/app/src/android/theme/app/ThemeDeviceActivity.java
index 6235fdf..78dc3d4 100644
--- a/hostsidetests/theme/app/src/android/theme/app/ThemeDeviceActivity.java
+++ b/hostsidetests/theme/app/src/android/theme/app/ThemeDeviceActivity.java
@@ -377,7 +377,6 @@
new Layout(R.layout.color_red_light, "color_red_light"),
new Layout(R.layout.datepicker, "datepicker",
new DatePickerModifier()),
- new Layout(R.layout.display_info, "display_info"),
new Layout(R.layout.edittext, "edittext"),
new Layout(R.layout.progressbar_horizontal_0, "progressbar_horizontal_0"),
new Layout(R.layout.progressbar_horizontal_100, "progressbar_horizontal_100"),
diff --git a/hostsidetests/theme/assets/24/420dpi.zip b/hostsidetests/theme/assets/24/420dpi.zip
new file mode 100644
index 0000000..1c380ff
--- /dev/null
+++ b/hostsidetests/theme/assets/24/420dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/24/560dpi.zip b/hostsidetests/theme/assets/24/560dpi.zip
new file mode 100644
index 0000000..a171f7c
--- /dev/null
+++ b/hostsidetests/theme/assets/24/560dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/24/xhdpi.zip b/hostsidetests/theme/assets/24/xhdpi.zip
new file mode 100644
index 0000000..96d4ae0
--- /dev/null
+++ b/hostsidetests/theme/assets/24/xhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/run_theme_capture_device.py b/hostsidetests/theme/run_theme_capture_device.py
index 23171db..8d4c72f 100755
--- a/hostsidetests/theme/run_theme_capture_device.py
+++ b/hostsidetests/theme/run_theme_capture_device.py
@@ -19,6 +19,7 @@
import sys
import threading
import time
+import traceback
import Queue
sys.path.append(sys.path[0])
from android_device import *
@@ -29,9 +30,7 @@
213 : "tvdpi",
240 : "hdpi",
320 : "xhdpi",
- 400 : "400dpi",
480 : "xxhdpi",
- 560 : "560dpi",
640 : "xxxhdpi",
}
@@ -60,6 +59,7 @@
raise
except:
print "Failed to execute thread:", sys.exc_info()[0]
+ traceback.print_exc()
q.task_done()
except KeyboardInterrupt:
raise
@@ -97,17 +97,19 @@
print "Found device: " + deviceSerial
device = androidDevice(deviceSerial)
- # outPath = outPath + "/%d/" % (device.getSdkLevel()) + deviceSerial
outPath = outPath + "/%d" % (device.getSdkLevel())
density = device.getDensity()
- resName = CTS_THEME_dict[density]
+ if CTS_THEME_dict.has_key(density):
+ resName = CTS_THEME_dict[density]
+ else:
+ resName = str(density) + "dpi"
device.uninstallApk("android.theme.app")
(out, err, success) = device.installApk(themeApkPath)
if not success:
print "Failed to install APK on " + deviceSerial
- printAdbResult(device, out, err)
+ printAdbResult(deviceSerial, out, err)
return False
print "Generating images on " + deviceSerial + "..."
diff --git a/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java b/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java
index 65a7928..fe917ae 100644
--- a/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java
+++ b/hostsidetests/tv/src/com/android/cts/tv/TvInputManagerHostTest.java
@@ -106,16 +106,25 @@
device.executeShellCommand(START_COMMAND);
// Re-install the input app so the monitoring app can get the onInputUpdated callback.
installPackage(TEST_APK);
- String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
String testString = "";
- Scanner in = new Scanner(logs);
- while (in.hasNextLine()) {
- String line = in.nextLine();
- if(line.contains(INPUT_UPDATED_STRING)) {
- testString = line.split(":")[1].trim();
+ for (int i = 0; i < 5; ++i) {
+ // Try 5 times as this sometimes fails.
+ String logs = device.executeAdbCommand(
+ "logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
+ Scanner in = new Scanner(logs);
+ while (in.hasNextLine()) {
+ String line = in.nextLine();
+ if (line.contains(INPUT_UPDATED_STRING)) {
+ testString = line.split(":")[1].trim();
+ }
}
+ in.close();
+ if (!testString.isEmpty()) {
+ break;
+ }
+ // Wait for the system service to handle the installation.
+ Thread.currentThread().sleep(100);
}
- in.close();
assertEquals("Incorrect test string", INPUT_UPDATED_STRING, testString);
}
diff --git a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
index d91944a..5acb17e 100644
--- a/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
+++ b/hostsidetests/ui/src/android/ui/cts/InstallTimeTest.java
@@ -44,6 +44,7 @@
private IAbi mAbi;
private static final String TAG = "InstallTimeTest";
+ private static final String REPORT_LOG_NAME = "CtsUiHostTestCases";
static final String PACKAGE = "com.replica.replicaisland";
static final String APK = "com.replica.replicaisland.apk";
private static final double OUTLIER_THRESHOLD = 0.1;
@@ -72,8 +73,10 @@
}
public void testInstallTime() throws Exception {
+ String streamName = "test_install_time";
MetricsReportLog report = new MetricsReportLog(mDevice.getSerialNumber(), mAbi.getName(),
- String.format("%s#%s", getClass().getName(), "testInstallTime"));
+ String.format("%s#%s", getClass().getName(), "testInstallTime"), REPORT_LOG_NAME,
+ streamName);
final int NUMBER_REPEAT = 10;
final IBuildInfo build = mBuild;
final ITestDevice device = mDevice;
@@ -89,12 +92,13 @@
device.installPackage(app, false, options);
}
});
- report.addValues("install time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("install_time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
if (stat.mDataCount != result.length) {
Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
}
- report.setSummary("install time", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.setSummary("install_time_average", stat.mAverage, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
report.submit();
}
diff --git a/libs/deviceutil/src/android/cts/util/MediaUtils.java b/libs/deviceutil/src/android/cts/util/MediaUtils.java
index 7ab806d..a87715d 100755
--- a/libs/deviceutil/src/android/cts/util/MediaUtils.java
+++ b/libs/deviceutil/src/android/cts/util/MediaUtils.java
@@ -35,6 +35,8 @@
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;
import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Map;
import android.util.Log;
@@ -461,6 +463,29 @@
return extractor;
}
+ /**
+ * return mime type of the resourceId
+ */
+ public static Collection<String> getDecodersForFormat(MediaFormat format) {
+ ArrayList<String> decoders = new ArrayList<String>();
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo info : mcl.getCodecInfos()) {
+ if (info.isEncoder()) {
+ continue;
+ }
+ CodecCapabilities caps = null;
+ try {
+ caps = info.getCapabilitiesForType(mime);
+ } catch (IllegalArgumentException e) { // mime is not supported
+ continue;
+ }
+ if (caps.isFormatSupported(format))
+ decoders.add(info.getName());
+ }
+ return decoders;
+ }
+
/*
* ------------------ HELPER METHODS FOR STATISTICS AND REPORTING ------------------
*/
diff --git a/tests/admin/Android.mk b/tests/admin/Android.mk
index e12cc94..60b7aeb 100644
--- a/tests/admin/Android.mk
+++ b/tests/admin/Android.mk
@@ -21,7 +21,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner mockito-target platform-test-annotations
+ ctstestrunner mockito-target
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 68c30ff..5dca2cc 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -2563,7 +2563,7 @@
// If unable to find a preview size, then log the failure, and skip this run.
if (previewSz == null) {
if (mStaticInfo.isCapabilitySupported(
- CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
mCollector.addMessage(String.format(
"Unable to find a preview size supporting given fps range %s",
fpsRange));
diff --git a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
index 02bb348..6ab55b0 100644
--- a/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/DngCreatorTest.java
@@ -591,7 +591,7 @@
Log.e(TAG, "Failed RAW patch file for camera " + deviceId + " saved to " +
rawFilePath);
- fail("Camera " + mCamera.getId() + ": RAW and JPEG image at for the same " +
+ fail("Camera " + deviceId + ": RAW and JPEG image at for the same " +
"frame are not similar, center patches have difference metric of " +
difference);
} finally {
diff --git a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
index 5c97d5c..7e28403 100644
--- a/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/PerformanceTest.java
@@ -61,6 +61,7 @@
*/
public class PerformanceTest extends Camera2SurfaceViewTestCase {
private static final String TAG = "PerformanceTest";
+ private static final String REPORT_LOG_NAME = "CtsCameraTestCases";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private static final int NUM_TEST_LOOPS = 5;
private static final int NUM_MAX_IMAGES = 4;
@@ -88,14 +89,11 @@
@Override
protected void setUp() throws Exception {
- mReportLog = new DeviceReportLog();
super.setUp();
}
@Override
protected void tearDown() throws Exception {
- // Deliver the report to host will automatically clear the report log.
- mReportLog.submit(getInstrumentation());
super.tearDown();
}
@@ -120,6 +118,9 @@
for (String id : mCameraIds) {
// Do NOT move these variables to outer scope
// They will be passed to DeviceReportLog and their references will be stored
+ String streamName = "test_camera_launch";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
double[] cameraOpenTimes = new double[NUM_TEST_LOOPS];
double[] configureStreamTimes = new double[NUM_TEST_LOOPS];
double[] startPreviewTimes = new double[NUM_TEST_LOOPS];
@@ -182,33 +183,32 @@
avgCameraLaunchTimes[counter] = Stat.getAverage(cameraLaunchTimes);
// Finish the data collection, report the KPIs.
- mReportLog.addValues("Camera " + id
- + ": Camera open time", cameraOpenTimes,
+ // ReportLog keys have to be lowercase underscored format.
+ mReportLog.addValues("camera_open_time", cameraOpenTimes, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ mReportLog.addValues("camera_configure_stream_time", configureStreamTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.addValues("Camera " + id
- + ": Camera configure stream time", configureStreamTimes,
+ mReportLog.addValues("camera_start_preview_time", startPreviewTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.addValues("Camera " + id
- + ": Camera start preview time", startPreviewTimes,
+ mReportLog.addValues("camera_camera_stop_preview", stopPreviewTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.addValues("Camera " + id
- + ": Camera stop preview", stopPreviewTimes,
+ mReportLog.addValues("camera_camera_close_time", cameraCloseTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.addValues("Camera " + id
- + ": Camera close time", cameraCloseTimes,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.addValues("Camera " + id
- + ": Camera launch time", cameraLaunchTimes,
+ mReportLog.addValues("camera_launch_time", cameraLaunchTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
}
finally {
closeImageReader();
}
counter++;
+ mReportLog.submit(getInstrumentation());
}
if (mCameraIds.length != 0) {
- mReportLog.setSummary("Camera launch average time for all cameras ",
+ String streamName = "test_camera_launch_average";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.setSummary("camera_launch_average_time_for_all_cameras",
Stat.getAverage(avgCameraLaunchTimes), ResultType.LOWER_BETTER, ResultUnit.MS);
+ mReportLog.submit(getInstrumentation());
}
}
@@ -232,6 +232,9 @@
for (String id : mCameraIds) {
// Do NOT move these variables to outer scope
// They will be passed to DeviceReportLog and their references will be stored
+ String streamName = "test_single_capture";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
double[] captureTimes = new double[NUM_TEST_LOOPS];
double[] getPartialTimes = new double[NUM_TEST_LOOPS];
double[] getResultTimes = new double[NUM_TEST_LOOPS];
@@ -301,20 +304,17 @@
// simulate real scenario (preview runs a bit)
waitForNumResults(previewResultListener, NUM_RESULTS_WAIT);
- stopPreviewAndDrain();
+ stopPreview();
}
- mReportLog.addValues("Camera " + id
- + ": Camera capture latency", captureTimes,
+ mReportLog.addValues("camera_capture_latency", captureTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
// If any of the partial results do not contain AE and AF state, then no report
if (isPartialTimingValid) {
- mReportLog.addValues("Camera " + id
- + ": Camera partial result latency", getPartialTimes,
+ mReportLog.addValues("camera_partial_result_latency", getPartialTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
}
- mReportLog.addValues("Camera " + id
- + ": Camera capture result latency", getResultTimes,
+ mReportLog.addValues("camera_capture_result_latency", getResultTimes,
ResultType.LOWER_BETTER, ResultUnit.MS);
avgResultTimes[counter] = Stat.getAverage(getResultTimes);
@@ -324,12 +324,16 @@
closeDevice();
}
counter++;
+ mReportLog.submit(getInstrumentation());
}
// Result will not be reported in CTS report if no summary is printed.
if (mCameraIds.length != 0) {
- mReportLog.setSummary("Camera capture result average latency for all cameras ",
+ String streamName = "test_single_capture_average";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.setSummary("camera_capture_result_average_latency_for_all_cameras",
Stat.getAverage(avgResultTimes), ResultType.LOWER_BETTER, ResultUnit.MS);
+ mReportLog.submit(getInstrumentation());
}
}
@@ -346,12 +350,16 @@
try {
openDevice(id);
-
+ String streamName = "test_reprocessing_latency";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValue("format", format, ResultType.NEUTRAL, ResultUnit.NONE);
reprocessingPerformanceTestByCamera(format, /*asyncMode*/false,
/*highQuality*/false);
} finally {
closeReaderWriters();
closeDevice();
+ mReportLog.submit(getInstrumentation());
}
}
}
@@ -371,12 +379,16 @@
try {
openDevice(id);
-
+ String streamName = "test_reprocessing_throughput";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValue("format", format, ResultType.NEUTRAL, ResultUnit.NONE);
reprocessingPerformanceTestByCamera(format, /*asyncMode*/true,
/*highQuality*/false);
} finally {
closeReaderWriters();
closeDevice();
+ mReportLog.submit(getInstrumentation());
}
}
}
@@ -395,12 +407,16 @@
try {
openDevice(id);
-
+ String streamName = "test_high_quality_reprocessing_latency";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValue("format", format, ResultType.NEUTRAL, ResultUnit.NONE);
reprocessingPerformanceTestByCamera(format, /*asyncMode*/false,
/*requireHighQuality*/true);
} finally {
closeReaderWriters();
closeDevice();
+ mReportLog.submit(getInstrumentation());
}
}
}
@@ -420,12 +436,16 @@
try {
openDevice(id);
-
+ String streamName = "test_high_quality_reprocessing_throughput";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValue("format", format, ResultType.NEUTRAL, ResultUnit.NONE);
reprocessingPerformanceTestByCamera(format, /*asyncMode*/true,
/*requireHighQuality*/true);
} finally {
closeReaderWriters();
closeDevice();
+ mReportLog.submit(getInstrumentation());
}
}
}
@@ -443,11 +463,15 @@
try {
openDevice(id);
-
+ String streamName = "test_reprocessing_capture_stall";
+ mReportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ mReportLog.addValue("camera_id", id, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValue("format", format, ResultType.NEUTRAL, ResultUnit.NONE);
reprocessingCaptureStallTestByCamera(format);
} finally {
closeReaderWriters();
closeDevice();
+ mReportLog.submit(getInstrumentation());
}
}
}
@@ -534,20 +558,17 @@
stopZslStreaming();
- String reprocessType = " YUV reprocessing ";
+ String reprocessType = "YUV reprocessing";
if (reprocessInputFormat == ImageFormat.PRIVATE) {
- reprocessType = " opaque reprocessing ";
+ reprocessType = "opaque reprocessing";
}
-
- mReportLog.addValues("Camera " + mCamera.getId()
- + ":" + reprocessType + " max capture timestamp gaps", maxCaptureGapsMs,
+ mReportLog.addValue("reprocess_type", reprocessType, ResultType.NEUTRAL, ResultUnit.NONE);
+ mReportLog.addValues("max_capture_timestamp_gaps", maxCaptureGapsMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.addValues("Camera " + mCamera.getId()
- + ":" + reprocessType + "capture average frame duration", averageFrameDurationMs,
+ mReportLog.addValues("capture_average_frame_duration", averageFrameDurationMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.setSummary("Camera reprocessing average max capture timestamp gaps for Camera "
- + mCamera.getId(), Stat.getAverage(maxCaptureGapsMs), ResultType.LOWER_BETTER,
- ResultUnit.MS);
+ mReportLog.setSummary("camera_reprocessing_average_max_capture_timestamp_gaps",
+ Stat.getAverage(maxCaptureGapsMs), ResultType.LOWER_BETTER, ResultUnit.MS);
// The max timestamp gap should be less than (captureStall + 1) x average frame
// duration * (1 + error margin).
@@ -634,9 +655,9 @@
stopZslStreaming();
- String reprocessType = " YUV reprocessing ";
+ String reprocessType = "YUV reprocessing";
if (reprocessInputFormat == ImageFormat.PRIVATE) {
- reprocessType = " opaque reprocessing ";
+ reprocessType = "opaque reprocessing";
}
// Report the performance data
@@ -646,23 +667,27 @@
if (requireHighQuality) {
captureMsg += " for High Quality noise reduction and edge modes";
}
- mReportLog.addValues("Camera " + mCamera.getId()
- + ":" + reprocessType + captureMsg, getImageLatenciesMs,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.setSummary("Camera reprocessing average latency for Camera " +
- mCamera.getId(), Stat.getAverage(getImageLatenciesMs), ResultType.LOWER_BETTER,
+ mReportLog.addValue("reprocess_type", reprocessType, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ mReportLog.addValue("capture_message", captureMsg, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ mReportLog.addValues("latency", getImageLatenciesMs, ResultType.LOWER_BETTER,
ResultUnit.MS);
+ mReportLog.setSummary("camera_reprocessing_average_latency",
+ Stat.getAverage(getImageLatenciesMs), ResultType.LOWER_BETTER, ResultUnit.MS);
} else {
captureMsg = "shot to shot latency";
if (requireHighQuality) {
captureMsg += " for High Quality noise reduction and edge modes";
}
- mReportLog.addValues("Camera " + mCamera.getId()
- + ":" + reprocessType + captureMsg, getImageLatenciesMs,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- mReportLog.setSummary("Camera reprocessing shot to shot average latency for Camera " +
- mCamera.getId(), Stat.getAverage(getImageLatenciesMs), ResultType.LOWER_BETTER,
+ mReportLog.addValue("reprocess_type", reprocessType, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ mReportLog.addValue("capture_message", captureMsg, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ mReportLog.addValues("latency", getImageLatenciesMs, ResultType.LOWER_BETTER,
ResultUnit.MS);
+ mReportLog.setSummary("camera_reprocessing_shot_to_shot_average_latency",
+ Stat.getAverage(getImageLatenciesMs), ResultType.LOWER_BETTER, ResultUnit.MS);
}
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 5736ebd..df89297 100644
--- a/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -2097,7 +2097,7 @@
checkTrueForKey(key, " value is out of range ",
facing >= CameraCharacteristics.LENS_FACING_FRONT &&
- facing <= CameraCharacteristics.LENS_FACING_BACK);
+ facing <= CameraCharacteristics.LENS_FACING_EXTERNAL);
return facing;
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index 9ffe095..8d141c4 100644
--- a/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/camera/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -101,6 +101,7 @@
protected Surface mPreviewSurface;
protected Size mPreviewSize;
protected List<Size> mOrderedPreviewSizes; // In descending order.
+ protected List<Size> m1080pBoundedOrderedPreviewSizes; // In descending order.
protected List<Size> mOrderedVideoSizes; // In descending order.
protected List<Size> mOrderedStillSizes; // In descending order.
protected HashMap<Size, Long> mMinPreviewFrameDurationMap;
@@ -581,6 +582,8 @@
if (mStaticInfo.isColorOutputSupported()) {
mOrderedPreviewSizes = getSupportedPreviewSizes(cameraId, mCameraManager,
getPreviewSizeBound(mWindowManager, PREVIEW_SIZE_BOUND));
+ m1080pBoundedOrderedPreviewSizes = getSupportedPreviewSizes(cameraId, mCameraManager,
+ PREVIEW_SIZE_BOUND);
mOrderedVideoSizes = getSupportedVideoSizes(cameraId, mCameraManager, PREVIEW_SIZE_BOUND);
mOrderedStillSizes = getSupportedStillSizes(cameraId, mCameraManager, null);
// Use ImageFormat.YUV_420_888 for now. TODO: need figure out what's format for preview
@@ -749,6 +752,22 @@
}
}
+ // Search again for sizes not bounded by display size
+ for (Size size : m1080pBoundedOrderedPreviewSizes) {
+ Long minDuration = mMinPreviewFrameDurationMap.get(size);
+ if (minDuration == null ||
+ minDuration == 0) {
+ if (mStaticInfo.isCapabilitySupported(
+ CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR)) {
+ throw new IllegalArgumentException(
+ "No min frame duration available for the size " + size);
+ }
+ continue;
+ }
+ if (minDuration <= (frameDurationRange[0] + MIN_FRAME_DURATION_ERROR_MARGIN)) {
+ return size;
+ }
+ }
return null;
}
diff --git a/tests/core/runner/Android.mk b/tests/core/runner/Android.mk
index 1355512..f2b83ed 100644
--- a/tests/core/runner/Android.mk
+++ b/tests/core/runner/Android.mk
@@ -45,7 +45,8 @@
compatibility-device-util \
android-support-test \
android.test.runner \
- vogarexpect
+ vogarexpect \
+ testng
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
diff --git a/tests/core/runner/src/com/android/cts/core/internal/runner/TestLoader.java b/tests/core/runner/src/com/android/cts/core/internal/runner/TestLoader.java
new file mode 100644
index 0000000..108e8fd
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/internal/runner/TestLoader.java
@@ -0,0 +1,258 @@
+/*
+ * 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.
+ */
+
+/**
+ * This file is a copy of https://cs.corp.google.com/android/frameworks/testing/runner/src/main/java/android/support/test/internal/runner/TestLoader.java
+ * The only changes that have been made starts with // Libcore-specific
+ */
+
+package com.android.cts.core.internal.runner;
+
+import android.util.Log;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class for loading JUnit3 and JUnit4 test classes given a set of potential class names.
+ */
+public final class TestLoader {
+
+ private static final String LOG_TAG = "TestLoader";
+ // Libcore-specific change: Fully qualified name of TestNG annotation class.
+ private static final String TESTNG_TEST = "org.testng.annotations.Test";
+
+ private Map<String, Class<?>> mLoadedClassesMap = new LinkedHashMap<String, Class<?>>();
+ private Map<String, Failure> mLoadFailuresMap = new LinkedHashMap<String, Failure>();
+
+ private ClassLoader mClassLoader;
+
+ /**
+ * Set the {@link ClassLoader} to be used to load test cases.
+ *
+ * @param loader {@link ClassLoader} to load test cases with.
+ */
+ public void setClassLoader(ClassLoader loader) {
+ mClassLoader = loader;
+ }
+
+ /**
+ * Loads the test class from a given class name if its not already loaded.
+ * <p/>
+ * Will store the result internally. Successfully loaded classes can be retrieved via
+ * {@link #getLoadedClasses()}, failures via {@link #getLoadFailures()}.
+ *
+ * @param className the class name to attempt to load
+ * @return the loaded class or null.
+ */
+ public Class<?> loadClass(String className) {
+ Class<?> loadedClass = doLoadClass(className);
+ if (loadedClass != null) {
+ mLoadedClassesMap.put(className, loadedClass);
+ }
+ return loadedClass;
+ }
+
+ protected ClassLoader getClassLoader() {
+ if (mClassLoader != null) {
+ return mClassLoader;
+ }
+
+ // TODO: InstrumentationTestRunner uses
+ // Class.forName(className, false, getTargetContext().getClassLoader());
+ // Evaluate if that is needed. Initial testing indicates
+ // getTargetContext().getClassLoader() == this.getClass().getClassLoader()
+ return this.getClass().getClassLoader();
+ }
+
+ private Class<?> doLoadClass(String className) {
+ if (mLoadFailuresMap.containsKey(className)) {
+ // Don't load classes that already failed to load
+ return null;
+ } else if (mLoadedClassesMap.containsKey(className)) {
+ // Class with the same name was already loaded, return it
+ return mLoadedClassesMap.get(className);
+ }
+
+ try {
+ ClassLoader myClassLoader = getClassLoader();
+ return Class.forName(className, false, myClassLoader);
+ } catch (ClassNotFoundException e) {
+ String errMsg = String.format("Could not find class: %s", className);
+ Log.e(LOG_TAG, errMsg);
+ Description description = Description.createSuiteDescription(className);
+ Failure failure = new Failure(description, e);
+ mLoadFailuresMap.put(className, failure);
+ }
+ return null;
+ }
+
+ /**
+ * Loads the test class from the given class name.
+ * <p/>
+ * Similar to {@link #loadClass(String)}, but will ignore classes that are
+ * not tests.
+ *
+ * @param className the class name to attempt to load
+ * @return the loaded class or null.
+ */
+ public Class<?> loadIfTest(String className) {
+ Class<?> loadedClass = doLoadClass(className);
+ if (loadedClass != null && isTestClass(loadedClass)) {
+ mLoadedClassesMap.put(className, loadedClass);
+ return loadedClass;
+ }
+ return null;
+ }
+
+ /**
+ * @return whether this {@link TestLoader} contains any loaded classes or load failures.
+ */
+ public boolean isEmpty() {
+ return mLoadedClassesMap.isEmpty() && mLoadFailuresMap.isEmpty();
+ }
+
+ /**
+ * Get the {@link Collection) of classes successfully loaded via
+ * {@link #loadIfTest(String)} calls.
+ */
+ public Collection<Class<?>> getLoadedClasses() {
+ return mLoadedClassesMap.values();
+ }
+
+ /**
+ * Get the {@link List) of {@link Failure} that occurred during
+ * {@link #loadIfTest(String)} calls.
+ */
+ public Collection<Failure> getLoadFailures() {
+ return mLoadFailuresMap.values();
+ }
+
+ /**
+ * Determines if given class is a valid test class.
+ *
+ * @param loadedClass
+ * @return <code>true</code> if loadedClass is a test
+ */
+ private boolean isTestClass(Class<?> loadedClass) {
+ try {
+ if (Modifier.isAbstract(loadedClass.getModifiers())) {
+ logDebug(String.format("Skipping abstract class %s: not a test",
+ loadedClass.getName()));
+ return false;
+ }
+ // Libcore-specific change: Also consider TestNG annotated classes.
+ if (isTestNgTestClass(loadedClass)) {
+ return true;
+ }
+ // TODO: try to find upstream junit calls to replace these checks
+ if (junit.framework.Test.class.isAssignableFrom(loadedClass)) {
+ // ensure that if a TestCase, it has at least one test method otherwise
+ // TestSuite will throw error
+ if (junit.framework.TestCase.class.isAssignableFrom(loadedClass)) {
+ return hasJUnit3TestMethod(loadedClass);
+ }
+ return true;
+ }
+ // TODO: look for a 'suite' method?
+ if (loadedClass.isAnnotationPresent(org.junit.runner.RunWith.class)) {
+ return true;
+ }
+ for (Method testMethod : loadedClass.getMethods()) {
+ if (testMethod.isAnnotationPresent(org.junit.Test.class)) {
+ return true;
+ }
+ }
+ logDebug(String.format("Skipping class %s: not a test", loadedClass.getName()));
+ return false;
+ } catch (Exception e) {
+ // Defensively catch exceptions - Will throw runtime exception if it cannot load methods.
+ // For earlier versions of Android (Pre-ICS), Dalvik might try to initialize a class
+ // during getMethods(), fail to do so, hide the error and throw a NoSuchMethodException.
+ // Since the java.lang.Class.getMethods does not declare such an exception, resort to a
+ // generic catch all.
+ // For ICS+, Dalvik will throw a NoClassDefFoundException.
+ Log.w(LOG_TAG, String.format("%s in isTestClass for %s", e.toString(),
+ loadedClass.getName()));
+ return false;
+ } catch (Error e) {
+ // defensively catch Errors too
+ Log.w(LOG_TAG, String.format("%s in isTestClass for %s", e.toString(),
+ loadedClass.getName()));
+ return false;
+ }
+ }
+
+ private boolean hasJUnit3TestMethod(Class<?> loadedClass) {
+ for (Method testMethod : loadedClass.getMethods()) {
+ if (isPublicTestMethod(testMethod)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // copied from junit.framework.TestSuite
+ private boolean isPublicTestMethod(Method m) {
+ return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
+ }
+
+ // copied from junit.framework.TestSuite
+ private boolean isTestMethod(Method m) {
+ return m.getParameterTypes().length == 0 && m.getName().startsWith("test")
+ && m.getReturnType().equals(Void.TYPE);
+ }
+
+ // Libcore-specific change: Add method for checking TestNG-annotated classes.
+ private static boolean isTestNgTestClass(Class<?> cls) {
+ // TestNG test is either marked @Test at the class
+ for (Annotation a : cls.getAnnotations()) {
+ if (a.annotationType().getName().equals(TESTNG_TEST)) {
+ return true;
+ }
+ }
+
+ // Or It's marked @Test at the method level
+ for (Method m : cls.getDeclaredMethods()) {
+ for (Annotation a : m.getAnnotations()) {
+ if (a.annotationType().getName().equals(TESTNG_TEST)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ /**
+ * Utility method for logging debug messages. Only actually logs a message if LOG_TAG is marked
+ * as loggable to limit log spam during normal use.
+ */
+ private void logDebug(String msg) {
+ if (Log.isLoggable(LOG_TAG, Log.DEBUG)) {
+ Log.d(LOG_TAG, msg);
+ }
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java b/tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java
index 8bc2f01..4b18cdc 100644
--- a/tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/AndroidJUnitRunnerConstants.java
@@ -24,7 +24,7 @@
public interface AndroidJUnitRunnerConstants {
/**
- * The names of the file containing the names of the tests to run.
+ * The name of the file containing the names of the tests to run.
*
* <p>This is an internal constant used within
* {@code android.support.test.internal.runner.RunnerArgs}, which is used on both the server
@@ -39,6 +39,21 @@
String ARGUMENT_TEST_FILE = "testFile";
/**
+ * The name of the file containing the names of the tests not to run.
+ *
+ * <p>This is an internal constant used within
+ * {@code android.support.test.internal.runner.RunnerArgs}, which is used on both the server
+ * and
+ * client side. The constant is used when there are too many test names to pass on the command
+ * line, in which case they are stored in a file that is pushed to the device and then the
+ * location of that file is passed in this argument. The {@code RunnerArgs} on the client will
+ * read the contents of that file in order to retrieve the list of names and then return that
+ * to
+ * its client without the client being aware of how that was done.
+ */
+ String ARGUMENT_NOT_TEST_FILE = "notTestFile";
+
+ /**
* A comma separated list of the names of test classes to run.
*
* <p>The equivalent constant in {@code InstrumentationTestRunner} is hidden and so not
diff --git a/tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java b/tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java
index 887762f..d995fd9 100644
--- a/tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/CoreTestRunner.java
@@ -55,6 +55,7 @@
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_DEBUG;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_LOG_ONLY;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_NOT_TEST_CLASS;
+import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_NOT_TEST_FILE;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_NOT_TEST_PACKAGE;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_TEST_CLASS;
import static com.android.cts.core.runner.AndroidJUnitRunnerConstants.ARGUMENT_TEST_FILE;
@@ -154,8 +155,18 @@
testNameSet.addAll(Arrays.asList(tests));
}
+ // Tests may be excluded from the run by passing a list of tests not to run,
+ // or by passing a fileName with a test not to run on each line.
Set<String> notTestNameSet = new HashSet<>();
- if ((arg = args.getString(ARGUMENT_NOT_TEST_CLASS)) != null) {
+ if ((arg = args.getString(ARGUMENT_NOT_TEST_FILE)) != null) {
+ // The tests are specified in a file.
+ try {
+ notTestNameSet.addAll(readTestsFromFile(arg));
+ } catch (IOException err) {
+ finish(Activity.RESULT_CANCELED, new Bundle());
+ return;
+ }
+ } else if ((arg = args.getString(ARGUMENT_NOT_TEST_CLASS)) != null) {
// The classes are specified in a String passed in the bundle
String[] tests = arg.split(",");
notTestNameSet.addAll(Arrays.asList(tests));
@@ -241,6 +252,9 @@
try {
RunnerBuilder runnerBuilder = new ExtendedAndroidRunnerBuilder(runnerParams);
Class[] classes = testList.getClassesToRun();
+ for (Class cls : classes) {
+ Log.d(TAG, "Found class to run: " + cls.getName());
+ }
Runner suite = new Computer().getSuite(runnerBuilder, classes);
if (suite instanceof Filterable) {
diff --git a/tests/core/runner/src/com/android/cts/core/runner/TestClassFinder.java b/tests/core/runner/src/com/android/cts/core/runner/TestClassFinder.java
index 1b15aec..6ad95f6 100644
--- a/tests/core/runner/src/com/android/cts/core/runner/TestClassFinder.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/TestClassFinder.java
@@ -13,23 +13,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.cts.core.runner;
import android.support.test.internal.runner.ClassPathScanner;
import android.support.test.internal.runner.ClassPathScanner.ClassNameFilter;
-import android.support.test.internal.runner.TestLoader;
import android.util.Log;
+
+import com.android.cts.core.internal.runner.TestLoader;
+
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Enumeration;
import java.util.List;
import java.util.Set;
+import dalvik.system.DexFile;
+
/**
* Find tests in the current APK.
*/
public class TestClassFinder {
+ private static final String TAG = "TestClassFinder";
+ private static final boolean DEBUG = false;
+
// Excluded test packages
private static final String[] DEFAULT_EXCLUDED_PACKAGES = {
"junit",
@@ -40,6 +49,36 @@
};
static Collection<Class<?>> getClasses(List<String> apks, ClassLoader loader) {
+ if (DEBUG) {
+ Log.d(TAG, "getClasses: =======================================");
+
+ for (String apkPath : apks) {
+ Log.d(TAG, "getClasses: -------------------------------");
+ Log.d(TAG, "getClasses: APK " + apkPath);
+
+ DexFile dexFile = null;
+ try {
+ dexFile = new DexFile(apkPath);
+ Enumeration<String> apkClassNames = dexFile.entries();
+ while (apkClassNames.hasMoreElements()) {
+ String apkClassName = apkClassNames.nextElement();
+ Log.d(TAG, "getClasses: DexClass element " + apkClassName);
+ }
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ } finally {
+ if (dexFile != null) {
+ try {
+ dexFile.close();
+ } catch (IOException e) {
+ throw new AssertionError(e);
+ }
+ }
+ }
+ Log.d(TAG, "getClasses: -------------------------------");
+ }
+ } // if DEBUG
+
List<Class<?>> classes = new ArrayList<>();
ClassPathScanner scanner = new ClassPathScanner(apks);
@@ -53,15 +92,24 @@
filter.add(new ExcludePackageNameFilter(defaultExcludedPackage));
}
+ // exclude any classes that aren't a "test class" (see #loadIfTest)
TestLoader testLoader = new TestLoader();
testLoader.setClassLoader(loader);
try {
Set<String> classNames = scanner.getClassPathEntries(filter);
for (String className : classNames) {
+ // Important: This further acts as an additional filter;
+ // classes that aren't a "test class" are never loaded.
Class<?> cls = testLoader.loadIfTest(className);
if (cls != null) {
classes.add(cls);
+
+ if (DEBUG) {
+ Log.d(TAG, "getClasses: Loaded " + className);
+ }
+ } else if (DEBUG) {
+ Log.d(TAG, "getClasses: Failed to load class " + className);
}
}
return classes;
@@ -69,6 +117,11 @@
Log.e(CoreTestRunner.TAG, "Failed to scan classes", e);
}
+
+ if (DEBUG) {
+ Log.d(TAG, "getClasses: =======================================");
+ }
+
return testLoader.getLoadedClasses();
}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
index 527f9fd..58ef951 100644
--- a/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/ExtendedAndroidRunnerBuilder.java
@@ -13,10 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package com.android.cts.core.runner.support;
import android.support.test.internal.runner.AndroidLogOnlyBuilder;
import android.support.test.internal.util.AndroidRunnerParams;
+import android.util.Log;
import org.junit.runners.model.RunnerBuilder;
import org.junit.runner.Runner;
@@ -26,7 +28,10 @@
*/
public class ExtendedAndroidRunnerBuilder extends AndroidRunnerBuilder {
- private final ExtendedAndroidLogOnlyBuilder androidLogOnlyBuilder;
+ private final ExtendedAndroidLogOnlyBuilder androidLogOnlyBuilder;
+ private static final boolean DEBUG = false;
+
+ private final TestNgRunnerBuilder mTestNgBuilder;
/**
* @param runnerParams {@link AndroidRunnerParams} that stores common runner parameters
@@ -34,16 +39,42 @@
public ExtendedAndroidRunnerBuilder(AndroidRunnerParams runnerParams) {
super(runnerParams, false /* CTSv1 filtered out Test suite() classes. */);
androidLogOnlyBuilder = new ExtendedAndroidLogOnlyBuilder(runnerParams);
+ mTestNgBuilder = new TestNgRunnerBuilder(runnerParams);
}
@Override
public Runner runnerForClass(Class<?> testClass) throws Throwable {
- // Check if this is a dry-run with -e log true argument passed to the runner.
- Runner runner = androidLogOnlyBuilder.runnerForClass(testClass);
- if (runner != null) {
- return runner;
- }
- // Otherwise use the default behaviour
- return super.runnerForClass(testClass);
+ if (DEBUG) {
+ Log.d("ExAndRunBuild", "runnerForClass: Searching runner for class " + testClass.getName());
+ }
+
+ Runner runner;
+ // Give TestNG tests a chance to participate in the Runner search first.
+ // (Note that the TestNG runner handles log-only runs by itself)
+ runner = mTestNgBuilder.runnerForClass(testClass);
+ if (runner != null) {
+ logFoundRunner(runner);
+ return runner;
+ }
+
+ // Check if this is a dry-run with -e log true argument passed to the runner.
+ runner = androidLogOnlyBuilder.runnerForClass(testClass);
+ if (runner != null) {
+ logFoundRunner(runner);
+ return runner;
+ }
+
+ // Use the normal Runner search mechanism (for Junit tests).
+ runner = super.runnerForClass(testClass);
+ logFoundRunner(runner);
+
+ return runner;
+ }
+
+ private static void logFoundRunner(Runner runner) {
+ if (DEBUG) {
+ Log.d("ExAndRunBuild", "runnerForClass: Found runner of type " +
+ ((runner == null) ? "<null>" : runner.getClass().getName()));
+ }
}
}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/SingleTestNGTestRunListener.java b/tests/core/runner/src/com/android/cts/core/runner/support/SingleTestNGTestRunListener.java
new file mode 100644
index 0000000..5568d08
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/SingleTestNGTestRunListener.java
@@ -0,0 +1,112 @@
+/*
+ * 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 com.android.cts.core.runner.support;
+
+import java.util.Arrays;
+
+/**
+ * Listener for TestNG runs that provides gtest-like console output.
+ *
+ * Prints a message like [RUN], [OK], [ERROR], [SKIP] to stdout
+ * as tests are being executed with their status.
+ *
+ * This output is also saved as the device logs (logcat) when the test is run through
+ * cts-tradefed.
+ */
+public class SingleTestNGTestRunListener implements org.testng.ITestListener {
+ private int mTestStarted = 0;
+
+ private static class Prefixes {
+ @SuppressWarnings("unused")
+ private static final String INFORMATIONAL_MARKER = "[----------]";
+ private static final String START_TEST_MARKER = "[ RUN ]";
+ private static final String OK_TEST_MARKER = "[ OK ]";
+ private static final String ERROR_TEST_RUN_MARKER = "[ ERROR ]";
+ private static final String SKIPPED_TEST_MARKER = "[ SKIP ]";
+ private static final String TEST_RUN_MARKER = "[==========]";
+ }
+
+ // How many tests did TestNG *actually* try to run?
+ public int getNumTestStarted() {
+ return mTestStarted;
+ }
+
+ @Override
+ public void onFinish(org.testng.ITestContext context) {
+ System.out.println(String.format("%s", Prefixes.TEST_RUN_MARKER));
+ }
+
+ @Override
+ public void onStart(org.testng.ITestContext context) {
+ System.out.println(String.format("%s", Prefixes.INFORMATIONAL_MARKER));
+ }
+
+ @Override
+ public void onTestFailedButWithinSuccessPercentage(org.testng.ITestResult result) {
+ onTestFailure(result);
+ }
+
+ @Override
+ public void onTestFailure(org.testng.ITestResult result) {
+ // All failures are coalesced into one '[ FAILED ]' message at the end
+ // This is because a single test method can run multiple times with different parameters.
+ // Since we only test a single method, it's safe to combine all failures into one
+ // failure at the end.
+ //
+ // The big pass/fail is printed from SingleTestNGTestRunner, not from the listener.
+ System.out.println(String.format("%s %s ::: %s", Prefixes.ERROR_TEST_RUN_MARKER,
+ getId(result), stringify(result.getThrowable())));
+ }
+
+ @Override
+ public void onTestSkipped(org.testng.ITestResult result) {
+ System.out.println(String.format("%s %s", Prefixes.SKIPPED_TEST_MARKER,
+ getId(result)));
+ }
+
+ @Override
+ public void onTestStart(org.testng.ITestResult result) {
+ mTestStarted++;
+ System.out.println(String.format("%s %s", Prefixes.START_TEST_MARKER,
+ getId(result)));
+ }
+
+ @Override
+ public void onTestSuccess(org.testng.ITestResult result) {
+ System.out.println(String.format("%s", Prefixes.OK_TEST_MARKER));
+ }
+
+ private String getId(org.testng.ITestResult test) {
+ // TestNG is quite complicated since tests can have arbitrary parameters.
+ // Use its code to stringify a result name instead of doing it ourselves.
+
+ org.testng.remote.strprotocol.TestResultMessage msg =
+ new org.testng.remote.strprotocol.TestResultMessage(
+ null, /*suite name*/
+ null, /*test name -- display the test method name instead */
+ test);
+
+ String className = test.getTestClass().getName();
+ //String name = test.getMethod().getMethodName();
+ return String.format("%s#%s", className, msg.toDisplayString());
+
+ }
+
+ private String stringify(Throwable error) {
+ return Arrays.toString(error.getStackTrace()).replaceAll("\n", " ");
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/SingleTestNgTestExecutor.java b/tests/core/runner/src/com/android/cts/core/runner/support/SingleTestNgTestExecutor.java
new file mode 100644
index 0000000..ccab7b0
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/SingleTestNgTestExecutor.java
@@ -0,0 +1,111 @@
+/*
+ * 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 com.android.cts.core.runner.support;
+
+import android.util.Log;
+
+import org.testng.TestNG;
+import org.testng.xml.XmlClass;
+import org.testng.xml.XmlInclude;
+import org.testng.xml.XmlSuite;
+import org.testng.xml.XmlTest;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Test executor to run a single TestNG test method.
+ */
+public class SingleTestNgTestExecutor {
+ // Execute any method which is in the class klass.
+ // The klass is passed in separately to handle inherited methods only.
+ // Returns true if all tests pass, false otherwise.
+ public static boolean execute(Class<?> klass, String methodName) {
+ if (klass == null) {
+ throw new NullPointerException("klass must not be null");
+ }
+
+ if (methodName == null) {
+ throw new NullPointerException("methodName must not be null");
+ }
+
+ //if (!method.getDeclaringClass().isAssignableFrom(klass)) {
+ // throw new IllegalArgumentException("klass must match method's declaring class");
+ //}
+
+ SingleTestNGTestRunListener listener = new SingleTestNGTestRunListener();
+
+ // Although creating a new testng "core" every time might seem heavyweight, in practice
+ // it seems to take a mere few milliseconds at most.
+ // Since we're running all the parameteric combinations of a test,
+ // this ends up being neglible relative to that.
+ TestNG testng = createTestNG(klass.getName(), methodName, listener);
+ testng.run();
+
+ if (listener.getNumTestStarted() <= 0) {
+ // It's possible to be invoked here with an arbitrary method name
+ // so print out a warning incase TestNG actually had a no-op.
+ Log.w("TestNgExec", "execute class " + klass.getName() + ", method " + methodName +
+ " had 0 tests executed. Not a test method?");
+ }
+
+ return !testng.hasFailure();
+ }
+
+ private static org.testng.TestNG createTestNG(String klass, String method,
+ SingleTestNGTestRunListener listener) {
+ org.testng.TestNG testng = new org.testng.TestNG();
+ testng.setUseDefaultListeners(false); // Don't create the testng-specific HTML/XML reports.
+ // It still prints the X/Y tests succeeded/failed summary to stdout.
+
+ // We don't strictly need this listener for CTS, but having it print SUCCESS/FAIL
+ // makes it easier to diagnose which particular combination of a test method had failed
+ // from looking at device logcat.
+ testng.addListener(listener);
+
+ /* Construct the following equivalent XML configuration:
+ *
+ * <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+ * <suite>
+ * <test>
+ * <classes>
+ * <class name="$klass">
+ * <include name="$method" />
+ * </class>
+ * </classes>
+ * </test>
+ * </suite>
+ *
+ * This will ensure that only a single klass/method is being run by testng.
+ * (It can still be run multiple times due to @DataProvider, with different parameters
+ * each time)
+ */
+ List<XmlSuite> suites = new ArrayList<>();
+ XmlSuite the_suite = new XmlSuite();
+ XmlTest the_test = new XmlTest(the_suite);
+ XmlClass the_class = new XmlClass(klass);
+ XmlInclude the_include = new XmlInclude(method);
+
+ the_class.getIncludedMethods().add(the_include);
+ the_test.getXmlClasses().add(the_class);
+ suites.add(the_suite);
+ testng.setXmlSuites(suites);
+
+ return testng;
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/TestNgRunner.java b/tests/core/runner/src/com/android/cts/core/runner/support/TestNgRunner.java
new file mode 100644
index 0000000..eff9d3c
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/TestNgRunner.java
@@ -0,0 +1,220 @@
+/*
+ * 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 com.android.cts.core.runner.support;
+
+import android.support.test.internal.util.AndroidRunnerParams;
+import android.util.Log;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+
+/**
+ * A {@link Runner} that can TestNG tests.
+ *
+ * <p>Implementation note: Avoid extending ParentRunner since that also has
+ * logic to handle BeforeClass/AfterClass and other junit-specific functionality
+ * that would be invalid for TestNG.</p>
+ */
+class TestNgRunner extends Runner implements Filterable {
+
+ private static final boolean DEBUG = false;
+
+ private static final String TESTNG_TEST = "org.testng.annotations.Test";
+
+ private Description mDescription;
+ /** Class name for debugging. */
+ private String mClassName;
+ /** Don't include the same method names twice. */
+ private HashSet<String> mMethodSet = new HashSet<>();
+ /** Don't actually run the test if this is true, just report passing. */
+ private final boolean mSkipExecution;
+
+ /**
+ * @param runnerParams {@link AndroidRunnerParams} that stores common runner parameters
+ */
+ TestNgRunner(Class<?> testClass, boolean skipExecution) {
+ mDescription = generateTestNgDescription(testClass);
+ mClassName = testClass.getName();
+ mSkipExecution = skipExecution;
+ }
+
+ // Runner implementation
+ @Override
+ public Description getDescription() {
+ return mDescription;
+ }
+
+ // Runner implementation
+ @Override
+ public int testCount() {
+ if (!descriptionHasChildren(getDescription())) { // Avoid NPE when description is null.
+ return 0;
+ }
+
+ // We always follow a flat Parent->Leaf hierarchy, so no recursion necessary.
+ return getDescription().testCount();
+ }
+
+ // Filterable implementation
+ @Override
+ public void filter(Filter filter) throws NoTestsRemainException {
+ mDescription = filterDescription(mDescription, filter);
+
+ if (!descriptionHasChildren(getDescription())) { // Avoid NPE when description is null.
+ if (DEBUG) {
+ Log.d("TestNgRunner",
+ "Filtering has removed all tests :( for class " + mClassName);
+ }
+ throw new NoTestsRemainException();
+ }
+
+ if (DEBUG) {
+ Log.d("TestNgRunner",
+ "Filtering has retained " + testCount() + " tests for class " + mClassName);
+ }
+ }
+
+ // Filterable implementation
+ @Override
+ public void run(RunNotifier notifier) {
+ if (!descriptionHasChildren(getDescription())) { // Avoid NPE when description is null.
+ // Nothing to do.
+ return;
+ }
+
+ for (Description child : getDescription().getChildren()) {
+ String className = child.getClassName();
+ String methodName = child.getMethodName();
+
+ Class<?> klass;
+ try {
+ klass = Class.forName(className, false, Thread.currentThread().getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new AssertionError(e);
+ }
+
+ notifier.fireTestStarted(child);
+
+ // CTS has a phase where it "collects" all the tests first.
+ // Just report that the test passes without actually running it here.
+ if (mSkipExecution) {
+ notifier.fireTestFinished(child);
+ continue;
+ }
+
+ // Avoid looking at all the methods by just using the string method name.
+ if (!SingleTestNgTestExecutor.execute(klass, methodName)) {
+ // TODO: get the error messages from testng somehow.
+ notifier.fireTestFailure(new Failure(child, new AssertionError()));
+ }
+ else {
+ notifier.fireTestFinished(child);
+ }
+ // TODO: Check @Test(enabled=false) and invoke #fireTestIgnored instead.
+ }
+ }
+
+ /**
+ * Recursively (preorder traversal) apply the filter to all the descriptions.
+ *
+ * @return null if the filter rejects the whole tree.
+ */
+ private static Description filterDescription(Description desc, Filter filter) {
+ if (!filter.shouldRun(desc)) { // XX: Does the filter itself do the recursion?
+ return null;
+ }
+
+ Description newDesc = desc.childlessCopy();
+
+ // Return leafs.
+ if (!descriptionHasChildren(desc)) {
+ return newDesc;
+ }
+
+ // Filter all subtrees, only copying them if the filter accepts them.
+ for (Description child : desc.getChildren()) {
+ Description filteredChild = filterDescription(child, filter);
+
+ if (filteredChild != null) {
+ newDesc.addChild(filteredChild);
+ }
+ }
+
+ return newDesc;
+ }
+
+ private Description generateTestNgDescription(Class<?> cls) {
+ // Add the overall class description as the parent.
+ Description parent = Description.createSuiteDescription(cls);
+
+ if (DEBUG) {
+ Log.d("TestNgRunner", "Generating TestNg Description for class " + cls.getName());
+ }
+
+ // Add each test method as a child.
+ for (Method m : cls.getDeclaredMethods()) {
+
+ // Filter to only 'public void' signatures.
+ if ((m.getModifiers() & Modifier.PUBLIC) == 0) {
+ continue;
+ }
+
+ if (!m.getReturnType().equals(Void.TYPE)) {
+ continue;
+ }
+
+ // Note that TestNG methods may actually have parameters
+ // (e.g. with @DataProvider) which TestNG will populate itself.
+
+ // Add [Class, MethodName] as a Description leaf node.
+ String name = m.getName();
+
+ if (!mMethodSet.add(name)) {
+ // Overloaded methods have the same name, don't add them twice.
+ if (DEBUG) {
+ Log.d("TestNgRunner", "Already added child " + cls.getName() + "#" + name);
+ }
+ continue;
+ }
+
+ Description child = Description.createTestDescription(cls, name);
+
+ parent.addChild(child);
+
+ if (DEBUG) {
+ Log.d("TestNgRunner", "Add child " + cls.getName() + "#" + name);
+ }
+ }
+
+ return parent;
+ }
+
+ private static boolean descriptionHasChildren(Description desc) {
+ // Note: Although "desc.isTest()" is equivalent to "!desc.getChildren().isEmpty()"
+ // we add the pre-requisite 2 extra null checks to avoid throwing NPEs.
+ return desc != null && desc.getChildren() != null && !desc.getChildren().isEmpty();
+ }
+}
diff --git a/tests/core/runner/src/com/android/cts/core/runner/support/TestNgRunnerBuilder.java b/tests/core/runner/src/com/android/cts/core/runner/support/TestNgRunnerBuilder.java
new file mode 100644
index 0000000..621eeb5
--- /dev/null
+++ b/tests/core/runner/src/com/android/cts/core/runner/support/TestNgRunnerBuilder.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.cts.core.runner.support;
+
+import android.support.test.internal.util.AndroidRunnerParams;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.junit.runner.Runner;
+import org.junit.runners.model.RunnerBuilder;
+
+import org.testng.annotations.Test;
+
+/**
+ * A {@link RunnerBuilder} that can TestNG tests.
+ */
+class TestNgRunnerBuilder extends RunnerBuilder {
+ private static final String TESTNG_TEST = "org.testng.annotations.Test";
+ private final AndroidRunnerParams mRunnerParams;
+
+ /**
+ * @param runnerParams {@link AndroidRunnerParams} that stores common runner parameters
+ */
+ TestNgRunnerBuilder(AndroidRunnerParams runnerParams) {
+ mRunnerParams = runnerParams;
+ }
+
+
+ // Returns a TestNG runner for this class, only if it is a class
+ // annotated with testng's @Test or has any methods with @Test in it.
+ @Override
+ public Runner runnerForClass(Class<?> testClass) {
+ if (isTestNgTestClass(testClass)) {
+ return new TestNgRunner(testClass, mRunnerParams.isSkipExecution());
+ }
+
+ return null;
+ }
+
+ private static boolean isTestNgTestClass(Class<?> cls) {
+ // TestNG test is either marked @Test at the class
+ if (cls.getAnnotation(Test.class) != null) {
+ return true;
+ }
+
+ // Or It's marked @Test at the method level
+ for (Method m : cls.getDeclaredMethods()) {
+ if (m.getAnnotation(Test.class) != null) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/tests/dram/src/android/dram/cts/BandwidthTest.java b/tests/dram/src/android/dram/cts/BandwidthTest.java
index 2096402..1eb307b 100644
--- a/tests/dram/src/android/dram/cts/BandwidthTest.java
+++ b/tests/dram/src/android/dram/cts/BandwidthTest.java
@@ -35,6 +35,7 @@
*/
public class BandwidthTest extends CtsAndroidTestCase {
private static final String TAG = BandwidthTest.class.getSimpleName();
+ private static final String REPORT_LOG_NAME = "CtsDramTestCases";
private static final int MEMCPY_REPETITION = 10;
private static final int MEMSET_REPETITION = 30;
private static final int REPEAT_IN_EACH_CALL = 100;
@@ -165,13 +166,13 @@
for (int i = 0; i < MEMCPY_REPETITION; i++) {
result[i] = MemoryNative.runMemcpy(bufferSize, repeatInEachCall);
}
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("memcpy time", result, ResultType.LOWER_BETTER,
- ResultUnit.MS);
+ String streamName = "run_memcpy";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValue("buffer_size", bufferSize, ResultType.NEUTRAL, ResultUnit.NONE);
+ report.addValues("memcpy_time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
double[] mbps = Stat.calcRatePerSecArray(
(double)bufferSize * repeatInEachCall / 1024.0 / 1024.0, result);
- report.addValues("memcpy throughput", mbps, ResultType.HIGHER_BETTER,
- ResultUnit.MBPS);
+ report.addValues("memcpy_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
Stat.StatResult stat = Stat.getStatWithOutlierRejection(mbps, OUTLIER_THRESHOLD);
if (stat.mDataCount != result.length) {
Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
@@ -183,9 +184,9 @@
double pixels = size.x * size.y;
// now this represents how many times the whole screen can be copied in a sec.
double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
- report.addValue("memcpy in fps", screensPerSecAverage,
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
- report.setSummary("memcpy throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ report.addValue("memcpy_in_fps", screensPerSecAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.FPS);
+ report.setSummary("memcpy_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
report.submit(getInstrumentation());
}
@@ -200,11 +201,13 @@
for (int i = 0; i < MEMSET_REPETITION; i++) {
result[i] = MemoryNative.runMemset(bufferSize, repeatInEachCall, MEMSET_CHAR);
}
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("memset time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ String streamName = "run_memset";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValue("buffer_size", bufferSize, ResultType.NEUTRAL, ResultUnit.NONE);
+ report.addValues("memset_time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
double[] mbps = Stat.calcRatePerSecArray(
(double)bufferSize * repeatInEachCall / 1024.0 / 1024.0, result);
- report.addValues("memset throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("memset_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
Stat.StatResult stat = Stat.getStatWithOutlierRejection(mbps, OUTLIER_THRESHOLD);
if (stat.mDataCount != result.length) {
Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
@@ -216,9 +219,9 @@
double pixels = size.x * size.y;
// now this represents how many times the whole screen can be copied in a sec.
double screensPerSecAverage = stat.mAverage / pixels * 1024.0 * 1024.0 / 4.0;
- report.addValue("memset in fps", screensPerSecAverage,
- ResultType.HIGHER_BETTER, ResultUnit.FPS);
- report.setSummary("memset throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ report.addValue("memset_in_fps", screensPerSecAverage, ResultType.HIGHER_BETTER,
+ ResultUnit.FPS);
+ report.setSummary("memset_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
report.submit(getInstrumentation());
}
diff --git a/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java b/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java
index 991f9bf..a6f069d 100644
--- a/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/AlmostFullTest.java
@@ -34,6 +34,7 @@
private static final String DIR_RANDOM_WR = "RANDOM_WR";
private static final String DIR_RANDOM_RD = "RANDOM_RD";
private static final String TAG = "AlmostFullTest";
+ private static final String REPORT_LOG_NAME = "CtsFileSystemTestCases";
private static final long FREE_SPACE_FINAL = 1000L * 1024 * 1024L;
@@ -107,10 +108,9 @@
}
final int BUFFER_SIZE = 10 * 1024 * 1024;
final int NUMBER_REPETITION = 10;
- DeviceReportLog report = new DeviceReportLog();
- FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, report, FILE_SIZE,
- BUFFER_SIZE, NUMBER_REPETITION);
- report.submit(getInstrumentation());
+ String streamName = "test_sequential_update";
+ FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, FILE_SIZE, BUFFER_SIZE,
+ NUMBER_REPETITION, REPORT_LOG_NAME, streamName);
}
// TODO: file size too small and caching will give wrong better result.
@@ -124,7 +124,8 @@
Log.w(TAG, "too little space: " + freeDisk);
return;
}
- DeviceReportLog report = new DeviceReportLog();
+ String streamName = "test_random_read";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize, BUFFER_SIZE);
report.submit(getInstrumentation());
}
@@ -138,7 +139,8 @@
Log.w(TAG, "too little space: " + freeDisk);
return;
}
- DeviceReportLog report = new DeviceReportLog();
+ String streamName = "test_random_update";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize, BUFFER_SIZE);
report.submit(getInstrumentation());
}
diff --git a/tests/filesystem/src/android/filesystem/cts/FileUtil.java b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
index baefaa0..fc8eee0 100755
--- a/tests/filesystem/src/android/filesystem/cts/FileUtil.java
+++ b/tests/filesystem/src/android/filesystem/cts/FileUtil.java
@@ -20,6 +20,7 @@
import android.cts.util.SystemUtil;
import android.util.Log;
+import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.MeasureRun;
import com.android.compatibility.common.util.MeasureTime;
import com.android.compatibility.common.util.ReportLog;
@@ -303,13 +304,12 @@
randomFile.close();
double[] mbps = Stat.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
times);
- report.addValues("read throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("read_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
// This is just the amount of IO returned from kernel. So this is performance neutral.
- report.addValues("read amount", rdAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
+ report.addValues("read_amount", rdAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
Stat.StatResult stat = Stat.getStat(mbps);
- report.setSummary("read throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ report.setSummary("read_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
}
@@ -356,13 +356,11 @@
randomFile.close();
double[] mbps = Stat.calcRatePerSecArray((double)fileSize / runsInOneGo / 1024 / 1024,
times);
- report.addValues("write throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- report.addValues("write amount", wrAmount, ResultType.NEUTRAL,
- ResultUnit.BYTE);
+ report.addValues("write_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("write_amount", wrAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
Stat.StatResult stat = Stat.getStat(mbps);
- report.setSummary("write throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ report.setSummary("write_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
}
@@ -376,8 +374,9 @@
* @param numberRepetition
* @throws IOException
*/
- public static void doSequentialUpdateTest(Context context, String dirName, ReportLog report,
- long fileSize, int bufferSize, int numberRepetition) throws Exception {
+ public static void doSequentialUpdateTest(Context context, String dirName, long fileSize,
+ int bufferSize, int numberRepetition, String reportName, String streamName)
+ throws Exception {
File file = FileUtil.createNewFilledFile(context,
dirName, fileSize);
final byte[] data = FileUtil.generateRandomData(bufferSize);
@@ -385,6 +384,8 @@
double[] mbpsAll = new double[numberRepetition * numberRepeatInOneRun];
for (int i = 0; i < numberRepetition; i++) {
Log.i(TAG, "starting " + i + " -th round");
+ DeviceReportLog report = new DeviceReportLog(reportName, streamName);
+ report.addValue("round", i, ResultType.NEUTRAL, ResultUnit.NONE);
final RandomAccessFile randomFile = new RandomAccessFile(file, "rwd"); // force O_SYNC
randomFile.seek(0L);
double[] times = MeasureTime.measure(numberRepeatInOneRun, new MeasureRun() {
@@ -397,15 +398,18 @@
randomFile.close();
double[] mbps = Stat.calcRatePerSecArray((double)bufferSize / 1024 / 1024,
times);
- report.addValues(i + "-th round throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
int offset = i * numberRepeatInOneRun;
for (int j = 0; j < mbps.length; j++) {
mbpsAll[offset + j] = mbps[j];
}
+ report.submit();
}
Stat.StatResult stat = Stat.getStat(mbpsAll);
- report.setSummary("update throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ DeviceReportLog report = new DeviceReportLog(reportName, String.format("%s_average",
+ streamName));
+ report.addValue("update_throughput", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
+ report.submit();
}
}
diff --git a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
index dff3723..d2d4e84 100644
--- a/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/RandomRWTest.java
@@ -24,6 +24,7 @@
public class RandomRWTest extends CtsAndroidTestCase {
private static final String DIR_RANDOM_WR = "RANDOM_WR";
private static final String DIR_RANDOM_RD = "RANDOM_RD";
+ private static final String REPORT_LOG_NAME = "CtsFileSystemTestCases";
@Override
protected void tearDown() throws Exception {
@@ -39,7 +40,8 @@
if (fileSize == 0) { // not enough space, give up
return;
}
- DeviceReportLog report = new DeviceReportLog();
+ String streamName = "test_random_read";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
FileUtil.doRandomReadTest(getContext(), DIR_RANDOM_RD, report, fileSize,
READ_BUFFER_SIZE);
report.submit(getInstrumentation());
@@ -50,7 +52,8 @@
public void testRandomUpdate() throws Exception {
final int WRITE_BUFFER_SIZE = 4 * 1024;
final long fileSize = 256 * 1024 * 1024;
- DeviceReportLog report = new DeviceReportLog();
+ String streamName = "test_random_update";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
FileUtil.doRandomWriteTest(getContext(), DIR_RANDOM_WR, report, fileSize,
WRITE_BUFFER_SIZE);
report.submit(getInstrumentation());
diff --git a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
index 3b7a45f..d725614 100644
--- a/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
+++ b/tests/filesystem/src/android/filesystem/cts/SequentialRWTest.java
@@ -34,6 +34,7 @@
private static final String DIR_SEQ_WR = "SEQ_WR";
private static final String DIR_SEQ_UPDATE = "SEQ_UPDATE";
private static final String DIR_SEQ_RD = "SEQ_RD";
+ private static final String REPORT_LOG_NAME = "CtsFileSystemTestCases";
private static final int BUFFER_SIZE = 10 * 1024 * 1024;
@Override
@@ -51,7 +52,8 @@
return;
}
final int numberOfFiles =(int)(fileSize / BUFFER_SIZE);
- DeviceReportLog report = new DeviceReportLog();
+ String streamName = "test_single_sequential_write";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
report.addValue("files", numberOfFiles, ResultType.NEUTRAL, ResultUnit.COUNT);
final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
final File[] files = FileUtil.createNewFiles(getContext(), DIR_SEQ_WR,
@@ -66,12 +68,10 @@
}
});
double[] mbps = Stat.calcRatePerSecArray((double)BUFFER_SIZE / 1024 / 1024, times);
- report.addValues("write throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
- report.addValues("write amount", wrAmount, ResultType.NEUTRAL,
- ResultUnit.BYTE);
+ report.addValues("write_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("write_amount", wrAmount, ResultType.NEUTRAL, ResultUnit.BYTE);
Stat.StatResult stat = Stat.getStat(mbps);
- report.setSummary("write throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ report.setSummary("write_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
report.submit(getInstrumentation());
}
@@ -83,10 +83,9 @@
return;
}
final int NUMBER_REPETITION = 6;
- DeviceReportLog report = new DeviceReportLog();
- FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, report, fileSize,
- BUFFER_SIZE, NUMBER_REPETITION);
- report.submit(getInstrumentation());
+ String streamName = "test_single_sequential_update";
+ FileUtil.doSequentialUpdateTest(getContext(), DIR_SEQ_UPDATE, fileSize, BUFFER_SIZE,
+ NUMBER_REPETITION, REPORT_LOG_NAME, streamName);
}
@TimeoutReq(minutes = 30)
@@ -99,8 +98,10 @@
final File file = FileUtil.createNewFilledFile(getContext(),
DIR_SEQ_RD, fileSize);
long finish = System.currentTimeMillis();
- DeviceReportLog report = new DeviceReportLog();
- report.addValue("write throughput for test file of length " + fileSize,
+ String streamName = "test_single_sequential_read";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValue("file_size", fileSize, ResultType.NEUTRAL, ResultUnit.NONE);
+ report.addValue("write_throughput",
Stat.calcRatePerSec((double)fileSize / 1024 / 1024, finish - start),
ResultType.HIGHER_BETTER, ResultUnit.MBPS);
@@ -121,10 +122,9 @@
}
});
double[] mbps = Stat.calcRatePerSecArray((double)fileSize / 1024 / 1024, times);
- report.addValues("read throughput",
- mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
+ report.addValues("read_throughput", mbps, ResultType.HIGHER_BETTER, ResultUnit.MBPS);
Stat.StatResult stat = Stat.getStat(mbps);
- report.setSummary("read throughput", stat.mAverage, ResultType.HIGHER_BETTER,
+ report.setSummary("read_throughput_average", stat.mAverage, ResultType.HIGHER_BETTER,
ResultUnit.MBPS);
report.submit(getInstrumentation());
}
diff --git a/tests/jank/src/android/jank/cts/CtsJankTestBase.java b/tests/jank/src/android/jank/cts/CtsJankTestBase.java
index fb2f867..6015726 100644
--- a/tests/jank/src/android/jank/cts/CtsJankTestBase.java
+++ b/tests/jank/src/android/jank/cts/CtsJankTestBase.java
@@ -27,22 +27,23 @@
public abstract class CtsJankTestBase extends JankTestBase {
+ private static final String REPORT_LOG_NAME = "CtsJankDeviceTestCases";
private UiDevice mDevice;
private DeviceReportLog mLog;
@Override
public void afterTest(Bundle metrics) {
String source = String.format("%s#%s", getClass().getCanonicalName(), getName());
- mLog.addValue(source, WindowContentFrameStatsMonitor.KEY_AVG_FPS,
+ mLog.addValue(source, "frame_fps",
metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_FPS),
ResultType.HIGHER_BETTER, ResultUnit.FPS);
- mLog.addValue(source, WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME,
+ mLog.addValue(source, "frame_max_frame_duration",
metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_LONGEST_FRAME),
ResultType.LOWER_BETTER, ResultUnit.MS);
- mLog.addValue(source, WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY,
+ mLog.addValue(source, "frame_max_jank",
metrics.getInt(WindowContentFrameStatsMonitor.KEY_MAX_NUM_JANKY),
ResultType.LOWER_BETTER, ResultUnit.COUNT);
- mLog.setSummary(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY,
+ mLog.setSummary("frame_avg_jank",
metrics.getDouble(WindowContentFrameStatsMonitor.KEY_AVG_NUM_JANKY),
ResultType.LOWER_BETTER, ResultUnit.COUNT);
}
@@ -50,7 +51,8 @@
@Override
protected void setUp() throws Exception {
super.setUp();
- mLog = new DeviceReportLog();
+ String streamName = "cts_device_jank_test";
+ mLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
// fix device orientation
mDevice = UiDevice.getInstance(getInstrumentation());
mDevice.setOrientationNatural();
diff --git a/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java b/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
index 4daabb7..d8e181c 100644
--- a/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
+++ b/tests/jdwp/runner/host-side/src/com/android/compatibility/testtype/DalvikTest.java
@@ -37,6 +37,7 @@
import com.android.tradefed.testtype.IRuntimeHintProvider;
import com.android.tradefed.testtype.IShardableTest;
import com.android.tradefed.testtype.ITestCollector;
+import com.android.tradefed.testtype.ITestFileFilterReceiver;
import com.android.tradefed.testtype.ITestFilterReceiver;
import com.android.tradefed.util.ArrayUtil;
import com.android.tradefed.util.TimeVal;
@@ -45,8 +46,10 @@
import vogar.ExpectationStore;
import vogar.ModeId;
+import java.io.BufferedReader;
import java.io.File;
import java.io.FilenameFilter;
+import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -54,7 +57,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -63,7 +65,8 @@
* A wrapper to run tests against Dalvik.
*/
public class DalvikTest implements IAbiReceiver, IBuildReceiver, IDeviceTest, IRemoteTest,
- IRuntimeHintProvider, IShardableTest, ITestCollector, ITestFilterReceiver {
+ IRuntimeHintProvider, IShardableTest, ITestCollector, ITestFileFilterReceiver,
+ ITestFilterReceiver {
private static final String TAG = DalvikTest.class.getSimpleName();
@@ -131,6 +134,16 @@
description = "The exclude filters of the test name to run.")
private List<String> mExcludeFilters = new ArrayList<>();
+ @Option(name = "test-file-include-filter",
+ description="A file containing a list of line separated test classes and optionally"
+ + " methods to include")
+ private File mIncludeTestFile = null;
+
+ @Option(name = "test-file-exclude-filter",
+ description="A file containing a list of line separated test classes and optionally"
+ + " methods to exclude")
+ private File mExcludeTestFile = null;
+
@Option(name = "runtime-hint",
isTimeVal = true,
description="The hint about the test's runtime.")
@@ -224,6 +237,22 @@
* {@inheritDoc}
*/
@Override
+ public void setIncludeTestFile(File testFile) {
+ mIncludeTestFile = testFile;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setExcludeTestFile(File testFile) {
+ mExcludeTestFile = testFile;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
public long getRuntimeHint() {
return mRuntimeHint;
}
@@ -244,56 +273,33 @@
String abiName = mAbi.getName();
String bitness = AbiUtils.getBitness(abiName);
- File temp = null;
- PrintWriter out = null;
+ File tmpExcludeFile = null;
try {
- Set<File> expectationFiles = new HashSet<>();
- for (File f : mBuildHelper.getTestsDir().listFiles(
- new ExpectationFileFilter(mRunName))) {
- expectationFiles.add(f);
- }
- ExpectationStore store = ExpectationStore.parse(expectationFiles, ModeId.DEVICE);
-
- ExpectationStore resourceStore = null;
- if (mKnownFailures != null) {
- Splitter splitter = Splitter.on(',').trimResults();
- Set<String> knownFailuresFileList =
- new LinkedHashSet<>(splitter.splitToList(mKnownFailures));
- resourceStore = ExpectationStore.parseResources(
- getClass(), knownFailuresFileList, ModeId.DEVICE);
- }
-
- // Work around because there are to many expectations to pass via command line
- temp = File.createTempFile("excludes", "txt");
- out = new PrintWriter(temp);
- for (String exclude : store.getAllFailures().keySet()) {
- out.println(exclude);
- }
- for (String exclude : store.getAllOutComes().keySet()) {
- out.println(exclude);
- }
- // Add expectations from resources
- if (resourceStore != null) {
- for (String exclude : resourceStore.getAllFailures().keySet()) {
- out.println(exclude);
- }
- for (String exclude : resourceStore.getAllOutComes().keySet()) {
- out.println(exclude);
- }
- }
- out.flush();
- if (!mDevice.pushFile(temp, EXCLUDE_FILE)) {
- Log.logAndDisplay(LogLevel.ERROR, TAG, "Couldn't push file: " + temp);
+ // push one file of exclude filters to the device
+ tmpExcludeFile = getExcludeFile();
+ if (!mDevice.pushFile(tmpExcludeFile, EXCLUDE_FILE)) {
+ Log.logAndDisplay(LogLevel.ERROR, TAG, "Couldn't push file: " + tmpExcludeFile);
}
} catch (IOException e) {
- throw new RuntimeException("Failed to parse expectations");
+ throw new RuntimeException("Failed to parse expectations", e);
} finally {
- if (out != null) {
- out.close();
+ if (tmpExcludeFile != null) {
+ tmpExcludeFile.delete();
}
- temp.delete();
}
+ // push one file of include filters to the device, if file exists
+ if (mIncludeTestFile != null) {
+ String path = mIncludeTestFile.getAbsolutePath();
+ if (!mIncludeTestFile.isFile() || !mIncludeTestFile.canRead()) {
+ throw new RuntimeException(String.format("Failed to read include file %s", path));
+ }
+ if (!mDevice.pushFile(mIncludeTestFile, INCLUDE_FILE)) {
+ Log.logAndDisplay(LogLevel.ERROR, TAG, "Couldn't push file: " + path);
+ }
+ }
+
+
// Create command
mDalvikArgs.add("-Duser.name=shell");
mDalvikArgs.add("-Duser.language=en");
@@ -374,6 +380,82 @@
mDevice.executeShellCommand(command, receiver, mPerTestTimeout, TimeUnit.MINUTES, 1);
}
+ /*
+ * Due to known failures, there are typically too many excludes to pass via command line.
+ * Collect excludes from .expectation files in the testcases directory, from files in the
+ * module's resources directory, and from mExcludeTestFile, if set.
+ */
+ private File getExcludeFile() throws IOException {
+ File excludeFile = null;
+ PrintWriter out = null;
+
+ try {
+ excludeFile = File.createTempFile("excludes", "txt");
+ out = new PrintWriter(excludeFile);
+ // create expectation store from set of expectation files found in testcases dir
+ Set<File> expectationFiles = new HashSet<>();
+ for (File f : mBuildHelper.getTestsDir().listFiles(
+ new ExpectationFileFilter(mRunName))) {
+ expectationFiles.add(f);
+ }
+ ExpectationStore testsDirStore =
+ ExpectationStore.parse(expectationFiles, ModeId.DEVICE);
+ // create expectation store from expectation files found in module resources dir
+ ExpectationStore resourceStore = null;
+ if (mKnownFailures != null) {
+ Splitter splitter = Splitter.on(',').trimResults();
+ Set<String> knownFailuresFiles =
+ new HashSet<>(splitter.splitToList(mKnownFailures));
+ resourceStore = ExpectationStore.parseResources(
+ getClass(), knownFailuresFiles, ModeId.DEVICE);
+ }
+ // Add expectations from testcases dir
+ for (String exclude : testsDirStore.getAllFailures().keySet()) {
+ out.println(exclude);
+ }
+ for (String exclude : testsDirStore.getAllOutComes().keySet()) {
+ out.println(exclude);
+ }
+ // Add expectations from resources dir
+ if (resourceStore != null) {
+ for (String exclude : resourceStore.getAllFailures().keySet()) {
+ out.println(exclude);
+ }
+ for (String exclude : resourceStore.getAllOutComes().keySet()) {
+ out.println(exclude);
+ }
+ }
+ // Add excludes from test-file-exclude-filter option
+ for (String exclude : getFiltersFromFile(mExcludeTestFile)) {
+ out.println(exclude);
+ }
+ out.flush();
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ return excludeFile;
+ }
+
+
+ /*
+ * Helper method that reads filters from a file into a set.
+ * Returns an empty set given a null file
+ */
+ private static Set<String> getFiltersFromFile(File f) throws IOException {
+ Set<String> filters = new HashSet<String>();
+ if (f != null) {
+ BufferedReader reader = new BufferedReader(new FileReader(f));
+ String filter = null;
+ while ((filter = reader.readLine()) != null) {
+ filters.add(filter);
+ }
+ reader.close();
+ }
+ return filters;
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/tests/libcore/Android.mk b/tests/libcore/Android.mk
index b24babd..72b6ebc 100644
--- a/tests/libcore/Android.mk
+++ b/tests/libcore/Android.mk
@@ -22,6 +22,7 @@
apache-harmony-tests \
bouncycastle-nojarjar \
conscrypt-tests \
+ core-ojtests-public \
core-tests \
cts-core-test-runner \
jsr166-tests \
diff --git a/tests/libcore/AndroidTest.xml b/tests/libcore/AndroidTest.xml
index b2fc10a..1e47502 100644
--- a/tests/libcore/AndroidTest.xml
+++ b/tests/libcore/AndroidTest.xml
@@ -32,5 +32,7 @@
<option name="instrumentation-arg" key="core-expectations"
value="/knownfailures.txt,/brokentests.txt,/icebox.txt,/taggedtests.txt,/expectations/cts-runner-specific-failures.txt" />
<option name="runtime-hint" value="45m"/>
+ <!-- 20x default timeout of 600sec -->
+ <option name="shell-timeout" value="12000000"/>
</test>
</configuration>
diff --git a/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java b/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java
index d737dbf..cbd8d52 100644
--- a/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java
+++ b/tests/openglperf2/src/android/opengl2/cts/primitive/GLPrimitiveBenchmark.java
@@ -30,6 +30,7 @@
private static final int NUM_FRAMES = 100;
private static final int NUM_ITERATIONS = 8;
private static final int TIMEOUT = 1000000;
+ private static final String REPORT_LOG_NAME = "CtsOpenGlPerf2TestCases";
public GLPrimitiveBenchmark() {
super(GLPrimitiveActivity.class);
@@ -40,7 +41,9 @@
*/
@TimeoutReq(minutes = 100)
public void testFullPipelineOffscreen() throws Exception {
- runBenchmark(BenchmarkName.FullPipeline, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_full_pipeline_offscreen";
+ runBenchmark(BenchmarkName.FullPipeline, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -48,7 +51,9 @@
*/
@TimeoutReq(minutes = 100)
public void testFullPipelineOnscreen() throws Exception {
- runBenchmark(BenchmarkName.FullPipeline, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_full_pipeline_onscreen";
+ runBenchmark(BenchmarkName.FullPipeline, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -56,7 +61,9 @@
*/
@TimeoutReq(minutes = 100)
public void testPixelOutputOffscreen() throws Exception {
- runBenchmark(BenchmarkName.PixelOutput, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_pixel_output_offscreen";
+ runBenchmark(BenchmarkName.PixelOutput, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -64,7 +71,9 @@
*/
@TimeoutReq(minutes = 100)
public void testPixelOutputOnscreen() throws Exception {
- runBenchmark(BenchmarkName.PixelOutput, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_pixel_output_onscreen";
+ runBenchmark(BenchmarkName.PixelOutput, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -72,7 +81,9 @@
*/
@TimeoutReq(minutes = 100)
public void testShaderPerfOffscreen() throws Exception {
- runBenchmark(BenchmarkName.ShaderPerf, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_shader_perf_offscreen";
+ runBenchmark(BenchmarkName.ShaderPerf, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -80,7 +91,9 @@
*/
@TimeoutReq(minutes = 100)
public void testShaderPerfOnscreen() throws Exception {
- runBenchmark(BenchmarkName.ShaderPerf, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_shader_perf_onscreen";
+ runBenchmark(BenchmarkName.ShaderPerf, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -88,7 +101,9 @@
*/
@TimeoutReq(minutes = 100)
public void testContextSwitchOffscreen() throws Exception {
- runBenchmark(BenchmarkName.ContextSwitch, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_context_switch_offscreen";
+ runBenchmark(BenchmarkName.ContextSwitch, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -96,7 +111,9 @@
*/
@TimeoutReq(minutes = 100)
public void testContextSwitchOnscreen() throws Exception {
- runBenchmark(BenchmarkName.ContextSwitch, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
+ String streamName = "test_context_switch_onscreen";
+ runBenchmark(BenchmarkName.ContextSwitch, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT,
+ streamName);
}
/**
@@ -107,10 +124,11 @@
* @param numFrames The number of frames to render.
* @param numIterations The number of iterations to run, each iteration has a bigger workload.
* @param timeout The milliseconds to wait for an iteration of the benchmark before timing out.
+ * @param streamName The name of the stream of test metrics.
* @throws Exception If the benchmark could not be run.
*/
private void runBenchmark(BenchmarkName benchmark, boolean offscreen, int numFrames,
- int numIterations, int timeout) throws Exception {
+ int numIterations, int timeout, String streamName) throws Exception {
String benchmarkName = benchmark.toString();
Intent intent = new Intent();
intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
@@ -132,8 +150,8 @@
// TODO: maybe standard deviation / RMSE will be useful?
- DeviceReportLog report = new DeviceReportLog();
- report.setSummary("Average FPS", score, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.setSummary("average_fps", score, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
report.submit(getInstrumentation());
}
}
diff --git a/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java b/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java
index 196207c..898ccfd 100644
--- a/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java
+++ b/tests/openglperf2/src/android/opengl2/cts/reference/GLReferenceBenchmark.java
@@ -31,6 +31,7 @@
private static final int NUM_SCENES = 2;
private static final int NUM_FRAMES = NUM_FRAMES_PER_SCENE * NUM_SCENES;
private static final int TIMEOUT = 1000000;
+ private static final String REPORT_LOG_NAME = "CtsOpenGlPerf2TestCases";
public GLReferenceBenchmark() {
super(GLReferenceActivity.class);
@@ -65,15 +66,16 @@
double updateAverage = updateSum / NUM_FRAMES;
double renderAverage = renderSum / NUM_FRAMES;
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("Set Up Times", setUpTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
- report.addValue("Update Time Average", updateAverage, ResultType.LOWER_BETTER,
+ String streamName = "test_reference_benchmark";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValues("set_up_times", setUpTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValue("update_time_average", updateAverage, ResultType.LOWER_BETTER,
ResultUnit.MS);
- report.addValue("Render Time Average", renderAverage, ResultType.LOWER_BETTER,
+ report.addValue("render_time_average", renderAverage, ResultType.LOWER_BETTER,
ResultUnit.MS);
totalTime = setUpTimes[0] + setUpTimes[1] + setUpTimes[2] + setUpTimes[3] +
updateAverage + renderAverage;
- report.setSummary("Total Time Average", totalTime, ResultType.LOWER_BETTER,
+ report.setSummary("total_time_average", totalTime, ResultType.LOWER_BETTER,
ResultUnit.MS);
report.submit(getInstrumentation());
}
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java b/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
index 7f8e2f6..a3a6bd1 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
@@ -31,6 +31,12 @@
extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
/**
+ * Name of the report log. Test metrics will be written out to ths report. The name must match
+ * the test module name.
+ */
+ private static final String REPORT_LOG_NAME = "CtsSampleDeviceTestCases";
+
+ /**
* Sample numbers used by the sample tests.
*/
private static final int MULTIPLICATION_NUMBER_1 = 23;
@@ -60,9 +66,8 @@
assertTrue("Multiplication result do not match", product == MULTIPLICATION_RESULT);
// Log metrics from the test.
- String reportLogName = "SampleDeviceTestMetrics";
- String streamName = "test_multiplication_metrics";
- DeviceReportLog reportLog = new DeviceReportLog(reportLogName, streamName);
+ String streamName = "test_multiplication";
+ DeviceReportLog reportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
reportLog.addValue(EXPECTED_PRODUCT_TAG, 1.0 * MULTIPLICATION_RESULT, ResultType.NEUTRAL,
ResultUnit.NONE);
reportLog.addValue(ACTUAL_PRODUCT_TAG, 1.0 * product, ResultType.NEUTRAL, ResultUnit.NONE);
@@ -74,7 +79,7 @@
* Sample test to check counting up.
*/
public void testCountUp() {
- String streamName = "test_count_up_metrics";
+ String streamName = "test_count_up";
countHelper(1, streamName);
}
@@ -82,7 +87,7 @@
* Sample test to check counting down.
*/
public void testCountDown() {
- String streamName = "test_count_down_metrics";
+ String streamName = "test_count_down";
countHelper(2, streamName);
}
@@ -111,8 +116,7 @@
}
// Log metrics.
- String reportLogName = "SampleDeviceTestMetrics";
- DeviceReportLog reportLog = new DeviceReportLog(reportLogName, streamName);
+ DeviceReportLog reportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
reportLog.addValue(START_TAG, 1.0 * start, ResultType.NEUTRAL, ResultUnit.NONE);
reportLog.addValue(END_TAG, 1.0 * end, ResultType.NEUTRAL, ResultUnit.NONE);
reportLog.setSummary(END_TAG, 1.0 * end, ResultType.NEUTRAL, ResultUnit.NONE);
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
index f8f7a6b..41384b0 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
@@ -36,6 +36,11 @@
public class SampleDeviceResultTest extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
/**
+ * Name of the report log to store test metrics.
+ */
+ private static final String REPORT_LOG_NAME = "CtsSampleDeviceTestCases";
+
+ /**
* The number of times to repeat the test.
*/
private static final int REPEAT = 5;
@@ -76,14 +81,13 @@
// Compute the stats.
Stat.StatResult stat = Stat.getStat(result);
// Create a new report to hold the metrics.
- String reportLogName = "SampleDeviceTestMetrics";
- String streamName = "test_sort_metrics";
- DeviceReportLog reportLog = new DeviceReportLog(reportLogName, streamName);
+ String streamName = "test_sort";
+ DeviceReportLog reportLog = new DeviceReportLog(REPORT_LOG_NAME, streamName);
// Add the results to the report.
reportLog.addValues("times", result, ResultType.LOWER_BETTER, ResultUnit.MS);
reportLog.addValue("min", stat.mMin, ResultType.LOWER_BETTER, ResultUnit.MS);
reportLog.addValue("max", stat.mMax, ResultType.LOWER_BETTER, ResultUnit.MS);
- // Every report must have a summary,
+ // Set a summary.
reportLog.setSummary("average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
// Submit the report to the given instrumentation.
reportLog.submit(getInstrumentation());
diff --git a/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java b/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
index fa7f402..6d8984a 100644
--- a/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
+++ b/tests/simplecpu/src/android/simplecpu/cts/SimpleCpuTest.java
@@ -38,6 +38,7 @@
private static final int NUMBER_REPEAT = 20;
// reject data outside +/- this value * median
private static final double OUTLIER_THRESHOLD = 0.1;
+ private static final String REPORT_LOG_NAME = "CtsSimpleCpuTestCases";
@Override
protected void setUp() throws Exception {
@@ -100,13 +101,15 @@
for (int i = 0; i < numberRepeat; i++) {
result[i] = CpuNative.runSort(arrayLength, numberRepeatInEachCall);
}
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("sorting time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
+ String streamName = "do_test_sort";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValue("array_length", arrayLength, ResultType.NEUTRAL, ResultUnit.NONE);
+ report.addValues("sorting_time", result, ResultType.LOWER_BETTER, ResultUnit.MS);
Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
if (stat.mDataCount != result.length) {
Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
}
- report.setSummary("sorting time", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.setSummary("sorting_time_average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
report.submit(getInstrumentation());
}
@@ -122,14 +125,16 @@
for (int i = 0; i < numberRepeat; i++) {
result[i] = CpuNative.runMatrixMultiplication(n, numberRepeatInEachCall);
}
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("matrix mutiplication time", result, ResultType.LOWER_BETTER,
+ String streamName = "do_matrix_multiplication";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValue("matrix_dimension", n, ResultType.NEUTRAL, ResultUnit.NONE);
+ report.addValues("matrix_mutiplication_time", result, ResultType.LOWER_BETTER,
ResultUnit.MS);
Stat.StatResult stat = Stat.getStatWithOutlierRejection(result, OUTLIER_THRESHOLD);
if (stat.mDataCount != result.length) {
Log.w(TAG, "rejecting " + (result.length - stat.mDataCount) + " outliers");
}
- report.setSummary("matrix mutiplication time", stat.mAverage,
+ report.setSummary("matrix_mutiplication_time_average", stat.mAverage,
ResultType.LOWER_BETTER, ResultUnit.MS);
report.submit(getInstrumentation());
}
diff --git a/tests/tests/accounts/Android.mk b/tests/tests/accounts/Android.mk
index dc17e0e..31af474 100644
--- a/tests/tests/accounts/Android.mk
+++ b/tests/tests/accounts/Android.mk
@@ -22,7 +22,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES := \
- CtsAccountTestsCommon ctstestrunner platform-test-annotations
+ CtsAccountTestsCommon ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java b/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
index 3024896..f80b628 100644
--- a/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
+++ b/tests/tests/content/src/android/content/res/cts/PrivateAttributeTest.java
@@ -26,7 +26,7 @@
*/
public class PrivateAttributeTest extends AndroidTestCase {
- private static final int sLastPublicAttr = 0x010104f1;
+ private static final int sLastPublicAttr = 0x01010527;
public void testNoAttributesAfterLastPublicAttribute() throws Exception {
final Resources res = getContext().getResources();
diff --git a/tests/tests/display/Android.mk b/tests/tests/display/Android.mk
index 5de5610..2b81ec1 100644
--- a/tests/tests/display/Android.mk
+++ b/tests/tests/display/Android.mk
@@ -27,7 +27,7 @@
LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_STATIC_JAVA_LIBRARIES := android-support-test platform-test-annotations
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-test
# Tag this module as a cts test artifact
LOCAL_COMPATIBILITY_SUITE := cts
diff --git a/tests/tests/dpi/Android.mk b/tests/tests/dpi/Android.mk
index 3f4cde5..0c158121 100644
--- a/tests/tests/dpi/Android.mk
+++ b/tests/tests/dpi/Android.mk
@@ -17,7 +17,7 @@
include $(CLEAR_VARS)
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner platform-test-annotations
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/draganddrop/AndroidManifest.xml b/tests/tests/draganddrop/AndroidManifest.xml
deleted file mode 100644
index 94540bb..0000000
--- a/tests/tests/draganddrop/AndroidManifest.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.dnd.cts">
-
- <application>
- <uses-library android:name="android.test.runner"/>
- </application>
-
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.dnd.cts"/>
-
-</manifest>
\ No newline at end of file
diff --git a/tests/tests/draganddrop/droptarget/Android.mk b/tests/tests/draganddrop/droptarget/Android.mk
deleted file mode 100644
index a729f71..0000000
--- a/tests/tests/draganddrop/droptarget/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-# 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)
-
-include $(CLEAR_VARS)
-
-# Don't include this package in any target
-LOCAL_MODULE_TAGS := tests
-# When built, explicitly put it in the data partition.
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Tag this module as a cts test artifact
-LOCAL_COMPATIBILITY_SUITE := cts
-
-LOCAL_PACKAGE_NAME := CtsDropTargetApp
-
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml b/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml
deleted file mode 100644
index 509debc..0000000
--- a/tests/tests/draganddrop/droptarget/res/layout/main_activity.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/target"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:background="#ddd">
- </TextView>
-
- <TextView
- android:id="@+id/result"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:text="@string/not_available_label">
- </TextView>
-
- <TextView
- android:id="@+id/drag_started"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:text="@string/not_available_label">
- </TextView>
-
- <TextView
- android:id="@+id/extra_value"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:text="@string/not_available_label">
- </TextView>
-
- <TextView
- android:id="@+id/details"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp">
- </TextView>
-
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java b/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java
deleted file mode 100644
index e91e9c9..0000000
--- a/tests/tests/draganddrop/src/android/dnd/cts/DragAndDropTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.dnd.cts;
-
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.Point;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
-import android.test.InstrumentationTestCase;
-
-import java.util.concurrent.TimeoutException;
-
-public class DragAndDropTest extends InstrumentationTestCase {
-
- private static final String DRAG_SOURCE_PKG = "android.dnd.cts.dragsource";
- private static final String DROP_TARGET_PKG = "android.dnd.cts.droptarget";
-
- private static final int TIMEOUT = 5000;
-
- // Constants copied from ActivityManager.StackId. If they are changed there, these must be
- // updated.
- public static final int FREEFORM_WORKSPACE_STACK_ID = 1;
- public static final int DOCKED_STACK_ID = 3;
-
- private UiDevice mDevice;
-
- public void setUp() throws TimeoutException {
- mDevice = UiDevice.getInstance(getInstrumentation());
- }
-
- private void startAppInStack(String packageName, int stackId, String mode) {
- Context context = getInstrumentation().getContext();
- Intent intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- intent.putExtra("mode", mode);
-
- ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(stackId);
- context.startActivity(intent, options.toBundle());
-
- // Wait for the app to appear
- mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), TIMEOUT);
- }
-
- private Point getVisibleCenter(String packageName, String sourceViewId) {
- return findObject(packageName, sourceViewId).getVisibleCenter();
- }
-
- private UiObject2 findObject(String packageName, String id) {
- return mDevice.findObject(By.res(packageName, id));
- }
-
- private void drag(Point srcPosition, Point tgtPosition) {
- mDevice.drag(srcPosition.x, srcPosition.y, tgtPosition.x, tgtPosition.y, 100);
- }
-
- private void doCrossAppDrag(String sourceMode, String targetMode, String expectedResult) {
- startAppInStack(DRAG_SOURCE_PKG, DOCKED_STACK_ID, sourceMode);
- Point srcPosition = getVisibleCenter(DRAG_SOURCE_PKG, "source");
-
- startAppInStack(DROP_TARGET_PKG, FREEFORM_WORKSPACE_STACK_ID, targetMode);
- Point tgtPosition = getVisibleCenter(DROP_TARGET_PKG, "target");
-
- drag(srcPosition, tgtPosition);
-
- // If we don't do that the next 'findObject' often fails.
- mDevice.click(tgtPosition.x, tgtPosition.y);
-
- UiObject2 result = findObject(DROP_TARGET_PKG, "result");
- assertNotNull("Result widget not found", result);
- assertEquals(expectedResult, result.getText());
- }
-
- private void assertDragStarted(String expectedResult) {
- UiObject2 drag_started = findObject(DROP_TARGET_PKG, "drag_started");
- assertEquals(expectedResult, drag_started.getText());
- }
-
- private void assertExtraValue(String expectedResult) {
- UiObject2 extra_value = findObject(DROP_TARGET_PKG, "extra_value");
- assertEquals(expectedResult, extra_value.getText());
- }
-
- public void testLocal() {
- doCrossAppDrag("disallow_global", "dont_request", "N/A");
- assertDragStarted("N/A");
- assertExtraValue("N/A");
- }
-
- public void testCancel() {
- doCrossAppDrag("cancel_soon", "dont_request", "N/A");
- assertDragStarted("DRAG_STARTED");
- assertExtraValue("OK");
- }
-
- public void testDontGrantDontRequest() {
- doCrossAppDrag("dont_grant", "dont_request", "Exception");
- assertDragStarted("DRAG_STARTED");
- assertExtraValue("OK");
- }
-
- public void testDontGrantRequestRead() {
- doCrossAppDrag("dont_grant", "request_read", "Null DragAndDropPermissions");
- }
-
- public void testDontGrantRequestWrite() {
- doCrossAppDrag("dont_grant", "request_write", "Null DragAndDropPermissions");
- }
-
- public void testGrantReadDontRequest() {
- doCrossAppDrag("grant_read", "dont_request", "Exception");
- }
-
- public void testGrantReadRequestRead() {
- doCrossAppDrag("grant_read", "request_read", "OK");
- }
-
- public void testGrantReadRequestWrite() {
- doCrossAppDrag("grant_read", "request_write", "Exception");
- }
-
- public void testGrantWriteDontRequest() {
- doCrossAppDrag("grant_write", "dont_request", "Exception");
- }
-
- public void testGrantWriteRequestRead() {
- doCrossAppDrag("grant_write", "request_read", "Exception");
- }
-
- public void testGrantWriteRequestWrite() {
- doCrossAppDrag("grant_write", "request_write", "OK");
- }
-
- public void testGrantReadPrefixRequestReadNested() {
- doCrossAppDrag("grant_read_prefix", "request_read_nested", "OK");
- }
-
- public void testGrantReadNoPrefixRequestReadNested() {
- doCrossAppDrag("grant_read_noprefix", "request_read_nested", "Exception");
- }
-
- public void testGrantPersistableRequestTakePersistable() {
- doCrossAppDrag("grant_read_persistable", "request_take_persistable", "OK");
- }
-
- public void testGrantReadRequestTakePersistable() {
- doCrossAppDrag("grant_read", "request_take_persistable", "Exception");
- }
-}
diff --git a/tests/tests/hardware/Android.mk b/tests/tests/hardware/Android.mk
index c38a751..9b3969c 100644
--- a/tests/tests/hardware/Android.mk
+++ b/tests/tests/hardware/Android.mk
@@ -24,8 +24,9 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctsdeviceutil compatibility-device-util platform-test-annotations
+LOCAL_STATIC_JAVA_LIBRARIES := ctsdeviceutil
+
+LOCAL_JAVA_LIBRARIES := platform-test-annotations
LOCAL_SDK_VERSION := current
@@ -59,8 +60,7 @@
compatibility-device-util \
ctstestrunner \
mockito-target \
- android-ex-camera2 \
- platform-test-annotations
+ android-ex-camera2
LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
diff --git a/tests/tests/keystore/Android.mk b/tests/tests/keystore/Android.mk
index fe98bc3..4688846 100644
--- a/tests/tests/keystore/Android.mk
+++ b/tests/tests/keystore/Android.mk
@@ -29,8 +29,7 @@
core-tests-support \
ctsdeviceutil \
ctstestrunner \
- guava \
- platform-test-annotations
+ guava
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4
index 9bf2124..29408c58 100644
--- a/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4
+++ b/tests/tests/media/res/raw/video_1280x720_mp4_hevc_1150kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm b/tests/tests/media/res/raw/video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
new file mode 100644
index 0000000..8f00ded
--- /dev/null
+++ b/tests/tests/media/res/raw/video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_176x144_mp4_mpeg2_105kbps_25fps_aac_stereo_128kbps_44100hz.mp4 b/tests/tests/media/res/raw/video_176x144_mp4_mpeg2_105kbps_25fps_aac_stereo_128kbps_44100hz.mp4
new file mode 100644
index 0000000..7875ff9
--- /dev/null
+++ b/tests/tests/media/res/raw/video_176x144_mp4_mpeg2_105kbps_25fps_aac_stereo_128kbps_44100hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_256x144_webm_vp9_hdr_83kbps_24fps.webm b/tests/tests/media/res/raw/video_256x144_webm_vp9_hdr_83kbps_24fps.webm
new file mode 100644
index 0000000..bc4ef33
--- /dev/null
+++ b/tests/tests/media/res/raw/video_256x144_webm_vp9_hdr_83kbps_24fps.webm
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4
index e3e3ef01..fbf714a 100644
--- a/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4
+++ b/tests/tests/media/res/raw/video_480x360_mp4_hevc_325kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4 b/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4
index 4eb6161..8d69e41 100644
--- a/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4
+++ b/tests/tests/media/res/raw/video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz.mp4
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioRecordTest.java b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
index afd6997..8c25186 100644
--- a/tests/tests/media/src/android/media/cts/AudioRecordTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioRecordTest.java
@@ -43,6 +43,7 @@
public class AudioRecordTest extends CtsAndroidTestCase {
private final static String TAG = "AudioRecordTest";
+ private static final String REPORT_LOG_NAME = "CtsMediaTestCases";
private AudioRecord mAudioRecord;
private int mHz = 44100;
private boolean mIsOnMarkerReachedCalled;
@@ -235,7 +236,7 @@
}
public void testAudioRecordResamplerMono8Bit() throws Exception {
- doTest("ResamplerResamplerMono8Bit", true /*localRecord*/, false /*customHandler*/,
+ doTest("resampler_mono_8bit", true /*localRecord*/, false /*customHandler*/,
1 /*periodsPerSecond*/, 1 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, false /*blocking*/,
false /*auditRecording*/, false /*isChannelIndex*/, 88200 /*TEST_SR*/,
@@ -243,7 +244,7 @@
}
public void testAudioRecordResamplerStereo8Bit() throws Exception {
- doTest("ResamplerStereo8Bit", true /*localRecord*/, false /*customHandler*/,
+ doTest("resampler_stereo_8bit", true /*localRecord*/, false /*customHandler*/,
0 /*periodsPerSecond*/, 3 /*markerPeriodsPerSecond*/,
true /*useByteBuffer*/, true /*blocking*/,
false /*auditRecording*/, false /*isChannelIndex*/, 45000 /*TEST_SR*/,
@@ -251,7 +252,7 @@
}
public void testAudioRecordLocalMono16Bit() throws Exception {
- doTest("LocalMono16Bit", true /*localRecord*/, false /*customHandler*/,
+ doTest("local_mono_16bit", true /*localRecord*/, false /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, true /*blocking*/,
false /*auditRecording*/, false /*isChannelIndex*/, 8000 /*TEST_SR*/,
@@ -259,7 +260,7 @@
}
public void testAudioRecordStereo16Bit() throws Exception {
- doTest("Stereo16Bit", false /*localRecord*/, false /*customHandler*/,
+ doTest("stereo_16bit", false /*localRecord*/, false /*customHandler*/,
2 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, false /*blocking*/,
false /*auditRecording*/, false /*isChannelIndex*/, 17000 /*TEST_SR*/,
@@ -267,7 +268,7 @@
}
public void testAudioRecordMonoFloat() throws Exception {
- doTest("MonoFloat", false /*localRecord*/, true /*customHandler*/,
+ doTest("mono_float", false /*localRecord*/, true /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, true /*blocking*/,
false /*auditRecording*/, false /*isChannelIndex*/, 32000 /*TEST_SR*/,
@@ -275,7 +276,7 @@
}
public void testAudioRecordLocalNonblockingStereoFloat() throws Exception {
- doTest("LocalNonblockingStereoFloat", true /*localRecord*/, true /*customHandler*/,
+ doTest("local_nonblocking_stereo_float", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, false /*blocking*/,
false /*auditRecording*/, false /*isChannelIndex*/, 48000 /*TEST_SR*/,
@@ -287,7 +288,7 @@
if (isLowRamDevice()) {
return; // skip. FIXME: reenable when AF memory allocation is updated.
}
- doTest("AuditByteBufferResamplerStereoFloat",
+ doTest("audit_byte_buffer_resampler_stereo_float",
false /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
true /*useByteBuffer*/, false /*blocking*/,
@@ -296,7 +297,7 @@
}
public void testAudioRecordAuditChannelIndexMonoFloat() throws Exception {
- doTest("AuditChannelIndexMonoFloat", true /*localRecord*/, true /*customHandler*/,
+ doTest("audit_channel_index_mono_float", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, false /*blocking*/,
true /*auditRecording*/, true /*isChannelIndex*/, 47000 /*TEST_SR*/,
@@ -309,7 +310,7 @@
if (isLowRamDevice()) {
return; // skip. FIXME: reenable when AF memory allocation is updated.
}
- doTest("AuditChannelIndex2", true /*localRecord*/, true /*customHandler*/,
+ doTest("audit_channel_index_2", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, false /*blocking*/,
true /*auditRecording*/, true /*isChannelIndex*/, 192000 /*TEST_SR*/,
@@ -320,7 +321,7 @@
// Audit buffers can run out of space with high numbers of channels,
// so keep the sample rate low.
public void testAudioRecordAuditChannelIndex5() throws Exception {
- doTest("AuditChannelIndex5", true /*localRecord*/, true /*customHandler*/,
+ doTest("audit_channel_index_5", true /*localRecord*/, true /*customHandler*/,
2 /*periodsPerSecond*/, 0 /*markerPeriodsPerSecond*/,
false /*useByteBuffer*/, false /*blocking*/,
true /*auditRecording*/, true /*isChannelIndex*/, 16000 /*TEST_SR*/,
@@ -1115,37 +1116,33 @@
}
// report this
- DeviceReportLog log = new DeviceReportLog();
- log.addValue(reportName + ": startRecording lag", coldInputStartTime,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": stop execution time", stopTime - stopRequestTime,
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Total record time expected", TEST_TIME_MS,
- ResultType.NEUTRAL, ResultUnit.MS);
- log.addValue(reportName + ": Total record time actual", endTime - firstSampleTime,
- ResultType.NEUTRAL, ResultUnit.MS);
- log.addValue(reportName + ": Total markers expected", markerPeriods,
- ResultType.NEUTRAL, ResultUnit.COUNT);
- log.addValue(reportName + ": Total markers actual", markerList.size(),
- ResultType.NEUTRAL, ResultUnit.COUNT);
- log.addValue(reportName + ": Total periods expected", updatePeriods,
- ResultType.NEUTRAL, ResultUnit.COUNT);
- log.addValue(reportName + ": Total periods actual", periodicList.size(),
- ResultType.NEUTRAL, ResultUnit.COUNT);
- log.addValue(reportName + ": Average Marker diff", markerStat.getAvg(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.setSummary(reportName + ": Unified abs diff",
- (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
+ DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, reportName);
+ log.addValue("start_recording_lag", coldInputStartTime, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("stop_execution_time", stopTime - stopRequestTime, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("total_record_time_expected", TEST_TIME_MS, ResultType.NEUTRAL, ResultUnit.MS);
+ log.addValue("total_record_time_actual", endTime - firstSampleTime, ResultType.NEUTRAL,
+ ResultUnit.MS);
+ log.addValue("total_markers_expected", markerPeriods, ResultType.NEUTRAL, ResultUnit.COUNT);
+ log.addValue("total_markers_actual", markerList.size(), ResultType.NEUTRAL,
+ ResultUnit.COUNT);
+ log.addValue("total_periods_expected", updatePeriods, ResultType.NEUTRAL, ResultUnit.COUNT);
+ log.addValue("total_periods_actual", periodicList.size(), ResultType.NEUTRAL,
+ ResultUnit.COUNT);
+ log.addValue("average_marker_diff", markerStat.getAvg(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("maximum_marker_abs_diff", markerStat.getMaxAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("average_marker_abs_diff", markerStat.getAvgAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("average_periodic_diff", periodicStat.getAvg(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("maximum_periodic_abs_diff", periodicStat.getMaxAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("average_periodic_abs_diff", periodicStat.getAvgAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.setSummary("unified_abs_diff", (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
ResultType.LOWER_BETTER, ResultUnit.MS);
log.submit(getInstrumentation());
}
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java b/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java
index 5aa180c..cf1a406 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackLatencyTest.java
@@ -28,10 +28,6 @@
import android.media.PlaybackParams;
import android.util.Log;
-import com.android.compatibility.common.util.DeviceReportLog;
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index d81c11c..fb64c8e 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -41,6 +41,7 @@
private final long WAIT_MSEC = 200;
private final int OFFSET_DEFAULT = 0;
private final int OFFSET_NEGATIVE = -10;
+ private static final String REPORT_LOG_NAME = "CtsMediaTestCases";
private void log(String testName, String message) {
Log.v(TAG, "[" + testName + "] " + message);
@@ -1911,11 +1912,13 @@
+ "audio output HAL");
return;
}
+ String streamName = "test_get_timestamp";
doTestTimestamp(
22050 /* sampleRate */,
AudioFormat.CHANNEL_OUT_MONO ,
AudioFormat.ENCODING_PCM_16BIT,
- AudioTrack.MODE_STREAM);
+ AudioTrack.MODE_STREAM,
+ streamName);
}
public void testFastTimestamp() throws Exception {
@@ -1924,15 +1927,17 @@
+ "audio output HAL");
return;
}
+ String streamName = "test_fast_timestamp";
doTestTimestamp(
AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC),
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
- AudioTrack.MODE_STREAM);
+ AudioTrack.MODE_STREAM,
+ streamName);
}
- private void doTestTimestamp(
- int sampleRate, int channelMask, int encoding, int transferMode) throws Exception {
+ private void doTestTimestamp(int sampleRate, int channelMask, int encoding, int transferMode,
+ String streamName) throws Exception {
// constants for test
final String TEST_NAME = "testGetTimestamp";
final int TEST_LOOP_CNT = 10;
@@ -2069,14 +2074,14 @@
track.release();
// Log the average jitter
if (cumulativeJitterCount > 0) {
- DeviceReportLog log = new DeviceReportLog();
+ DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, streamName);
final float averageJitterInFrames = cumulativeJitter / cumulativeJitterCount;
final float averageJitterInMs = averageJitterInFrames * 1000 / sampleRate;
final float maxJitterInMs = maxJitter * 1000 / sampleRate;
// ReportLog needs at least one Value and Summary.
- log.addValue("Maximum Jitter", maxJitterInMs,
+ log.addValue("maximum_jitter", maxJitterInMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
- log.setSummary("Average Jitter", averageJitterInMs,
+ log.setSummary("average_jitter", averageJitterInMs,
ResultType.LOWER_BETTER, ResultUnit.MS);
log.submit(getInstrumentation());
}
diff --git a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
index 37affd0..971bfb3 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrack_ListenerTest.java
@@ -33,6 +33,7 @@
public class AudioTrack_ListenerTest extends CtsAndroidTestCase {
private final static String TAG = "AudioTrack_ListenerTest";
+ private static final String REPORT_LOG_NAME = "CtsMediaTestCases";
private final static int TEST_SR = 11025;
private final static int TEST_CONF = AudioFormat.CHANNEL_OUT_MONO;
private final static int TEST_FORMAT = AudioFormat.ENCODING_PCM_8BIT;
@@ -53,25 +54,26 @@
};
public void testAudioTrackCallback() throws Exception {
- doTest("Streaming Local Looper", true /*localTrack*/, false /*customHandler*/,
+ doTest("streaming_local_looper", true /*localTrack*/, false /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STREAM);
}
public void testAudioTrackCallbackWithHandler() throws Exception {
// with 100 periods per second, trigger back-to-back notifications.
- doTest("Streaming Private Handler", false /*localTrack*/, true /*customHandler*/,
+ doTest("streaming_private_handler", false /*localTrack*/, true /*customHandler*/,
100 /*periodsPerSecond*/, 10 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STREAM);
// verify mHandler is used only for accessing its associated Looper
assertFalse(mIsHandleMessageCalled);
}
public void testStaticAudioTrackCallback() throws Exception {
- doTest("Static", false /*localTrack*/, false /*customHandler*/,
+ doTest("static", false /*localTrack*/, false /*customHandler*/,
100 /*periodsPerSecond*/, 10 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STATIC);
}
public void testStaticAudioTrackCallbackWithHandler() throws Exception {
- doTest("Static Private Handler", false /*localTrack*/, true /*customHandler*/,
+ String streamName = "test_static_audio_track_callback_handler";
+ doTest("static_private_handler", false /*localTrack*/, true /*customHandler*/,
30 /*periodsPerSecond*/, 2 /*markerPeriodsPerSecond*/, AudioTrack.MODE_STATIC);
// verify mHandler is used only for accessing its associated Looper
assertFalse(mIsHandleMessageCalled);
@@ -205,21 +207,20 @@
}
// report this
- DeviceReportLog log = new DeviceReportLog();
- log.addValue(reportName + ": Average Marker diff", markerStat.getAvg(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Maximum Marker abs diff", markerStat.getMaxAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Average Marker abs diff", markerStat.getAvgAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Average Periodic diff", periodicStat.getAvg(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Maximum Periodic abs diff", periodicStat.getMaxAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.addValue(reportName + ": Average Periodic abs diff", periodicStat.getAvgAbs(),
- ResultType.LOWER_BETTER, ResultUnit.MS);
- log.setSummary(reportName + ": Unified abs diff",
- (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
+ DeviceReportLog log = new DeviceReportLog(REPORT_LOG_NAME, reportName);
+ log.addValue("average_marker_diff", markerStat.getAvg(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("maximum_marker_abs_diff", markerStat.getMaxAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("average_marker_abs_diff", markerStat.getAvgAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("average_periodic_diff", periodicStat.getAvg(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("maximum_periodic_abs_diff", periodicStat.getMaxAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.addValue("average_periodic_abs_diff", periodicStat.getAvgAbs(), ResultType.LOWER_BETTER,
+ ResultUnit.MS);
+ log.setSummary("unified_abs_diff", (periodicStat.getAvgAbs() + markerStat.getAvgAbs()) / 2,
ResultType.LOWER_BETTER, ResultUnit.MS);
log.submit(getInstrumentation());
}
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 33583be..15ac82f 100755
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -47,6 +47,7 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.zip.CRC32;
import java.util.concurrent.TimeUnit;
@@ -1930,9 +1931,9 @@
testFd.getLength());
extractor.selectTrack(0);
- int numframes = decodeWithChecks(extractor, CHECKFLAG_RETURN_OUTPUTFRAMES
- | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH, resetMode, s,
- eosframe, null, null);
+ int numframes = decodeWithChecks(null /* decoderName */, extractor,
+ CHECKFLAG_RETURN_OUTPUTFRAMES | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
+ resetMode, s, eosframe, null, null);
extractor.release();
testFd.close();
@@ -1949,7 +1950,8 @@
extractor.selectTrack(0);
// fails CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH
- int outputSize = decodeWithChecks(extractor, CHECKFLAG_RETURN_OUTPUTSIZE, resetMode, null,
+ int outputSize = decodeWithChecks(null /* decoderName */, extractor,
+ CHECKFLAG_RETURN_OUTPUTSIZE, resetMode, null,
eosframe, null, null);
extractor.release();
@@ -1957,10 +1959,16 @@
return outputSize;
}
+ /*
+ * Test all decoders' EOS behavior.
+ */
private void testEOSBehavior(int movie, int stopatsample) throws Exception {
testEOSBehavior(movie, new int[] {stopatsample});
}
+ /*
+ * Test all decoders' EOS behavior.
+ */
private void testEOSBehavior(int movie, int[] stopAtSample) throws Exception {
Surface s = null;
AssetFileDescriptor testFd = mResources.openRawResourceFd(movie);
@@ -1969,42 +1977,45 @@
testFd.getLength());
extractor.selectTrack(0); // consider variable looping on track
MediaFormat format = extractor.getTrackFormat(0);
- if (!MediaUtils.checkDecoderForFormat(format)) {
- return; // skip
- }
- List<Long> outputChecksums = new ArrayList<Long>();
- List<Long> outputTimestamps = new ArrayList<Long>();
- Arrays.sort(stopAtSample);
- int last = stopAtSample.length - 1;
- // decode reference (longest sequence to stop at + 100) and
- // store checksums/pts in outputChecksums and outputTimestamps
- // (will fail CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH)
- decodeWithChecks(extractor,
- CHECKFLAG_SETCHECKSUM | CHECKFLAG_SETPTS | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
- RESET_MODE_NONE, s,
- stopAtSample[last] + 100, outputChecksums, outputTimestamps);
+ Collection<String> decoderNames = MediaUtils.getDecodersForFormat(format);
+ for (String decoderName: decoderNames) {
+ List<Long> outputChecksums = new ArrayList<Long>();
+ List<Long> outputTimestamps = new ArrayList<Long>();
+ Arrays.sort(stopAtSample);
+ int last = stopAtSample.length - 1;
- // decode stopAtSample requests in reverse order (longest to
- // shortest) and compare to reference checksums/pts in
- // outputChecksums and outputTimestamps
- for (int i = last; i >= 0; --i) {
- if (true) { // reposition extractor
- extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
- } else { // create new extractor
- extractor.release();
- extractor = new MediaExtractor();
- extractor.setDataSource(testFd.getFileDescriptor(),
- testFd.getStartOffset(), testFd.getLength());
- extractor.selectTrack(0); // consider variable looping on track
- }
- decodeWithChecks(extractor,
- CHECKFLAG_COMPARECHECKSUM | CHECKFLAG_COMPAREPTS
- | CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH
- | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
+ // decode reference (longest sequence to stop at + 100) and
+ // store checksums/pts in outputChecksums and outputTimestamps
+ // (will fail CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH)
+ decodeWithChecks(decoderName, extractor,
+ CHECKFLAG_SETCHECKSUM | CHECKFLAG_SETPTS | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
RESET_MODE_NONE, s,
- stopAtSample[i], outputChecksums, outputTimestamps);
+ stopAtSample[last] + 100, outputChecksums, outputTimestamps);
+
+ // decode stopAtSample requests in reverse order (longest to
+ // shortest) and compare to reference checksums/pts in
+ // outputChecksums and outputTimestamps
+ for (int i = last; i >= 0; --i) {
+ if (true) { // reposition extractor
+ extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
+ } else { // create new extractor
+ extractor.release();
+ extractor = new MediaExtractor();
+ extractor.setDataSource(testFd.getFileDescriptor(),
+ testFd.getStartOffset(), testFd.getLength());
+ extractor.selectTrack(0); // consider variable looping on track
+ }
+ decodeWithChecks(decoderName, extractor,
+ CHECKFLAG_COMPARECHECKSUM | CHECKFLAG_COMPAREPTS
+ | CHECKFLAG_COMPAREINPUTOUTPUTSAMPLEMATCH
+ | CHECKFLAG_COMPAREINPUTOUTPUTPTSMATCH,
+ RESET_MODE_NONE, s,
+ stopAtSample[i], outputChecksums, outputTimestamps);
+ }
+ extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
}
+
extractor.release();
testFd.close();
}
@@ -2020,10 +2031,13 @@
/**
* Decodes frames with parameterized checks and return values.
+ * If decoderName is provided, mediacodec will create that decoder. Otherwise,
+ * mediacodec will use the default decoder provided by platform.
* The integer return can be selected through the checkFlags variable.
*/
- private static int decodeWithChecks(MediaExtractor extractor, int checkFlags, int resetMode,
- Surface surface, int stopAtSample,
+ private static int decodeWithChecks(
+ String decoderName, MediaExtractor extractor,
+ int checkFlags, int resetMode, Surface surface, int stopAtSample,
List<Long> outputChecksums, List<Long> outputTimestamps)
throws Exception {
int trackIndex = extractor.getSampleTrackIndex();
@@ -2033,7 +2047,8 @@
ByteBuffer[] codecInputBuffers;
ByteBuffer[] codecOutputBuffers;
- MediaCodec codec = createDecoder(format);
+ MediaCodec codec =
+ decoderName == null ? createDecoder(format) : MediaCodec.createByCodecName(decoderName);
Log.i("@@@@", "using codec: " + codec.getName());
codec.configure(format, surface, null /* crypto */, 0 /* flags */);
codec.start();
@@ -2253,37 +2268,42 @@
public void testEOSBehaviorH264() throws Exception {
// this video has an I frame at 44
- testEOSBehavior(R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
- new int[] {44, 45, 55});
+ testEOSBehavior(
+ R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
+ new int[] {1, 44, 45, 55});
}
public void testEOSBehaviorHEVC() throws Exception {
- testEOSBehavior(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz, 17);
- testEOSBehavior(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz, 23);
- testEOSBehavior(R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz, 49);
+ testEOSBehavior(
+ R.raw.video_480x360_mp4_hevc_650kbps_30fps_aac_stereo_128kbps_48000hz,
+ new int[] {1, 17, 23, 49});
}
public void testEOSBehaviorH263() throws Exception {
// this video has an I frame every 12 frames.
- testEOSBehavior(R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
- new int[] {24, 25, 48, 50});
+ testEOSBehavior(
+ R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
+ new int[] {1, 24, 25, 48, 50});
}
public void testEOSBehaviorMpeg4() throws Exception {
// this video has an I frame every 12 frames
- testEOSBehavior(R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
- new int[] {24, 25, 48, 50, 2});
+ testEOSBehavior(
+ R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
+ new int[] {1, 24, 25, 48, 50, 2});
}
public void testEOSBehaviorVP8() throws Exception {
// this video has an I frame at 46
- testEOSBehavior(R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
- new int[] {46, 47, 57, 45});
+ testEOSBehavior(
+ R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ new int[] {1, 46, 47, 57, 45});
}
public void testEOSBehaviorVP9() throws Exception {
// this video has an I frame at 44
- testEOSBehavior(R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
- new int[] {44, 45, 55, 43});
+ testEOSBehavior(
+ R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ new int[] {1, 44, 45, 55, 43});
}
/* from EncodeDecodeTest */
diff --git a/tests/tests/media/src/android/media/cts/EncoderTest.java b/tests/tests/media/src/android/media/cts/EncoderTest.java
index e48af7e..72f090e 100644
--- a/tests/tests/media/src/android/media/cts/EncoderTest.java
+++ b/tests/tests/media/src/android/media/cts/EncoderTest.java
@@ -187,11 +187,9 @@
57821391502855l, // fail @ 32000 in zero-lead mode
};
- private Random mRandom = new Random(1);
-
private int queueInputBuffer(
MediaCodec codec, ByteBuffer[] inputBuffers, int index,
- InputStream istream, int mode, long timeUs) {
+ InputStream istream, int mode, long timeUs, Random random) {
ByteBuffer buffer = inputBuffers[index];
buffer.rewind();
int size = buffer.limit();
@@ -218,8 +216,8 @@
}
while (true) {
try {
- int next = mRandom.nextInt();
- buffer.putInt(mRandom.nextInt());
+ int next = random.nextInt();
+ buffer.putInt(random.nextInt());
} catch (BufferOverflowException ex) {
break;
}
@@ -295,8 +293,9 @@
if (sSaveResults) {
try {
String outFile = "/data/local/tmp/transcoded-" + componentName +
- "-" + sampleRate + "-" + channelCount + "-" + outBitrate +
- "-" + mode + "-" + startSeed + ".mp4";
+ "-" + sampleRate + "Hz-" + channelCount + "ch-" + outBitrate +
+ "bps-" + mode + "-" + resid + "-" + startSeed + "-" +
+ (android.os.Process.is64Bit() ? "64bit" : "32bit") + ".mp4";
new File("outFile").delete();
muxer = new MediaMuxer(outFile, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
// The track can't be added until we have the codec specific data
@@ -310,7 +309,7 @@
istream = mContext.getResources().openRawResource(resid);
}
- mRandom.setSeed(startSeed);
+ Random random = new Random(startSeed);
MediaCodec codec;
try {
codec = MediaCodec.createByCodecName(componentName);
@@ -360,7 +359,7 @@
doneSubmittingInput = true;
} else {
int size = queueInputBuffer(
- codec, codecInputBuffers, index, istream, mode, timeUs);
+ codec, codecInputBuffers, index, istream, mode, timeUs, random);
numBytesSubmitted += size;
diff --git a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
index deb561b..c1c672d 100644
--- a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
@@ -419,10 +419,44 @@
private static native boolean testPlaybackNative(Surface surface,
int fd, long startOffset, long length);
- public void testMuxer() throws Exception {
+ public void testMuxerAvc() throws Exception {
testMuxer(R.raw.video_1280x720_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, false);
}
+ public void testMuxerH263() throws Exception {
+ testMuxer(R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_11025hz, false);
+ }
+
+ public void testMuxerHevc() throws Exception {
+ testMuxer(R.raw.video_640x360_mp4_hevc_450kbps_30fps_aac_stereo_128kbps_48000hz, false);
+ }
+
+ public void testMuxerVp8() throws Exception {
+ testMuxer(R.raw.video_640x360_webm_vp8_2048kbps_30fps_vorbis_stereo_128kbps_48000hz, true);
+ }
+
+ public void testMuxerVp9() throws Exception {
+ testMuxer(
+ R.raw.video_1280x720_webm_vp9_csd_309kbps_25fps_vorbis_stereo_128kbps_48000hz,
+ true);
+ }
+
+ public void testMuxerVp9NoCsd() throws Exception {
+ testMuxer(R.raw.video_640x360_webm_vp9_1600kbps_30fps_vorbis_stereo_128kbps_48000hz, true);
+ }
+
+ public void testMuxerVp9Hdr() throws Exception {
+ testMuxer(R.raw.video_256x144_webm_vp9_hdr_83kbps_24fps, true);
+ }
+
+ public void testMuxerMpeg2() throws Exception {
+ testMuxer(R.raw.video_176x144_mp4_mpeg2_105kbps_25fps_aac_stereo_128kbps_44100hz, false);
+ }
+
+ public void testMuxerMpeg4() throws Exception {
+ testMuxer(R.raw.video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz, false);
+ }
+
private void testMuxer(int res, boolean webm) throws Exception {
if (!MediaUtils.checkCodecsForResource(mContext, res)) {
return; // skip
@@ -450,12 +484,15 @@
remux.setDataSource(out.getFileDescriptor());
assertEquals("mismatched numer of tracks", org.getTrackCount(), remux.getTrackCount());
- for (int i = 0; i < 2; i++) {
+ // allow duration mismatch for webm files as ffmpeg does not consider the duration of the
+ // last frame while libwebm (and our framework) does.
+ final long maxDurationDiffUs = webm ? 50000 : 0; // 50ms for webm
+ for (int i = 0; i < org.getTrackCount(); i++) {
MediaFormat format1 = org.getTrackFormat(i);
MediaFormat format2 = remux.getTrackFormat(i);
Log.i("@@@", "org: " + format1);
Log.i("@@@", "remux: " + format2);
- assertTrue("different formats", compareFormats(format1, format2));
+ assertTrue("different formats", compareFormats(format1, format2, maxDurationDiffUs));
}
org.release();
@@ -463,13 +500,71 @@
MediaPlayer player1 = MediaPlayer.create(mContext, res);
MediaPlayer player2 = MediaPlayer.create(mContext, Uri.parse("file://" + tmpFile));
- assertEquals("duration is different", player1.getDuration(), player2.getDuration());
+ assertEquals("duration is different",
+ player1.getDuration(), player2.getDuration(), maxDurationDiffUs * 0.001);
player1.release();
player2.release();
new File(tmpFile).delete();
}
- boolean compareFormats(MediaFormat f1, MediaFormat f2) {
+ private String hexString(ByteBuffer buf) {
+ if (buf == null) {
+ return "(null)";
+ }
+ final char digits[] =
+ { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+
+ StringBuilder hex = new StringBuilder();
+ for (int i = buf.position(); i < buf.limit(); ++i) {
+ byte c = buf.get(i);
+ hex.append(digits[(c >> 4) & 0xf]);
+ hex.append(digits[c & 0xf]);
+ }
+ return hex.toString();
+ }
+
+ /** returns: null if key is in neither formats, true if they match and false otherwise */
+ private Boolean compareByteBufferInFormats(MediaFormat f1, MediaFormat f2, String key) {
+ ByteBuffer bufF1 = f1.containsKey(key) ? f1.getByteBuffer(key) : null;
+ ByteBuffer bufF2 = f2.containsKey(key) ? f2.getByteBuffer(key) : null;
+ if (bufF1 == null && bufF2 == null) {
+ return null;
+ }
+ if (bufF1 == null || !bufF1.equals(bufF2)) {
+ Log.i("@@@", "org " + key + ": " + hexString(bufF1));
+ Log.i("@@@", "rmx " + key + ": " + hexString(bufF2));
+ return false;
+ }
+ return true;
+ }
+
+ private boolean compareFormats(MediaFormat f1, MediaFormat f2, long maxDurationDiffUs) {
+ final String KEY_DURATION = MediaFormat.KEY_DURATION;
+
+ // allow some difference in durations
+ if (maxDurationDiffUs > 0
+ && f1.containsKey(KEY_DURATION) && f2.containsKey(KEY_DURATION)
+ && Math.abs(f1.getLong(KEY_DURATION)
+ - f2.getLong(KEY_DURATION)) <= maxDurationDiffUs) {
+ f2.setLong(KEY_DURATION, f1.getLong(KEY_DURATION));
+ }
+
+ // verify hdr-static-info
+ if (Boolean.FALSE.equals(compareByteBufferInFormats(f1, f2, "hdr-static-info"))) {
+ return false;
+ }
+
+ // verify CSDs
+ for (int i = 0;; ++i) {
+ String key = "csd-" + i;
+ Boolean match = compareByteBufferInFormats(f1, f2, key);
+ if (match == null) {
+ break;
+ } else if (match == false) {
+ return false;
+ }
+ }
+
// there's no good way to compare two MediaFormats, so compare their string
// representation
return f1.toString().equals(f2.toString());
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index bbee284..5397fc6a 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -25,7 +25,7 @@
LOCAL_MULTILIB := both
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctsdeviceutil ctstestrunner guava platform-test-annotations
+ ctsdeviceutil ctstestrunner guava
LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libctsos_jni libnativehelper_compat_libc++
diff --git a/tests/tests/permission/Android.mk b/tests/tests/permission/Android.mk
index c37ddfc..af0f8c4 100644
--- a/tests/tests/permission/Android.mk
+++ b/tests/tests/permission/Android.mk
@@ -30,7 +30,7 @@
LOCAL_JAVA_LIBRARIES := telephony-common
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner guava android-ex-camera2 platform-test-annotations
+ ctstestrunner guava android-ex-camera2
LOCAL_JNI_SHARED_LIBRARIES := libctspermission_jni libnativehelper_compat_libc++
diff --git a/tests/tests/provider/Android.mk b/tests/tests/provider/Android.mk
index 59fb9f6..30d3e71 100644
--- a/tests/tests/provider/Android.mk
+++ b/tests/tests/provider/Android.mk
@@ -33,7 +33,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctsdeviceutil ctstestrunner platform-test-annotations
+ ctsdeviceutil ctstestrunner
LOCAL_JNI_SHARED_LIBRARIES := libcts_jni libnativehelper_compat_libc++
diff --git a/tests/tests/security/src/android/security/cts/HwRngTest.java b/tests/tests/security/src/android/security/cts/HwRngTest.java
index 7654b6f..e654f9d 100644
--- a/tests/tests/security/src/android/security/cts/HwRngTest.java
+++ b/tests/tests/security/src/android/security/cts/HwRngTest.java
@@ -45,20 +45,22 @@
private static final String HWRNG_DRIVER_NAME = "hwrng";
private static final int HWRNG_DRIVER_MAJOR = 10;
private static final int HWRNG_DRIVER_MINOR = 183;
+ private static final String REPORT_LOG_NAME = "CtsSecurityTestCases";
/**
* Reports whether the {@code /dev/hw_random} device is found. This test always passes.
*/
public void testDeviceFilePresent() {
- DeviceReportLog report = new DeviceReportLog();
+ String streamName = "test_device_file_present";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
// Need to report at least one value, otherwise summary won't be logged.
report.addValue(
- DEV_HW_RANDOM + " found",
+ "hw_random_found" /* key cannot contain special chars */,
DEV_HW_RANDOM.exists() ? 1 : 0,
ResultType.WARNING,
ResultUnit.NONE);
report.setSummary(
- "Hardware RNG exposed",
+ "hardware_rng_exposed",
DEV_HW_RANDOM.exists() ? 1 : 0,
ResultType.WARNING,
ResultUnit.NONE);
diff --git a/tests/tests/theme/Android.mk b/tests/tests/theme/Android.mk
index 8b69a09..0f370d0 100644
--- a/tests/tests/theme/Android.mk
+++ b/tests/tests/theme/Android.mk
@@ -24,8 +24,7 @@
# When built, explicitly put it in the data partition.
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_STATIC_JAVA_LIBRARIES := \
- ctstestrunner platform-test-annotations
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/view/Android.mk b/tests/tests/view/Android.mk
index 57dc0ce..6a8d49c 100644
--- a/tests/tests/view/Android.mk
+++ b/tests/tests/view/Android.mk
@@ -29,7 +29,7 @@
LOCAL_JAVA_LIBRARIES := android.test.runner
LOCAL_STATIC_JAVA_LIBRARIES := \
- ctsdeviceutil ctstestrunner mockito-target platform-test-annotations
+ ctsdeviceutil ctstestrunner mockito-target
LOCAL_JNI_SHARED_LIBRARIES := libctsview_jni libnativehelper_compat_libc++
diff --git a/tests/tests/webkit/Android.mk b/tests/tests/webkit/Android.mk
index 3a09f77..d133d80 100644
--- a/tests/tests/webkit/Android.mk
+++ b/tests/tests/webkit/Android.mk
@@ -27,8 +27,7 @@
ctsdeviceutil \
ctsdeviceutillegacy \
ctstestserver \
- ctstestrunner \
- platform-test-annotations
+ ctstestrunner
LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/tests/widget/Android.mk b/tests/tests/widget/Android.mk
index 96f10fc..4bc9eee 100644
--- a/tests/tests/widget/Android.mk
+++ b/tests/tests/widget/Android.mk
@@ -25,8 +25,7 @@
mockito-target \
android-common \
ctsdeviceutil \
- ctstestrunner \
- platform-test-annotations
+ ctstestrunner
LOCAL_JAVA_LIBRARIES := android.test.runner
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index 35b7851..9f611ad 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -4238,6 +4238,12 @@
// Tap the view to show InsertPointController.
TouchUtils.tapView(this, mTextView);
+ // bad workaround for waiting onStartInputView of LeanbackIme.apk done
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
// Execute SelectAll context menu.
mActivity.runOnUiThread(new Runnable() {
@@ -4249,6 +4255,7 @@
// The selection must be whole of the text contents.
assertEquals(0, mTextView.getSelectionStart());
+ assertEquals("Hello, World.", mTextView.getText().toString());
assertEquals(mTextView.length(), mTextView.getSelectionEnd());
}
diff --git a/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java b/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
index b5fa019..f1e8ae5 100644
--- a/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
+++ b/tests/tvprovider/src/android/tvprovider/cts/TvProviderPerfTest.java
@@ -51,6 +51,7 @@
public class TvProviderPerfTest extends CtsAndroidTestCase {
private static final int TRANSACTION_RUNS = 100;
private static final int QUERY_RUNS = 10;
+ private static final String REPORT_LOG_NAME = "CtsTvProviderTestCases";
private ContentResolver mContentResolver;
private String mInputId;
@@ -106,9 +107,10 @@
}
}
});
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("Elapsed time for insert: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ String streamName = "test_channels";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValues("elapsed_time_for_insert", applyBatchTimes, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
averages[0] = Stat.getAverage(applyBatchTimes);
// Update
@@ -135,8 +137,8 @@
}
});
}
- report.addValues("Elapsed time for update: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_update", applyBatchTimes, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
averages[1] = Stat.getAverage(applyBatchTimes);
// Query channels
@@ -151,8 +153,8 @@
}
}
});
- report.addValues("Elapsed time for query (channels): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_query_channels", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[2] = Stat.getAverage(applyBatchTimes);
// Query a channel
@@ -171,8 +173,8 @@
}
});
}
- report.addValues("Elapsed time for query (a channel): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_query_a_channel", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[3] = Stat.getAverage(applyBatchTimes);
// Delete
@@ -182,13 +184,12 @@
mContentResolver.delete(TvContract.buildChannelsUriForInput(mInputId), null, null);
}
});
- report.addValues("Elapsed time for delete: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_delete", applyBatchTimes, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
averages[4] = Stat.getAverage(applyBatchTimes);
- report.addValues("Average elapsed time for insert, update, query (channels), "
- + "query (a channel), delete: ",
- averages, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("average_elapsed_time_for_insert_update_query_channels_query_a_channel_"
+ + "delete", averages, ResultType.LOWER_BETTER, ResultUnit.MS);
report.submit(getInstrumentation());
}
@@ -245,9 +246,10 @@
}
}
});
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("Elapsed time for insert: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ String streamName = "test_programs";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValues("elapsed_time_for_insert", applyBatchTimes, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
averages[0] = Stat.getAverage(applyBatchTimes);
// Update
@@ -281,8 +283,8 @@
}
}
});
- report.addValues("Elapsed time for update: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_update", applyBatchTimes, ResultType.LOWER_BETTER,
+ ResultUnit.MS);
averages[1] = Stat.getAverage(applyBatchTimes);
// Query programs
@@ -297,8 +299,8 @@
}
}
});
- report.addValues("Elapsed time for query (programs): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_query_programs", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[2] = Stat.getAverage(applyBatchTimes);
// Query programs with selection
@@ -317,8 +319,8 @@
}
}
});
- report.addValues("Elapsed time for query (programs with selection): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_query_programs_with_selection", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[3] = Stat.getAverage(applyBatchTimes);
// Query a program
@@ -337,8 +339,8 @@
}
});
}
- report.addValues("Elapsed time for query (a program): ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_query_a_program", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[4] = Stat.getAverage(applyBatchTimes);
// Delete programs
@@ -354,8 +356,8 @@
null, null);
}
});
- report.addValues("Elapsed time for delete programs: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_delete_programs", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[5] = Stat.getAverage(applyBatchTimes);
// Delete channels
@@ -366,14 +368,12 @@
mContentResolver.delete(channelUri, null, null);
}
});
- report.addValues("Elapsed time for delete channels: ",
- applyBatchTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("elapsed_time_for_delete_channels", applyBatchTimes,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
averages[6] = Stat.getAverage(applyBatchTimes);
- report.addValues("Average elapsed time for insert, update, query (programs), "
- + "query (programs with selection), query (a channel), delete (channels), "
- + "delete (programs): ",
- averages, ResultType.LOWER_BETTER, ResultUnit.MS);
+ report.addValues("average_elapsed_time_for_all_operations", averages,
+ ResultType.LOWER_BETTER, ResultUnit.MS);
report.submit(getInstrumentation());
}
}
diff --git a/tests/ui/src/android/ui/cts/ScrollingTest.java b/tests/ui/src/android/ui/cts/ScrollingTest.java
index 4902807..da2f334 100644
--- a/tests/ui/src/android/ui/cts/ScrollingTest.java
+++ b/tests/ui/src/android/ui/cts/ScrollingTest.java
@@ -28,6 +28,9 @@
import java.io.IOException;
public class ScrollingTest extends ActivityInstrumentationTestCase2<ScrollingActivity> {
+
+ private static final String REPORT_LOG_NAME = "CtsUiDeviceTestCases";
+
private ScrollingActivity mActivity;
public ScrollingTest() {
@@ -69,10 +72,12 @@
assertTrue(activity.scrollToTop());
}
});
- DeviceReportLog report = new DeviceReportLog();
- report.addValues("scrolling time", results, ResultType.LOWER_BETTER,ResultUnit.MS);
+ String streamName = "test_full_scrolling";
+ DeviceReportLog report = new DeviceReportLog(REPORT_LOG_NAME, streamName);
+ report.addValues("scrolling_time", results, ResultType.LOWER_BETTER,ResultUnit.MS);
Stat.StatResult stat = Stat.getStat(results);
- report.setSummary("scrolling time", stat.mAverage, ResultType.LOWER_BETTER,ResultUnit.MS);
+ report.setSummary("scrolling_time_average", stat.mAverage,
+ ResultType.LOWER_BETTER,ResultUnit.MS);
report.submit(getInstrumentation());
}
}
diff --git a/tools/cts-tradefed/res/config/cts.xml b/tools/cts-tradefed/res/config/cts.xml
index ee94f6a..2eb0c3e 100644
--- a/tools/cts-tradefed/res/config/cts.xml
+++ b/tools/cts-tradefed/res/config/cts.xml
@@ -23,10 +23,6 @@
<option name="enable-root" value="false" />
- <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:rerun-from-file:true" />
- <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:rerun-from-file-attempts:1" />
- <option name="compatibility:test-arg" value="com.android.tradefed.testtype.AndroidJUnitTest:fallback-to-serial-rerun:false" />
-
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.PropertyCheck">
<option name="property-name" value="ro.build.type" />
<option name="expected-value" value="user"/> <!-- Device should have user build -->
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
index 651ee39..47e4837 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/tradefed/CtsTradefedTest.java
@@ -34,6 +34,7 @@
private static final String SUITE_NAME = "CTS";
private static final String SUITE_PLAN = "cts";
private static final String DYNAMIC_CONFIG_URL = "";
+ private static final long START_TIME = 123456L;
public void testSuiteInfoLoad() throws Exception {
// Test the values in the manifest can be loaded
@@ -46,7 +47,7 @@
CompatibilityBuildProvider provider = new CompatibilityBuildProvider();
IBuildInfo info = provider.getBuild();
CompatibilityBuildHelper helper = new CompatibilityBuildHelper(info);
- helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL);
+ helper.init(SUITE_PLAN, DYNAMIC_CONFIG_URL, START_TIME);
assertEquals("Incorrect suite full name", SUITE_FULL_NAME, helper.getSuiteFullName());
assertEquals("Incorrect suite name", SUITE_NAME, helper.getSuiteName());
FileUtil.recursiveDelete(root);