Merge "Cover more PendingIntent whitelist scenarios." into nyc-mr1-dev
diff --git a/apps/CameraITS/pymodules/its/objects.py b/apps/CameraITS/pymodules/its/objects.py
index ac384fb..58fe4ec 100644
--- a/apps/CameraITS/pymodules/its/objects.py
+++ b/apps/CameraITS/pymodules/its/objects.py
@@ -71,7 +71,7 @@
return float(r["numerator"]) / float(r["denominator"])
def manual_capture_request(
- sensitivity, exp_time, linear_tonemap=False, props=None):
+ sensitivity, exp_time, f_distance = 0.0, linear_tonemap=False, props=None):
"""Return a capture request with everything set to manual.
Uses identity/unit color correction, and the default tonemap curve.
@@ -81,6 +81,7 @@
sensitivity: The sensitivity value to populate the request with.
exp_time: The exposure time, in nanoseconds, to populate the request
with.
+ f_distance: The focus distance to populate the request with.
linear_tonemap: [Optional] whether a linear tonemap should be used
in this request.
props: [Optional] the object returned from
@@ -105,6 +106,7 @@
"android.colorCorrection.transform":
int_to_rational([1,0,0, 0,1,0, 0,0,1]),
"android.colorCorrection.gains": [1,1,1,1],
+ "android.lens.focusDistance" : f_distance,
"android.tonemap.mode": 1,
"android.shading.mode": 1
}
diff --git a/apps/CameraITS/tests/scene1/test_auto_vs_manual.py b/apps/CameraITS/tests/scene1/test_auto_vs_manual.py
index a9efa0b..c5f5e29 100644
--- a/apps/CameraITS/tests/scene1/test_auto_vs_manual.py
+++ b/apps/CameraITS/tests/scene1/test_auto_vs_manual.py
@@ -56,7 +56,7 @@
print "Auto transform:", xform_a
# Manual capture 1: WB
- req = its.objects.manual_capture_request(sens, exp)
+ req = its.objects.manual_capture_request(sens, exp, focus)
req["android.colorCorrection.transform"] = xform_rat
req["android.colorCorrection.gains"] = gains
cap_man1 = cam.do_capture(req)
diff --git a/apps/CameraITS/tests/scene1/test_crop_region_raw.py b/apps/CameraITS/tests/scene1/test_crop_region_raw.py
index 7973755..f2d788e 100644
--- a/apps/CameraITS/tests/scene1/test_crop_region_raw.py
+++ b/apps/CameraITS/tests/scene1/test_crop_region_raw.py
@@ -64,7 +64,7 @@
# Use a manual request with a linear tonemap so that the YUV and RAW
# should look the same (once converted by the its.image module).
e, s = its.target.get_target_exposure_combos(cam)["minSensitivity"]
- req = its.objects.manual_capture_request(s,e, True, props)
+ req = its.objects.manual_capture_request(s,e, 0.0, True, props)
cap1_raw, cap1_yuv = cam.do_capture(req, cam.CAP_RAW_YUV)
# Capture with a crop region.
diff --git a/apps/CameraITS/tests/scene1/test_dng_noise_model.py b/apps/CameraITS/tests/scene1/test_dng_noise_model.py
index 51270b6..2e3ecbb5 100644
--- a/apps/CameraITS/tests/scene1/test_dng_noise_model.py
+++ b/apps/CameraITS/tests/scene1/test_dng_noise_model.py
@@ -54,7 +54,7 @@
# Expose for the scene with min sensitivity
sens_min, sens_max = props['android.sensor.info.sensitivityRange']
sens_step = (sens_max - sens_min) / NUM_STEPS
- s_ae,e_ae,_,_,_ = cam.do_3a(get_results=True)
+ s_ae,e_ae,_,_,f_dist = cam.do_3a(get_results=True)
s_e_prod = s_ae * e_ae
sensitivities = range(sens_min, sens_max, sens_step)
@@ -64,7 +64,7 @@
# Capture a raw frame with the desired sensitivity.
exp = int(s_e_prod / float(sens))
- req = its.objects.manual_capture_request(sens, exp)
+ req = its.objects.manual_capture_request(sens, exp, f_dist)
cap = cam.do_capture(req, cam.CAP_RAW)
# Test each raw color channel (R, GR, GB, B):
diff --git a/apps/CameraITS/tests/scene1/test_exposure.py b/apps/CameraITS/tests/scene1/test_exposure.py
index dc4a790..6299f79 100644
--- a/apps/CameraITS/tests/scene1/test_exposure.py
+++ b/apps/CameraITS/tests/scene1/test_exposure.py
@@ -62,7 +62,8 @@
s_test = round(s*m)
e_test = s_e_product / s_test
print "Testing s:", s_test, "e:", e_test
- req = its.objects.manual_capture_request(s_test, e_test, True, props)
+ req = its.objects.manual_capture_request(
+ s_test, e_test, 0.0, True, props)
cap = cam.do_capture(req)
s_res = cap["metadata"]["android.sensor.sensitivity"]
e_res = cap["metadata"]["android.sensor.exposureTime"]
diff --git a/apps/CameraITS/tests/scene1/test_jpeg.py b/apps/CameraITS/tests/scene1/test_jpeg.py
index 7bc038d..6b14411 100644
--- a/apps/CameraITS/tests/scene1/test_jpeg.py
+++ b/apps/CameraITS/tests/scene1/test_jpeg.py
@@ -33,7 +33,7 @@
its.caps.per_frame_control(props))
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
# YUV
size = its.objects.get_available_output_sizes("yuv", props)[0]
diff --git a/apps/CameraITS/tests/scene1/test_latching.py b/apps/CameraITS/tests/scene1/test_latching.py
index a7da421..6e42c23 100644
--- a/apps/CameraITS/tests/scene1/test_latching.py
+++ b/apps/CameraITS/tests/scene1/test_latching.py
@@ -44,20 +44,20 @@
b_means = []
reqs = [
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s*2,e, True, props),
- its.objects.manual_capture_request(s*2,e, True, props),
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s, e*2, True, props),
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s*2,e, True, props),
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s, e*2, True, props),
- its.objects.manual_capture_request(s, e, True, props),
- its.objects.manual_capture_request(s, e*2, True, props),
- its.objects.manual_capture_request(s, e*2, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s*2,e, 0.0, True, props),
+ its.objects.manual_capture_request(s*2,e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e*2, 0.0, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s*2,e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e*2, 0.0, True, props),
+ its.objects.manual_capture_request(s, e, 0.0, True, props),
+ its.objects.manual_capture_request(s, e*2, 0.0, True, props),
+ its.objects.manual_capture_request(s, e*2, 0.0, True, props),
]
caps = cam.do_capture(reqs, fmt)
diff --git a/apps/CameraITS/tests/scene1/test_param_color_correction.py b/apps/CameraITS/tests/scene1/test_param_color_correction.py
index 09b3707..8623426 100644
--- a/apps/CameraITS/tests/scene1/test_param_color_correction.py
+++ b/apps/CameraITS/tests/scene1/test_param_color_correction.py
@@ -42,7 +42,7 @@
# Baseline request
e, s = its.target.get_target_exposure_combos(cam)["midSensitivity"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
req["android.colorCorrection.mode"] = 0
# Transforms:
diff --git a/apps/CameraITS/tests/scene1/test_param_exposure_time.py b/apps/CameraITS/tests/scene1/test_param_exposure_time.py
index 0c0aab1..576516c 100644
--- a/apps/CameraITS/tests/scene1/test_param_exposure_time.py
+++ b/apps/CameraITS/tests/scene1/test_param_exposure_time.py
@@ -39,7 +39,7 @@
e,s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
for i,e_mult in enumerate([0.8, 0.9, 1.0, 1.1, 1.2]):
- req = its.objects.manual_capture_request(s, e * e_mult, True, props)
+ req = its.objects.manual_capture_request(s, e * e_mult, 0.0, True, props)
cap = cam.do_capture(req)
img = its.image.convert_capture_to_rgb_image(cap)
its.image.write_image(
diff --git a/apps/CameraITS/tests/scene1/test_param_flash_mode.py b/apps/CameraITS/tests/scene1/test_param_flash_mode.py
index 38f864f..5ef6fd6 100644
--- a/apps/CameraITS/tests/scene1/test_param_flash_mode.py
+++ b/apps/CameraITS/tests/scene1/test_param_flash_mode.py
@@ -39,7 +39,7 @@
# linear tonemap.
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
e /= 4
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
for f in [0,1,2]:
req["android.flash.mode"] = f
diff --git a/apps/CameraITS/tests/scene1/test_raw_burst_sensitivity.py b/apps/CameraITS/tests/scene1/test_raw_burst_sensitivity.py
index e176312..1d2a6b1 100644
--- a/apps/CameraITS/tests/scene1/test_raw_burst_sensitivity.py
+++ b/apps/CameraITS/tests/scene1/test_raw_burst_sensitivity.py
@@ -47,14 +47,14 @@
# Digital gains might not be visible on RAW data
sens_max = props['android.sensor.maxAnalogSensitivity']
sens_step = (sens_max - sens_min) / NUM_STEPS
- s_ae,e_ae,_,_,_ = cam.do_3a(get_results=True)
+ s_ae,e_ae,_,_,f_dist = cam.do_3a(get_results=True)
s_e_prod = s_ae * e_ae
reqs = []
settings = []
for s in range(sens_min, sens_max, sens_step):
e = int(s_e_prod / float(s))
- req = its.objects.manual_capture_request(s, e)
+ req = its.objects.manual_capture_request(s, e, f_dist)
reqs.append(req)
settings.append((s,e))
diff --git a/apps/CameraITS/tests/scene1/test_raw_sensitivity.py b/apps/CameraITS/tests/scene1/test_raw_sensitivity.py
index cc0ce14..e49ee34 100644
--- a/apps/CameraITS/tests/scene1/test_raw_sensitivity.py
+++ b/apps/CameraITS/tests/scene1/test_raw_sensitivity.py
@@ -45,14 +45,14 @@
# Digital gains might not be visible on RAW data
sens_max = props['android.sensor.maxAnalogSensitivity']
sens_step = (sens_max - sens_min) / NUM_STEPS
- s_ae,e_ae,_,_,_ = cam.do_3a(get_results=True)
+ s_ae,e_ae,_,_,f_dist = cam.do_3a(get_results=True)
s_e_prod = s_ae * e_ae
variances = []
for s in range(sens_min, sens_max, sens_step):
e = int(s_e_prod / float(s))
- req = its.objects.manual_capture_request(s, e)
+ req = its.objects.manual_capture_request(s, e, f_dist)
# Capture raw+yuv, but only look at the raw.
cap,_ = cam.do_capture(req, cam.CAP_RAW_YUV)
diff --git a/apps/CameraITS/tests/scene1/test_tonemap_sequence.py b/apps/CameraITS/tests/scene1/test_tonemap_sequence.py
index 54d3d65..0db70b8 100644
--- a/apps/CameraITS/tests/scene1/test_tonemap_sequence.py
+++ b/apps/CameraITS/tests/scene1/test_tonemap_sequence.py
@@ -35,12 +35,12 @@
its.caps.manual_post_proc(props) and
its.caps.per_frame_control(props))
- sens, exp_time, _,_,_ = cam.do_3a(do_af=False,get_results=True)
+ sens, exp_time, _,_,f_dist = cam.do_3a(do_af=True,get_results=True)
means = []
# Capture 3 manual shots with a linear tonemap.
- req = its.objects.manual_capture_request(sens, exp_time, True, props)
+ req = its.objects.manual_capture_request(sens, exp_time, f_dist, True, props)
for i in [0,1,2]:
cap = cam.do_capture(req)
img = its.image.convert_capture_to_rgb_image(cap)
@@ -49,7 +49,7 @@
means.append(tile.mean(0).mean(0))
# Capture 3 manual shots with the default tonemap.
- req = its.objects.manual_capture_request(sens, exp_time, False)
+ req = its.objects.manual_capture_request(sens, exp_time, f_dist, False)
for i in [3,4,5]:
cap = cam.do_capture(req)
img = its.image.convert_capture_to_rgb_image(cap)
diff --git a/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py b/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py
index 0c428fc..0d3726d 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_jpeg_all.py
@@ -35,7 +35,7 @@
# Use a manual request with a linear tonemap so that the YUV and JPEG
# should look the same (once converted by the its.image module).
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
rgbs = []
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py b/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py
index 78378eb..f559c2b 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_jpeg.py
@@ -41,7 +41,7 @@
# Use a manual request with a linear tonemap so that the YUV and JPEG
# should look the same (once converted by the its.image module).
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
cap_yuv, cap_jpeg = cam.do_capture(req, [fmt_yuv, fmt_jpeg])
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
index bfa6a28..a5ceaba 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw.py
@@ -36,7 +36,7 @@
# Use a manual request with a linear tonemap so that the YUV and RAW
# should look the same (once converted by the its.image module).
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
max_raw_size = \
its.objects.get_available_output_sizes("raw", props)[0]
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
index 322af10..f281089 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw10.py
@@ -36,7 +36,7 @@
# Use a manual request with a linear tonemap so that the YUV and RAW
# should look the same (once converted by the its.image module).
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
max_raw10_size = \
its.objects.get_available_output_sizes("raw10", props)[0]
diff --git a/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py b/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
index b3cca0b..5b6051a 100644
--- a/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
+++ b/apps/CameraITS/tests/scene1/test_yuv_plus_raw12.py
@@ -36,7 +36,7 @@
# Use a manual request with a linear tonemap so that the YUV and RAW
# should look the same (once converted by the its.image module).
e, s = its.target.get_target_exposure_combos(cam)["midExposureTime"]
- req = its.objects.manual_capture_request(s, e, True, props)
+ req = its.objects.manual_capture_request(s, e, 0.0, True, props)
max_raw12_size = \
its.objects.get_available_output_sizes("raw12", props)[0]
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index a5fc819..ec9d6e8 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -45,6 +45,8 @@
THRES_L_CP_TEST = 0.02
# pass/fail threshold of mini size images for crop test
THRES_XS_CP_TEST = 0.05
+ # Crop test will allow at least THRES_MIN_PIXEL offset
+ THRES_MIN_PIXEL = 4
PREVIEW_SIZE = (1920, 1080) # preview size
aspect_ratio_gt = 1 # ground truth
failed_ar = [] # streams failed the aspect ration test
@@ -84,7 +86,7 @@
print "AWB transform", xform
print "AF distance", focus
req = its.objects.manual_capture_request(
- sens, exp, True, props)
+ sens, exp, focus, True, props)
xform_rat = its.objects.float_to_rational(xform)
req["android.colorCorrection.gains"] = gains
req["android.colorCorrection.transform"] = xform_rat
@@ -150,8 +152,8 @@
img = its.image.convert_capture_to_rgb_image(frm_iter)
img_name = "%s_%s_with_%s_w%d_h%d.png" \
% (NAME, fmt_iter, fmt_cmpr, w_iter, h_iter)
- aspect_ratio, cc_ct, _ = measure_aspect_ratio(img, raw_avlb,
- img_name)
+ aspect_ratio, cc_ct, (cc_w, cc_h) = \
+ measure_aspect_ratio(img, raw_avlb, img_name)
# check pass/fail for aspect ratio
# image size >= LARGE_SIZE: use THRES_L_AR_TEST
# image size == 0 (extreme case): THRES_XS_AR_TEST
@@ -176,14 +178,23 @@
# image size == 0 (extreme case): thres_xs_cp_test
# 0 < image size < LARGE_SIZE: scale between
# thres_xs_cp_test and thres_l_cp_test
+ # Also, allow at least THRES_MIN_PIXEL off to
+ # prevent threshold being too tight for very
+ # small circle
thres_hori_cp_test = max(thres_l_cp_test,
thres_xs_cp_test + w_iter *
(thres_l_cp_test-thres_xs_cp_test)/LARGE_SIZE)
+ min_threshold_h = THRES_MIN_PIXEL / cc_w
+ thres_hori_cp_test = max(thres_hori_cp_test,
+ min_threshold_h)
thres_range_h_cp = (cc_ct_gt["hori"]-thres_hori_cp_test,
cc_ct_gt["hori"]+thres_hori_cp_test)
thres_vert_cp_test = max(thres_l_cp_test,
thres_xs_cp_test + h_iter *
(thres_l_cp_test-thres_xs_cp_test)/LARGE_SIZE)
+ min_threshold_v = THRES_MIN_PIXEL / cc_h
+ thres_vert_cp_test = max(thres_vert_cp_test,
+ min_threshold_v)
thres_range_v_cp = (cc_ct_gt["vert"]-thres_vert_cp_test,
cc_ct_gt["vert"]+thres_vert_cp_test)
if cc_ct["hori"] < thres_range_h_cp[0] \
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
index b0486ef..cb4324c 100644
--- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/GenericDeviceInfo.java
@@ -56,6 +56,7 @@
public static final String BUILD_VERSION_SDK_INT = "build_version_sdk_int";
public static final String BUILD_VERSION_BASE_OS = "build_version_base_os";
public static final String BUILD_VERSION_SECURITY_PATCH = "build_version_security_patch";
+ public static final String BUILD_REFERENCE_FINGERPRINT = "build_reference_fingerprint";
private final Map<String, String> mDeviceInfo = new HashMap<>();
@@ -75,6 +76,8 @@
store.addResult(BUILD_SERIAL, Build.SERIAL);
store.addResult(BUILD_VERSION_RELEASE, Build.VERSION.RELEASE);
store.addResult(BUILD_VERSION_SDK, Build.VERSION.SDK);
+ store.addResult(BUILD_REFERENCE_FINGERPRINT,
+ SystemProperties.get("ro.build.reference.fingerprint", ""));
// Collect build fields available in API level 21
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
diff --git a/tools/cts-tradefed/res/config/system-status-checkers.xml b/common/host-side/tradefed/res/config/system-status-checkers.xml
similarity index 100%
rename from tools/cts-tradefed/res/config/system-status-checkers.xml
rename to common/host-side/tradefed/res/config/system-status-checkers.xml
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 1335fc6..ebdc1e6 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
@@ -485,6 +485,11 @@
@Override
public void testLog(String name, LogDataType type, InputStreamSource stream) {
// This is safe to be invoked on either the master or a shard ResultReporter
+ if (isShardResultReporter()) {
+ // Shard ResultReporters forward testLog to the mMasterResultReporter
+ mMasterResultReporter.testLog(name, type, stream);
+ return;
+ }
try {
LogFileSaver saver = new LogFileSaver(mLogDir);
File logFile = saver.saveAndZipLogData(name, type, stream.createInputStream());
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 b6cd48f..dd91d11 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
@@ -60,6 +60,7 @@
BUILD_KEYS.put("cts:build_version_sdk", "ro.build.version.sdk");
BUILD_KEYS.put("cts:build_version_base_os", "ro.build.version.base_os");
BUILD_KEYS.put("cts:build_version_security_patch", "ro.build.version.security_patch");
+ BUILD_KEYS.put("cts:build_reference_fingerprint", "ro.build.reference.fingerprint");
}
@Option(name = CompatibilityTest.SKIP_DEVICE_INFO_OPTION,
diff --git a/hostsidetests/services/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
index 3523478..00c6352 100755
--- a/hostsidetests/services/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activitymanager/app/AndroidManifest.xml
@@ -159,6 +159,15 @@
android:exported="true"
android:launchMode="singleInstance"
/>
+ <activity android:name=".TrampolineActivity"
+ android:exported="true"
+ android:theme="@android:style/Theme.NoDisplay"
+ />
+ <activity-alias android:enabled="true"
+ android:exported="true"
+ android:name=".EntryPointAliasActivity"
+ android:targetActivity=".TrampolineActivity" >
+ </activity-alias>
</application>
</manifest>
diff --git a/hostsidetests/services/activitymanager/app/src/android/server/app/TrampolineActivity.java b/hostsidetests/services/activitymanager/app/src/android/server/app/TrampolineActivity.java
new file mode 100644
index 0000000..4b80482
--- /dev/null
+++ b/hostsidetests/services/activitymanager/app/src/android/server/app/TrampolineActivity.java
@@ -0,0 +1,50 @@
+/*
+ * 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.server.app;
+
+import android.os.Bundle;
+
+import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
+import android.content.Intent;
+
+public class TrampolineActivity extends AbstractLifecycleLogActivity {
+
+ private static final String TAG = TrampolineActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ // Add a delay here to expose more easily a failure case where the real target
+ // activity is visible before it's launched, because its task is being brought
+ // to foreground. We need to verify that 'am start' is unblocked correctly.
+ try {
+ Thread.sleep(2000);
+ } catch(InterruptedException e) {}
+ Intent intent = new Intent(this, SingleTaskActivity.class);
+ intent.setFlags(FLAG_ACTIVITY_CLEAR_TOP | FLAG_ACTIVITY_NEW_TASK);
+
+ startActivity(intent);
+ finish();
+ }
+
+ @Override
+ protected String getTag() {
+ return TAG;
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAmStartOptionsTests.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAmStartOptionsTests.java
new file mode 100644
index 0000000..0083be4
--- /dev/null
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerAmStartOptionsTests.java
@@ -0,0 +1,228 @@
+/*
+ * 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.server.cts;
+
+import com.android.tradefed.device.DeviceNotAvailableException;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+
+public class ActivityManagerAmStartOptionsTests extends ActivityManagerTestBase {
+
+ private static final String TEST_ACTIVITY_NAME = "TestActivity";
+ private static final String ENTRYPOINT_ACTIVITY_NAME = "EntryPointAliasActivity";
+ private static final String SINGLE_TASK_ACTIVITY_NAME = "SingleTaskActivity";
+
+ public void testDashD() throws Exception {
+ final String[] waitForActivitiesVisible = new String[] {TEST_ACTIVITY_NAME};
+ AmStartLogcatVerifier verifier = new AmStartLogcatVerifier("android.server.app", TEST_ACTIVITY_NAME);
+
+ // Run at least 2 rounds to verify that -D works with an existing process.
+ // -D could fail in this case if the force stop of process is broken.
+ for (int i = 0; i < 2; i++) {
+ clearLogcat();
+ executeShellCommand(getAmStartCmd(TEST_ACTIVITY_NAME) + " -D");
+
+ // visibleOnly=false as the first window popping up will be the debugger window.
+ mAmWmState.computeState(mDevice, false, waitForActivitiesVisible);
+ verifier.verifyDashD();
+ }
+ }
+
+ public void testDashW_Direct() throws Exception {
+ testDashW(SINGLE_TASK_ACTIVITY_NAME, SINGLE_TASK_ACTIVITY_NAME);
+ }
+
+ public void testDashW_Indirect() throws Exception {
+ testDashW(ENTRYPOINT_ACTIVITY_NAME, SINGLE_TASK_ACTIVITY_NAME);
+ }
+
+ private void testDashW(final String entryActivity, final String actualActivity)
+ throws Exception {
+ AmStartLogcatVerifier verifier = new AmStartLogcatVerifier("android.server.app", actualActivity);
+
+ // Test cold start
+ startActivityAndVerifyResult(verifier, entryActivity, actualActivity, true);
+
+ // Test warm start
+ pressHomeButton();
+ startActivityAndVerifyResult(verifier, entryActivity, actualActivity, false);
+
+ // Test "hot" start (app already in front)
+ startActivityAndVerifyResult(verifier, entryActivity, actualActivity, false);
+ }
+
+ private static final Pattern sNotStartedWarningPattern = Pattern.compile(
+ "Warning: Activity not started(.*)");
+ private static final Pattern sStatusPattern = Pattern.compile(
+ "Status: (.*)");
+ private static final Pattern sActivityPattern = Pattern.compile(
+ "Activity: (.*)");
+ private static final String sStatusOk = "ok";
+
+ private void startActivityAndVerifyResult(
+ final AmStartLogcatVerifier verifier, final String entryActivity,
+ final String actualActivity, boolean shouldStart) throws Exception {
+ clearLogcat();
+
+ // Pass in different data only when cold starting. This is to make the intent
+ // different in subsequent warm/hot launches, so that the entrypoint alias
+ // activity is always started, but the actual activity is not started again
+ // because of the NEW_TASK and singleTask flags.
+ final String result = executeShellCommand(getAmStartCmd(entryActivity) + " -W"
+ + (shouldStart ? " -d about:blank" : ""));
+
+ // Verify shell command return value
+ verifyShellOutput(result, actualActivity, shouldStart);
+
+ // Verify adb logcat log
+ verifier.verifyDashW(shouldStart);
+ }
+
+ private void verifyShellOutput(
+ final String result, final String activity, boolean shouldStart) {
+ boolean warningFound = false;
+ String status = null;
+ String reportedActivity = null;
+ String componentActivityName = getActivityComponentName(activity);
+
+ for (String line : result.split("\\n")) {
+ Matcher matcher = sNotStartedWarningPattern.matcher(line);
+ if (matcher.matches()) {
+ warningFound = true;
+ continue;
+ }
+ matcher = sStatusPattern.matcher(line);
+ if (matcher.matches()) {
+ status = matcher.group(1);
+ continue;
+ }
+ matcher = sActivityPattern.matcher(line);
+ if (matcher.matches()) {
+ reportedActivity = matcher.group(1);
+ continue;
+ }
+ }
+
+ assertTrue("Status " + status + " is not ok", sStatusOk.equals(status));
+ assertTrue("Reported activity is " + reportedActivity + " not " + componentActivityName,
+ componentActivityName.equals(reportedActivity));
+
+ if (shouldStart && warningFound) {
+ fail("Should start new activity but brought something to front.");
+ } else if (!shouldStart && !warningFound){
+ fail("Should bring existing activity to front but started new activity.");
+ }
+ }
+
+ private static final Pattern sStartProcPattern =
+ Pattern.compile("(.+): Start proc (\\d+):(.*) for activity (.*)");
+ private static final Pattern sKillingPattern =
+ Pattern.compile("(.+): Killing (\\d+):(.*)");
+ private static final Pattern sWaitingForDebuggerPattern =
+ Pattern.compile("(.+): Application (.+) is waiting for the debugger (.*)");
+ private static final Pattern sDisplayTimePattern =
+ Pattern.compile("(.+): Displayed (.*): (\\+{0,1})([0-9]+)ms(.*)");
+
+ private class AmStartLogcatVerifier {
+ private String mPrevProcId;
+ private final String mPackageName;
+ private final String mActivityName;
+
+ AmStartLogcatVerifier(String packageName, String activityName) {
+ mPackageName = packageName;
+ mActivityName = activityName;
+ }
+
+ void verifyDashD() throws DeviceNotAvailableException {
+ boolean prevProcKilled = false;;
+ boolean waitingForDebugger = false;
+ String newProcId = null;
+ final String[] componentNames = new String[] {"ActivityManager", "ActivityThread"};
+
+ for (String line : getDeviceLogsForComponents(componentNames)) {
+ line = line.trim();
+
+ Matcher matcher = sStartProcPattern.matcher(line);
+ if (matcher.matches()) {
+ final String activity = matcher.group(4);
+ if (activity.contains(mActivityName)) {
+ newProcId = matcher.group(2);
+ }
+ continue;
+ }
+
+ matcher = sKillingPattern.matcher(line);
+ if (matcher.matches()) {
+ final String procId = matcher.group(2);
+ if (procId.equals(mPrevProcId)) {
+ prevProcKilled = true;
+ }
+ continue;
+ }
+
+ matcher = sWaitingForDebuggerPattern.matcher(line);
+ if (matcher.matches()) {
+ final String packageName = matcher.group(2);
+ if (packageName.equals(mPackageName)) {
+ waitingForDebugger = true;
+ }
+ continue;
+ }
+ }
+
+ assertTrue("Didn't kill exisiting proc " + mPrevProcId + ".",
+ mPrevProcId == null || prevProcKilled);
+ assertTrue("Didn't start new proc.", newProcId != null);
+ assertTrue("Didn't wait for debugger.", waitingForDebugger);
+
+ mPrevProcId = newProcId;
+ }
+
+ void verifyDashW(boolean shouldStart) throws DeviceNotAvailableException {
+ int displayCount = 0;
+ String activityName = null;
+
+ for (String line : getDeviceLogsForComponent("ActivityManager")) {
+ line = line.trim();
+
+ Matcher matcher = sDisplayTimePattern.matcher(line);
+ if (matcher.matches()) {
+ activityName = matcher.group(2);
+ // Ignore activitiy displays from other packages, we don't
+ // want some random activity starts to ruin our test.
+ if (!activityName.startsWith("android.server.app")) {
+ continue;
+ }
+ if (!shouldStart) {
+ fail("Shouldn't display anything but displayed " + activityName);
+ }
+ displayCount++;
+ }
+ }
+ final String expectedActivityName = getActivityComponentName(mActivityName);
+ if (shouldStart) {
+ if (displayCount != 1) {
+ fail("Should display exactly one activity but displayed " + displayCount);
+ } else if (!expectedActivityName.equals(activityName)) {
+ fail("Should display " + expectedActivityName +
+ " but displayed " + activityName);
+ }
+ }
+ }
+ }
+}
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
index 04b0653..067f873 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/ActivityManagerTestBase.java
@@ -74,6 +74,8 @@
private static final String AM_MOVE_TASK = "am stack movetask ";
+ private static final String INPUT_KEYEVENT_HOME = "input keyevent 3";
+
/** A reference to the device under test. */
protected ITestDevice mDevice;
@@ -182,6 +184,10 @@
+ " 0 0 " + taskWidth + " " + taskHeight);
}
+ protected void pressHomeButton() throws DeviceNotAvailableException {
+ executeShellCommand(INPUT_KEYEVENT_HOME);
+ }
+
// Utility method for debugging, not used directly here, but useful, so kept around.
protected void printStacksAndTasks() throws DeviceNotAvailableException {
CollectingOutputReceiver outputReceiver = new CollectingOutputReceiver();
@@ -395,10 +401,20 @@
}
}
- private String[] getDeviceLogsForActivity(String activityName)
+ protected String[] getDeviceLogsForComponent(String componentName)
throws DeviceNotAvailableException {
- return mDevice.executeAdbCommand("logcat", "-v", "brief", "-d", activityName + ":I", "*:S")
- .split("\\n");
+ return mDevice.executeAdbCommand(
+ "logcat", "-v", "brief", "-d", componentName + ":I", "*:S").split("\\n");
+ }
+
+ protected String[] getDeviceLogsForComponents(final String[] componentNames)
+ throws DeviceNotAvailableException {
+ String filters = "";
+ for (int i = 0; i < componentNames.length; i++) {
+ filters += componentNames[i] + ":I ";
+ }
+ return mDevice.executeAdbCommand(
+ "logcat", "-v", "brief", "-d", filters, "*:S").split("\\n");
}
private static final Pattern sCreatePattern = Pattern.compile("(.+): onCreate");
@@ -422,7 +438,7 @@
protected ReportedSizes getLastReportedSizesForActivity(String activityName)
throws DeviceNotAvailableException {
- final String[] lines = getDeviceLogsForActivity(activityName);
+ final String[] lines = getDeviceLogsForComponent(activityName);
for (int i = lines.length - 1; i >= 0; i--) {
final String line = lines[i].trim();
final Matcher matcher = sNewConfigPattern.matcher(line);
@@ -446,7 +462,7 @@
int mDestroyCount;
public ActivityLifecycleCounts(String activityName) throws DeviceNotAvailableException {
- for (String line : getDeviceLogsForActivity(activityName)) {
+ for (String line : getDeviceLogsForComponent(activityName)) {
line = line.trim();
Matcher matcher = sCreatePattern.matcher(line);
diff --git a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
index 3f66c18..a057013 100644
--- a/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
+++ b/hostsidetests/services/activitymanager/src/android/server/cts/WindowManagerState.java
@@ -49,6 +49,8 @@
"mCurrentFocus=Window\\{([0-9a-fA-F]+) u(\\d+) (\\S+)\\}");
private static final Pattern sAppErrorFocusedWindowPattern = Pattern.compile(
"mCurrentFocus=Window\\{([0-9a-fA-F]+) u(\\d+) Application Error\\: (\\S+)\\}");
+ private static final Pattern sWaitingForDebuggerFocusedWindowPattern = Pattern.compile(
+ "mCurrentFocus=Window\\{([0-9a-fA-F]+) u(\\d+) Waiting For Debugger\\: (\\S+)\\}");
private static final Pattern sFocusedAppPattern =
Pattern.compile("mFocusedApp=AppWindowToken\\{(.+) token=Token\\{(.+) "
@@ -58,7 +60,8 @@
private static final Pattern[] sExtractStackExitPatterns = {
sStackIdPattern, sWindowPattern, sStartingWindowPattern, sExitingWindowPattern,
- sFocusedWindowPattern, sAppErrorFocusedWindowPattern, sFocusedAppPattern };
+ sFocusedWindowPattern, sAppErrorFocusedWindowPattern,
+ sWaitingForDebuggerFocusedWindowPattern, sFocusedAppPattern };
// Windows in z-order with the top most at the front of the list.
private List<String> mWindows = new ArrayList();
@@ -182,6 +185,15 @@
continue;
}
+ matcher = sWaitingForDebuggerFocusedWindowPattern.matcher(line);
+ if (matcher.matches()) {
+ log(line);
+ final String focusedWindow = matcher.group(3);
+ log(focusedWindow);
+ mFocusedWindow = focusedWindow;
+ continue;
+ }
+
matcher = sFocusedAppPattern.matcher(line);
if (matcher.matches()) {
log(line);
diff --git a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
index 855f74c..519ad84 100644
--- a/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
+++ b/hostsidetests/theme/src/android/theme/cts/ThemeHostTest.java
@@ -278,6 +278,7 @@
}
private static boolean checkHardwareTypeSkipTest(String hardwareTypeString) {
- return hardwareTypeString.contains("android.hardware.type.watch");
+ return hardwareTypeString.contains("android.hardware.type.watch")
+ || hardwareTypeString.contains("android.hardware.type.television");
}
}
diff --git a/tests/app/src/android/app/cts/SystemFeaturesTest.java b/tests/app/src/android/app/cts/SystemFeaturesTest.java
index 864f1be..aca79fc 100644
--- a/tests/app/src/android/app/cts/SystemFeaturesTest.java
+++ b/tests/app/src/android/app/cts/SystemFeaturesTest.java
@@ -48,6 +48,8 @@
import java.util.List;
import java.util.Set;
+import junit.framework.AssertionFailedError;
+
/**
* Test for checking that the {@link PackageManager} is reporting the correct features.
*/
@@ -258,10 +260,18 @@
public void testNfcFeatures() {
if (NfcAdapter.getDefaultAdapter(mContext) != null) {
- assertAvailable(PackageManager.FEATURE_NFC);
- assertAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ // Watches MAY support all FEATURE_NFC features when an NfcAdapter is available, but
+ // non-watches MUST support them both.
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ assertOneAvailable(PackageManager.FEATURE_NFC,
+ PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ } else {
+ assertAvailable(PackageManager.FEATURE_NFC);
+ assertAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ }
} else {
assertNotAvailable(PackageManager.FEATURE_NFC);
+ assertNotAvailable(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
}
}
@@ -457,7 +467,11 @@
}
public void testUsbAccessory() {
- assertAvailable(PackageManager.FEATURE_USB_ACCESSORY);
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) &&
+ !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEVISION) &&
+ !mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ assertAvailable(PackageManager.FEATURE_USB_ACCESSORY);
+ }
}
public void testWifiFeature() throws Exception {
@@ -494,6 +508,16 @@
mAvailableFeatures.contains(feature));
}
+ private void assertOneAvailable(String feature1, String feature2) {
+ if ((mPackageManager.hasSystemFeature(feature1) && mAvailableFeatures.contains(feature1)) ||
+ (mPackageManager.hasSystemFeature(feature2) && mAvailableFeatures.contains(feature2))) {
+ return;
+ } else {
+ throw new AssertionFailedError("Must support at least one of " + feature1 + " or " +
+ feature2);
+ }
+ }
+
private void assertFeature(boolean exist, String feature) {
if (exist) {
assertAvailable(feature);
diff --git a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
index a367d37..3c762cf 100644
--- a/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/SurfaceViewPreviewTest.java
@@ -451,17 +451,18 @@
* validated.
*/
private void previewFpsRangeTestByCamera() throws Exception {
- Size maxPreviewSz = mOrderedPreviewSizes.get(0);
+ Size maxPreviewSz;
Range<Integer>[] fpsRanges = mStaticInfo.getAeAvailableTargetFpsRangesChecked();
boolean antiBandingOffIsSupported = mStaticInfo.isAntiBandingOffModeSupported();
Range<Integer> fpsRange;
CaptureRequest.Builder requestBuilder =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
- startPreview(requestBuilder, maxPreviewSz, resultListener);
for (int i = 0; i < fpsRanges.length; i += 1) {
fpsRange = fpsRanges[i];
+ maxPreviewSz = getMaxPreviewSizeForFpsRange(fpsRange);
+ startPreview(requestBuilder, maxPreviewSz, resultListener);
requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
// Turn off auto antibanding to avoid exposure time and frame duration interference
@@ -482,9 +483,9 @@
verifyPreviewTargetFpsRange(resultListener, NUM_FRAMES_VERIFIED, fpsRange,
maxPreviewSz);
+ stopPreview();
+ resultListener.drain();
}
-
- stopPreview();
}
private void verifyPreviewTargetFpsRange(SimpleCaptureCallback resultListener,
diff --git a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
index 03ab3cf..4452953 100644
--- a/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
+++ b/tests/tests/content/src/android/content/cts/AvailableIntentsTest.java
@@ -24,6 +24,7 @@
import android.content.pm.ResolveInfo;
import android.media.RingtoneManager;
import android.net.Uri;
+import android.os.storage.StorageManager;
import android.provider.AlarmClock;
import android.provider.MediaStore;
import android.provider.Settings;
@@ -243,7 +244,7 @@
assertCanBeHandled(new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS));
}
- public void testDeletionHelper() {
- assertCanBeHandled(new Intent(Settings.ACTION_DELETION_HELPER_SETTINGS));
+ public void testManageStorage() {
+ assertCanBeHandled(new Intent(StorageManager.ACTION_MANAGE_STORAGE));
}
}
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
index d678e1e..5dabdfd 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/AnimatedVectorDrawableTest.java
@@ -152,21 +152,20 @@
imageView.setImageDrawable(d1);
d1.start();
d1.stop();
+ d1.setBounds(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
+ mBitmap.eraseColor(0);
+ d1.draw(mCanvas);
}
});
+
getInstrumentation().waitForIdleSync();
-
- d1.setBounds(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT);
- mBitmap.eraseColor(0);
- d1.draw(mCanvas);
-
int endColor = mBitmap.getPixel(IMAGE_WIDTH / 2, IMAGE_HEIGHT / 2);
- assertEquals("Center point's color must be green", 0xFF00FF00, endColor);
-
if (DBG_DUMP_PNG) {
saveVectorDrawableIntoPNG(mBitmap, resId);
}
+
+ assertEquals("Center point's color must be green", 0xFF00FF00, endColor);
}
@SmallTest
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index 1407cc9..8a82706 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -45,10 +45,10 @@
static const std::string kVendorLibraryPath = "/vendor/lib";
#endif
-// This is not complete list - just a small subset
+// This is not the complete list - just a small subset
// of the libraries that should reside in /system/lib
// (in addition to kSystemPublicLibraries)
-static std::unordered_set<std::string> kSystemLibraries = {
+static std::vector<std::string> kSystemLibraries = {
"libart.so",
"libandroid_runtime.so",
"libbinder.so",
@@ -61,39 +61,6 @@
"libutils.so",
};
-template <typename F>
-static bool for_each_file(const std::string& dir, F functor, std::string* error_msg) {
- auto dir_deleter = [](DIR* handle) { closedir(handle); };
- std::unique_ptr<DIR, decltype(dir_deleter)> dirp(opendir(dir.c_str()), dir_deleter);
- if (dirp == nullptr) {
- *error_msg = strerror(errno);
- return false;
- }
-
- dirent* dp;
- while ((dp = readdir(dirp.get())) != nullptr) {
- // skip "." and ".."
- if (strcmp(".", dp->d_name) == 0 ||
- strcmp("..", dp->d_name) == 0) {
- continue;
- }
-
- if (!functor(dp->d_name, error_msg)) {
- return false;
- }
- }
-
- return true;
-}
-
-static bool should_be_accessible(const std::string& public_library_path,
- const std::unordered_set<std::string>& public_libraries,
- const std::string& path) {
- std::string name = basename(path.c_str());
- return (public_libraries.find(name) != public_libraries.end()) &&
- (public_library_path + "/" + name == path);
-}
-
static bool is_directory(const std::string path) {
struct stat sb;
if (stat(path.c_str(), &sb) != -1) {
@@ -107,10 +74,18 @@
return kSystemLibraryPath + "/libdl.so" == path;
}
-static bool check_lib(const std::string& public_library_path,
- const std::unordered_set<std::string>& public_libraries,
- const std::string& path,
- std::string* error_msg) {
+static bool already_loaded(const std::string& library, const std::string& err) {
+ if (err.find("dlopen failed: library \"" + library + "\"") != 0 ||
+ err.find("is not accessible for the namespace \"classloader-namespace\"") == std::string::npos) {
+ return false;
+ }
+ return true;
+}
+
+static bool check_lib(const std::string& path,
+ const std::string& library_path,
+ const std::unordered_set<std::string>& libraries,
+ std::vector<std::string>* errors) {
if (is_libdl(path)) {
// TODO (dimitry): we skip check for libdl.so because
// 1. Linker will fail to check accessibility because it imposes as libdl.so (see http://b/27106625)
@@ -119,83 +94,99 @@
return true;
}
- auto dlcloser = [](void* handle) { dlclose(handle); };
- std::unique_ptr<void, decltype(dlcloser)> handle(dlopen(path.c_str(), RTLD_NOW), dlcloser);
- if (should_be_accessible(public_library_path, public_libraries, path)) {
+ std::unique_ptr<void, int (*)(void*)> handle(dlopen(path.c_str(), RTLD_NOW), dlclose);
+
+ // The current restrictions on public libraries:
+ // - It must exist only in the top level directory of "library_path".
+ // - No library with the same name can be found in a sub directory.
+ // - Each public library does not contain any directory components.
+
+ // Check if this library should be considered a public library.
+ std::string baselib = basename(path.c_str());
+ if (libraries.find(baselib) != libraries.end() &&
+ library_path + "/" + baselib == path) {
if (handle.get() == nullptr) {
- *error_msg = "The library \"" + path + "\" should be accessible but isn't: " + dlerror();
+ errors->push_back("The library \"" + path +
+ "\" is a public library but it cannot be loaded: " + dlerror());
return false;
}
} else if (handle.get() != nullptr) {
- *error_msg = "The library \"" + path + "\" should not be accessible";
+ errors->push_back("The library \"" + path + "\" is not a public library but it loaded.");
return false;
} else { // (handle == nullptr && !shouldBeAccessible(path))
// Check the error message
std::string err = dlerror();
-
- if (err.find("dlopen failed: library \"" + path + "\"") != 0 ||
- err.find("is not accessible for the namespace \"classloader-namespace\"") == std::string::npos) {
- *error_msg = "unexpected dlerror: " + err;
+ if (!already_loaded(path, err)) {
+ errors->push_back("unexpected dlerror: " + err);
return false;
}
}
return true;
}
-static bool check_libs(const std::string& public_library_path,
- const std::unordered_set<std::string>& public_libraries,
- const std::unordered_set<std::string>& mandatory_files,
- std::string* error) {
- std::list<std::string> dirs;
- dirs.push_back(public_library_path);
-
+static bool check_path(const std::string& library_path,
+ const std::unordered_set<std::string> libraries,
+ std::vector<std::string>* errors) {
+ bool success = true;
+ std::list<std::string> dirs = { library_path };
while (!dirs.empty()) {
- const auto dir = dirs.front();
+ std::string dir = dirs.front();
dirs.pop_front();
- bool success = for_each_file(dir, [&](const char* name, std::string* error_msg) {
- std::string path = dir + "/" + name;
- if (is_directory(path)) {
- dirs.push_back(path);
- return true;
- }
- return check_lib(public_library_path, public_libraries, path, error_msg);
- }, error);
-
- if (!success) {
- return false;
+ auto dir_deleter = [](DIR* handle) { closedir(handle); };
+ std::unique_ptr<DIR, decltype(dir_deleter)> dirp(opendir(dir.c_str()), dir_deleter);
+ if (dirp == nullptr) {
+ errors->push_back("Failed to open " + dir + ": " + strerror(errno));
+ success = false;
+ continue;
}
- // Check mandatory files - the grey list
- for (const auto& name : mandatory_files) {
- std::string path = public_library_path + "/" + name;
- if (!check_lib(public_library_path, public_libraries, path, error)) {
- return false;
+ dirent* dp;
+ while ((dp = readdir(dirp.get())) != nullptr) {
+ // skip "." and ".."
+ if (strcmp(".", dp->d_name) == 0 || strcmp("..", dp->d_name) == 0) {
+ continue;
+ }
+
+ std::string path = dir + "/" + dp->d_name;
+ if (is_directory(path)) {
+ dirs.push_back(path);
+ } else if (!check_lib(path, library_path, libraries, errors)) {
+ success = false;
}
}
}
- return true;
+ return success;
}
static bool jobject_array_to_set(JNIEnv* env,
jobjectArray java_libraries_array,
std::unordered_set<std::string>* libraries,
std::string* error_msg) {
+ error_msg->clear();
size_t size = env->GetArrayLength(java_libraries_array);
+ bool success = true;
for (size_t i = 0; i<size; ++i) {
ScopedLocalRef<jstring> java_soname(
env, (jstring) env->GetObjectArrayElement(java_libraries_array, i));
std::string soname(ScopedUtfChars(env, java_soname.get()).c_str());
+ // Verify that the name doesn't contain any directory components.
+ if (soname.rfind('/') != std::string::npos) {
+ *error_msg += "\n---Illegal value, no directories allowed: " + soname;
+ continue;
+ }
+
// Check to see if the string ends in " 32" or " 64" to indicate the
// library is only public for one bitness.
size_t space_pos = soname.rfind(' ');
if (space_pos != std::string::npos) {
std::string type = soname.substr(space_pos + 1);
if (type != "32" && type != "64") {
- *error_msg = "public library line is malformed: " + soname;
- return false;
+ *error_msg += "\n---Illegal value at end of line (only 32 or 64 allowed): " + soname;
+ success = false;
+ continue;
}
#if defined(__LP64__)
if (type == "32") {
@@ -214,7 +205,7 @@
libraries->insert(soname);
}
- return true;
+ return success;
}
extern "C" JNIEXPORT jstring JNICALL
@@ -223,21 +214,55 @@
jclass clazz __attribute__((unused)),
jobjectArray java_system_public_libraries,
jobjectArray java_vendor_public_libraries) {
- std::string error;
-
+ bool success = true;
+ std::vector<std::string> errors;
+ std::string error_msg;
std::unordered_set<std::string> vendor_public_libraries;
- std::unordered_set<std::string> system_public_libraries;
- std::unordered_set<std::string> empty_set;
- if (!jobject_array_to_set(env, java_vendor_public_libraries, &vendor_public_libraries, &error)) {
- return env->NewStringUTF(("Vendor " + error).c_str());
- }
- if (!jobject_array_to_set(env, java_system_public_libraries, &system_public_libraries, &error)) {
- return env->NewStringUTF(("System " + error).c_str());
+ if (!jobject_array_to_set(env, java_vendor_public_libraries, &vendor_public_libraries,
+ &error_msg)) {
+ success = false;
+ errors.push_back("Errors in vendor public library file:" + error_msg);
}
- if (!check_libs(kSystemLibraryPath, system_public_libraries, kSystemLibraries, &error) ||
- !check_libs(kVendorLibraryPath, vendor_public_libraries, empty_set, &error)) {
- return env->NewStringUTF(error.c_str());
+ std::unordered_set<std::string> system_public_libraries;
+ if (!jobject_array_to_set(env, java_system_public_libraries, &system_public_libraries,
+ &error_msg)) {
+ success = false;
+ errors.push_back("Errors in system public library file:" + error_msg);
+ }
+
+ // Check the system libraries.
+ if (!check_path(kSystemLibraryPath, system_public_libraries, &errors)) {
+ success = false;
+ }
+
+ // Check that the mandatory system libraries are present - the grey list
+ for (const auto& name : kSystemLibraries) {
+ std::string library = kSystemLibraryPath + "/" + name;
+ void* handle = dlopen(library.c_str(), RTLD_NOW);
+ if (handle == nullptr) {
+ std::string err = dlerror();
+ // If the library is already loaded, then dlopen failing is okay.
+ if (!already_loaded(library, err)) {
+ errors.push_back("Mandatory system library \"" + library + "\" failed to load: " + err);
+ success = false;
+ }
+ } else {
+ dlclose(handle);
+ }
+ }
+
+ // Check the vendor libraries.
+ if (!check_path(kVendorLibraryPath, vendor_public_libraries, &errors)) {
+ success = false;
+ }
+
+ if (!success) {
+ std::string error_str;
+ for (const auto& line : errors) {
+ error_str += line + '\n';
+ }
+ return env->NewStringUTF(error_str.c_str());
}
return nullptr;
diff --git a/tests/tests/media/assets/520x360h264decodertest.mp4 b/tests/tests/media/assets/520x360h264decodertest.mp4
new file mode 100644
index 0000000..362568c
--- /dev/null
+++ b/tests/tests/media/assets/520x360h264decodertest.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/h264decodertest520x360golden.png b/tests/tests/media/res/raw/h264decodertest520x360golden.png
new file mode 100644
index 0000000..fe4663d
--- /dev/null
+++ b/tests/tests/media/res/raw/h264decodertest520x360golden.png
Binary files differ
diff --git a/tests/tests/media/res/raw/h264decodertest520x360original.png b/tests/tests/media/res/raw/h264decodertest520x360original.png
new file mode 100644
index 0000000..c0fd752
--- /dev/null
+++ b/tests/tests/media/res/raw/h264decodertest520x360original.png
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
index 3f4dde0..0a3165b 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTest.java
@@ -19,98 +19,123 @@
import android.annotation.TargetApi;
import android.content.Context;
-import android.cts.util.MediaUtils;
import android.graphics.Bitmap;
-import android.os.Build;
-import android.util.DisplayMetrics;
-import android.util.Log;
import android.view.View;
-import android.view.WindowManager;
-@TargetApi(16)
+@TargetApi(24)
public class DecodeAccuracyTest extends DecodeAccuracyTestBase {
private static final String TAG = DecodeAccuracyTest.class.getSimpleName();
private static final String H264_VIDEO_FILE_NAME = "480ph264decodertest.mp4";
private static final String VP9_VIDEO_FILE_NAME = "360pvp9decodertest.webm";
+ private static final String H264_CROPPED_VIDEO_FILE_NAME = "520x360h264decodertest.mp4";
private static final int ALLOWED_GREATEST_PIXEL_DIFFERENCE = 90;
private static final int OFFSET = 10;
/* <------------- Tests Using H264 -------------> */
public void testH264GLViewVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runH264DecodeAccuracyTest(
new GLSurfaceViewFactory(),
new VideoFormat(H264_VIDEO_FILE_NAME));
}
public void testH264GLViewLargerHeightVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runH264DecodeAccuracyTest(
new GLSurfaceViewFactory(),
getLargerHeightVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
}
public void testH264GLViewLargerWidthVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runH264DecodeAccuracyTest(
new GLSurfaceViewFactory(),
getLargerWidthVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
}
public void testH264SurfaceViewVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runH264DecodeAccuracyTest(
new SurfaceViewFactory(),
new VideoFormat(H264_VIDEO_FILE_NAME));
}
public void testH264SurfaceViewLargerHeightVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runH264DecodeAccuracyTest(
new SurfaceViewFactory(),
getLargerHeightVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
}
public void testH264SurfaceViewLargerWidthVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runH264DecodeAccuracyTest(
new SurfaceViewFactory(),
getLargerWidthVideoFormat(new VideoFormat(H264_VIDEO_FILE_NAME)));
}
/* <------------- Tests Using VP9 -------------> */
public void testVP9GLViewVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runVP9DecodeAccuracyTest(
new GLSurfaceViewFactory(),
new VideoFormat(VP9_VIDEO_FILE_NAME));
}
public void testVP9GLViewLargerHeightVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runVP9DecodeAccuracyTest(
new GLSurfaceViewFactory(),
getLargerHeightVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
}
public void testVP9GLViewLargerWidthVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runVP9DecodeAccuracyTest(
new GLSurfaceViewFactory(),
getLargerWidthVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
}
public void testVP9SurfaceViewVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runVP9DecodeAccuracyTest(
new SurfaceViewFactory(),
new VideoFormat(VP9_VIDEO_FILE_NAME));
}
public void testVP9SurfaceViewLargerHeightVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runVP9DecodeAccuracyTest(
new SurfaceViewFactory(),
getLargerHeightVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
}
public void testVP9SurfaceViewLargerWidthVideoDecode() throws Exception {
- runDecodeAccuracyTest(
+ runVP9DecodeAccuracyTest(
new SurfaceViewFactory(),
getLargerWidthVideoFormat(new VideoFormat(VP9_VIDEO_FILE_NAME)));
}
- private void runDecodeAccuracyTest(VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
+ /* <------------- Tests H264 with cropping -------------> */
+ public void testH264GLViewCroppedVideoDecode() throws Exception {
+ runH264DecodeCroppedTest(
+ new GLSurfaceViewFactory(),
+ new VideoFormat(H264_CROPPED_VIDEO_FILE_NAME));
+ }
+
+ public void testH264SurfaceViewCroppedVideoDecode() throws Exception {
+ runH264DecodeCroppedTest(
+ new SurfaceViewFactory(),
+ new VideoFormat(H264_CROPPED_VIDEO_FILE_NAME));
+ }
+
+ private void runH264DecodeAccuracyTest(
+ VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
+ runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.h264decodertestgolden);
+ }
+
+ private void runVP9DecodeAccuracyTest(
+ VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
+ runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.vp9decodertestgolden);
+ }
+
+ private void runH264DecodeCroppedTest(
+ VideoViewFactory videoViewFactory, VideoFormat videoFormat) {
+ runDecodeAccuracyTest(videoViewFactory, videoFormat, R.raw.h264decodertest520x360golden);
+ }
+
+ private void runDecodeAccuracyTest(
+ VideoViewFactory videoViewFactory, VideoFormat videoFormat, int goldenResId) {
checkNotNull(videoViewFactory);
checkNotNull(videoFormat);
View videoView = videoViewFactory.createView(getHelper().getContext());
@@ -123,7 +148,7 @@
// so it needs to be created before start decoding.
final VideoViewSnapshot videoViewSnapshot = videoViewFactory.getVideoViewSnapshot();
decodeVideo(videoFormat, videoViewFactory);
- validateResult(videoFormat, videoViewSnapshot);
+ validateResult(videoFormat, videoViewSnapshot, goldenResId);
if (videoView != null) {
getHelper().cleanUpView(videoView);
@@ -140,20 +165,16 @@
assertTrue("Failed to decode the video.", playerResult.isSuccess());
}
- private void validateResult(VideoFormat videoFormat, VideoViewSnapshot videoViewSnapshot) {
+ private void validateResult(
+ VideoFormat videoFormat, VideoViewSnapshot videoViewSnapshot, int goldenResId) {
final Bitmap result = getHelper().generateBitmapFromVideoViewSnapshot(videoViewSnapshot);
- final Bitmap golden;
- final String mime = videoFormat.getMimeType();
- if (mime.equals(MimeTypes.VIDEO_H264)) {
- golden = getHelper().generateBitmapFromImageResourceId(R.raw.h264decodertestgolden);
- } else if (mime.equals(MimeTypes.VIDEO_VP9)) {
- golden = getHelper().generateBitmapFromImageResourceId(R.raw.vp9decodertestgolden);
- } else {
- fail("Unsupported MIME type " + mime);
- return;
- }
- final BitmapCompare.Difference difference = BitmapCompare.computeDifference(golden, result);
- assertTrue("Greatest pixel difference is "
+ final Bitmap golden = getHelper().generateBitmapFromImageResourceId(goldenResId);
+ final BitmapCompare.Difference difference = BitmapCompare.computeMinimumDifference(
+ result, golden, videoFormat.getOriginalWidth(), videoFormat.getOriginalHeight());
+ assertTrue("With the best matched border crop ("
+ + difference.bestMatchBorderCrop.first + ", "
+ + difference.bestMatchBorderCrop.second + "), "
+ + "greatest pixel difference is "
+ difference.greatestPixelDifference
+ (difference.greatestPixelDifferenceCoordinates != null
? " at (" + difference.greatestPixelDifferenceCoordinates.first + ", "
diff --git a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
index 3e3c866f..47029d6b 100644
--- a/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
+++ b/tests/tests/media/src/android/media/cts/DecodeAccuracyTestBase.java
@@ -617,6 +617,7 @@
/**
* Factory for building a {@link SurfaceView}
*/
+@TargetApi(24)
class SurfaceViewFactory extends VideoViewFactory implements SurfaceHolder.Callback {
private static final String TAG = SurfaceViewFactory.class.getSimpleName();
@@ -1294,6 +1295,8 @@
private int height = UNSET;
private int maxWidth = UNSET;
private int maxHeight = UNSET;
+ private int originalWidth = UNSET;
+ private int originalHeight = UNSET;
public VideoFormat(String filename, Uri uri) {
this.filename = filename;
@@ -1331,6 +1334,9 @@
public void setWidth(int width) {
this.width = width;
+ if (this.originalWidth == UNSET) {
+ this.originalWidth = width;
+ }
}
public void setMaxWidth(int maxWidth) {
@@ -1345,8 +1351,15 @@
return maxWidth;
}
+ public int getOriginalWidth() {
+ return originalWidth;
+ }
+
public void setHeight(int height) {
this.height = height;
+ if (this.originalHeight == UNSET) {
+ this.originalHeight = height;
+ }
}
public void setMaxHeight(int maxHeight) {
@@ -1361,6 +1374,10 @@
return maxHeight;
}
+ public int getOriginalHeight() {
+ return originalHeight;
+ }
+
private Uri createCacheFile(Context context) {
try {
File cacheFile = new File(context.getCacheDir(), filename);
@@ -1563,22 +1580,167 @@
return (int) Math.round(Math.sqrt(result));
}
+ /**
+ * Crops the border of the array representing an image by hBorderSize
+ * pixels on the left and right borders, and by vBorderSize pixels on the
+ * top and bottom borders (so the width is 2 * hBorderSize smaller and
+ * the height is 2 * vBorderSize smaller), then scales the image up to
+ * match the original size using bilinear interpolation.
+ */
+ private static Bitmap shrinkAndScaleBilinear(
+ Bitmap input, double hBorderSize, double vBorderSize) {
+
+ int width = input.getWidth();
+ int height = input.getHeight();
+
+ // Compute the proper step sizes
+ double xInc = ((double) width - 1 - hBorderSize * 2) / (double) (width - 1);
+ double yInc = ((double) height - 1 - vBorderSize * 2) / (double) (height - 1);
+
+ // Read the input bitmap into RGB arrays.
+ int[] inputPixels = new int[width * height];
+ input.getPixels(inputPixels, 0, width, 0, 0, width, height);
+ int[][] inputRgb = new int[width * height][3];
+ for (int i = 0; i < width * height; ++i) {
+ inputRgb[i][0] = Color.red(inputPixels[i]);
+ inputRgb[i][1] = Color.green(inputPixels[i]);
+ inputRgb[i][2] = Color.blue(inputPixels[i]);
+ }
+ inputPixels = null;
+
+ // Prepare the output buffer.
+ int[] outputPixels = new int[width * height];
+
+ // Start the iteration. The first y coordinate is vBorderSize.
+ double y = vBorderSize;
+ for (int yIndex = 0; yIndex < height; ++yIndex) {
+ // The first x coordinate is hBorderSize.
+ double x = hBorderSize;
+ for (int xIndex = 0; xIndex < width; ++xIndex) {
+ // Determine the square of interest.
+ int left = (int)x; // This is floor(x).
+ int top = (int)y; // This is floor(y).
+ int right = left + 1;
+ int bottom = top + 1;
+
+ // (u, v) is the fractional part of (x, y).
+ double u = x - (double)left;
+ double v = y - (double)top;
+
+ // Precompute necessary products to save time.
+ double p00 = (1.0 - u) * (1.0 - v);
+ double p01 = (1.0 - u) * v;
+ double p10 = u * (1.0 - v);
+ double p11 = u * v;
+
+ // Clamp the indices to prevent out-of-bound that may be caused
+ // by round-off error.
+ if (left >= width) left = width - 1;
+ if (top >= height) top = height - 1;
+ if (right >= width) right = width - 1;
+ if (bottom >= height) bottom = height - 1;
+
+ // Sample RGB values from the four corners.
+ int[] rgb00 = inputRgb[top * width + left];
+ int[] rgb01 = inputRgb[bottom * width + left];
+ int[] rgb10 = inputRgb[top * width + right];
+ int[] rgb11 = inputRgb[bottom * width + right];
+
+ // Interpolate each component of RGB separately.
+ int[] mixedColor = new int[3];
+ for (int k = 0; k < 3; ++k) {
+ mixedColor[k] = (int)Math.round(
+ p00 * (double) rgb00[k] + p01 * (double) rgb01[k]
+ + p10 * (double) rgb10[k] + p11 * (double) rgb11[k]);
+ }
+ // Convert RGB to bitmap Color format and store.
+ outputPixels[yIndex * width + xIndex] = Color.rgb(
+ mixedColor[0], mixedColor[1], mixedColor[2]);
+ x += xInc;
+ }
+ y += yInc;
+ }
+ // Assemble the output buffer into a Bitmap object.
+ return Bitmap.createBitmap(outputPixels, width, height, input.getConfig());
+ }
+
+ /**
+ * Calls computeDifference on multiple cropped-and-scaled versions of
+ * bitmap2.
+ */
+ @TargetApi(12)
+ public static Difference computeMinimumDifference(
+ Bitmap bitmap1, Bitmap bitmap2, Pair<Double, Double>[] borderCrops) {
+
+ // Compute the difference with the original image (bitmap2) first.
+ Difference minDiff = computeDifference(bitmap1, bitmap2);
+ // Then go through the list of borderCrops.
+ for (Pair<Double, Double> borderCrop : borderCrops) {
+ // Compute the difference between bitmap1 and a transformed
+ // version of bitmap2.
+ Bitmap bitmap2s = shrinkAndScaleBilinear(bitmap2, borderCrop.first, borderCrop.second);
+ Difference d = computeDifference(bitmap1, bitmap2s);
+ // Keep the minimum difference.
+ if (d.greatestPixelDifference < minDiff.greatestPixelDifference) {
+ minDiff = d;
+ minDiff.bestMatchBorderCrop = borderCrop;
+ }
+ }
+ return minDiff;
+ }
+
+ /**
+ * Calls computeMinimumDifference on a default list of borderCrop.
+ */
+ @TargetApi(12)
+ public static Difference computeMinimumDifference(
+ Bitmap bitmap1, Bitmap bitmap2, int trueWidth, int trueHeight) {
+
+ double hBorder = (double) bitmap1.getWidth() / (double) trueWidth;
+ double vBorder = (double) bitmap1.getHeight() / (double) trueHeight;
+ double hBorderH = 0.5 * hBorder; // Half-texel horizontal border
+ double vBorderH = 0.5 * vBorder; // Half-texel vertical border
+ return computeMinimumDifference(
+ bitmap1,
+ bitmap2,
+ new Pair[] {
+ Pair.create(hBorderH, 0.0),
+ Pair.create(hBorderH, vBorderH),
+ Pair.create(0.0, vBorderH),
+ Pair.create(hBorder, 0.0),
+ Pair.create(hBorder, vBorder),
+ Pair.create(0.0, vBorder)
+ });
+ // This default list of borderCrop comes from the behavior of
+ // GLConsumer.computeTransformMatrix().
+ }
+
/* Describes the difference between two {@link Bitmap} instances. */
public static final class Difference {
public final int greatestPixelDifference;
public final Pair<Integer, Integer> greatestPixelDifferenceCoordinates;
+ public Pair<Double, Double> bestMatchBorderCrop;
private Difference(int greatestPixelDifference) {
- this(greatestPixelDifference, null);
+ this(greatestPixelDifference, null, Pair.create(0.0, 0.0));
}
private Difference(
int greatestPixelDifference,
Pair<Integer, Integer> greatestPixelDifferenceCoordinates) {
+ this(greatestPixelDifference, greatestPixelDifferenceCoordinates,
+ Pair.create(0.0, 0.0));
+ }
+
+ private Difference(
+ int greatestPixelDifference,
+ Pair<Integer, Integer> greatestPixelDifferenceCoordinates,
+ Pair<Double, Double> bestMatchBorderCrop) {
this.greatestPixelDifference = greatestPixelDifference;
this.greatestPixelDifferenceCoordinates = greatestPixelDifferenceCoordinates;
- }
+ this.bestMatchBorderCrop = bestMatchBorderCrop;
+ }
}
}
diff --git a/tests/tests/provider/src/android/provider/cts/Settings_SystemTest.java b/tests/tests/provider/src/android/provider/cts/Settings_SystemTest.java
index b3c545e..badc88e 100644
--- a/tests/tests/provider/src/android/provider/cts/Settings_SystemTest.java
+++ b/tests/tests/provider/src/android/provider/cts/Settings_SystemTest.java
@@ -99,6 +99,12 @@
// first query exist rows
Cursor c = cr.query(System.CONTENT_URI, null, null, null, null);
+
+ // backup fontScale
+ Configuration cfg = new Configuration();
+ System.getConfiguration(cr, cfg);
+ float store = cfg.fontScale;
+
try {
assertNotNull(c);
int origCount = c.getCount();
@@ -131,25 +137,20 @@
assertNotNull(c);
assertEquals(origCount, c.getCount());
- // backup fontScale
- Configuration cfg = new Configuration();
- System.getConfiguration(cr, cfg);
- float store = cfg.fontScale;
-
// update fontScale row
cfg = new Configuration();
- cfg.fontScale = 10.0f;
+ cfg.fontScale = 1.2f;
assertTrue(System.putConfiguration(cr, cfg));
System.getConfiguration(cr, cfg);
- assertEquals(10.0f, cfg.fontScale);
+ assertEquals(1.2f, cfg.fontScale);
+ } finally {
+ // TODO should clean up more better
+ c.close();
// restore the fontScale
cfg.fontScale = store;
assertTrue(System.putConfiguration(cr, cfg));
- } finally {
- // TODO should clean up more better
- c.close();
}
}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/refocus/d1new/RefocusFilterd1new.java b/tests/tests/renderscript/src/android/renderscript/cts/refocus/d1new/RefocusFilterd1new.java
index 3942982..52bc4de 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/refocus/d1new/RefocusFilterd1new.java
+++ b/tests/tests/renderscript/src/android/renderscript/cts/refocus/d1new/RefocusFilterd1new.java
@@ -143,8 +143,9 @@
startnow = System.nanoTime();
//scriptC.forEach_MarkLayerMask(buffers.inAllocation);
- // Pass sharp meta allocation directly into the kernel
- scriptC.forEach_MarkLayerMaskPassInput(buffers.sharpActualDepthAllocation, buffers.sharpDilatedDepthAllocation);
+ // Pass the sharp actual depth allocation directly into the kernel, and modify the dilated depth
+ // allocation which is set as a global.
+ scriptC.forEach_MarkLayerMaskPassInput(buffers.sharpActualDepthAllocation);
endnow = System.nanoTime();
Log.d(myTAG, "MarkLayerMask: "+(endnow - startnow)+ " ns" );
@@ -213,8 +214,9 @@
startnow = System.nanoTime();
//scriptC.forEach_MarkLayerMask(buffers.inAllocation);
- // Pass sharp meta allocation directly into the kernel
- scriptC.forEach_MarkLayerMaskPassInput(buffers.sharpActualDepthAllocation, buffers.sharpDilatedDepthAllocation);
+ // Pass the sharp actual depth allocation directly into the kernel, and modify the dilated depth
+ // allocation which is set as a global.
+ scriptC.forEach_MarkLayerMaskPassInput(buffers.sharpActualDepthAllocation);
endnow = System.nanoTime();
Log.d(myTAG, "MarkLayerMask: "+(endnow - startnow)+ " ns" );
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_d1new_helper.rsh b/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_d1new_helper.rsh
index 39c8d90..77a0c31 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_d1new_helper.rsh
+++ b/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_d1new_helper.rsh
@@ -73,7 +73,7 @@
}
// Converts min_dist to a matte value.
- rsSetElementAt_uchar(g_sharp_matte, (uchar)(dilation_radius + 1 - (int)half_sqrt((float)min_dist)), index_sharp_meta);
+ rsSetElementAt_uchar(g_sharp_matte, (uchar)(dilation_radius + 1 - (int)(half_sqrt((float)min_dist) + 0.5f)), index_sharp_meta);
// If sharp->matte > 0, depth must be within the depth range of this layer.
rsSetElementAt_uchar(g_sharp_dilated_depth, (uchar)depth, index_sharp_meta);
}
@@ -113,7 +113,7 @@
current_meta_index += jump_to_next_row;
}
// Converts min_dist to a matte value.
- rsSetElementAt_uchar(g_sharp_matte, (uchar)(dilation_radius + 1 - (int)half_sqrt((float)min_dist)), index_sharp_meta);
+ rsSetElementAt_uchar(g_sharp_matte, (uchar)(dilation_radius + 1 - (int)(half_sqrt((float)min_dist) + 0.5f)), index_sharp_meta);
// If sharp->matte > 0, depth must be within the depth range of this layer.
return (uchar)depth;
}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_fast_d1new.rs b/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_fast_d1new.rs
index e7342c6..e21db8a 100644
--- a/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_fast_d1new.rs
+++ b/tests/tests/renderscript/src/android/renderscript/cts/refocus/layered_filter_fast_d1new.rs
@@ -181,8 +181,8 @@
// Another version of MarkLayerMask kernel that directly passes input allocation to kernels
// Input: g_sharp_actual_depth
// Output: g_sharp_dilated_depth
-uchar __attribute__((kernel)) MarkLayerMaskPassInput(uchar in_sharp_actual_depth, uint32_t x) {
- if (!OnTheLayer(in_sharp_actual_depth, g_target_layer_i2)) return rsGetElementAt_uchar(g_sharp_dilated_depth, x);
+void __attribute__((kernel)) MarkLayerMaskPassInput(uchar in_sharp_actual_depth, uint32_t x) {
+ if (!OnTheLayer(in_sharp_actual_depth, g_target_layer_i2)) return;
// Marks this pixel as active.
rsSetElementAt_uchar(g_sharp_active, 1, x);
@@ -209,7 +209,8 @@
ValidDepthNotOnTheLayer(sharp_actual_depth, g_target_layer_i2);
if (!is_this_pixel_on_boundary) {
- return in_sharp_actual_depth;
+ rsSetElementAt_uchar(g_sharp_dilated_depth, in_sharp_actual_depth, x);
+ return;
}
// Marks pixels near the boundary of active pixels to compute matte later.
@@ -235,9 +236,8 @@
}
current_meta_index += jump_to_next_row;
}
-
- return in_sharp_actual_depth;
}
+
// Distance transform in processing layers in pass one from the back-most to
// the sharp depth.
void __attribute__((kernel))
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
index 108adf0..6f90433 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -182,4 +182,27 @@
.runWithComparer(mExactComparer);
}
+ @Test
+ public void testSaveLayerRounding() {
+ createTest()
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.saveLayerAlpha(10.5f, 10.5f, 79.5f, 79.5f, 255);
+ canvas.drawRect(20, 20, 70, 70, new Paint());
+ canvas.restore();
+ })
+ .runWithVerifier(new RectVerifier(Color.WHITE, Color.BLACK,
+ new Rect(20, 20, 70, 70)));
+ }
+
+ @Test
+ public void testUnclippedSaveLayerRounding() {
+ createTest()
+ .addCanvasClient((canvas, width, height) -> {
+ canvas.saveLayerAlpha(10.5f, 10.5f, 79.5f, 79.5f, 255, 0);
+ canvas.drawRect(20, 20, 70, 70, new Paint());
+ canvas.restore();
+ })
+ .runWithVerifier(new RectVerifier(Color.WHITE, Color.BLACK,
+ new Rect(20, 20, 70, 70)));
+ }
}
diff --git a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
index 24cff32..3da1b54 100644
--- a/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
+++ b/tools/device-setup/TestDeviceSetup/src/android/tests/getinfo/DeviceInfoConstants.java
@@ -76,7 +76,6 @@
public static final String MEMORY_CLASS = "memory_class";
public static final String LARGE_MEMORY_CLASS = "large_memory_class";
public static final String TOTAL_MEMORY = "total_memory";
- public static final String REFERENCE_BUILD_FINGERPRINT =
- "reference_build_fingerprint";
+ public static final String REFERENCE_BUILD_FINGERPRINT = "reference_build_fingerprint";
public static final String AVAILABLE_PROCESSORS = "available_processors";
}