summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-07-26 10:16:17 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-07-26 10:16:17 +0000
commitdb5499df1e973804caf6de309705670375be9f6e (patch)
treebd693c08a5c7309ae3485731913339ea2222c714
parent0420b3d93a8c4cf178347ed8bef0b41b28731b63 (diff)
parent9e646bf2047dbaed2672db8d281f15e4e850d63c (diff)
downloadcts-android13-mainline-go-art-release.tar.gz
Snap for 8870366 from 9e646bf2047dbaed2672db8d281f15e4e850d63c to mainline-go-art-releaseaml_go_art_330913000android13-mainline-go-art-release
Change-Id: I2c28ddecf298c51db2011dc22b8e1a5e43dad7fe
-rw-r--r--apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py9
-rw-r--r--apps/CameraITS/tests/scene2_a/test_auto_flash.py4
-rw-r--r--apps/CameraITS/tests/scene3/test_edge_enhancement.py11
-rw-r--r--apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py25
-rw-r--r--apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py31
-rw-r--r--apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py6
-rw-r--r--apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py6
-rw-r--r--apps/CameraITS/utils/its_session_utils.py12
-rw-r--r--apps/CtsVerifier/Android.bp3
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml201
-rw-r--r--apps/CtsVerifier/res/layout/ble_rssi_precision.xml60
-rw-r--r--apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml66
-rw-r--r--apps/CtsVerifier/res/layout/clipboard_preview.xml80
-rw-r--r--apps/CtsVerifier/res/layout/nan_precision.xml92
-rw-r--r--apps/CtsVerifier/res/layout/uwb_precision.xml51
-rw-r--r--apps/CtsVerifier/res/layout/uwb_short_range.xml51
-rw-r--r--apps/CtsVerifier/res/values/strings.xml19
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java21
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java11
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java7
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java12
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java22
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java115
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java21
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java115
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java13
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java113
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java140
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java44
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java52
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java271
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java60
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java100
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java95
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java6
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS3
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java4
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java4
-rw-r--r--common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java33
-rw-r--r--common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java12
-rw-r--r--common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java6
-rw-r--r--hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java20
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java8
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java31
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxHostTest.java2
-rw-r--r--hostsidetests/securitybulletin/Android.bp1
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java46
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java54
-rw-r--r--hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml1
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp8
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml18
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml21
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java164
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java98
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml35
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml38
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java151
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java62
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java4
-rw-r--r--tests/app/app/assets/picture_800_by_600.pngbin0 -> 22715 bytes
-rw-r--r--tests/app/src/android/app/cts/NotificationTemplateTest.kt7
-rw-r--r--tests/camera/Android.bp1
-rw-r--r--tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java6
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java384
-rw-r--r--tests/camera/src/android/hardware/camera2/cts/RecordingTest.java13
-rw-r--r--tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java29
-rw-r--r--tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java17
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java3
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java6
-rw-r--r--tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java6
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java12
-rw-r--r--tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java6
-rw-r--r--tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java2
-rw-r--r--tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java9
-rw-r--r--tests/media/src/android/mediav2/cts/CodecInfoTest.java6
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java550
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java45
-rw-r--r--tests/mediapc/common/src/android/mediapc/cts/common/Utils.java28
-rwxr-xr-xtests/tests/assist/common/src/android/assist/common/Utils.java1
-rw-r--r--tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java11
-rw-r--r--tests/tests/assist/src/android/assist/cts/AssistTestBase.java4
-rw-r--r--tests/tests/bluetooth/AndroidTest.xml2
-rw-r--r--tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java17
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java7
-rw-r--r--tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java4
-rw-r--r--tests/tests/media/common/src/android/media/cts/CodecState.java4
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java6
-rw-r--r--tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java255
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java1
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java542
-rw-r--r--tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java6
-rw-r--r--tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java1
-rw-r--r--tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt2
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt3
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt19
-rw-r--r--tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt22
-rw-r--r--tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt8
-rw-r--r--tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java3
-rw-r--r--tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java132
-rw-r--r--tests/tests/systemui/Android.bp1
-rw-r--r--tests/tests/systemui/AndroidManifest.xml1
-rw-r--r--tests/tests/systemui/src/android/systemui/cts/LightBarTests.java36
-rw-r--r--tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java130
-rw-r--r--tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java50
-rw-r--r--tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java2
-rw-r--r--tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java4
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java76
117 files changed, 2610 insertions, 2785 deletions
diff --git a/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py b/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
index 7d8b9f2c11e..e407fd65899 100644
--- a/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
+++ b/apps/CameraITS/tests/scene1_1/test_ev_compensation_basic.py
@@ -71,7 +71,6 @@ class EvCompensationBasicTest(its_base_test.ItsBaseTest):
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
log_path = self.log_path
- debug = self.debug_mode
test_name_w_path = os.path.join(log_path, NAME)
# check SKIP conditions
@@ -113,11 +112,6 @@ class EvCompensationBasicTest(its_base_test.ItsBaseTest):
caps = cam.do_capture([req]*THRESH_CONVERGE_FOR_EV, fmt)
luma_locked = []
for i, cap in enumerate(caps):
- if debug:
- img = image_processing_utils.convert_capture_to_rgb_image(
- cap, props)
- image_processing_utils.write_image(
- img, f'{test_name_w_path}_ev{ev}_frame{i}.jpg')
if cap['metadata']['android.control.aeState'] == LOCKED:
ev_meta = cap['metadata']['android.control.aeExposureCompensation']
logging.debug('cap EV compensation: %d', ev_meta)
@@ -132,7 +126,8 @@ class EvCompensationBasicTest(its_base_test.ItsBaseTest):
rel_tol=luma_locked_rtol):
raise AssertionError(f'AE locked lumas: {luma_locked}, '
f'RTOL: {luma_locked_rtol}')
- logging.debug('lumas in AE locked captures: %s', str(lumas))
+ logging.debug('lumas per frame ev %d: %s', ev, str(luma_locked))
+ logging.debug('mean lumas in AE locked captures: %s', str(lumas))
if caps[THRESH_CONVERGE_FOR_EV-1]['metadata'][
'android.control.aeState'] != LOCKED:
raise AssertionError(f'No AE lock by {THRESH_CONVERGE_FOR_EV} frame.')
diff --git a/apps/CameraITS/tests/scene2_a/test_auto_flash.py b/apps/CameraITS/tests/scene2_a/test_auto_flash.py
index b20da2dbc54..c00cd5c358c 100644
--- a/apps/CameraITS/tests/scene2_a/test_auto_flash.py
+++ b/apps/CameraITS/tests/scene2_a/test_auto_flash.py
@@ -107,10 +107,10 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
test_name = os.path.join(self.log_path, _TEST_NAME)
# check SKIP conditions
- first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
camera_properties_utils.skip_unless(
camera_properties_utils.flash(props) and
- first_api_level >= its_session_utils.ANDROID13_API_LEVEL)
+ vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL)
# establish connection with lighting controller
arduino_serial_port = lighting_control_utils.lighting_control(
diff --git a/apps/CameraITS/tests/scene3/test_edge_enhancement.py b/apps/CameraITS/tests/scene3/test_edge_enhancement.py
index c6a3bcbc878..c1b63c7a503 100644
--- a/apps/CameraITS/tests/scene3/test_edge_enhancement.py
+++ b/apps/CameraITS/tests/scene3/test_edge_enhancement.py
@@ -67,17 +67,17 @@ def do_capture_and_determine_sharpness(
for n in range(NUM_SAMPLES):
cap = cam.do_capture(req, out_surface, repeat_request=req)
y, _, _ = image_processing_utils.convert_capture_to_planes(cap)
- chart.img = image_processing_utils.normalize_img(
- image_processing_utils.get_image_patch(
- y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm))
+ chart.img = image_processing_utils.get_image_patch(
+ y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm)
if n == 0:
image_processing_utils.write_image(
chart.img, '%s_edge=%d.jpg' % (
os.path.join(log_path, NAME), edge_mode))
edge_mode_res = cap['metadata']['android.edge.mode']
sharpness_list.append(
- image_processing_utils.compute_image_sharpness(chart.img))
-
+ image_processing_utils.compute_image_sharpness(chart.img)*255)
+ logging.debug('edge mode: %d, sharpness values: %s',
+ edge_mode_res, sharpness_list)
return {'edge_mode': edge_mode_res, 'sharpness': np.mean(sharpness_list)}
@@ -89,7 +89,6 @@ class EdgeEnhancementTest(its_base_test.ItsBaseTest):
"""
def test_edge_enhancement(self):
- logging.debug('Starting %s', NAME)
with its_session_utils.ItsSession(
device_id=self.dut.serial,
camera_id=self.camera_id,
diff --git a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
index c5e9b1974c3..d67ebe4366b 100644
--- a/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
+++ b/apps/CameraITS/tests/scene3/test_reprocess_edge_enhancement.py
@@ -107,16 +107,15 @@ def do_capture_and_determine_sharpness(
caps = cam.do_capture([req]*NUM_SAMPLES, [out_surface], reprocess_format)
for n in range(NUM_SAMPLES):
y, _, _ = image_processing_utils.convert_capture_to_planes(caps[n])
- chart.img = image_processing_utils.normalize_img(
- image_processing_utils.get_image_patch(
- y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm))
+ chart.img = image_processing_utils.get_image_patch(
+ y, chart.xnorm, chart.ynorm, chart.wnorm, chart.hnorm)
if n == 0:
image_processing_utils.write_image(
chart.img, '%s_reprocess_fmt_%s_edge=%d.jpg' % (
os.path.join(log_path, NAME), reprocess_format, edge_mode))
edge_mode_res = caps[n]['metadata']['android.edge.mode']
sharpness_list.append(
- image_processing_utils.compute_image_sharpness(chart.img))
+ image_processing_utils.compute_image_sharpness(chart.img)*255)
logging.debug('Sharpness list for edge mode %d: %s',
edge_mode, str(sharpness_list))
return {'edge_mode': edge_mode_res, 'sharpness': np.mean(sharpness_list)}
@@ -134,7 +133,6 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
"""
def test_reprocess_edge_enhancement(self):
- logging.debug('Starting %s', NAME)
logging.debug('Edge modes: %s', str(EDGE_MODES))
with its_session_utils.ItsSession(
device_id=self.dut.serial,
@@ -179,9 +177,10 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
# Initialize plot
pylab.figure('reprocess_result')
- pylab.title(NAME)
- pylab.xlabel('Edge Enhance Mode')
- pylab.ylabel('Sharpness')
+ pylab.suptitle(NAME)
+ pylab.title(str(EDGE_MODES))
+ pylab.xlabel('Edge Enhancement Mode')
+ pylab.ylabel('Image Sharpness')
pylab.xticks(EDGE_MODES_VALUES)
# Get the sharpness for each edge mode for regular requests
@@ -244,6 +243,7 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
logging.debug('Check reprocess format: %s', reprocess_format)
check_edge_modes(sharpnesses_reprocess[reprocess_format])
+ # Check reprocessing doesn't make everyting worse
hq_div_off_reprocess = (
sharpnesses_reprocess[reprocess_format][EDGE_MODES['HQ']] /
sharpnesses_reprocess[reprocess_format][EDGE_MODES['OFF']])
@@ -251,11 +251,10 @@ class ReprocessEdgeEnhancementTest(its_base_test.ItsBaseTest):
sharpness_regular[EDGE_MODES['HQ']] /
sharpness_regular[EDGE_MODES['OFF']])
logging.debug('Verify reprocess HQ ~= reg HQ relative to OFF')
- if not math.isclose(hq_div_off_reprocess, hq_div_off_regular,
- rel_tol=SHARPNESS_RTOL):
- raise AssertionError(f'HQ/OFF_reprocess: {hq_div_off_reprocess:.4f}, '
- f'HQ/OFF_reg: {hq_div_off_regular:.4f}, '
- f'RTOL: {SHARPNESS_RTOL}')
+ if hq_div_off_reprocess < hq_div_off_regular*(1-SHARPNESS_RTOL):
+ raise AssertionError(
+ f'HQ/OFF_{reprocess_format}: {hq_div_off_reprocess:.4f}, '
+ f'HQ/OFF_reg: {hq_div_off_regular:.4f}, RTOL: {SHARPNESS_RTOL}')
if __name__ == '__main__':
diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
index 1f5b7c0bad9..2781f18805e 100644
--- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
+++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
@@ -35,9 +35,9 @@ _MAX_STABILIZED_RADIUS_RATIO = 1.2 # radius of circle in stabilized preview
_ROUNDESS_DELTA_THRESHOLD = 0.05
_MAX_CENTER_THRESHOLD_PERCENT = 0.075
-_MAX_DIMENSION_SIZE = (1920, 1440) # max mandatory preview stream resolution
+_MAX_AREA = 1920 * 1440 # max mandatory preview stream resolution
_MIN_CENTER_THRESHOLD_PERCENT = 0.02
-_MIN_DIMENSION_SIZE = (176, 144) # assume QCIF to be min preview size
+_MIN_AREA = 176 * 144 # assume QCIF to be min preview size
def _collect_data(cam, video_size, stabilize):
@@ -93,23 +93,19 @@ def _calculate_center_offset_threshold(image_size):
threshold value ratio between which the circle centers can differ
"""
- max_diagonal = _point_distance(0, 0,
- _MAX_DIMENSION_SIZE[0], _MAX_DIMENSION_SIZE[1])
- min_diagonal = _point_distance(0, 0,
- _MIN_DIMENSION_SIZE[0], _MIN_DIMENSION_SIZE[1])
+ img_area = image_size[0] * image_size[1]
- img_diagonal = _point_distance(0, 0, image_size[0], image_size[1])
+ normalized_area = ((img_area - _MIN_AREA) /
+ (_MAX_AREA - _MIN_AREA))
- normalized_diagonal = ((img_diagonal - min_diagonal) /
- (max_diagonal - min_diagonal))
-
- if normalized_diagonal > 1 or normalized_diagonal < 0:
- raise AssertionError(f'normalized diagonal > 1 or < 0!'
- f' img_diag: {img_diagonal}, '
- f' normalized_diagonal: {normalized_diagonal}')
+ if normalized_area > 1 or normalized_area < 0:
+ raise AssertionError(f'normalized area > 1 or < 0! '
+ f'image_size[0]: {image_size[0]}, '
+ f'image_size[1]: {image_size[1]}, '
+ f'normalized_area: {normalized_area}')
# Threshold should be larger for images with smaller resolution
- normalized_threshold_percent = ((1 - normalized_diagonal) *
+ normalized_threshold_percent = ((1 - normalized_area) *
(_MAX_CENTER_THRESHOLD_PERCENT -
_MIN_CENTER_THRESHOLD_PERCENT))
@@ -144,7 +140,7 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
# Load scene.
its_session_utils.load_scene(cam, props, self.scene,
- self.tablet, chart_distance=0)
+ self.tablet, self.chart_distance)
# Check skip condition
first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
@@ -253,7 +249,8 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest):
f'{_ROUNDESS_DELTA_THRESHOLD}, '
f'actual ratio difference: {roundness_diff}. ')
- # Distance between centers
+ # Distance between centers, x_offset and y_offset are relative to the
+ # radius of the circle, so they're normalized. Not pixel values.
unstab_center = (ustab_circle['x_offset'], ustab_circle['y_offset'])
logging.debug('unstabilized center: %s', unstab_center)
stab_center = (stab_circle['x_offset'], stab_circle['y_offset'])
diff --git a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
index 6eaca195c22..bb713672e00 100644
--- a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
@@ -137,13 +137,13 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest):
logging.debug('physical available focal lengths: %s', str(fls_physical))
# Check SKIP conditions.
- first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
camera_properties_utils.skip_unless(
- first_api_level >= its_session_utils.ANDROID13_API_LEVEL)
+ vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL)
# Load scene.
its_session_utils.load_scene(cam, props, self.scene,
- self.tablet, chart_distance=0)
+ self.tablet, self.chart_distance)
# Determine camera capabilities.
supported_video_qualities = cam.get_supported_video_qualities(
diff --git a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
index 0be38b56d11..195d5670eba 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py
@@ -129,7 +129,7 @@ class VideoStabilizationTest(its_base_test.ItsBaseTest):
in gyroscope movement. Test is a PASS if rotation is reduced in video.
"""
- def test_video_stability(self):
+ def test_video_stabilization(self):
rot_rig = {}
log_path = self.log_path
@@ -139,12 +139,12 @@ class VideoStabilizationTest(its_base_test.ItsBaseTest):
hidden_physical_id=self.hidden_physical_id) as cam:
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
- first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
supported_stabilization_modes = props[
'android.control.availableVideoStabilizationModes']
camera_properties_utils.skip_unless(
- first_api_level >= its_session_utils.ANDROID13_API_LEVEL and
+ vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL and
_VIDEO_STABILIZATION_MODE in supported_stabilization_modes)
# Raise error if not FRONT or REAR facing camera
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index e91565e250f..c2065ba6ac4 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -1612,6 +1612,18 @@ def get_first_api_level(device_id):
return first_api_level
+def get_vendor_api_level(device_id):
+ """Return the int value for the vendor API level of the device."""
+ cmd = 'adb -s %s shell getprop ro.vendor.api_level' % device_id
+ try:
+ vendor_api_level = int(subprocess.check_output(cmd.split()).rstrip())
+ logging.debug('First vendor API level: %d', vendor_api_level)
+ except (subprocess.CalledProcessError, ValueError):
+ logging.error('No vendor_api_level. Setting to build version.')
+ vendor_api_level = get_build_sdk_version(device_id)
+ return vendor_api_level
+
+
class ItsSessionUtilsTests(unittest.TestCase):
"""Run a suite of unit tests on this module."""
diff --git a/apps/CtsVerifier/Android.bp b/apps/CtsVerifier/Android.bp
index b4485d19e99..024e0387c6f 100644
--- a/apps/CtsVerifier/Android.bp
+++ b/apps/CtsVerifier/Android.bp
@@ -91,6 +91,7 @@ android_library {
"CtsForceStopHelper-constants",
"ctsmediautil",
"DpmWrapper",
+ "MediaPerformanceClassCommon",
],
libs: ["telephony-common"] + ["android.test.runner.stubs"] + ["android.test.base.stubs"] + ["android.test.mock.stubs"] + ["android.car-test-stubs"] + ["voip-common"] + ["truth-prebuilt"],
@@ -114,7 +115,7 @@ android_test {
compile_multilib: "both",
- manifest: "AndroidManifest-verifierConfig.xml",
+ additional_manifests: ["AndroidManifest-verifierConfig.xml"],
jni_libs: [
"libctsverifier_jni",
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 5a257de64f1..e179e697749 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -248,6 +248,7 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
+ <meta-data android:name="CddTest" android:value="3.8.17/C-1-1,C-2-1" />
<meta-data android:name="test_category" android:value="@string/test_category_features" />
<meta-data android:name="test_excluded_features"
android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" />
@@ -2052,6 +2053,9 @@
<meta-data android:name="test_required_features" android:value="android.hardware.wifi" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="CddTest" android:value="7.4.5.2" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.ConnectivityManager#registerNetworkCallback|android.net.ConnectivityManager#unregisterNetworkCallback|android.net.ConnectivityManager#getLinkProperties" />
</activity>
<activity android:name=".net.MultiNetworkConnectivityTestActivity"
@@ -2068,6 +2072,8 @@
android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
<meta-data android:name="display_mode"
android:value="multi_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.net.ConnectivityManager#getNetworkCapabilities|android.net.ConnectivityManager#getAllNetworks|android.net.ConnectivityManager#requestNetwork|android.net.ConnectivityManager#unregisterNetworkCallback|android.net.ConnectivityManager#getActiveNetwork|android.net.ConnectivityManager#getNetworkInfo|android.net.ConnectivityManager#reportNetworkConnectivity" />
</activity>
<activity android:name=".nfc.NfcTestActivity"
@@ -2861,6 +2867,32 @@
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
android:value="single_display_mode" />
+ <meta-data android:name="ApiTest"
+ android:value="android.hardware.Camera#getParameters|
+ android.hardware.Camera#lock|
+ android.hardware.Camera#setDisplayOrientation|
+ android.hardware.Camera#setPreviewCallback|
+ android.hardware.Camera#setParameters|
+ android.hardware.Camera#setPreviewTexture|
+ android.hardware.Camera#startPreview|
+ android.hardware.Camera#stopPreview|
+ android.hardware.Camera#unlock|
+ android.media.MediaRecorder#prepare|
+ android.media.MediaRecorder#release|
+ android.media.MediaRecorder#reset|
+ android.media.MediaRecorder#setAudioEncoder|
+ android.media.MediaRecorder#setAudioSource|
+ android.media.MediaRecorder#setCamera|
+ android.media.MediaRecorder#setOnErrorListener|
+ android.media.MediaRecorder#setOutputFormat|
+ android.media.MediaRecorder#setOutputFile|
+ android.media.MediaRecorder#setProfile|
+ android.media.MediaRecorder#setVideoEncoder|
+ android.media.MediaRecorder#setVideoEncodingBitRate|
+ android.media.MediaRecorder#setVideoSize|
+ android.media.MediaRecorder#setVideoSource|
+ android.media.MediaRecorder#start|
+ android.media.MediaRecorder#stop" />
</activity>
<activity android:name=".camera.its.ItsTestActivity"
@@ -3901,174 +3933,6 @@
android:value="single_display_mode" />
</activity>
- <!-- CTS Verifier Presence Test Top Screen -->
- <activity
- android:name=".presence.PresenceTestActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/presence_test" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/test_category_networking" />
- <meta-data android:name="display_mode"
- android:value="single_display_mode" />
- </activity>
-
- <!--
- CTS Verifier Uwb Precision Test Screen
- test category : uwb
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.UwbPrecisionActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/uwb_precision" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/uwb" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data android:name="CddTest"
- android:value="7.4.9/C-1-1" />
- </activity>
-
- <!--
- CTS Verifier Uwb Short Range Test Screen
- test category : uwb
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.UwbShortRangeActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/uwb_short_range" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/uwb" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data
- android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data
- android:name="CddTest"
- android:value="7.4.9/C-1-2" />
- </activity>
-
- <!--
- CTS Verifier BLE RSSI Precision Test Screen
- test category : BLE
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.BleRssiPrecisionActivity"
- android:exported="true"
- android:label="@string/ble_rssi_precision_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/ble" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data
- android:name="test_required_features"
- android:value="android.hardware.bluetooth_le" />
- <meta-data
- android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data
- android:name="CddText"
- android:value="7.4.3/C-7-1" />
- </activity>
-
- <!--
- CTS Verifier BLE Rx/Tx Calibration Test Screen
- test category : BLE
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.BleRxTxCalibrationActivity"
- android:exported="true"
- android:label="@string/ble_rx_tx_calibration_name">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/ble" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data
- android:name="test_required_features"
- android:value="android.hardware.bluetooth_le" />
- <meta-data
- android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data
- android:name="CddText"
- android:value="7.4.3/C-7-2" />
- </activity>
-
- <!-- CTS Verifier Nan Precision and Bias Test Screen
- test category : wifi_nan
- test parent : PresenceTestActivity
- -->
- <activity
- android:name=".presence.NanPrecisionTestActivity"
- android:configChanges="keyboardHidden|orientation|screenSize"
- android:exported="true"
- android:label="@string/nan_precision" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="android.cts.intent.category.MANUAL_TEST" />
- </intent-filter>
-
- <meta-data
- android:name="test_category"
- android:value="@string/wifi_nan" />
- <meta-data
- android:name="test_parent"
- android:value="com.android.cts.verifier.presence.PresenceTestActivity" />
- <meta-data android:name="display_mode"
- android:value="single_display_mode" />
- <meta-data android:name="CddTest"
- android:value="7.4.2.5/H-1-1|7.4.2.5/H-1-2" />
- </activity>
-
<activity-alias
android:name=".CtsVerifierActivity"
android:label="@string/app_name"
@@ -6159,6 +6023,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_logcat" />
+ <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" />
</activity>
<activity android:name=".displaycutout.DisplayCutoutTestActivity"
diff --git a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml b/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
deleted file mode 100644
index 5f01e1fc442..00000000000
--- a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding"
- tools:ignore="Autofill">
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:text="@string/ble_rssi_precision_test_instructions"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical" />
-
- <EditText
- android:id="@+id/report_rssi_range"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_ble_rssi_range"
- android:inputType="number" />
-
- <EditText
- android:id="@+id/report_reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"
- android:inputType="text" />
-
- <include
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons" />
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml b/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml
deleted file mode 100644
index 3ca955b7e30..00000000000
--- a/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2022 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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding"
- tools:ignore="Autofill">
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
-
- <LinearLayout
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
-
- <TextView
- android:text="@string/ble_rx_tx_calibration_test_instructions"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical" />
-
- <EditText
- android:id="@+id/report_channels_rssi_range"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_channels_ble_rssi_range"
- android:inputType="number" />
-
- <EditText
- android:id="@+id/report_cores_rssi_range"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_cores_ble_rssi_range"
- android:inputType="number" />
-
- <EditText
- android:id="@+id/report_reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"
- android:inputType="text" />
-
- <include
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons" />
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/clipboard_preview.xml b/apps/CtsVerifier/res/layout/clipboard_preview.xml
index 85f38c8eef7..efec118cb4d 100644
--- a/apps/CtsVerifier/res/layout/clipboard_preview.xml
+++ b/apps/CtsVerifier/res/layout/clipboard_preview.xml
@@ -31,86 +31,6 @@
android:layout_marginBottom="100dp"
android:layout_marginTop="30dp"
android:text="@string/clipboard_preview_test_copy_button"/>
-
- <TableLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b1"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="1"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b2"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="2"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b3"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="3"/>
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- </TableRow>
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b4"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="4"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b5"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="5"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b6"
- android:layout_width="50dp"
- android:layout_height="50dp"
- android:text="6"/>
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- </TableRow>
- <TableRow
- android:layout_width="match_parent"
- android:layout_height="50dp">
- <View android:layout_weight="3"
- android:layout_height="match_parent"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b7"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:text="7"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b8"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:text="8"/>
- <Button android:layout_weight="1"
- android:id="@+id/clipboard_preview_test_b9"
- android:layout_width="50dp"
- android:layout_height="match_parent"
- android:text="9"/>
- <View android:layout_weight="3"
- android:layout_height="50dp"/>
- </TableRow>
- </TableLayout>
- <Button
- android:id="@+id/clipboard_preview_test_b0"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="0"/>
<include
android:id="@+id/clipboard_preview_test_pass_fail"
android:layout_width="match_parent"
diff --git a/apps/CtsVerifier/res/layout/nan_precision.xml b/apps/CtsVerifier/res/layout/nan_precision.xml
deleted file mode 100644
index c81a9c4f120..00000000000
--- a/apps/CtsVerifier/res/layout/nan_precision.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 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.
- -->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding">
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:text="@string/nan_precision_instruction"
- android:id="@+id/nan_precision_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <EditText android:id="@+id/nan_bandwidth"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="number"
- android:hint="@string/report_nan_bandwidth_mhz"/>
- <EditText android:id="@+id/distance_range_10cm_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_10cm_gt_68p"/>
- <EditText android:id="@+id/distance_range_1m_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_1m_gt_68p"/>
- <EditText android:id="@+id/distance_range_3m_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_3m_gt_68p"/>
- <EditText android:id="@+id/distance_range_5m_gt_68p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_5m_gt_68p"/>
- <EditText android:id="@+id/distance_range_10cm_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_10cm_gt_90p"/>
- <EditText android:id="@+id/distance_range_1m_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_1m_gt_90p"/>
- <EditText android:id="@+id/distance_range_3m_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_3m_gt_90p"/>
- <EditText android:id="@+id/distance_range_5m_gt_90p"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_5m_gt_90p"/>
- <EditText android:id="@+id/reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons"/>
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/uwb_precision.xml b/apps/CtsVerifier/res/layout/uwb_precision.xml
deleted file mode 100644
index 14e996d6f5f..00000000000
--- a/apps/CtsVerifier/res/layout/uwb_precision.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding">
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:text="@string/uwb_precision_instruction"
- android:id="@+id/uwb_precision_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <EditText android:id="@+id/distance_range_cm"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:inputType="numberDecimal"
- android:hint="@string/report_distance_range_cm"/>
- <EditText android:id="@+id/reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons"/>
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/uwb_short_range.xml b/apps/CtsVerifier/res/layout/uwb_short_range.xml
deleted file mode 100644
index 9afc6e5a6b4..00000000000
--- a/apps/CtsVerifier/res/layout/uwb_short_range.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2022 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.
--->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- style="@style/RootLayoutPadding">
- <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:text="@string/uwb_short_range_instruction"
- android:id="@+id/uwb_short_range_instruction"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:scrollbars="vertical"/>
- <LinearLayout android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <EditText android:id="@+id/distance_median_meters"
- android:layout_width="wrap_content"
- android:inputType="numberDecimal"
- android:layout_height="wrap_content"
- android:hint="@string/report_distance_median_meters"/>
- <EditText android:id="@+id/reference_device"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="@string/report_reference_device"/>
- </LinearLayout>
-
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/pass_fail_buttons"/>
- </LinearLayout>
- </ScrollView>
-</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 4862965ba9d..0f32b34e78e 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -32,6 +32,16 @@
<string name="finish_button_text">Finish</string>
<string name="fail_and_next_button_text">Fail and Next</string>
+ <!-- Strings for CtsReportLog warning -->
+ <string name="reportlog_warning_title">CTS-Verifier Report Log</string>
+ <string name="reportlog_warning_body">Can\'t create folder for CTS-Verifier Report Logs.
+ \n\nPlease enable Report Log creation by exiting CTS Verifier and running the following commands:
+ \n\n<code>adb shell appops set com.android.cts.verifier android:read_device_identifiers allow</code>
+ \n\n<code>adb shell appops set com.android.cts.verifier MANAGE_EXTERNAL_STORAGE 0</code>
+ \n\nTest instructions are found in the \"Using CTS Verifier\" document found at
+ <a href="https://source.android.com/compatibility/cts/verifier">https://source.android.com/compatibility/cts/verifier</a>
+ </string>
+
<!-- Strings for TestListActivity -->
<string name="test_category_audio">Audio</string>
<string name="test_category_camera">Camera</string>
@@ -301,9 +311,11 @@
</string>
<string name="clipboard_preview_test_instructions">
Press the \'Copy\' button to copy the secret code to the clipboard.
- \n\nUse the clipboard preview UI, or the clipboard editor component to view the secret code.
- \n\nEnter the secret code using the buttons below.
+ \n\n If nothing happens, press Fail.
+ \n\n If you see the word "FAIL" appear on screen, press Fail.
+ \n\n If you see a confirmation that content has been copied to the clipboard, press Pass.
</string>
+ <string name="clipboard_preview_test_secret">FAIL</string>
<string name="clipboard_preview_test_copy_button">Copy</string>
@@ -778,7 +790,7 @@
<!-- BLE Advertising Set test strings -->
<string name="ble_advertising_set_test_name">Bluetooth LE Advertising Set Test</string>
<string name="ble_advertising_set_test_info">Bluetooth LE Advertising Set tests AdvertisingSet and AdvertisingSetCallback APIs.</string>
- <string name="ble_advertising_set_test_instruction">Press the \"Set Up\" button first, then start the test by pressing the \"Start Test\" button. UI thread may freeze for a few seconds while enabling/disabling bluetooth adapter.</string>
+ <string name="ble_advertising_set_test_instruction">Press the \"Start Test\" button. UI thread may freeze for a few seconds while enabling/disabling bluetooth adapter.</string>
<string name="ble_advertising_set_start_test">Start Test</string>
<string name="ble_advertising_set_running_test">Running Test...</string>
<string name="ble_advertising_set_finished_test">Finished Test</string>
@@ -5480,6 +5492,7 @@ You should be prompted to select credentials; choose the ones you just installed
<string name="audio_general_test_not_run">Test Not Run</string>
<string name="audio_general_testnotcompleted">Test not completed.</string>
+ <string name="audio_general_reportlogtest">[Can\'t Write ReportLog]</string>
<!-- Audio Loopback Latency Test -->
<string name="audio_loopback_latency_test">Audio Loopback Latency Test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java
index b013bb7180e..a93e3b58c33 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java
@@ -74,6 +74,10 @@ public class CtsVerifierReportLog extends ReportLog {
}
}
+ public boolean isOpen() {
+ return mStore != 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
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
index 0294ff78e7c..7b993eefc58 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java
@@ -32,7 +32,6 @@ import android.database.Cursor;
import android.os.Bundle;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
@@ -146,6 +145,8 @@ public class PassFailButtons {
private final CtsVerifierReportLog mReportLog;
private final TestResultHistoryCollection mHistoryCollection;
+ protected boolean mRequireReportLogToPass;
+
public Activity() {
this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName());
this.mHistoryCollection = new TestResultHistoryCollection();
@@ -159,6 +160,10 @@ public class PassFailButtons {
.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "PassFailButtons");
mWakeLock.acquire();
}
+
+ if (!this.mReportLog.isOpen()) {
+ showReportLogWarningDialog(this);
+ }
}
@Override
@@ -212,6 +217,14 @@ public class PassFailButtons {
}
/**
+ * A mechanism to block tests from passing if no ReportLog data has been collected.
+ * @return true if the ReportLog is open OR if the test does not require that.
+ */
+ public boolean isReportLogOkToPass() {
+ return !mRequireReportLogToPass || mReportLog.isOpen();
+ }
+
+ /**
* @return The name of the file to store the (suite of) ReportLog information.
*/
@Override
@@ -527,6 +540,12 @@ public class PassFailButtons {
activity.showDialog(INFO_DIALOG_ID, args);
}
+ protected static void showReportLogWarningDialog(final android.app.Activity activity) {
+ showInfoDialog(activity,
+ R.string.reportlog_warning_title, R.string.reportlog_warning_body, -1);
+ }
+
+
protected static Dialog createDialog(final android.app.Activity activity, int id, Bundle args) {
switch (id) {
case INFO_DIALOG_ID:
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 528d9149588..83b32def714 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -182,12 +182,15 @@ public class AnalogHeadsetAudioActivity
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass_noheadset));
return true;
} else {
- boolean pass = mPlugIntentReceived &&
- mHeadsetDeviceInfo != null &&
- mPlaybackSuccess &&
- (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
+ boolean pass = isReportLogOkToPass()
+ && mPlugIntentReceived
+ && mHeadsetDeviceInfo != null
+ && mPlaybackSuccess
+ && (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
if (pass) {
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
+ } else if (!isReportLogOkToPass()) {
+ mResultsTxt.setText(getResources().getString(R.string.audio_general_reportlogtest));
}
return pass;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
index 48795efc142..3c1b8a1151e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
@@ -542,8 +542,10 @@ public class AudioAEC extends AudioFrequencyActivity implements View.OnClickList
Log.v(TAG, "Test EndedOk. " + testId + " str:"+str);
showView(mProgress, false);
mResultTest.setText("test completed. " + str);
- if (mTestAECPassed) {
- getPassButton().setEnabled(true);;
+ if (!isReportLogOkToPass()) {
+ mResultTest.setText(getResources().getString(R.string.audio_general_reportlogtest));
+ } else if (mTestAECPassed) {
+ getPassButton().setEnabled(true);
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
index a6bd4add994..79d3e3b2b0b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java
@@ -294,6 +294,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
getPassButton().setEnabled(false);
setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1);
+ mRequireReportLogToPass = true;
+
mClaimsOutput = AudioSystemFlags.claimsOutput(this);
mClaimsInput = AudioSystemFlags.claimsInput(this);
mClaimsProAudio = AudioSystemFlags.claimsProAudio(this);
@@ -683,7 +685,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
mResultsText[mTestRoute].setText(testSpec.getResultString());
LoopbackLatencyRequirements requirements = new LoopbackLatencyRequirements();
- boolean pass = requirements.evaluate(mClaimsProAudio,
+ boolean pass = isReportLogOkToPass()
+ && requirements.evaluate(mClaimsProAudio,
Build.VERSION.MEDIA_PERFORMANCE_CLASS,
mTestSpecs[TESTROUTE_DEVICE].isMeasurementValid()
? mTestSpecs[TESTROUTE_DEVICE].mMeanLatencyMS : 0.0,
@@ -694,8 +697,12 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity {
getPassButton().setEnabled(pass);
- String resultText = requirements.getResultsString();
- mTestStatusText.setText(resultText);
+ StringBuilder sb = new StringBuilder();
+ if (!isReportLogOkToPass()) {
+ sb.append(getResources().getString(R.string.audio_general_reportlogtest) + "\n");
+ }
+ sb.append(requirements.getResultsString());
+ mTestStatusText.setText(sb.toString());
showWait(false);
enableStartButtons(true);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index 215d26fd65b..8ff23588889 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -154,6 +154,8 @@ public class AudioTap2ToneActivity
String yesString = getResources().getString(R.string.audio_general_yes);
String noString = getResources().getString(R.string.audio_general_no);
+ mRequireReportLogToPass = true;
+
boolean claimsProAudio = AudioSystemFlags.claimsProAudio(this);
boolean claimsLowLatencyAudio = AudioSystemFlags.claimsLowLatencyAudio(this);
@@ -311,11 +313,14 @@ public class AudioTap2ToneActivity
}
double averageLatency = mLatencyAve[mActiveTestAPI];
- boolean pass = averageLatency != 0 && averageLatency <= mMaxRequiredLatency;
+ boolean pass = isReportLogOkToPass()
+ && averageLatency != 0 && averageLatency <= mMaxRequiredLatency;
if (pass) {
mSpecView.setText("Average: " + averageLatency + " ms <= "
+ mMaxRequiredLatency + " ms -- PASS");
+ } else if (!isReportLogOkToPass()) {
+ mSpecView.setText(getResources().getString(R.string.audio_general_reportlogtest));
} else {
mSpecView.setText("Average: " + averageLatency + " ms > "
+ mMaxRequiredLatency + " ms -- FAIL");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
index 126d15fdacb..e93d2b319ff 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
@@ -158,11 +158,9 @@ public class ProAudioActivity
boolean usbOK = mClaimsUSBHostMode && mClaimsUSBPeripheralMode;
boolean hdmiOK = !mClaimsHDMI || isHDMIValid();
- boolean hasPassed = !mClaimsProAudio ||
- (mClaimsLowLatencyAudio &&
- mClaimsMIDI &&
- usbOK &&
- hdmiOK);
+ boolean hasPassed = isReportLogOkToPass()
+ && !mClaimsProAudio
+ || (mClaimsLowLatencyAudio && mClaimsMIDI && usbOK && hdmiOK);
getPassButton().setEnabled(hasPassed);
return hasPassed;
@@ -172,7 +170,9 @@ public class ProAudioActivity
boolean hasPassed = calculatePass();
Resources strings = getResources();
- if (hasPassed) {
+ if (!isReportLogOkToPass()) {
+ mTestStatusLbl.setText(getResources().getString(R.string.audio_general_reportlogtest));
+ } else if (hasPassed) {
mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_pass));
} else if (!mClaimsMIDI) {
mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_midinotreported));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java
index bc23048c28e..6270a5a8311 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java
@@ -20,23 +20,17 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
-
import android.os.Bundle;
import android.os.Handler;
-
import android.util.Log;
-
import android.widget.TextView;
import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
-
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R; // needed to access resource in CTSVerifier project namespace.
@@ -173,9 +167,10 @@ public class USBAudioPeripheralNotificationsTest extends PassFailButtons.Activit
// Test Status
//
private boolean calculatePass() {
- return mUsbHeadsetInReceived && mUsbHeadsetOutReceived &&
- mUsbDeviceInReceived && mUsbDeviceOutReceived &&
- mPlugIntentReceived;
+ return isReportLogOkToPass()
+ && mUsbHeadsetInReceived && mUsbHeadsetOutReceived
+ && mUsbDeviceInReceived && mUsbDeviceOutReceived
+ && mPlugIntentReceived;
}
//
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java
index 07a70c69cb4..164992b94a9 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java
@@ -99,11 +99,6 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity {
R.string.ble_advertising_set_test_info, -1);
getPassButton().setEnabled(false);
- mBluetoothManager = getSystemService(BluetoothManager.class);
- mBluetoothAdapter = mBluetoothManager.getAdapter();
- mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
- mCallback = new TestAdvertisingSetCallback();
-
mTestAdapter = new TestAdapter(this, setupTestList());
ListView listView = findViewById(R.id.ble_advertising_set_tests);
listView.setAdapter(mTestAdapter);
@@ -133,9 +128,7 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity {
testEnableAndDisableAdvertising();
testSetAdvertisingData();
testSetAdvertisingParameters();
- if (mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
- testPeriodicAdvertising();
- }
+ testPeriodicAdvertising();
testSetScanResponseData();
stopAdvertisingSet();
} catch (InterruptedException e) {
@@ -167,6 +160,11 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity {
});
mAllTestsPassed = 0;
+
+ mBluetoothManager = getSystemService(BluetoothManager.class);
+ mBluetoothAdapter = mBluetoothManager.getAdapter();
+ mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
+ mCallback = new TestAdvertisingSetCallback();
}
private void startAdvertisingSet() throws InterruptedException {
@@ -323,11 +321,9 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity {
testList.add(R.string.ble_advertising_set_enable_disable);
testList.add(R.string.ble_advertising_set_advertising_data);
testList.add(R.string.ble_advertising_set_advertising_params);
- if (mBluetoothAdapter.isLePeriodicAdvertisingSupported()) {
- testList.add(R.string.ble_advertising_set_periodic_advertising_data);
- testList.add(R.string.ble_advertising_set_periodic_advertising_enabled_disabled);
- testList.add(R.string.ble_advertising_set_periodic_advertising_params);
- }
+ testList.add(R.string.ble_advertising_set_periodic_advertising_data);
+ testList.add(R.string.ble_advertising_set_periodic_advertising_enabled_disabled);
+ testList.add(R.string.ble_advertising_set_periodic_advertising_params);
testList.add(R.string.ble_advertising_set_scan_response_data);
testList.add(R.string.ble_advertising_set_stop);
return testList;
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 861c6f68810..212f988d205 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
@@ -1847,6 +1847,8 @@ public class ItsService extends Service implements SensorEventListener {
// s1440p which is the max supported stream size in a combination, when preview
// stabilization is on.
Size maxPreviewSize = new Size(1920, 1440);
+ // QCIF, we test only sizes >= this.
+ Size minPreviewSize = new Size(176, 144);
Size[] outputSizes = configMap.getOutputSizes(ImageFormat.YUV_420_888);
if (outputSizes == null) {
mSocketRunnableObj.sendResponse("supportedPreviewSizes", "");
@@ -1857,6 +1859,8 @@ public class ItsService extends Service implements SensorEventListener {
.distinct()
.filter(s -> s.getWidth() * s.getHeight()
<= maxPreviewSize.getWidth() * maxPreviewSize.getHeight())
+ .filter(s -> s.getWidth() * s.getHeight()
+ >= minPreviewSize.getWidth() * minPreviewSize.getHeight())
.sorted(Comparator.comparingInt(s -> s.getWidth() * s.getHeight()))
.map(Size::toString)
.collect(Collectors.joining(";"));
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index d83464bd549..692538a81c3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -21,9 +21,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
-import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
-import android.os.Build;
+import android.mediapc.cts.common.PerformanceClassEvaluator;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
@@ -31,6 +30,11 @@ import android.view.WindowManager;
import android.widget.TextView;
import android.widget.Toast;
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
@@ -39,17 +43,11 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
import com.android.cts.verifier.ArrayTestListAdapter;
@@ -59,6 +57,7 @@ import com.android.cts.verifier.TestResult;
import org.json.JSONArray;
import org.json.JSONObject;
+import org.junit.rules.TestName;
/**
* Test for Camera features that require that the camera be aimed at a specific test scene.
@@ -81,12 +80,6 @@ public class ItsTestActivity extends DialogTestListActivity {
Arrays.asList(new String[] {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED}));
private static final int MAX_SUMMARY_LEN = 200;
- private static final int MPC12_CAMERA_LAUNCH_THRESHOLD = 600; // ms
- private static final int MPC12_JPEG_CAPTURE_THRESHOLD = 1000; // ms
-
- private static final String MPC_TESTS_REPORT_LOG_NAME = "MediaPerformanceClassLogs";
- private static final String MPC_TESTS_REPORT_LOG_SECTION = "CameraIts";
-
private static final Pattern MPC12_CAMERA_LAUNCH_PATTERN =
Pattern.compile("camera_launch_time_ms:(\\d+(\\.\\d+)?)");
private static final Pattern MPC12_JPEG_CAPTURE_PATTERN =
@@ -95,8 +88,12 @@ public class ItsTestActivity extends DialogTestListActivity {
private final ResultReceiver mResultsReceiver = new ResultReceiver();
private boolean mReceiverRegistered = false;
+ public final TestName mTestName = new TestName();
+
// Initialized in onCreate
List<String> mToBeTestedCameraIds = null;
+ String mPrimaryRearCameraId = null;
+ String mPrimaryFrontCameraId = null;
// Scenes
private static final ArrayList<String> mSceneIds = new ArrayList<String> () {{
@@ -132,8 +129,15 @@ public class ItsTestActivity extends DialogTestListActivity {
private final HashMap<ResultKey, String> mSummaryMap = new HashMap<>();
// All primary cameras for which MPC level test has run
private Set<ResultKey> mExecutedMpcTests = null;
- // Map primary camera id to MPC level
- private final HashMap<String, Integer> mMpcLevelMap = new HashMap<>();
+ private static final String MPC_LAUNCH_REQ_NUM = "2.2.7.2/7.5/H-1-6";
+ private static final String MPC_JPEG_CAPTURE_REQ_NUM = "2.2.7.2/7.5/H-1-5";
+ // Performance class evaluator used for writing test result
+ PerformanceClassEvaluator mPce = new PerformanceClassEvaluator(mTestName);
+ PerformanceClassEvaluator.CameraLatencyRequirement mJpegLatencyReq =
+ mPce.addR7_5__H_1_5();
+ PerformanceClassEvaluator.CameraLatencyRequirement mLaunchLatencyReq =
+ mPce.addR7_5__H_1_6();
+
final class ResultKey {
public final String cameraId;
@@ -266,10 +270,7 @@ public class ItsTestActivity extends DialogTestListActivity {
JSONArray metrics = sceneResult.getJSONArray("mpc_metrics");
for (int i = 0; i < metrics.length(); i++) {
String mpcResult = metrics.getString(i);
- if (!matchMpcResult(cameraId, mpcResult, MPC12_CAMERA_LAUNCH_PATTERN,
- "2.2.7.2/7.5/H-1-6", MPC12_CAMERA_LAUNCH_THRESHOLD) &&
- !matchMpcResult(cameraId, mpcResult, MPC12_JPEG_CAPTURE_PATTERN,
- "2.2.7.2/7.5/H-1-5", MPC12_JPEG_CAPTURE_THRESHOLD)) {
+ if (!matchMpcResult(cameraId, mpcResult)) {
Log.e(TAG, "Error parsing MPC result string:" + mpcResult);
return;
}
@@ -294,17 +295,6 @@ public class ItsTestActivity extends DialogTestListActivity {
summary.toString(), 1.0, ResultType.NEUTRAL, ResultUnit.NONE);
}
- // Save MPC info once both front primary and rear primary data are collected.
- if (mExecutedMpcTests.size() == 4) {
- ItsTestActivity.this.getReportLog().addValue(
- "Version", "0.0.1", ResultType.NEUTRAL, ResultUnit.NONE);
- for (Map.Entry<String, Integer> entry : mMpcLevelMap.entrySet()) {
- ItsTestActivity.this.getReportLog().addValue(entry.getKey(),
- entry.getValue(), ResultType.NEUTRAL, ResultUnit.NONE);
- }
- ItsTestActivity.this.getReportLog().submit();
- }
-
// Display current progress
StringBuilder progress = new StringBuilder();
for (ResultKey k : mAllScenes) {
@@ -367,28 +357,44 @@ public class ItsTestActivity extends DialogTestListActivity {
}
}
- private boolean matchMpcResult(String cameraId, String mpcResult, Pattern pattern,
- String reqNum, float threshold) {
- Matcher matcher = pattern.matcher(mpcResult);
- boolean match = matcher.matches();
- final int LATEST_MPC_LEVEL = Build.VERSION_CODES.TIRAMISU;
+ private boolean matchMpcResult(String cameraId, String mpcResult) {
+ Matcher launchMatcher = MPC12_CAMERA_LAUNCH_PATTERN.matcher(mpcResult);
+ boolean launchMatches = launchMatcher.matches();
- if (match) {
- // Store test result
- ItsTestActivity.this.getReportLog().addValue("Cam" + cameraId,
- mpcResult, ResultType.NEUTRAL, ResultUnit.NONE);
+ Matcher jpegMatcher = MPC12_JPEG_CAPTURE_PATTERN.matcher(mpcResult);
+ boolean jpegMatches = jpegMatcher.matches();
- float latency = Float.parseFloat(matcher.group(1));
- int mpcLevel = latency < threshold ? LATEST_MPC_LEVEL : 0;
- mExecutedMpcTests.add(new ResultKey(cameraId, reqNum));
+ if (!launchMatches && !jpegMatches) {
+ return false;
+ }
+ if (!cameraId.equals(mPrimaryRearCameraId) &&
+ !cameraId.equals(mPrimaryFrontCameraId)) {
+ return false;
+ }
- if (mMpcLevelMap.containsKey(reqNum)) {
- mpcLevel = Math.min(mpcLevel, mMpcLevelMap.get(reqNum));
+ if (launchMatches) {
+ float latency = Float.parseFloat(launchMatcher.group(1));
+ if (cameraId.equals(mPrimaryRearCameraId)) {
+ mLaunchLatencyReq.setRearCameraLatency(latency);
+ } else {
+ mLaunchLatencyReq.setFrontCameraLatency(latency);
+ }
+ mExecutedMpcTests.add(new ResultKey(cameraId, MPC_LAUNCH_REQ_NUM));
+ } else {
+ float latency = Float.parseFloat(jpegMatcher.group(1));
+ if (cameraId.equals(mPrimaryRearCameraId)) {
+ mJpegLatencyReq.setRearCameraLatency(latency);
+ } else {
+ mJpegLatencyReq.setFrontCameraLatency(latency);
}
- mMpcLevelMap.put(reqNum, mpcLevel);
+ mExecutedMpcTests.add(new ResultKey(cameraId, MPC_JPEG_CAPTURE_REQ_NUM));
}
- return match;
+ // Save MPC info once both front primary and rear primary data are collected.
+ if (mExecutedMpcTests.size() == 4) {
+ mPce.submit();
+ }
+ return true;
}
}
@@ -397,8 +403,11 @@ public class ItsTestActivity extends DialogTestListActivity {
// Hide the test if all camera devices are legacy
CameraManager manager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);
try {
- ItsUtils.ItsCameraIdList cameraIdList = ItsUtils.getItsCompatibleCameraIds(manager);
+ ItsUtils.ItsCameraIdList cameraIdList =
+ ItsUtils.getItsCompatibleCameraIds(manager);
mToBeTestedCameraIds = cameraIdList.mCameraIdCombos;
+ mPrimaryRearCameraId = cameraIdList.mPrimaryRearCameraId;
+ mPrimaryFrontCameraId = cameraIdList.mPrimaryFrontCameraId;
} catch (ItsException e) {
Toast.makeText(ItsTestActivity.this,
"Received error from camera service while checking device capabilities: "
@@ -499,14 +508,4 @@ public class ItsTestActivity extends DialogTestListActivity {
setInfoResources(R.string.camera_its_test, R.string.camera_its_test_info, -1);
setPassFailButtonClickListeners();
}
-
- @Override
- public String getReportFileName() {
- return MPC_TESTS_REPORT_LOG_NAME;
- }
-
- @Override
- public String getReportSectionName() {
- return MPC_TESTS_REPORT_LOG_SECTION;
- }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
index c648e8e18d9..734b4a2a780 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java
@@ -16,28 +16,24 @@
package com.android.cts.verifier.camera.its;
-import android.content.Context;
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
-import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.Image.Plane;
-import android.net.Uri;
-import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.Size;
import com.android.ex.camera2.blocking.BlockingCameraManager;
-import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
import com.android.ex.camera2.blocking.BlockingStateCallback;
import org.json.JSONArray;
@@ -322,6 +318,9 @@ public class ItsUtils {
// Camera Id combos (ids from CameraIdList, and hidden physical camera Ids
// in the form of [logical camera id]:[hidden physical camera id]
public List<String> mCameraIdCombos;
+ // Primary rear and front camera Ids (as defined in MPC)
+ public String mPrimaryRearCameraId;
+ public String mPrimaryFrontCameraId;
}
public static ItsCameraIdList getItsCompatibleCameraIds(CameraManager manager)
@@ -345,6 +344,18 @@ public class ItsUtils {
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE;
final int LOGICAL_MULTI_CAMERA =
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA;
+
+ final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing != null) {
+ if (facing == CameraMetadata.LENS_FACING_BACK
+ && outList.mPrimaryRearCameraId == null) {
+ outList.mPrimaryRearCameraId = id;
+ } else if (facing == CameraMetadata.LENS_FACING_FRONT
+ && outList.mPrimaryFrontCameraId == null) {
+ outList.mPrimaryFrontCameraId = id;
+ }
+ }
+
for (int capability : actualCapabilities) {
if (capability == BACKWARD_COMPAT) {
haveBC = true;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java
index 3587e6f9b8c..63b8904fa03 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java
@@ -18,49 +18,22 @@ package com.android.cts.verifier.clipboard;
import android.content.ClipData;
+import android.content.ClipDescription;
import android.content.ClipboardManager;
-import android.graphics.Color;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.view.View;
import android.widget.Button;
import com.android.cts.verifier.PassFailButtons;
import com.android.cts.verifier.R;
-import java.util.concurrent.ThreadLocalRandom;
-
/**
- * A CTS Verifier test case for validating the user-visible clipboard preview.
- *
- * This test assumes bluetooth is turned on and the device is already paired with a second device.
- * Note: the second device need not be an Android device; it could be a laptop or desktop.
+ * A CTS Verifier test case for validating the user-visible clipboard confirmation.
*/
public class ClipboardPreviewTestActivity extends PassFailButtons.Activity {
- /**
- * The content of the test file being transferred.
- */
- private static final String TEST_STRING = "Sample Test String";
- /**
- * The name of the test file being transferred.
- */
- private final int[] mSecretCode = new int[4];
- private final int[] mSecretGuess = new int[4];
- private final int[] mButtons = {
- R.id.clipboard_preview_test_b0,
- R.id.clipboard_preview_test_b1,
- R.id.clipboard_preview_test_b2,
- R.id.clipboard_preview_test_b3,
- R.id.clipboard_preview_test_b4,
- R.id.clipboard_preview_test_b5,
- R.id.clipboard_preview_test_b6,
- R.id.clipboard_preview_test_b7,
- R.id.clipboard_preview_test_b8,
- R.id.clipboard_preview_test_b9
- };
- private int mGuessIndex = 0;
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -74,87 +47,29 @@ public class ClipboardPreviewTestActivity extends PassFailButtons.Activity {
copyButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- generateAndCopySecret();
+ setClipboardData();
}
});
- disableKeypad();
+ disablePassFail();
}
- private void generateAndCopySecret() {
- String s = "";
- resetState();
- for (int i = 0; i < mSecretCode.length; ++i) {
- mSecretCode[i] = ThreadLocalRandom.current().nextInt(0, 10);
- s += mSecretCode[i];
- }
+ private void setClipboardData() {
ClipboardManager cm = this.getSystemService(ClipboardManager.class);
- cm.setPrimaryClip(ClipData.newPlainText("Secret", s));
- enableKeypad();
- }
- private void enableKeypad() {
- for (int i = 0; i < mButtons.length; ++i) {
- Button numButton = findViewById(mButtons[i]);
- numButton.setBackgroundColor(Color.GREEN);
- int finalI = i;
- numButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- buttonClicked(finalI);
- }
- });
- }
+ ClipData cd = ClipData.newPlainText("",
+ getString(R.string.clipboard_preview_test_secret));
+ PersistableBundle pb = new PersistableBundle(1);
+ pb.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true);
+ cd.getDescription().setExtras(pb);
+ cm.setPrimaryClip(cd);
+ enablePassFail();
}
- private void disableKeypad() {
- for (int i = 0; i < mButtons.length; ++i) {
- Button numButton = findViewById(mButtons[i]);
- numButton.setOnClickListener(null);
- numButton.setBackgroundColor(Color.LTGRAY);
- }
- }
-
- private void resetState() {
- for (int i = 0; i < mSecretGuess.length; ++i) {
- mSecretGuess[i] = -1;
- }
- mGuessIndex = 0;
- View v = findViewById(R.id.clipboard_preview_test_pass_fail);
+ private void disablePassFail() {
findViewById(R.id.clipboard_preview_test_pass_fail).setVisibility(View.INVISIBLE);
- findViewById(R.id.fail_button).setVisibility(View.VISIBLE);
- findViewById(R.id.pass_button).setVisibility(View.VISIBLE);
- }
-
- private void buttonClicked(int i) {
- if (mGuessIndex < mSecretGuess.length) {
- mSecretGuess[mGuessIndex] = i;
- ++mGuessIndex;
- }
- checkSolution();
- }
-
- private void checkSolution() {
- boolean testPassed = true;
- if (mGuessIndex == mSecretGuess.length) {
- for (int i = 0; i < mSecretGuess.length && i < mSecretCode.length; ++i) {
- if (mSecretGuess[i] != mSecretCode[i]) {
- testPassed = false;
- }
- }
- markPassed(testPassed);
- disableKeypad();
- }
}
- private void markPassed(boolean passed) {
+ private void enablePassFail() {
findViewById(R.id.clipboard_preview_test_pass_fail).setVisibility(View.VISIBLE);
- if (passed) {
- findViewById(R.id.fail_button).setVisibility(View.INVISIBLE);
- } else {
- findViewById(R.id.pass_button).setVisibility(View.INVISIBLE);
- }
-
}
-
-
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java
index b8b96023cb7..97ec07acf78 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java
@@ -118,7 +118,7 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity
/** Stop observing to associated device and then disassociate. */
private void disassociate(AssociationInfo association) {
- String deviceAddress = association.getDeviceMacAddressAsString();
+ String deviceAddress = association.getDeviceMacAddress().toString();
mCompanionDeviceManager.stopObservingDevicePresence(deviceAddress);
mCompanionDeviceManager.disassociate(association.getId());
Log.d(LOG_TAG, "Disassociated with device: " + deviceAddress);
@@ -142,11 +142,14 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity
AssociationInfo association =
data.getParcelableExtra(CompanionDeviceManager.EXTRA_ASSOCIATION,
AssociationInfo.class);
- String deviceAddress = association.getDeviceMacAddressAsString();
// This test is for bluetooth devices, which should all have a MAC address.
- if (deviceAddress == null) fail("The device was present but its address was null.");
+ if (association == null || association.getDeviceMacAddress() == null) {
+ fail("The device was present but its address was null.");
+ return;
+ }
+ String deviceAddress = association.getDeviceMacAddress().toString();
mCompanionDeviceManager.startObservingDevicePresence(deviceAddress);
mCurrentAssociation = getAssociation(association.getId());
Log.d(LOG_TAG, "Associated with device: " + deviceAddress);
@@ -285,7 +288,9 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity
@Override
boolean verify() {
// Check that it is associated and being observed.
- return mCurrentAssociation != null && mCurrentAssociation.isNotifyOnDeviceNearby();
+ // Bypass inaccessible AssociationInfo#isNotifyOnDeviceNearby() with toString()
+ return mCurrentAssociation != null
+ && mCurrentAssociation.toString().contains("mNotifyOnDeviceNearby=true");
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java
index 37760d54440..11829c3d4b7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java
@@ -45,7 +45,7 @@ public class DevicePresenceListener extends CompanionDeviceService {
@Override
public void onDeviceAppeared(AssociationInfo association) {
NEARBY_DEVICES.add(association.getId());
- String message = "Device appeared: " + association.getDeviceMacAddressAsString();
+ String message = "Device appeared: " + association.getDeviceMacAddress();
Log.d(LOG_TAG, message);
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
@@ -53,7 +53,7 @@ public class DevicePresenceListener extends CompanionDeviceService {
@Override
public void onDeviceDisappeared(AssociationInfo association) {
NEARBY_DEVICES.remove(association.getId());
- String message = "Device disappeared: " + association.getDeviceMacAddressAsString();
+ String message = "Device disappeared: " + association.getDeviceMacAddress();
Log.d(LOG_TAG, message);
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
deleted file mode 100644
index 1548910093a..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2011 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.verifier.presence;
-
-import android.app.AlertDialog;
-import android.bluetooth.BluetoothAdapter;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/** Tests the precision of the device's RSSI measurement wtfdelet */
-public class BleRssiPrecisionActivity extends PassFailButtons.Activity {
- private static final String TAG = BleRssiPrecisionActivity.class.getName();
-
- // Report log schema
- private static final String KEY_RSSI_RANGE_DBM = "rssi_range_dbm";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
-
- // Thresholds
- private static final int MAX_RSSI_RANGE_DBM = 18;
-
- private EditText reportRssiRangeEditText;
- private EditText reportReferenceDeviceEditText;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_rssi_precision);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- reportRssiRangeEditText = findViewById(R.id.report_rssi_range);
- reportReferenceDeviceEditText = findViewById(R.id.report_reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_BLUETOOTH_LE);
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- if (!adapter.isEnabled()) {
- new AlertDialog.Builder(this)
- .setTitle(R.string.ble_bluetooth_disable_title)
- .setMessage(R.string.ble_bluetooth_disable_message)
- .setOnCancelListener(dialog -> finish())
- .create().show();
- }
-
- reportRssiRangeEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- reportReferenceDeviceEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(checkDistanceRangeInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkDistanceRangeInput() {
- String rssiRangeInput = reportRssiRangeEditText.getText().toString();
-
- if (!rssiRangeInput.isEmpty()) {
- int rssiRange = Integer.parseInt(rssiRangeInput);
- // RSSI range must be inputted and within acceptable range before test can be passed
- return rssiRange <= MAX_RSSI_RANGE_DBM;
- }
- return false;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device must be inputted before test can be passed
- return !reportReferenceDeviceEditText.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String rssiRange = reportRssiRangeEditText.getText().toString();
- String referenceDevice = reportReferenceDeviceEditText.getText().toString();
-
- if (!rssiRange.isEmpty()) {
- Log.i(TAG, "BLE RSSI Range (dBm): " + rssiRange);
- getReportLog().addValue(KEY_RSSI_RANGE_DBM, Integer.parseInt(rssiRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "BLE Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java
deleted file mode 100644
index 2de7edffe7c..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2011 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.verifier.presence;
-
-import android.app.AlertDialog;
-import android.bluetooth.BluetoothAdapter;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/**
- * Tests that the device's Rx/Tx calibration results in a median range (cm) within the specified
- * bounds
- */
-public class BleRxTxCalibrationActivity extends PassFailButtons.Activity {
- private static final String TAG = BleRxTxCalibrationActivity.class.getName();
-
- // Report log schema
- private static final String KEY_CHANNEL_RSSI_RANGE = "channel_rssi_range";
- private static final String KEY_CORE_RSSI_RANGE = "core_rssi_range";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
-
- // Thresholds
- private static final int MAX_RSSI_RANGE = 6;
-
- private EditText reportChannelsRssiRangeEditText;
- private EditText reportCoresRssiRangeEditText;
- private EditText reportReferenceDeviceEditText;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.ble_rx_tx_calibration);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- reportChannelsRssiRangeEditText = findViewById(R.id.report_channels_rssi_range);
- reportCoresRssiRangeEditText = findViewById(R.id.report_cores_rssi_range);
- reportReferenceDeviceEditText = findViewById(R.id.report_reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_BLUETOOTH_LE);
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- if (!adapter.isEnabled()) {
- new AlertDialog.Builder(this)
- .setTitle(R.string.ble_bluetooth_disable_title)
- .setMessage(R.string.ble_bluetooth_disable_message)
- .setOnCancelListener(dialog -> finish())
- .create().show();
- }
-
- reportChannelsRssiRangeEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- reportCoresRssiRangeEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- reportReferenceDeviceEditText.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(
- checkChannelRssiInput() && checkCoreRssiInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkChannelRssiInput() {
- String channelsRssiRangeInput = reportChannelsRssiRangeEditText.getText().toString();
- if (!channelsRssiRangeInput.isEmpty()) {
- int channelsRssiRange = Integer.parseInt(channelsRssiRangeInput);
- // RSSI range must be inputted and within acceptable range before test can be passed
- return channelsRssiRange <= MAX_RSSI_RANGE;
- }
- return false;
- }
-
- private boolean checkCoreRssiInput() {
- String coresRssiRangeInput = reportCoresRssiRangeEditText.getText().toString();
- if (!coresRssiRangeInput.isEmpty()) {
- int coresRssiRange = Integer.parseInt(coresRssiRangeInput);
- // RSSI range must be inputted and within acceptable range before test can be passed
- return coresRssiRange <= MAX_RSSI_RANGE;
- }
- // This field is optional, so return true even if the user has not inputted anything
- return true;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device must be inputted before test can be passed
- return !reportReferenceDeviceEditText.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String channelRssiRange = reportChannelsRssiRangeEditText.getText().toString();
- String coreRssiRange = reportCoresRssiRangeEditText.getText().toString();
- String referenceDevice = reportReferenceDeviceEditText.getText().toString();
-
- if (!channelRssiRange.isEmpty()) {
- Log.i(TAG, "BLE RSSI Range Across Channels (dBm): " + channelRssiRange);
- getReportLog().addValue(KEY_CHANNEL_RSSI_RANGE, Integer.parseInt(channelRssiRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!coreRssiRange.isEmpty()) {
- Log.i(TAG, "BLE RSSI Range Across Cores (dBm): " + coreRssiRange);
- getReportLog().addValue(KEY_CORE_RSSI_RANGE, Integer.parseInt(coreRssiRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "BLE Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java
deleted file mode 100644
index 256fe3a078d..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2022 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.verifier.presence;
-import android.app.Activity;
-import android.content.Context;
-import android.util.Log;
-import android.view.View;
-import android.widget.Toast;
-
-/**
- * Checks if a device supports a hardware feature needed for a test, and passes the test
- * automatically otherwise.
- */
-public class DeviceFeatureChecker {
-
- /** Checks if a feature is supported.
- *
- * @param feature must be a string defined in PackageManager
- */
- public static void checkFeatureSupported(Context context, View passButton, String feature) {
- if (!context.getPackageManager().hasSystemFeature(feature)) {
- String message = String.format("Device does not support %s, automatically passing test",
- feature);
- Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
- Log.e(context.getClass().getName(), message);
- passButton.performClick();
- Activity activity = (Activity) (context);
- activity.finish();
- }
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java
deleted file mode 100644
index 2de68a5a78e..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2022 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.verifier.presence;
-
-import android.text.Editable;
-import android.text.TextWatcher;
-
-/**
- * Handles editable text inputted into test activities.
- */
-public class InputTextHandler {
-
- /** Callback that is executed when text is changed. Takes modified text as input. */
- public interface OnTextChanged {
- void run(Editable s);
- }
-
- /**
- * Generic text changed handler that will execute the provided callback when text is modified.
- *
- * @param callback called when text is changed, and passed the modified text
- */
- public static TextWatcher getOnTextChangedHandler(OnTextChanged callback) {
- return new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
-
- @Override
- public void afterTextChanged(Editable s) {
- callback.run(s);
- }
- };
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java
deleted file mode 100644
index 458d1920eca..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2022 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.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import com.google.common.collect.ImmutableMap;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Activity for testing that NAN measurements are within the acceptable ranges
- */
-public class NanPrecisionTestActivity extends PassFailButtons.Activity {
- private static final String TAG = NanPrecisionTestActivity.class.getName();
-
- // Report log schema
- private static final String KEY_BANDWIDTH = "nan_bandwidth";
- private static final String KEY_MEASUREMENT_RANGE_10CM_AT_68P = "measurement_range_10cm_68p";
- private static final String KEY_MEASUREMENT_RANGE_1M_AT_68P = "measurement_range_1m_68p";
- private static final String KEY_MEASUREMENT_RANGE_3M_AT_68p = "measurement_range_3m_68p";
- private static final String KEY_MEASUREMENT_RANGE_5M_AT_68p = "measurement_range_5m_68p";
- private static final String KEY_MEASUREMENT_RANGE_10CM_AT_90P = "measurement_range_10cm_90p";
- private static final String KEY_MEASUREMENT_RANGE_1M_AT_90P = "measurement_range_1m_90p";
- private static final String KEY_MEASUREMENT_RANGE_3M_AT_90p = "measurement_range_3m_90p";
- private static final String KEY_MEASUREMENT_RANGE_5M_AT_90p = "measurement_range_5m_90p";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
-
- // Thresholds
- private static final int MAX_DISTANCE_RANGE_METERS_160MHZ = 2;
- private static final int MAX_DISTANCE_RANGE_METERS_80MHZ = 4;
- private static final int MAX_DISTANCE_RANGE_METERS_40MHZ = 8;
- private static final int MAX_DISTANCE_RANGE_METERS_20MHZ = 16;
-
- // Maps NAN bandwidths to acceptable range thresholds
- private static final ImmutableMap<Integer, Integer> BANDWIDTH_TO_THRESHOLD_MAP =
- ImmutableMap.of(160, MAX_DISTANCE_RANGE_METERS_160MHZ, 80,
- MAX_DISTANCE_RANGE_METERS_80MHZ, 40, MAX_DISTANCE_RANGE_METERS_40MHZ, 20,
- MAX_DISTANCE_RANGE_METERS_20MHZ);
-
- private EditText mBandwidthMhz;
- private EditText mMeasurementRange10cmGt68p;
- private EditText mMeasurementRange1mGt68p;
- private EditText mMeasurementRange3mGt68p;
- private EditText mMeasurementRange5mGt68p;
- private EditText mMeasurementRange10cmGt90p;
- private EditText mMeasurementRange1mGt90p;
- private EditText mMeasurementRange3mGt90p;
- private EditText mMeasurementRange5mGt90p;
- private EditText mReferenceDeviceInput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.nan_precision);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- mBandwidthMhz = (EditText) findViewById(R.id.nan_bandwidth);
- mMeasurementRange10cmGt68p = (EditText) findViewById(R.id.distance_range_10cm_gt_68p);
- mMeasurementRange1mGt68p = (EditText) findViewById(R.id.distance_range_1m_gt_68p);
- mMeasurementRange3mGt68p = (EditText) findViewById(R.id.distance_range_3m_gt_68p);
- mMeasurementRange5mGt68p = (EditText) findViewById(R.id.distance_range_5m_gt_68p);
- mMeasurementRange10cmGt90p = (EditText) findViewById(R.id.distance_range_10cm_gt_90p);
- mMeasurementRange1mGt90p = (EditText) findViewById(R.id.distance_range_1m_gt_90p);
- mMeasurementRange3mGt90p = (EditText) findViewById(R.id.distance_range_3m_gt_90p);
- mMeasurementRange5mGt90p = (EditText) findViewById(R.id.distance_range_5m_gt_90p);
- mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_WIFI_AWARE);
-
- mBandwidthMhz.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange10cmGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange1mGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange3mGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange5mGt68p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange10cmGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange1mGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange3mGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mMeasurementRange5mGt90p.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mReferenceDeviceInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(checkMeasurementRange68thPercentileInput()
- && checkMeasurementRange90thPercentileInput()
- && checkReferenceDeviceInput());
- }
-
- private boolean checkMeasurementRange68thPercentileInput() {
- return checkRequiredMeasurementRangeInput(mMeasurementRange10cmGt68p,
- mMeasurementRange1mGt68p, mMeasurementRange3mGt68p, mMeasurementRange5mGt68p);
- }
-
- private boolean checkMeasurementRange90thPercentileInput() {
- String measurementRangeInput10cmGt90p = mMeasurementRange10cmGt90p.getText().toString();
- String measurementRangeInput1mGt90p = mMeasurementRange1mGt90p.getText().toString();
- String measurementRangeInput3mGt90p = mMeasurementRange3mGt90p.getText().toString();
- String measurementRangeInput5mGt90p = mMeasurementRange5mGt90p.getText().toString();
- List<String> optionalMeasurementRangeList = Arrays.asList(measurementRangeInput10cmGt90p,
- measurementRangeInput1mGt90p,
- measurementRangeInput3mGt90p, measurementRangeInput5mGt90p);
-
- boolean inputted = false;
- for (String input : optionalMeasurementRangeList) {
- if (!input.isEmpty()) {
- inputted = true;
- break;
- }
- }
- // If one of the ranges is inputted for one of the distances, then it becomes required
- // that the ranges are inputted for all the distances and for tests to pass, must be
- // acceptable values
- return !inputted || checkRequiredMeasurementRangeInput(mMeasurementRange10cmGt90p,
- mMeasurementRange1mGt90p, mMeasurementRange3mGt90p, mMeasurementRange5mGt90p);
- }
-
- private boolean checkRequiredMeasurementRangeInput(EditText rangeInput10cm,
- EditText rangeInput1m, EditText rangeInput3m, EditText rangeInput5m) {
- String bandwidthInputMhz = mBandwidthMhz.getText().toString();
- String measurementRangeInput10cmGt = rangeInput10cm.getText().toString();
- String measurementRangeInput1mGt = rangeInput1m.getText().toString();
- String measurementRangeInput3mGt = rangeInput3m.getText().toString();
- String measurementRangeInput5mGt = rangeInput5m.getText().toString();
- List<String> requiredMeasurementRangeList = Arrays.asList(measurementRangeInput10cmGt,
- measurementRangeInput1mGt,
- measurementRangeInput3mGt, measurementRangeInput5mGt);
-
- for (String input : requiredMeasurementRangeList) {
- if (bandwidthInputMhz.isEmpty() || input.isEmpty()) {
- // Distance range must be inputted for all fields so fail early otherwise
- return false;
- }
- if (!BANDWIDTH_TO_THRESHOLD_MAP.containsKey(Integer.parseInt(bandwidthInputMhz))) {
- // bandwidth must be one of the expected thresholds
- return false;
- }
- double distanceRange = Double.parseDouble(input);
- int bandwidth = Integer.parseInt(bandwidthInputMhz);
- if (distanceRange > BANDWIDTH_TO_THRESHOLD_MAP.get(bandwidth)) {
- // All inputs must be in acceptable range so fail early otherwise
- return false;
- }
- }
- return true;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device used must be inputted before test can be passed.
- return !mReferenceDeviceInput.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String nanBandwidthMhz = mBandwidthMhz.getText().toString();
- String measurementRange10cmGt68p = mMeasurementRange10cmGt68p.getText().toString();
- String measurementRange1mGt68p = mMeasurementRange1mGt68p.getText().toString();
- String measurementRange3mGt68p = mMeasurementRange3mGt68p.getText().toString();
- String measurementRange5mGt68p = mMeasurementRange5mGt68p.getText().toString();
- String measurementRange10cmGt90p = mMeasurementRange10cmGt90p.getText().toString();
- String measurementRange1mGt90p = mMeasurementRange1mGt90p.getText().toString();
- String measurementRange3mGt90p = mMeasurementRange3mGt90p.getText().toString();
- String measurementRange5mGt90p = mMeasurementRange5mGt90p.getText().toString();
- String referenceDevice = mReferenceDeviceInput.getText().toString();
-
- if (!nanBandwidthMhz.isEmpty()) {
- Log.i(TAG, "NAN Bandwidth at which data was collected: " + nanBandwidthMhz);
- getReportLog().addValue(KEY_BANDWIDTH,
- Integer.parseInt(nanBandwidthMhz),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange10cmGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 10cm: " + measurementRange10cmGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_10CM_AT_68P,
- Double.parseDouble(measurementRange10cmGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange1mGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 1m: " + measurementRange1mGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_1M_AT_68P,
- Double.parseDouble(measurementRange1mGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange3mGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 3m: " + measurementRange3mGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_3M_AT_68p,
- Double.parseDouble(measurementRange3mGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange5mGt68p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 5m: " + measurementRange5mGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_5M_AT_68p,
- Double.parseDouble(measurementRange5mGt68p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange10cmGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 10cm: " + measurementRange10cmGt68p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_10CM_AT_90P,
- Double.parseDouble(measurementRange10cmGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange1mGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 1m: " + measurementRange1mGt90p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_1M_AT_90P,
- Double.parseDouble(measurementRange1mGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange3mGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 3m: " + measurementRange3mGt90p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_3M_AT_90p,
- Double.parseDouble(measurementRange3mGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!measurementRange5mGt90p.isEmpty()) {
- Log.i(TAG, "NAN Measurement Range at 5m: " + measurementRange5mGt90p);
- getReportLog().addValue(KEY_MEASUREMENT_RANGE_5M_AT_90p,
- Double.parseDouble(measurementRange5mGt90p),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
-
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "NAN Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS
deleted file mode 100644
index e8744995b6c..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Bug component: 1106357
-asalo@google.com
-jbabs@google.com
-christinatao@google.com \ No newline at end of file
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java
deleted file mode 100644
index 67766931591..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2022 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.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.SystemProperties;
-
-import com.android.cts.verifier.ManifestTestListAdapter;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class PresenceTestActivity extends PassFailButtons.TestListActivity {
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.pass_fail_list);
- setPassFailButtonClickListeners();
-
- List<String> disabledTest = new ArrayList<String>();
- boolean isTv = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- if (isTv) {
- setInfoResources(R.string.presence_test, R.string.presence_test_tv_info, -1);
- int firstSdk = SystemProperties.getInt("ro.product.first_api_level", 0);
- if (firstSdk < Build.VERSION_CODES.TIRAMISU) {
- disabledTest.add("com.android.cts.verifier.presence.UwbPrecisionActivity");
- disabledTest.add("com.android.cts.verifier.presence.UwbShortRangeActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleRssiPrecisionActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleRxTxCalibrationActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleRxOffsetActivity");
- disabledTest.add("com.android.cts.verifier.presence.BleTxOffsetActivity");
- disabledTest.add("com.android.cts.verifier.presence.NanPrecisionTestActivity");
- }
- } else {
- setInfoResources(R.string.presence_test, R.string.presence_test_info, -1);
- }
-
- setTestListAdapter(new ManifestTestListAdapter(this, PresenceTestActivity.class.getName(),
- disabledTest.toArray(new String[disabledTest.size()])));
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java
deleted file mode 100644
index 5d1ff8628dd..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2022 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.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/**
- * Activity for testing that UWB distance and angle of arrival measurements are within the right
- * range.
- */
-public class UwbPrecisionActivity extends PassFailButtons.Activity {
- private static final String TAG = UwbPrecisionActivity.class.getName();
- // Report log schema
- private static final String KEY_DISTANCE_RANGE_CM = "distance_range_cm";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
- // Thresholds
- private static final int MAX_DISTANCE_RANGE_CM = 30;
-
- private EditText mDistanceRangeInput;
- private EditText mReferenceDeviceInput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.uwb_precision);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- mDistanceRangeInput = (EditText) findViewById(R.id.distance_range_cm);
- mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_UWB);
-
- mDistanceRangeInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mReferenceDeviceInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(
- checkDistanceRangeInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkDistanceRangeInput() {
- String distanceRangeInput = mDistanceRangeInput.getText().toString();
- if (!distanceRangeInput.isEmpty()) {
- double distanceRange = Double.parseDouble(distanceRangeInput);
- // Distance range must be inputted and within acceptable range before test can be
- // passed.
- return distanceRange <= MAX_DISTANCE_RANGE_CM;
- }
- return false;
- }
-
- private boolean checkReferenceDeviceInput() {
- // Reference device must be inputted before test can be passed.
- return !mReferenceDeviceInput.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String distanceRange = mDistanceRangeInput.getText().toString();
- String referenceDevice = mReferenceDeviceInput.getText().toString();
- if (!distanceRange.isEmpty()) {
- Log.i(TAG, "UWB Distance Range: " + distanceRange);
- getReportLog().addValue(KEY_DISTANCE_RANGE_CM, Double.parseDouble(distanceRange),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- if (!referenceDevice.isEmpty()) {
- Log.i(TAG, "UWB Reference Device: " + referenceDevice);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java
deleted file mode 100644
index 7f14800b68c..00000000000
--- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2022 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.verifier.presence;
-
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.text.Editable;
-import android.util.Log;
-import android.widget.EditText;
-
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
-/**
- * Activity for testing that UWB distance measurements are within the acceptable median.
- */
-public class UwbShortRangeActivity extends PassFailButtons.Activity {
- private static final String TAG = UwbShortRangeActivity.class.getName();
- // Report log schema
- private static final String KEY_DISTANCE_MEDIAN_CM = "distance_median_cm";
- private static final String KEY_REFERENCE_DEVICE = "reference_device";
- // Median Thresholds
- private static final double MIN_MEDIAN = 0.75;
- private static final double MAX_MEDIAN = 1.25;
- private EditText mMedianInput;
- private EditText mReferenceDeviceInput;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.uwb_short_range);
- setPassFailButtonClickListeners();
- getPassButton().setEnabled(false);
-
- mMedianInput = (EditText) findViewById(R.id.distance_median_meters);
- mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device);
-
- DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(),
- PackageManager.FEATURE_UWB);
-
- mMedianInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- mReferenceDeviceInput.addTextChangedListener(
- InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs()));
- }
-
- private void checkTestInputs() {
- getPassButton().setEnabled(checkMedianInput() && checkReferenceDeviceInput());
- }
-
- private boolean checkMedianInput() {
- String medianInput = mMedianInput.getText().toString();
- if (!medianInput.isEmpty()) {
- double median = Double.parseDouble(medianInput);
- return median >= MIN_MEDIAN && median <= MAX_MEDIAN;
- }
- return false;
- }
-
- private boolean checkReferenceDeviceInput() {
- return !mReferenceDeviceInput.getText().toString().isEmpty();
- }
-
- @Override
- public void recordTestResults() {
- String medianInput = mMedianInput.getText().toString();
- String referenceDeviceInput = mReferenceDeviceInput.getText().toString();
- if (!medianInput.isEmpty()) {
- Log.i(TAG, "UWB Distance Median: " + medianInput);
- getReportLog().addValue(KEY_DISTANCE_MEDIAN_CM, Double.parseDouble(medianInput),
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- if (!referenceDeviceInput.isEmpty()) {
- Log.i(TAG, "UWB Reference Device: " + referenceDeviceInput);
- getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDeviceInput, ResultType.NEUTRAL,
- ResultUnit.NONE);
- }
- getReportLog().submit();
- }
-}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
index 055f26f7af6..c0df10c996e 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/MediaCodecFlushActivity.java
@@ -66,9 +66,9 @@ public class MediaCodecFlushActivity extends PassFailButtons.Activity {
private void playVideo() {
try {
- mPlayer.start();
mPlayer.prepare();
- mPlayer.startThread();
+ mPlayer.startCodec();
+ mPlayer.play();
mHandler.postDelayed(this::pauseStep, 5000);
} catch(Exception e) {
Log.d(TAG, "Could not play video", e);
@@ -95,7 +95,7 @@ public class MediaCodecFlushActivity extends PassFailButtons.Activity {
private void resumeStep() {
try {
- mPlayer.start();
+ mPlayer.resume();
mHandler.postDelayed(this::enablePassButton, 3000);
} catch(Exception e) {
Log.d(TAG, "Could not resume video", e);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS
new file mode 100644
index 00000000000..4744ab89f6b
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/OWNERS
@@ -0,0 +1,3 @@
+# Buganizer component id: 687598
+blindahl@google.com
+narcisaam@google.com
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java
index 0163c62fcf1..c4461431b59 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tunnelmode/VolumeLevelChangesActivity.java
@@ -209,10 +209,10 @@ public class VolumeLevelChangesActivity extends PassFailButtons.Activity {
private void playVideo() {
try {
- mPlayer.start();
mPlayer.prepare();
+ mPlayer.startCodec();
mPlayer.setLoopEnabled(true);
- mPlayer.startThread();
+ mPlayer.play();
} catch (Exception e) {
Log.d(TAG, "Could not play the video.", e);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
index 641ab20846f..94ef5363424 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/tv/display/ModeSwitchingTestActivity.java
@@ -221,10 +221,10 @@ public class ModeSwitchingTestActivity extends PassFailButtons.Activity {
private void playVideo() {
try {
- mPlayer.start();
mPlayer.prepare();
+ mPlayer.startCodec();
mPlayer.setLoopEnabled(true);
- mPlayer.startThread();
+ mPlayer.play();
} catch (Exception e) {
Log.d(TAG, "Could not play video", e);
}
diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java
new file mode 100644
index 00000000000..03d21f43d2a
--- /dev/null
+++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/annotations/RequireMultiUserSupport.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.bedstead.harrier.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to indicate that a test requires multi-user support.
+ *
+ * <p>This can be enforced by using {@code DeviceState}.
+ */
+@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+//@Experimental
+public @interface RequireMultiUserSupport {
+}
diff --git a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
index b28b815a9de..7bd649dc895 100644
--- a/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
+++ b/common/device-side/bedstead/harrier/src/main/java/com/android/bedstead/harrier/DeviceState.java
@@ -67,6 +67,7 @@ import com.android.bedstead.harrier.annotations.RequireDoesNotHaveFeature;
import com.android.bedstead.harrier.annotations.RequireFeature;
import com.android.bedstead.harrier.annotations.RequireHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireLowRamDevice;
+import com.android.bedstead.harrier.annotations.RequireMultiUserSupport;
import com.android.bedstead.harrier.annotations.RequireNotHeadlessSystemUserMode;
import com.android.bedstead.harrier.annotations.RequireNotLowRamDevice;
import com.android.bedstead.harrier.annotations.RequirePackageInstalled;
@@ -786,6 +787,12 @@ public final class DeviceState extends HarrierRule {
ensureGlobalSettingSet(
ensureGlobalSettingSetAnnotation.key(),
ensureGlobalSettingSetAnnotation.value());
+ continue;
+ }
+
+ if (annotation instanceof RequireMultiUserSupport) {
+ requireMultiUserSupport();
+ continue;
}
}
@@ -2528,4 +2535,9 @@ public final class DeviceState extends HarrierRule {
}
TestApis.settings().global().putString(key, value);
}
+
+ private void requireMultiUserSupport() {
+ assumeTrue("This test is only supported on multi user devices",
+ TestApis.users().supportsMultipleUsers());
+ }
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java
index 200feb70b24..0ce2d7fe2e8 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/users/Users.java
@@ -40,6 +40,7 @@ import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;
import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.annotations.Experimental;
import com.android.bedstead.nene.exceptions.AdbException;
import com.android.bedstead.nene.exceptions.AdbParseException;
import com.android.bedstead.nene.exceptions.NeneException;
@@ -485,6 +486,11 @@ public final class Users {
return mCachedUsers.get(id);
}
+ @Experimental
+ public boolean supportsMultipleUsers() {
+ return UserManager.supportsMultipleUsers();
+ }
+
static Stream<UserInfo> users() {
if (Permissions.sIgnorePermissions.get()) {
return sUserManager.getUsers(
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
index 4da5fff7f0b..9c8a81d05f7 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/UserControlDisabledPackagesTest.java
@@ -25,6 +25,8 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
import java.util.ArrayList;
/**
@@ -41,6 +43,7 @@ public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
private static final String SIMPLE_APP_PKG = "com.android.cts.launcherapps.simpleapp";
private static final String SIMPLE_APP_ACTIVITY =
"com.android.cts.launcherapps.simpleapp.SimpleActivityImmediateExit";
+ private static final String ARG_PID_BEFORE_STOP = "pidOfSimpleapp";
public void testSetUserControlDisabledPackages() throws Exception {
ArrayList<String> protectedPackages = new ArrayList<>();
@@ -86,14 +89,15 @@ public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
// Check if package is part of UserControlDisabledPackages before checking if
// package is stopped since it is a necessary condition to prevent stopping of
// package
-
assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho()))
.containsExactly(SIMPLE_APP_PKG);
- assertPackageRunningState(/* running= */ true);
+ assertPackageRunningState(/* running= */ true,
+ InstrumentationRegistry.getArguments().getString(ARG_PID_BEFORE_STOP, "-1"));
}
public void testFgsStopWithUserControlEnabled() throws Exception {
- assertPackageRunningState(/* running= */ false);
+ assertPackageRunningState(/* running= */ false,
+ InstrumentationRegistry.getArguments().getString(ARG_PID_BEFORE_STOP, "-1"));
assertThat(mDevicePolicyManager.getUserControlDisabledPackages(getWho())).isEmpty();
}
@@ -120,9 +124,15 @@ public class UserControlDisabledPackagesTest extends BaseDeviceOwnerTest {
return pid.length() > 0;
}
- private void assertPackageRunningState(boolean shouldBeRunning) throws Exception {
+ private void assertPackageRunningState(boolean shouldBeRunning, String argPid)
+ throws Exception {
+ String pid = executeShellCommand(String.format("pidof %s", SIMPLE_APP_PKG)).trim();
+
+ final boolean samePid = pid.equals(argPid);
+ final boolean stillRunning = samePid && isPackageRunning(SIMPLE_APP_PKG);
+
assertWithMessage("Package %s running for user %s", SIMPLE_APP_PKG,
getCurrentUser().getIdentifier())
- .that(isPackageRunning(SIMPLE_APP_PKG)).isEqualTo(shouldBeRunning);
+ .that(stillRunning).isEqualTo(shouldBeRunning);
}
}
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
index c87a7f8d7f4..d1773d0e8e6 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java
@@ -70,6 +70,7 @@ public class DeviceOwnerTest extends BaseDeviceOwnerTest {
private static final String TEST_APP_LOCATION = "/data/local/tmp/cts/packageinstaller/";
private static final String ARG_NETWORK_LOGGING_BATCH_COUNT = "batchCount";
+ private static final String ARG_PID_BEFORE_STOP = "pidOfSimpleapp";
private static final String LAUNCHER_TESTS_HAS_LAUNCHER_ACTIVITY_APK =
"CtsHasLauncherActivityApp.apk";
@@ -1059,13 +1060,16 @@ public class DeviceOwnerTest extends BaseDeviceOwnerTest {
*/
private void tryFgsStoppingProtectedPackage(int userId, boolean canUserStopPackage)
throws Exception {
+ String pid = executeShellCommand(String.format("pidof %s", SIMPLE_APP_PKG)).trim();
fgsStopPackageForUser(SIMPLE_APP_PKG, userId);
if (canUserStopPackage) {
executeDeviceTestMethod(".UserControlDisabledPackagesTest",
- "testFgsStopWithUserControlEnabled");
+ "testFgsStopWithUserControlEnabled",
+ Collections.singletonMap(ARG_PID_BEFORE_STOP, pid));
} else {
executeDeviceTestMethod(".UserControlDisabledPackagesTest",
- "testFgsStopWithUserControlDisabled");
+ "testFgsStopWithUserControlDisabled",
+ Collections.singletonMap(ARG_PID_BEFORE_STOP, pid));
}
}
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 099a0ab7276..35cb549c529 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -1772,6 +1772,37 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
/**
+ * Test that renaming file paths to an external directory such as Android/* and Android/* /*
+ * except Android/media/* /* is not allowed.
+ */
+ @Test
+ public void testRenameFileToAppSpecificDir() throws Exception {
+ final File testFile = new File(getExternalMediaDir(), IMAGE_FILE_NAME);
+ final File testFileNew = new File(getExternalMediaDir(), NONMEDIA_FILE_NAME);
+
+ try {
+ // Create a file in app's external media directory
+ if (!testFile.exists()) {
+ assertThat(testFile.createNewFile()).isTrue();
+ }
+
+ final String androidDirPath = getExternalStorageDir().getPath() + "/Android";
+
+ // Verify that we can't rename a file to Android/ or Android/data or
+ // Android/media directory
+ assertCantRenameFile(testFile, new File(androidDirPath, IMAGE_FILE_NAME));
+ assertCantRenameFile(testFile, new File(androidDirPath + "/data", IMAGE_FILE_NAME));
+ assertCantRenameFile(testFile, new File(androidDirPath + "/media", IMAGE_FILE_NAME));
+
+ // Verify that we can rename a file to app specific media directory.
+ assertCanRenameFile(testFile, testFileNew);
+ } finally {
+ testFile.delete();
+ testFileNew.delete();
+ }
+ }
+
+ /**
* Test that renaming directories is allowed and aligns to default directory restrictions.
*/
@Test
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 573035c2de3..13ade8b0585 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -1367,7 +1367,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
@CddTest(requirement="9.7")
@Test
public void testDrmServerDomain() throws DeviceNotAvailableException {
- assertDomainN("u:r:drmserver:s0", "/system/bin/drmserver", "/system/bin/drmserver64");
+ assertDomainHasExecutable("u:r:drmserver:s0", "/system/bin/drmserver", "/system/bin/drmserver64");
}
/* Installd is always running */
diff --git a/hostsidetests/securitybulletin/Android.bp b/hostsidetests/securitybulletin/Android.bp
index 30b61613f08..25242273f6b 100644
--- a/hostsidetests/securitybulletin/Android.bp
+++ b/hostsidetests/securitybulletin/Android.bp
@@ -43,6 +43,7 @@ java_test_host {
cc_defaults {
name: "cts_hostsidetests_securitybulletin_defaults",
+ auto_gen_config: false,
compile_multilib: "both",
multilib: {
lib32: {
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java
index 12287b0151d..95c90d4ec4b 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -16,43 +16,39 @@
package android.security.cts;
-import android.platform.test.annotations.AppModeFull;
+import static org.junit.Assume.assumeNoException;
+
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
-import org.junit.Assert;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2021_0954 extends StsExtraBusinessLogicHostTestBase {
- private static final String TEST_PKG = "android.security.cts.cve_2021_0954";
- private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
- private static final String TEST_APP = "CVE-2021-0954.apk";
- private ITestDevice device;
-
- @Before
- public void setUp() throws Exception {
- device = getDevice();
- uninstallPackage(device, TEST_PKG);
-
- /* Wake up the screen */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
- }
+ private static final String TEST_PKG = "android.security.cts.CVE_2021_0954";
- @AppModeFull
@AsbSecurityTest(cveBugId = 143559931)
@Test
public void testPocCVE_2021_0954() throws Exception {
- installPackage(TEST_APP);
- AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
- device);
- runDeviceTests(TEST_PKG, TEST_CLASS, "testVulnerableActivityPresence");
+ try {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ installPackage("CVE-2021-0954.apk");
+ AdbUtils.runCommandLine(
+ "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW", device);
+ runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java
new file mode 100644
index 00000000000..e661b4ff4a1
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static org.junit.Assume.assumeNoException;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2022_20353 extends StsExtraBusinessLogicHostTestBase {
+
+ @AsbSecurityTest(cveBugId = 221041256)
+ @Test
+ public void testPocCVE_2022_20353() {
+ try {
+ final String testPkg = "android.security.cts.CVE_2022_20353";
+ ITestDevice device = getDevice();
+
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+
+ // to generate NOTICE.html if not already present
+ AdbUtils.runCommandLine("am start -a android.settings.LICENSE", device);
+
+ installPackage("CVE-2022-20353.apk");
+
+ runDeviceTests(testPkg, testPkg + ".DeviceTest", "testDefaultRingtonePreference");
+ } catch (Exception e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml
index 7f819bcaab4..ef3e6cdf869 100644
--- a/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/BUG-182282630/AndroidManifest.xml
@@ -17,6 +17,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.security.cts.BUG_182282630"
android:targetSandboxVersion="2">
+ <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<application
android:label="@string/app_name"
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp
index aa9f71f574b..59350cf546f 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -18,10 +18,10 @@
android_test_helper_app {
name: "CVE-2021-0954",
defaults: ["cts_support_defaults"],
- srcs: ["src/**/*.java"],
+ srcs: [
+ "src/**/*.java"
+ ],
test_suites: [
- "cts",
- "vts10",
"sts",
],
static_libs: [
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml
index a7e0218c422..75299c4ddfe 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml
@@ -1,5 +1,5 @@
<!--
- Copyright 2021 The Android Open Source Project
+ Copyright 2022 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,25 +13,19 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
- package="android.security.cts.cve_2021_0954"
+ package="android.security.cts.CVE_2021_0954"
android:versionCode="1"
android:versionName="1.0">
-
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
-
- <application
- android:allowBackup="true"
- android:label="CVE_2021_0954"
- android:supportsRtl="true">
- <uses-library android:name="android.test.runner" />
+ <application>
<service android:name=".PocService"
android:enabled="true"
- android:exported="false" />
+ android:exported="true" />
</application>
-
<instrumentation
android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.security.cts.cve_2021_0954" />
+ android:targetPackage="android.security.cts.CVE_2021_0954" />
</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml
new file mode 100644
index 00000000000..363df0001d7
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="noAssumptionFailure">0</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml
new file mode 100644
index 00000000000..7c4d959b70f
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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.
+-->
+
+<resources>
+ <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string>
+ <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+ <string name="cmdDumpsysActivity">dumpsys activity %1$s</string>
+ <string name="empty"></string>
+ <string name="overlayErrorMessage">Device is vulnerable to b/143559931 hence any app with
+ "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string>
+ <string name="mResumedTrue">mResumed=true</string>
+ <string name="messageKey">message</string>
+ <string name="overlayButtonText">OverlayButton</string>
+ <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string>
+ <string name="resultKey">result</string>
+ <string name="sharedPreferences">CVE_2021_0954_prefs</string>
+ <string name="timedOutPocActivity">Timed out waiting on a result from PocActivity</string>
+ <string name="vulClass">com.android.internal.app.ResolverActivity</string>
+ <string name="vulClassAuto">com.android.car.activityresolver.CarResolverActivity</string>
+ <string name="vulPkg">android</string>
+ <string name="vulPkgAuto">com.android.car.activityresolver</string>
+ <string name="vulActivityNotRunningError">The %1$s is not currently running on the device
+ </string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java
index f98690625e9..9a94ef953c1 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,17 +14,20 @@
* limitations under the License.
*/
-package android.security.cts.cve_2021_0954;
+package android.security.cts.CVE_2021_0954;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
+
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
-import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.pm.PackageManager;
import android.provider.Settings;
import androidx.test.runner.AndroidJUnit4;
@@ -32,90 +35,107 @@ import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
- private static final String TEST_PKG = "android.security.cts.cve_2021_0954";
- private static final String TEST_VULNERABLE_PKG = "android";
- private static final String TEST_VULNERABLE_ACTIVITY =
- "com.android.internal.app.ResolverActivity";
- private static final int LAUNCH_TIMEOUT_MS = 20000;
- private static final String vulnerableActivityName = "ResolverActivity";
- private UiDevice mDevice;
- String activityDump = "";
-
- private void startOverlayService() {
- Context context = getApplicationContext();
- assertNotNull(context);
- Intent intent = new Intent(context, PocService.class);
- assertNotNull(intent);
-
- if (Settings.canDrawOverlays(getApplicationContext())) {
- context.startService(intent);
- } else {
- try {
- context.startService(intent);
- } catch (Exception e) {
- throw new RuntimeException("Unable to start the overlay service", e);
- }
- }
+ private Context mContext = getApplicationContext();
+ private static final int TIMEOUT_MS = 10000;
+
+ private boolean hasFeature(String feature) {
+ return mContext.getPackageManager().hasSystemFeature(feature);
}
- public void startVulnerableActivity() {
- Context context = getApplicationContext();
- Intent intent = new Intent();
- intent.setClassName(TEST_VULNERABLE_PKG, TEST_VULNERABLE_ACTIVITY);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- assumeNoException("Activity not found on device", e);
- }
+ private boolean isAuto() {
+ return hasFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
- @Before
- public void setUp() throws Exception {
- mDevice = UiDevice.getInstance(getInstrumentation());
+ String getStringRes(int key) {
+ return mContext.getResources().getString(key);
+ }
- /* Start the vulnerable activity */
- startVulnerableActivity();
- if (!mDevice.wait(Until.hasObject(By.res("android:id/contentPanel")
- .clazz("android.widget.ScrollView").pkg("android")), LAUNCH_TIMEOUT_MS)) {
- return;
- }
+ String getStringResWithArg(int key, String arg) {
+ return mContext.getResources().getString(key, arg);
+ }
- /* Start the overlay service */
- startOverlayService();
+ int getIntegerRes(int key) {
+ return mContext.getResources().getInteger(key);
}
@Test
- public void testVulnerableActivityPresence() {
- Pattern overlayTextPattern = Pattern.compile("OverlayButton", Pattern.CASE_INSENSITIVE);
- if (!mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS)) {
- return;
- }
-
- /*
- * Check if the currently running activity is the vulnerable activity, if not abort the test
- */
+ public void testOverlayButtonPresence() {
try {
- activityDump = mDevice.executeShellCommand("dumpsys activity");
- } catch (IOException e) {
- throw new RuntimeException("Could not execute dumpsys activity command");
- }
- Pattern activityPattern =
- Pattern.compile("mResumedActivity.*" + vulnerableActivityName + ".*\n");
- if (!activityPattern.matcher(activityDump).find()) {
- return;
+ UiDevice device = UiDevice.getInstance(getInstrumentation());
+
+ /* Start the overlay service */
+ assumeTrue(getStringRes(R.string.canNotDrawOverlaysMsg),
+ Settings.canDrawOverlays(mContext));
+ Intent intent = new Intent(mContext, PocService.class);
+ mContext.startService(intent);
+
+ /* Wait for a result from overlay service */
+ SharedPreferences sharedPrefs = mContext.getSharedPreferences(
+ getStringRes(R.string.sharedPreferences), Context.MODE_PRIVATE);
+ final Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(getStringRes(R.string.resultKey))) {
+ preferenceChanged.release();
+ }
+ }
+ };
+ sharedPrefs.registerOnSharedPreferenceChangeListener(listener);
+ assumeTrue(preferenceChanged.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ int result = sharedPrefs.getInt(getStringRes(R.string.resultKey),
+ getIntegerRes(R.integer.assumptionFailure));
+ String message = sharedPrefs.getString(getStringRes(R.string.messageKey),
+ getStringRes(R.string.defaultSemaphoreMsg));
+ assumeTrue(message, result != getIntegerRes(R.integer.assumptionFailure));
+
+ /* Wait for the UI of overlay window to appear */
+ Pattern overlayTextPattern = Pattern.compile(
+ mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE);
+ assumeTrue(mContext.getString(R.string.overlayUiScreenError),
+ device.wait(Until.hasObject(By.text(overlayTextPattern)), TIMEOUT_MS));
+
+ /* Start the vulnerable activity */
+ intent = new Intent();
+ String vulActivity = getStringRes(R.string.vulClass);
+ String vulPkg = getStringRes(R.string.vulPkg);
+ if (isAuto()) {
+ vulActivity = getStringRes(R.string.vulClassAuto);
+ vulPkg = getStringRes(R.string.vulPkgAuto);
+ }
+ intent.setClassName(vulPkg, vulActivity);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ /* Wait until the object of overlay window is gone */
+ boolean overlayDisallowed =
+ device.wait(Until.gone(By.pkg(mContext.getPackageName())), TIMEOUT_MS);
+
+ /*
+ * Check if the currently running activity is the vulnerable activity, if not abort the
+ * test
+ */
+ String activityDump = device.executeShellCommand(
+ getStringResWithArg(R.string.cmdDumpsysActivity, vulActivity));
+ Pattern activityPattern = Pattern.compile(getStringRes(R.string.mResumedTrue));
+ assumeTrue(getStringRes(R.string.vulActivityNotRunningError),
+ activityPattern.matcher(activityDump).find());
+
+ /* Failing the test as fix is not present */
+ assertTrue(getStringResWithArg(R.string.overlayErrorMessage, vulActivity),
+ overlayDisallowed);
+ } catch (Exception e) {
+ assumeNoException(e);
}
- String message = "Device is vulnerable to b/143559931 hence any app with "
- + "SYSTEM_ALERT_WINDOW can overlay the ResolverActivity screen";
- assertNull(message, mDevice.findObject(By.text(overlayTextPattern)));
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java
index 82b78a2beba..79270baa65e 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -14,47 +14,65 @@
* limitations under the License.
*/
-package android.security.cts.cve_2021_0954;
+package android.security.cts.CVE_2021_0954;
import android.app.Service;
+import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.PixelFormat;
-import android.os.Handler;
import android.os.IBinder;
-import android.provider.Settings;
import android.view.Gravity;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.Button;
public class PocService extends Service {
- public static Button mButton;
- private WindowManager mWindowManager;
- private WindowManager.LayoutParams mLayoutParams;
+ Button mButton;
+ WindowManager mWindowManager;
- private static int getScreenWidth() {
+ private int getScreenWidth() {
return Resources.getSystem().getDisplayMetrics().widthPixels;
}
- private static int getScreenHeight() {
+ private int getScreenHeight() {
return Resources.getSystem().getDisplayMetrics().heightPixels;
}
+ String getStringRes(int key) {
+ return getResources().getString(key);
+ }
+
+ int getIntegerRes(int key) {
+ return getResources().getInteger(key);
+ }
+
@Override
public void onCreate() {
- super.onCreate();
- mWindowManager = getSystemService(WindowManager.class);
- mLayoutParams = new WindowManager.LayoutParams();
- mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
- mLayoutParams.format = PixelFormat.OPAQUE;
- mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
- mLayoutParams.width = getScreenWidth();
- mLayoutParams.height = getScreenHeight();
- mLayoutParams.x = getScreenWidth() / 2;
- mLayoutParams.y = getScreenHeight() / 2;
+ try {
+ super.onCreate();
+ mWindowManager = getSystemService(WindowManager.class);
+ LayoutParams layoutParams = new LayoutParams();
+ layoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY;
+ layoutParams.flags =
+ LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
+ layoutParams.format = PixelFormat.OPAQUE;
+ layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
+ layoutParams.width = getScreenWidth();
+ layoutParams.height = getScreenHeight();
+ layoutParams.x = getScreenWidth() / 2;
+ layoutParams.y = getScreenHeight() / 2;
+
+ /* Show the floating window */
+ mButton = new Button(this);
+ mButton.setText(getString(R.string.overlayButtonText));
+ mWindowManager.addView(mButton, layoutParams);
+ } catch (Exception e) {
+ sendTestResult(getIntegerRes(R.integer.assumptionFailure), e.getMessage());
+ return;
+ }
+ sendTestResult(getIntegerRes(R.integer.noAssumptionFailure), getStringRes(R.string.empty));
}
@Override
@@ -63,31 +81,27 @@ public class PocService extends Service {
}
@Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- showFloatingWindow();
- return super.onStartCommand(intent, flags, startId);
- }
-
- @Override
public void onDestroy() {
- if (mWindowManager != null && mButton != null) {
- mWindowManager.removeView(mButton);
+ try {
+ if (mWindowManager != null && mButton != null) {
+ mWindowManager.removeView(mButton);
+ }
+ super.onDestroy();
+ } catch (Exception e) {
+ sendTestResult(getIntegerRes(R.integer.assumptionFailure), e.getMessage());
}
- super.onDestroy();
}
- private void showFloatingWindow() {
- if (Settings.canDrawOverlays(this)) {
- mButton = new Button(getApplicationContext());
- mButton.setText("OverlayButton");
- mWindowManager.addView(mButton, mLayoutParams);
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- onDestroy();
- }
- }, 60000); // one minute
- mButton.setTag(mButton.getVisibility());
+ private void sendTestResult(int result, String message) {
+ try {
+ SharedPreferences sh = getSharedPreferences(getStringRes(R.string.sharedPreferences),
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getStringRes(R.string.resultKey), result);
+ edit.putString(getStringRes(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore the exception
}
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp
new file mode 100644
index 00000000000..37d35eb74f2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2022-20353",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ sdk_version: "current",
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml
new file mode 100644
index 00000000000..d4129ac8823
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.security.cts.CVE_2022_20353">
+ <application
+ android:label="@string/appName"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.RINGTONE_PICKER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2022_20353" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml
new file mode 100644
index 00000000000..3207c29a0bd
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <integer name="assumptionFailure">-1</integer>
+ <integer name="success">0</integer>
+ <integer name="timeoutMs">20000</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml
new file mode 100644
index 00000000000..27e87f65446
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2022 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.
+ -->
+
+<resources>
+ <string name="alwaysButtonId">android:id/button_always</string>
+ <string name="appName">CVE-2022-20353</string>
+ <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string>
+ <string name="failureMessage">
+ Device is vulnerable to b/221041256!! Privilege escalation possible in
+ com.android.settings.DefaultRingtonePreference
+ </string>
+ <string name="fileName">NOTICE.html</string>
+ <string name="getRingtoneCmd">settings get system ringtone</string>
+ <string name="messageKey">message</string>
+ <string name="noticeUri">
+ content://com.android.settings.files/my_cache/NOTICE.html
+ </string>
+ <string name="resType">string</string>
+ <string name="resultKey">result</string>
+ <string name="setRingtoneCmd">settings put system ringtone</string>
+ <string name="sharedPreferences">sharedPreferences</string>
+ <string name="textResId">ringtone_title</string>
+ <string name="uiObjectNotFoundMsg">Unable to find UiObject with %1$s text/id</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java
new file mode 100644
index 00000000000..af1f9782ab0
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20353;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
+import android.content.res.Resources;
+import android.provider.Settings;
+
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ Resources mResources;
+ UiDevice mDevice;
+ Context mContext;
+
+ // Wait for UiObject to appear and click on the UiObject if it is visible
+ private boolean clickUiObject(BySelector selector) {
+ boolean objectFound =
+ mDevice.wait(Until.hasObject(selector), mResources.getInteger(R.integer.timeoutMs));
+ if (objectFound) {
+ mDevice.findObject(selector).click();
+ }
+ return objectFound;
+ }
+
+ @Test
+ public void testDefaultRingtonePreference() {
+ String defaultRingtone = null;
+ try {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mContext = getInstrumentation().getContext();
+ mResources = mContext.getResources();
+ defaultRingtone =
+ mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd));
+
+ Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mContext.startActivity(intent);
+
+ String settingsPackageName =
+ intent.resolveActivity(mContext.getPackageManager()).getPackageName();
+ Context settingsContext = mContext.createPackageContext(settingsPackageName,
+ Context.CONTEXT_IGNORE_SECURITY);
+ Resources res = settingsContext.getPackageManager()
+ .getResourcesForApplication(settingsPackageName);
+ String text = settingsContext
+ .getString(res.getIdentifier(mContext.getString(R.string.textResId),
+ mContext.getString(R.string.resType), settingsPackageName));
+ // scroll until text 'Phone ringtone' is visible
+ UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+ uiScrollable.scrollTextIntoView(text);
+ // click on 'Phone ringtone'
+ BySelector selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text),
+ clickUiObject(selector));
+ // select CTS PoC app
+ text = mContext.getString(R.string.appName);
+ selector = By.text(text);
+ assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text),
+ clickUiObject(selector));
+ // select 'Always'
+ String resId = mContext.getString(R.string.alwaysButtonId);
+ selector = By.res(resId);
+ assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, resId),
+ clickUiObject(selector));
+
+ SharedPreferences sharedPrefs = mContext.getSharedPreferences(
+ mContext.getString(R.string.sharedPreferences), Context.MODE_APPEND);
+ Semaphore preferenceChanged = new Semaphore(0);
+ OnSharedPreferenceChangeListener sharedPrefListener =
+ new OnSharedPreferenceChangeListener() {
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
+ String key) {
+ if (key.equals(mContext.getString(R.string.resultKey))) {
+ preferenceChanged.release();
+ }
+ }
+ };
+ sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefListener);
+ // wait for PocActivity to complete
+ assumeTrue(preferenceChanged.tryAcquire(mResources.getInteger(R.integer.timeoutMs),
+ TimeUnit.MILLISECONDS));
+ int result = sharedPrefs.getInt(mContext.getString(R.string.resultKey),
+ mResources.getInteger(R.integer.assumptionFailure));
+ String message = sharedPrefs.getString(mContext.getString(R.string.messageKey),
+ mContext.getString(R.string.defaultSemaphoreMsg));
+ assumeTrue(message, result != mResources.getInteger(R.integer.assumptionFailure));
+
+ String ringtoneUri = "";
+ boolean isVulnerable = false;
+ long startTime = System.currentTimeMillis();
+ while ((System.currentTimeMillis() - startTime) < mResources
+ .getInteger(R.integer.timeoutMs)) {
+ ringtoneUri =
+ mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd));
+ if (ringtoneUri.contains(mContext.getString(R.string.fileName))) {
+ isVulnerable = true;
+ break;
+ }
+ }
+ assertFalse(mContext.getString(R.string.failureMessage), isVulnerable);
+ } catch (Exception e) {
+ assumeNoException(e);
+ } finally {
+ try {
+ // reset ringtone to default (other than 'null') present before test
+ mDevice.executeShellCommand(
+ mContext.getString(R.string.setRingtoneCmd) + " " + defaultRingtone);
+ mDevice.pressHome();
+ } catch (Exception e) {
+ // ignore exception here
+ }
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java
new file mode 100644
index 00000000000..977e647d2e2
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 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.security.cts.CVE_2022_20353;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Bundle;
+
+/* PocActivity is required in this test since it is required that CTS PoC app is selected when */
+/* choosing an app for setting default ringtone. RingtonePicker appears due to actions done in */
+/* DeviceTest. */
+public class PocActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ try {
+ super.onCreate(savedInstanceState);
+ Intent intent = new Intent();
+ /* set NOTICE.html file uri as EXTRA_RINGTONE_PICKED_URI which sets NOTICE.html as */
+ /* default ringtone if vulnerability is present */
+ intent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI,
+ Uri.parse(getString(R.string.noticeUri)));
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ sendTestResult(getResources().getInteger(R.integer.success), "");
+ } catch (Exception e) {
+ sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage());
+ }
+ }
+
+ void sendTestResult(int result, String message) {
+ try {
+ SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences),
+ Context.MODE_PRIVATE);
+ SharedPreferences.Editor edit = sh.edit();
+ edit.putInt(getString(R.string.resultKey), result);
+ edit.putString(getString(R.string.messageKey), message);
+ edit.commit();
+ } catch (Exception e) {
+ // ignore exception here
+ }
+ }
+
+}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java
index be665ba4013..7f29d44673c 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java
@@ -69,10 +69,6 @@ public final class ConfigUtils {
.addAllowedLogSource("AID_SYSTEM")
.addAllowedLogSource("AID_BLUETOOTH")
.addAllowedLogSource("com.android.bluetooth")
- // TODO(b/236681553): Remove this.
- .addAllowedLogSource("com.android.bluetooth.services")
- // TODO(b/236681553): Remove this.
- .addAllowedLogSource("com.google.android.bluetooth.services")
.addAllowedLogSource("AID_LMKD")
.addAllowedLogSource("AID_MEDIA")
.addAllowedLogSource("AID_RADIO")
diff --git a/tests/app/app/assets/picture_800_by_600.png b/tests/app/app/assets/picture_800_by_600.png
new file mode 100644
index 00000000000..dc8f3d49bdc
--- /dev/null
+++ b/tests/app/app/assets/picture_800_by_600.png
Binary files differ
diff --git a/tests/app/src/android/app/cts/NotificationTemplateTest.kt b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
index 6db8aa69bed..bef1319fba1 100644
--- a/tests/app/src/android/app/cts/NotificationTemplateTest.kt
+++ b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
@@ -32,6 +32,7 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.annotation.ColorInt
import androidx.test.filters.SmallTest
+import com.android.compatibility.common.util.CddTest;
import com.google.common.truth.Truth.assertThat
import org.junit.Assume
import kotlin.test.assertFailsWith
@@ -283,8 +284,9 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
}
}
+ @CddTest(requirement = "3.8.3.1/C-2-1")
fun testPromoteBigPicture_withBigPictureUriIcon() {
- val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
+ val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
val pictureIcon = Icon.createWithContentUri(pictureUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_media_play)
@@ -385,8 +387,9 @@ class NotificationTemplateTest : NotificationTemplateTestBase() {
!!.sameAs(picture)).isTrue()
}
+ @CddTest(requirement = "3.8.3.1/C-2-1")
fun testBigPicture_withBigLargeIcon_withContentUri() {
- val iconUri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
+ val iconUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
val icon = Icon.createWithContentUri(iconUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_media_play)
diff --git a/tests/camera/Android.bp b/tests/camera/Android.bp
index aae58c689b7..c2334fc3b4c 100644
--- a/tests/camera/Android.bp
+++ b/tests/camera/Android.bp
@@ -65,6 +65,7 @@ android_test {
"truth-prebuilt",
"androidx.heifwriter_heifwriter",
"androidx.test.rules",
+ "MediaPerformanceClassCommon",
],
jni_libs: [
"libctscamera2_jni",
diff --git a/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java b/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java
index feb5567963f..772e7a599cb 100644
--- a/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java
+++ b/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java
@@ -36,6 +36,7 @@ import android.hardware.camera2.params.SessionConfiguration;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
+import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.test.AndroidTestCase;
@@ -210,8 +211,9 @@ public class SPerfClassTest extends AndroidTestCase {
* Version.MEDIA_PERFORMANCE_CLASS
*/
public void testSPerfClassJpegSizes() throws Exception {
- boolean isSPerfClass = CameraTestUtils.isSPerfClass();
- if (!isSPerfClass) {
+ final boolean isAtLeastSPerfClass =
+ (Build.VERSION.MEDIA_PERFORMANCE_CLASS >= Build.VERSION_CODES.S);
+ if (!isAtLeastSPerfClass) {
return;
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index 6af7758c533..d7dd63d1ff2 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -55,6 +55,10 @@ import android.hardware.camera2.params.DynamicRangeProfiles;
import android.hardware.camera2.params.RecommendedStreamConfigurationMap;
import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.cts.helpers.CameraUtils;
+import android.mediapc.cts.common.Requirement;
+import android.mediapc.cts.common.RequiredMeasurement;
+import android.mediapc.cts.common.RequirementConstants;
+import android.mediapc.cts.common.PerformanceClassEvaluator;
import android.media.CamcorderProfile;
import android.media.ImageReader;
import android.os.Build;
@@ -74,15 +78,11 @@ import android.view.WindowMetrics;
import androidx.test.rule.ActivityTestRule;
-import androidx.test.InstrumentationRegistry;
-
import com.android.compatibility.common.util.CddTest;
-import com.android.compatibility.common.util.DeviceReportLog;
-import com.android.compatibility.common.util.ResultType;
-import com.android.compatibility.common.util.ResultUnit;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@@ -92,12 +92,10 @@ import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.function.BiPredicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static android.hardware.camera2.cts.CameraTestUtils.MPC_REPORT_LOG_NAME;
-import static android.hardware.camera2.cts.CameraTestUtils.MPC_STREAM_NAME;
-
/**
* Extended tests for static camera characteristics.
*/
@@ -113,6 +111,9 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
*/
private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5
+ @Rule
+ public final TestName mTestName = new TestName();
+
private List<CameraCharacteristics> mCharacteristics;
private static final Size FULLHD = new Size(1920, 1080);
@@ -131,10 +132,6 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
private static final long PREVIEW_RUN_MS = 500;
private static final long FRAME_DURATION_30FPS_NSEC = (long) 1e9 / 30;
- private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000;
- private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000;
- private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000;
-
private static final long MIN_UHR_SENSOR_RESOLUTION = 24000000;
/*
* HW Levels short hand
@@ -2857,28 +2854,70 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
}
/**
- * Update performance class level based on condition
- *
- * @param condition whether the condition is met for passLevel
- * @param passLevel the highest performance class level when condition is true
- * @param failLevel the performance class when condition is false
+ * Camera hardware level requirement for Media Performance Class
*/
- private int updatePerfClassLevel(boolean condition, int passLevel, int failLevel) {
- return condition ? passLevel : failLevel;
- }
+ public static class PrimaryCameraHwLevelReq extends Requirement {
+ private static final String TAG = PrimaryCameraHwLevelReq.class.getSimpleName();
+
+ /**
+ * Creates a >= predicate for camera hardware level
+ */
+ private static BiPredicate<Integer, Integer> camHwLevelGte() {
+ return new BiPredicate<Integer, Integer>() {
+ @Override
+ public boolean test(Integer actual, Integer expected) {
+ return StaticMetadata.hardwareLevelPredicate(actual, expected);
+ }
- /**
- * Update perf class level based on meetSPerfClass and meetRPerfClass.
- */
- private int updatePerfClassLevelRS(boolean meetSPerfClass, boolean meetRPerfClass,
- int perfClassLevel) {
- if (!meetRPerfClass) {
- return CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else if (!meetSPerfClass &&
- perfClassLevel > CameraTestUtils.PERFORMANCE_CLASS_R) {
- return Math.min(CameraTestUtils.PERFORMANCE_CLASS_R, perfClassLevel);
- }
- return perfClassLevel;
+ @Override
+ public String toString() {
+ return "Camera Hardware Level Greater than or equal to";
+ }
+ };
+ }
+ private static final BiPredicate<Integer, Integer> CAM_HW_LEVEL_GTE = camHwLevelGte();
+ private PrimaryCameraHwLevelReq(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setPrimaryRearCameraHwlLevel(Integer hwLevel) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_HWL_LEVEL, hwLevel);
+ }
+
+ public void setPrimaryFrontCameraHwlLevel(Integer hwLevel) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_HWL_LEVEL, hwLevel);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-3] MUST support android.info.supportedHardwareLevel property as FULL or
+ * better for back primary and LIMITED or better for front primary camera.
+ */
+ public static PrimaryCameraHwLevelReq createPrimaryCameraHwLevelReq() {
+ RequiredMeasurement<Integer> rearCameraHwlLevel = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.REAR_CAMERA_HWL_LEVEL)
+ .setPredicate(CAM_HW_LEVEL_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .addRequiredValue(Build.VERSION_CODES.S,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .build();
+ RequiredMeasurement<Integer> frontCameraHwlLevel = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_HWL_LEVEL)
+ .setPredicate(CAM_HW_LEVEL_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED)
+ .addRequiredValue(Build.VERSION_CODES.S,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU,
+ CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
+ .build();
+ return new PrimaryCameraHwLevelReq(RequirementConstants.R7_5__H_1_3,
+ rearCameraHwlLevel, frontCameraHwlLevel);
+ }
}
/**
@@ -2893,30 +2932,31 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
// ids.
return;
}
- boolean assertRPerfClass = CameraTestUtils.isRPerfClass();
- boolean assertSPerfClass = CameraTestUtils.isSPerfClass();
- boolean assertTPerfClass = CameraTestUtils.isTPerfClass();
- boolean assertPerfClass = (assertRPerfClass || assertSPerfClass || assertTPerfClass);
-
- // R & S Performance Class
- int perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH13 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH14 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH18 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
-
- // T Performance Class
- int perfClassLevelH19 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH110 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH111 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH112 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH113 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
- int perfClassLevelH114 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT;
-
- DeviceReportLog reportLog = new DeviceReportLog(MPC_REPORT_LOG_NAME, MPC_STREAM_NAME);
-
- String primaryRearId = null;
- String primaryFrontId = null;
+ PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName);
+ PerformanceClassEvaluator.PrimaryCameraRequirement primaryRearReq =
+ pce.addPrimaryRearCameraReq();
+ PerformanceClassEvaluator.PrimaryCameraRequirement primaryFrontReq =
+ pce.addPrimaryFrontCameraReq();
+ PrimaryCameraHwLevelReq hwLevelReq = pce.addRequirement(
+ PrimaryCameraHwLevelReq.createPrimaryCameraHwLevelReq());
+ PerformanceClassEvaluator.CameraTimestampSourceRequirement timestampSourceReq =
+ pce.addR7_5__H_1_4();
+ PerformanceClassEvaluator.CameraRawRequirement rearRawReq =
+ pce.addR7_5__H_1_8();
+ PerformanceClassEvaluator.Camera240FpsRequirement hfrReq =
+ pce.addR7_5__H_1_9();
+ PerformanceClassEvaluator.UltraWideZoomRatioRequirement ultrawideZoomRatioReq =
+ pce.addR7_5__H_1_10();
+ PerformanceClassEvaluator.ConcurrentRearFrontRequirement concurrentRearFrontReq =
+ pce.addR7_5__H_1_11();
+ PerformanceClassEvaluator.PreviewStabilizationRequirement previewStabilizationReq =
+ pce.addR7_5__H_1_12();
+ PerformanceClassEvaluator.LogicalMultiCameraRequirement logicalMultiCameraReq =
+ pce.addR7_5__H_1_13();
+ PerformanceClassEvaluator.StreamUseCaseRequirement streamUseCaseReq =
+ pce.addR7_5__H_1_14();
+
+ HashSet<String> primaryCameras = new HashSet<String>();
for (int i = 0; i < mCameraIdsUnderTest.length; i++) {
String cameraId = mCameraIdsUnderTest[i];
boolean isPrimaryRear = CameraTestUtils.isPrimaryRearFacingCamera(
@@ -2940,42 +2980,27 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
List<Size> videoSizes = CameraTestUtils.getSupportedVideoSizes(cameraId,
mCameraManager, null /*bound*/);
+ Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE);
if (isPrimaryRear) {
- primaryRearId = cameraId;
- if (sensorResolution < MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION) {
- mCollector.expectTrue("Primary rear camera resolution should be at least " +
- MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION + " pixels, is "+
- sensorResolution, !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
- reportLog.addValue("rear camera resolution", sensorResolution,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ primaryCameras.add(cameraId);
+ primaryRearReq.setPrimaryCameraSupported(true);
+ primaryRearReq.setResolution(sensorResolution);
+ hwLevelReq.setPrimaryRearCameraHwlLevel(staticInfo.getHardwareLevelChecked());
+ timestampSourceReq.setRearCameraTimestampSource(timestampSource);
// 4K @ 30fps
boolean supportUHD = videoSizes.contains(UHD);
boolean supportDC4K = videoSizes.contains(DC4K);
- reportLog.addValue("rear camera 4k support", supportUHD | supportDC4K,
- ResultType.NEUTRAL, ResultUnit.NONE);
- if (!supportUHD && !supportDC4K) {
- mCollector.expectTrue("Primary rear camera should support 4k video recording",
- !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
+ boolean support4K = (supportUHD || supportDC4K);
+ primaryRearReq.setVideoSizeReqSatisfied(support4K);
+ if (support4K) {
long minFrameDuration = config.getOutputMinFrameDuration(
android.media.MediaRecorder.class, supportDC4K ? DC4K : UHD);
- reportLog.addValue("rear camera 4k frame duration", minFrameDuration,
- ResultType.NEUTRAL, ResultUnit.NONE);
- if (minFrameDuration >= (1e9 / 29.9)) {
- mCollector.expectTrue("Primary rear camera should support 4k video @ 30fps",
- !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
+ primaryRearReq.setVideoFps(1e9 / minFrameDuration);
}
// H-1-9
boolean supportHighSpeed = staticInfo.isCapabilitySupported(CONSTRAINED_HIGH_SPEED);
- mCollector.expectTrue("Primary rear camera should support high speed recording",
- !assertTPerfClass || supportHighSpeed);
boolean support240Fps = false;
if (supportHighSpeed) {
Size[] availableHighSpeedSizes = config.getHighSpeedVideoSizes();
@@ -2995,101 +3020,29 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
break;
}
}
- mCollector.expectTrue("Primary rear camera should support HD or FULLHD @ 240",
- !assertTPerfClass || support240Fps);
}
- perfClassLevelH19 = updatePerfClassLevel(support240Fps,
- perfClassLevelH19, CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue("rear camera 720p/1080p @ 240fps support", support240Fps,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ hfrReq.setRear240FpsSupported(support240Fps);
} else {
- primaryFrontId = cameraId;
- if (sensorResolution < MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION) {
- mCollector.expectTrue("Primary front camera resolution should be at least "
- + MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is "
- + sensorResolution, !(assertSPerfClass || assertTPerfClass));
- perfClassLevelH12 = Math.min(
- perfClassLevelH12, CameraTestUtils.PERFORMANCE_CLASS_R);
- }
- if (sensorResolution < MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION) {
- mCollector.expectTrue("Primary front camera resolution should be at least " +
- MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is "+
- sensorResolution, !assertRPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
- reportLog.addValue("front camera resolution", sensorResolution,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ primaryCameras.add(cameraId);
+ primaryFrontReq.setPrimaryCameraSupported(true);
+ primaryFrontReq.setResolution(sensorResolution);
+ hwLevelReq.setPrimaryFrontCameraHwlLevel(staticInfo.getHardwareLevelChecked());
+ timestampSourceReq.setFrontCameraTimestampSource(timestampSource);
// 1080P @ 30fps
boolean supportFULLHD = videoSizes.contains(FULLHD);
- reportLog.addValue("front camera 1080p support", supportFULLHD,
- ResultType.NEUTRAL, ResultUnit.NONE);
- if (!supportFULLHD) {
- mCollector.expectTrue(
- "Primary front camera should support 1080P video recording",
- !assertPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
+ primaryFrontReq.setVideoSizeReqSatisfied(supportFULLHD);
+ if (supportFULLHD) {
long minFrameDuration = config.getOutputMinFrameDuration(
android.media.MediaRecorder.class, FULLHD);
- if (minFrameDuration >= (1e9 / 29.9)) {
- mCollector.expectTrue(
- "Primary front camera should support 1080P video @ 30fps",
- !assertPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- }
- reportLog.addValue("front camera 1080p frame duration", minFrameDuration,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ primaryFrontReq.setVideoFps(1e9 / minFrameDuration);
}
}
- String facingString = isPrimaryRear ? "rear" : "front";
- // H-1-3
- if (assertTPerfClass || assertSPerfClass || (assertRPerfClass && isPrimaryRear)) {
- mCollector.expectTrue("Primary " + facingString +
- " camera should be at least FULL, but is " +
- toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
- staticInfo.isHardwareLevelAtLeastFull());
- } else if (assertRPerfClass) {
- mCollector.expectTrue("Primary " + facingString +
- " camera should be at least LIMITED, but is " +
- toStringHardwareLevel(staticInfo.getHardwareLevelChecked()),
- staticInfo.isHardwareLevelAtLeastLimited());
- }
-
- reportLog.addValue(facingString + " camera hardware level",
- staticInfo.getHardwareLevelChecked(), ResultType.NEUTRAL, ResultUnit.NONE);
- if (isPrimaryRear) {
- perfClassLevelH13 = updatePerfClassLevel(staticInfo.isHardwareLevelAtLeastFull(),
- perfClassLevelH13, CameraTestUtils.PERFORMANCE_CLASS_NOT_MET);
- } else {
- perfClassLevelH13 = updatePerfClassLevelRS(staticInfo.isHardwareLevelAtLeastFull(),
- staticInfo.isHardwareLevelAtLeastLimited(), perfClassLevelH13);
- }
-
- // H-1-4
- Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE);
- reportLog.addValue(facingString + " timestampSource",
- timestampSource, ResultType.NEUTRAL, ResultUnit.NONE);
- boolean realtimeTimestamp = (timestampSource != null &&
- timestampSource.equals(CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME));
- mCollector.expectTrue(
- "Primary " + facingString + " camera should support real-time timestamp source",
- !assertPerfClass || realtimeTimestamp);
- perfClassLevelH14 = updatePerfClassLevel(realtimeTimestamp, perfClassLevelH14,
- CameraTestUtils.PERFORMANCE_CLASS_NOT_MET);
-
// H-1-8
if (isPrimaryRear) {
boolean supportRaw = staticInfo.isCapabilitySupported(RAW);
- reportLog.addValue(facingString + " camera raw support",
- supportRaw, ResultType.NEUTRAL, ResultUnit.NONE);
- if (assertSPerfClass || assertTPerfClass) {
- mCollector.expectTrue("Primary rear camera should support RAW capability",
- supportRaw);
- }
- perfClassLevelH18 = updatePerfClassLevel(supportRaw, perfClassLevelH18,
- CameraTestUtils.PERFORMANCE_CLASS_R);
+ rearRawReq.setRearRawSupported(supportRaw);
}
// H-1-10
@@ -3098,96 +3051,45 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase {
Range<Float> zoomRatioRange = staticInfo.getZoomRatioRangeChecked();
boolean meetH110 = (primaryToMaxFovRatio >= 1.0f - FOV_THRESHOLD)
|| (zoomRatioRange.getLower() < 1.0f - FOV_THRESHOLD);
- mCollector.expectTrue("Primary " + facingString + " camera must support zoomRatio < "
- + "1.0f if there is an ultrawide lens with the same facing",
- !assertTPerfClass || meetH110);
- perfClassLevelH110 = updatePerfClassLevel(meetH110, perfClassLevelH110,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera supports maximum FOV using zoom ratio",
- meetH110, ResultType.NEUTRAL, ResultUnit.NONE);
+ if (isPrimaryRear) {
+ ultrawideZoomRatioReq.setRearUltraWideZoomRatioReqMet(meetH110);
+ } else {
+ ultrawideZoomRatioReq.setFrontUltraWideZoomRatioReqMet(meetH110);
+ }
// H-1-12
- boolean meetH112 = staticInfo.isPreviewStabilizationSupported();
- mCollector.expectTrue("Primary " + facingString + " camera must support preview "
- + "stabilization", !assertTPerfClass || meetH112);
- perfClassLevelH112 = updatePerfClassLevel(meetH112, perfClassLevelH112,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera preview stabilization", meetH112,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ boolean previewStab = staticInfo.isPreviewStabilizationSupported();
+ if (isPrimaryRear) {
+ previewStabilizationReq.setRearPreviewStabilizationSupported(previewStab);
+ } else {
+ previewStabilizationReq.setFrontPreviewStabilizationSupported(previewStab);
+ }
// H-1-13
int facing = staticInfo.getLensFacingChecked();
int numOfPhysicalRgbCameras = getNumberOfRgbPhysicalCameras(facing);
- boolean meetH113 = (numOfPhysicalRgbCameras <= 1) || staticInfo.isLogicalMultiCamera();
- mCollector.expectTrue("Primary " + facingString + " camera must be LOGICAL_MULTI_CAMERA"
- + " in case of multiple RGB cameras with same facing",
- !assertTPerfClass || meetH113);
- perfClassLevelH113 = updatePerfClassLevel(meetH113, perfClassLevelH113,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera is LOGICAL_MULTI_CAMERA in case of multiple "
- + "RGB cameras with same facing", meetH113, ResultType.NEUTRAL,
- ResultUnit.NONE);
+ boolean logicalMultiCameraReqMet =
+ (numOfPhysicalRgbCameras <= 1) || staticInfo.isLogicalMultiCamera();
+ if (isPrimaryRear) {
+ logicalMultiCameraReq.setRearLogicalMultiCameraReqMet(logicalMultiCameraReqMet);
+ } else {
+ logicalMultiCameraReq.setFrontLogicalMultiCameraReqMet(logicalMultiCameraReqMet);
+ }
// H-1-14
- boolean meetH114 = staticInfo.isStreamUseCaseSupported();
- mCollector.expectTrue("Primary " + facingString + " camera must support stream "
- + "use case", !assertTPerfClass || meetH114);
- perfClassLevelH114 = updatePerfClassLevel(meetH114, perfClassLevelH114,
- CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue(facingString + " camera stream use case", meetH114,
- ResultType.NEUTRAL, ResultUnit.NONE);
- }
- HashSet<String> primaryCameras = new HashSet<String>();
- if (primaryRearId == null) {
- mCollector.expectTrue("There must be a primary rear camera for performance class.",
- !assertPerfClass);
- perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
- primaryCameras.add(primaryRearId);
- }
- if (primaryFrontId == null) {
- mCollector.expectTrue("There must be a primary front camera for performance class.",
- !assertPerfClass);
- perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET;
- } else {
- primaryCameras.add(primaryFrontId);
+ boolean streamUseCaseSupported = staticInfo.isStreamUseCaseSupported();
+ if (isPrimaryRear) {
+ streamUseCaseReq.setRearStreamUseCaseSupported(streamUseCaseSupported);
+ } else {
+ streamUseCaseReq.setFrontStreamUseCaseSupported(streamUseCaseSupported);
+ }
}
-
// H-1-11
Set<Set<String>> concurrentCameraIds = mCameraManager.getConcurrentCameraIds();
boolean supportPrimaryFrontBack = concurrentCameraIds.contains(primaryCameras);
- mCollector.expectTrue("Concurrent primary front and primary back streaming must be "
- + "supported", !assertTPerfClass || supportPrimaryFrontBack);
- perfClassLevelH111 = updatePerfClassLevel(supportPrimaryFrontBack,
- perfClassLevelH111, CameraTestUtils.PERFORMANCE_CLASS_S);
- reportLog.addValue("concurrent front back support", supportPrimaryFrontBack,
- ResultType.NEUTRAL, ResultUnit.NONE);
-
- reportLog.addValue("Version", "0.0.1", ResultType.NEUTRAL, ResultUnit.NONE);
- final String PERF_CLASS_REQ_NUM_PREFIX = "2.2.7.2/7.5/";
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-1",
- perfClassLevelH11, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-2",
- perfClassLevelH12, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-3",
- perfClassLevelH13, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-4",
- perfClassLevelH14, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-8",
- perfClassLevelH18, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-9",
- perfClassLevelH19, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-10",
- perfClassLevelH110, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-11",
- perfClassLevelH111, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-12",
- perfClassLevelH112, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-13",
- perfClassLevelH113, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-14",
- perfClassLevelH114, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.submit(InstrumentationRegistry.getInstrumentation());
+ concurrentRearFrontReq.setConcurrentRearFrontSupported(supportPrimaryFrontBack);
+
+ pce.submitAndCheck();
}
/**
diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
index 3c88a3a445c..c9c28eac4bf 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java
@@ -1234,8 +1234,13 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
mOutMediaFileName = mDebugFileNameBase + "/test_cslowMo_video_" +
captureRate + "fps_" + id + "_" + size.toString() + ".mp4";
- Log.v(TAG, "previewFrameRate:" + previewFrameRate);
- prepareRecording(size, previewFrameRate, captureRate);
+
+ // b/239101664 It appears that video frame rates higher than 30 fps may not
+ // trigger slow motion recording consistently.
+ int videoFrameRate = previewFrameRate > VIDEO_FRAME_RATE ?
+ VIDEO_FRAME_RATE : previewFrameRate;
+ Log.v(TAG, "videoFrameRate:" + videoFrameRate);
+ prepareRecording(size, videoFrameRate, captureRate);
SystemClock.sleep(PREVIEW_DURATION_MS);
@@ -1243,7 +1248,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
SimpleCaptureCallback resultListener = new SimpleCaptureCallback();
// Start recording
- startSlowMotionRecording(/*useMediaRecorder*/true, previewFrameRate,
+ startSlowMotionRecording(/*useMediaRecorder*/true, videoFrameRate,
captureRate, fpsRange, resultListener,
/*useHighSpeedSession*/true);
@@ -1256,7 +1261,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase {
startConstrainedPreview(fpsRange, previewResultListener);
// Convert number of frames camera produced into the duration in unit of ms.
- float frameDurationMs = 1000.0f / previewFrameRate;
+ float frameDurationMs = 1000.0f / videoFrameRate;
float durationMs = resultListener.getTotalNumFrames() * frameDurationMs;
// Validation.
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
index e8d616880e7..4a86b49e51a 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -142,8 +142,6 @@ public class CameraTestUtils extends Assert {
public static final String OFFLINE_CAMERA_ID = "offline_camera_id";
public static final String REPORT_LOG_NAME = "CtsCameraTestCases";
- public static final String MPC_REPORT_LOG_NAME = "MediaPerformanceClassLogs";
- public static final String MPC_STREAM_NAME = "CameraCts";
private static final int EXIF_DATETIME_LENGTH = 19;
private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60;
@@ -3815,33 +3813,6 @@ public class CameraTestUtils extends Assert {
return zoomRatios;
}
- public static final int PERFORMANCE_CLASS_NOT_MET = 0;
- public static final int PERFORMANCE_CLASS_R = Build.VERSION_CODES.R;
- public static final int PERFORMANCE_CLASS_S = Build.VERSION_CODES.R + 1;
- public static final int PERFORMANCE_CLASS_T = Build.VERSION_CODES.S + 2;
- public static final int PERFORMANCE_CLASS_CURRENT = PERFORMANCE_CLASS_T;
-
- /**
- * Check whether this mobile device is R performance class as defined in CDD
- */
- public static boolean isRPerfClass() {
- return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R;
- }
-
- /**
- * Check whether this mobile device is S performance class as defined in CDD
- */
- public static boolean isSPerfClass() {
- return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S;
- }
-
- /**
- * Check whether this mobile device is T performance class as defined in CDD
- */
- public static boolean isTPerfClass() {
- return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_T;
- }
-
/**
* Check whether a camera Id is a primary rear facing camera
*/
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index fc8c4db5164..f1886859d67 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -229,6 +229,13 @@ public class StaticMetadata {
* at least the desired one (but could be higher)
*/
public boolean isHardwareLevelAtLeast(int level) {
+ int deviceLevel = getHardwareLevelChecked();
+
+ return hardwareLevelPredicate(deviceLevel, level);
+ }
+
+ // Return true if level1 is at least level2
+ public static boolean hardwareLevelPredicate(int level1, int level2) {
final int[] sortedHwLevels = {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL,
@@ -236,19 +243,19 @@ public class StaticMetadata {
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3
};
- int deviceLevel = getHardwareLevelChecked();
- if (level == deviceLevel) {
+
+ if (level1 == level2) {
return true;
}
for (int sortedlevel : sortedHwLevels) {
- if (sortedlevel == level) {
+ if (sortedlevel == level2) {
return true;
- } else if (sortedlevel == deviceLevel) {
+ } else if (sortedlevel == level1) {
return false;
}
}
- Assert.fail("Unknown hardwareLevel " + level + " and device hardware level " + deviceLevel);
+ Assert.fail("Unknown hardwareLevel " + level1 + " and device hardware level " + level2);
return false;
}
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java
index 2c3934ccc75..bdf4bc6fde2 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/CloneProfileDeviceOwnerTest.java
@@ -27,6 +27,7 @@ import android.os.UserManager;
import com.android.bedstead.harrier.BedsteadJUnit4;
import com.android.bedstead.harrier.DeviceState;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
+import com.android.bedstead.harrier.annotations.RequireMultiUserSupport;
import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDeviceOwner;
@@ -52,6 +53,7 @@ public class CloneProfileDeviceOwnerTest {
@EnsureHasDeviceOwner
@EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
@RequireRunOnPrimaryUser
+ @RequireMultiUserSupport
public void createCloneProfile_hasDeviceOwner_fails() {
assertThrows(NeneException.class,
() -> TestApis.users().createUser()
@@ -67,6 +69,7 @@ public class CloneProfileDeviceOwnerTest {
@EnsureHasNoDeviceOwner
@EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS)
@RequireRunOnPrimaryUser
+ @RequireMultiUserSupport
public void createCloneProfile_noDeviceOwner_succeeds() {
UserReference cloneUser = TestApis.users().createUser()
.parent(TestApis.users().instrumented())
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
index 286ccae00a8..1c35d480d81 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java
@@ -54,6 +54,7 @@ import com.android.bedstead.harrier.annotations.EnsureHasNoWorkProfile;
import com.android.bedstead.harrier.annotations.EnsureHasPermission;
import com.android.bedstead.harrier.annotations.Postsubmit;
import com.android.bedstead.harrier.annotations.RequireFeature;
+import com.android.bedstead.harrier.annotations.RequireMultiUserSupport;
import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasDeviceOwner;
import com.android.bedstead.harrier.annotations.enterprise.EnsureHasNoDpc;
@@ -65,6 +66,7 @@ import com.android.bedstead.nene.utils.Poll;
import com.android.bedstead.remotedpc.RemoteDpc;
import com.android.bedstead.testapp.TestApp;
import com.android.bedstead.testapp.TestAppInstance;
+import com.android.compatibility.common.util.CddTest;
import com.android.eventlib.truth.EventLogsSubject;
import com.android.queryable.queries.ActivityQuery;
@@ -140,6 +142,7 @@ public class DevicePolicyManagementRoleHolderTest {
@EnsureHasNoDpc
@EnsureHasNoSecondaryUser
@Test
+ @CddTest(requirements = {"3.9.4/C-3-1"})
public void createAndProvisionManagedProfile_roleHolderIsInWorkProfile()
throws ProvisioningException, InterruptedException {
UserHandle profile = null;
@@ -172,7 +175,9 @@ public class DevicePolicyManagementRoleHolderTest {
@EnsureHasDeviceOwner
@RequireRunOnPrimaryUser
@EnsureHasNoSecondaryUser
+ @RequireMultiUserSupport
@Test
+ @CddTest(requirements = {"3.9.4/C-3-1"})
public void createAndManageUser_roleHolderIsInManagedUser() throws InterruptedException {
UserHandle managedUser = null;
String roleHolderPackageName = null;
@@ -313,6 +318,7 @@ public class DevicePolicyManagementRoleHolderTest {
@EnsureHasNoWorkProfile
@RequireRunOnPrimaryUser
@EnsureHasNoDpc
+ @RequireMultiUserSupport
public void shouldAllowBypassingDevicePolicyManagementRoleQualification_withUsers_returnsFalse()
throws Exception {
resetInternalShouldAllowBypassingState();
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
index fcf71d0a19c..dfe77fb4121 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java
@@ -45,6 +45,7 @@ import com.android.bedstead.harrier.policies.UserControlDisabledPackages;
import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.packages.Package;
+import com.android.bedstead.nene.utils.Poll;
import com.android.bedstead.testapp.TestApp;
import com.android.bedstead.testapp.TestAppInstance;
import com.android.queryable.queries.StringQuery;
@@ -235,6 +236,11 @@ public final class UserControlDisabledPackagesTest {
private void assertPackageStopped(String packageName)
throws Exception {
+ Poll.forValue("Package " + packageName + " stopped", () -> isPackageStopped(packageName))
+ .toBeEqualTo(true)
+ .errorOnFail()
+ .await();
+
assertWithMessage("Package %s not stopped", packageName)
.that(isPackageStopped(packageName)).isTrue();
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
index c13c4eec7f8..9fd1a41a416 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java
@@ -21,6 +21,7 @@ import static android.server.wm.jetpack.second.Components.SECOND_UNTRUSTED_EMBED
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.assumeActivityEmbeddingSupportedDevice;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -33,6 +34,7 @@ import android.content.Intent;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
import android.server.wm.WindowManagerState.Task;
import android.window.TaskFragmentCreationParams;
import android.window.TaskFragmentInfo;
@@ -49,6 +51,7 @@ import org.junit.Test;
* Build/Install/Run:
* atest CtsWindowManagerDeviceTestCases:TaskFragmentTrustedModeTest
*/
+@Presubmit
public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
private final ComponentName mTranslucentActivity = new ComponentName(mContext,
@@ -248,7 +251,7 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
*/
@Test
public void testUntrustedModeTaskFragment_startActivityInTaskFragmentOutsideOfParentBounds() {
- final Task parentTask = mWmState.getRootTask(mOwnerTaskId);
+ Task parentTask = mWmState.getRootTask(mOwnerTaskId);
final Rect parentBounds = new Rect(parentTask.getBounds());
final IBinder errorCallbackToken = new Binder();
final WindowContainerTransaction wct = new WindowContainerTransaction()
@@ -263,8 +266,11 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase {
// It is disallowed to start activity to TaskFragment with bounds outside of its parent
// in untrusted mode.
assertTaskFragmentError(errorCallbackToken, SecurityException.class);
- mWmState.waitForAppTransitionIdleOnDisplay(mOwnerActivity.getDisplayId());
- mWmState.assertNotExist(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY);
+
+ parentTask = mWmState.getRootTask(mOwnerTaskId);
+ assertWithMessage("Activity must be started in parent Task because it's not"
+ + " allowed to be embedded").that(parentTask.mActivities).contains(
+ mWmState.getActivity(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY));
}
/**
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 65465b27895..8dc33b1f745 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -59,6 +59,7 @@ import android.app.AlertDialog;
import android.app.Instrumentation;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
@@ -226,6 +227,11 @@ public class WindowInsetsControllerTests extends WindowManagerTestBase {
final Instrumentation instrumentation = getInstrumentation();
assumeThat(MockImeSession.getUnavailabilityReason(instrumentation.getContext()),
nullValue());
+ final Resources resources = instrumentation.getContext().getResources();
+ final boolean isHideNavBarForKeyboardEnabled = resources.getBoolean(
+ resources.getIdentifier("config_hideNavBarForKeyboard", "bool", "android"));
+ assumeFalse("Device is configured to not show navigation bar for keyboard",
+ isHideNavBarForKeyboardEnabled);
final MockImeSession imeSession = MockImeHelper.createManagedMockImeSession(this);
final ImeEventStream stream = imeSession.openEventStream();
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
index ccd8659e3de..8855dee537b 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java
@@ -32,7 +32,7 @@ public final class Watermark {
*
* <p>See Bug 174534092 about why we ended up having this.</p>
*/
- private static final int TOLERANCE = 4;
+ private static final int TOLERANCE = 6;
/**
* A utility class that represents A8R8G8B bitmap as an integer array.
diff --git a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
index 08ddca145d9..6516de9d8a1 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/GeocoderTest.java
@@ -33,10 +33,12 @@ import android.content.Intent;
import android.content.pm.PackageManager.ResolveInfoFlags;
import android.location.Geocoder;
import android.location.Geocoder.GeocodeListener;
+import android.platform.test.annotations.AppModeFull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.RetryRule;
import org.junit.Before;
@@ -73,6 +75,8 @@ public class GeocoderTest {
}
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocation")
+ @AppModeFull(reason = "b/238831704 - Test cases don't apply for Instant apps")
@Test
public void testGetFromLocation() {
assumeTrue(Geocoder.isPresent());
@@ -82,6 +86,7 @@ public class GeocoderTest {
verify(listener, timeout(10000)).onGeocode(anyList());
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocation")
@Test
public void testGetFromLocation_sync() throws Exception {
assumeTrue(Geocoder.isPresent());
@@ -89,6 +94,7 @@ public class GeocoderTest {
mGeocoder.getFromLocation(60, 30, 5);
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocation")
@Test
public void testGetFromLocation_badInput() {
GeocodeListener listener = mock(GeocodeListener.class);
@@ -102,6 +108,7 @@ public class GeocoderTest {
() -> mGeocoder.getFromLocation(10, 181, 5, listener));
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocationName")
@Test
public void testGetFromLocationName() {
assumeTrue(Geocoder.isPresent());
@@ -111,6 +118,7 @@ public class GeocoderTest {
verify(listener, timeout(10000)).onGeocode(anyList());
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocationName")
@Test
public void testGetFromLocationName_sync() throws Exception {
assumeTrue(Geocoder.isPresent());
@@ -118,6 +126,7 @@ public class GeocoderTest {
mGeocoder.getFromLocationName("Dalvik,Iceland", 5);
}
+ @ApiTest(apis = "android.location.Geocoder#getFromLocationName")
@Test
public void testGetFromLocationName_badInput() {
GeocodeListener listener = mock(GeocodeListener.class);
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index 5f9aa09c891..14ebd28d08e 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -158,10 +158,10 @@ public class CodecInfoTest {
.noneMatch(x -> x == COLOR_FormatSurface));
}
- // For devices launching with Android T, if a codec supports an HDR profile, it must
- // advertise P010 support
+ // For devices launching with Android T, if a codec supports an HDR profile and device
+ // supports HDR display, it must advertise P010 support
int[] HdrProfileArray = mProfileHdrMap.get(mMediaType);
- if (FIRST_SDK_IS_AT_LEAST_T && HdrProfileArray != null) {
+ if (VNDK_IS_AT_LEAST_T && HdrProfileArray != null && DISPLAY_HDR_TYPES.length > 0) {
for (CodecProfileLevel pl : caps.profileLevels) {
if (IntStream.of(HdrProfileArray).anyMatch(x -> x == pl.profile)) {
assertFalse(mCodecInfo.getName() + " supports HDR profile " + pl.profile + "," +
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 327fb9cf6c9..d3fd2921d5a 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assume.assumeTrue;
+import android.hardware.camera2.CameraMetadata;
import android.media.MediaFormat;
import android.os.Build;
@@ -849,7 +850,493 @@ public class PerformanceClassEvaluator {
}
}
- private <R extends Requirement> R addRequirement(R req) {
+ public static class PrimaryCameraRequirement extends Requirement {
+ private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000;
+ private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000;
+ private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000;
+ private static final String TAG = PrimaryCameraRequirement.class.getSimpleName();
+
+ private PrimaryCameraRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setPrimaryCameraSupported(boolean hasPrimaryCamera) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_AVAILABLE,
+ hasPrimaryCamera);
+ }
+
+ public void setResolution(long resolution) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_RESOLUTION,
+ resolution);
+ }
+
+ public void setVideoSizeReqSatisfied(boolean videoSizeReqSatisfied) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED,
+ videoSizeReqSatisfied);
+ }
+
+ public void setVideoFps(double videoFps) {
+ this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS, videoFps);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-1] MUST have a primary rear facing camera with a resolution of at
+ * least 12 megapixels supporting video capture at 4k@30fps
+ */
+ public static PrimaryCameraRequirement createRearPrimaryCamera() {
+ RequiredMeasurement<Boolean> hasPrimaryCamera = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_AVAILABLE)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Long> cameraResolution = RequiredMeasurement
+ .<Long>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_RESOLUTION)
+ .setPredicate(RequirementConstants.LONG_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.S, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION)
+ .build();
+
+ RequiredMeasurement<Boolean> videoSizeReqSatisfied = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Double> videoFps = RequiredMeasurement
+ .<Double>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS)
+ .setPredicate(RequirementConstants.DOUBLE_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.S, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 29.9)
+ .build();
+
+ return new PrimaryCameraRequirement(RequirementConstants.R7_5__H_1_1,
+ hasPrimaryCamera, cameraResolution, videoSizeReqSatisfied,
+ videoFps);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-2] MUST have a primary front facing camera with a resolution of
+ * at least 4 megapixels supporting video capture at 1080p@30fps.
+ */
+ public static PrimaryCameraRequirement createFrontPrimaryCamera() {
+ RequiredMeasurement<Boolean> hasPrimaryCamera = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_AVAILABLE)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Long> cameraResolution = RequiredMeasurement
+ .<Long>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_RESOLUTION)
+ .setPredicate(RequirementConstants.LONG_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.S, MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU,
+ MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION)
+ .build();
+
+ RequiredMeasurement<Boolean> videoSizeReqSatisfied = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, true)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ RequiredMeasurement<Double> videoFps = RequiredMeasurement
+ .<Double>builder()
+ .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS)
+ .setPredicate(RequirementConstants.DOUBLE_GTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.S, 29.9)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 29.9)
+ .build();
+
+ return new PrimaryCameraRequirement(RequirementConstants.R7_5__H_1_2,
+ hasPrimaryCamera, cameraResolution, videoSizeReqSatisfied,
+ videoFps);
+ }
+ }
+
+ public static class CameraTimestampSourceRequirement extends Requirement {
+ private static final String TAG = CameraTimestampSourceRequirement.class.getSimpleName();
+ private static final int TIMESTAMP_REALTIME =
+ CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME;
+
+ private CameraTimestampSourceRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearCameraTimestampSource(Integer timestampSource) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_TIMESTAMP_SOURCE,
+ timestampSource);
+ }
+
+ public void setFrontCameraTimestampSource(Integer timestampSource) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_TIMESTAMP_SOURCE,
+ timestampSource);
+ }
+ /**
+ * [2.2.7.2/7.5/H-1-4] MUST support CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME
+ * for both primary cameras.
+ */
+ public static CameraTimestampSourceRequirement createTimestampSourceReq() {
+ RequiredMeasurement<Integer> rearTimestampSource = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.REAR_CAMERA_TIMESTAMP_SOURCE)
+ .setPredicate(RequirementConstants.INTEGER_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.S, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TIMESTAMP_REALTIME)
+ .build();
+ RequiredMeasurement<Integer> frontTimestampSource = RequiredMeasurement
+ .<Integer>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_TIMESTAMP_SOURCE)
+ .setPredicate(RequirementConstants.INTEGER_EQ)
+ .addRequiredValue(Build.VERSION_CODES.R, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.S, TIMESTAMP_REALTIME)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TIMESTAMP_REALTIME)
+ .build();
+
+ return new CameraTimestampSourceRequirement(RequirementConstants.R7_5__H_1_4,
+ rearTimestampSource, frontTimestampSource);
+ }
+ }
+
+ public static class CameraLatencyRequirement extends Requirement {
+ private static final String TAG = CameraTimestampSourceRequirement.class.getSimpleName();
+
+ private CameraLatencyRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearCameraLatency(float latency) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_LATENCY, latency);
+ }
+
+ public void setFrontCameraLatency(float latency) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_LATENCY, latency);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-5] MUST have camera2 JPEG capture latency < 1000ms for 1080p resolution
+ * as measured by the CTS camera PerformanceTest under ITS lighting conditions
+ * (3000K) for both primary cameras.
+ */
+ public static CameraLatencyRequirement createJpegLatencyReq() {
+ RequiredMeasurement<Float> rearJpegLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.REAR_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1000.0f)
+ .build();
+ RequiredMeasurement<Float> frontJpegLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 1000.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1000.0f)
+ .build();
+
+ return new CameraLatencyRequirement(RequirementConstants.R7_5__H_1_5,
+ rearJpegLatency, frontJpegLatency);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-6] MUST have camera2 startup latency (open camera to first
+ * preview frame) < 600ms as measured by the CTS camera PerformanceTest under ITS lighting
+ * conditions (3000K) for both primary cameras.
+ */
+ public static CameraLatencyRequirement createLaunchLatencyReq() {
+ RequiredMeasurement<Float> rearLaunchLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.REAR_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 600.0f)
+ .build();
+ RequiredMeasurement<Float> frontLaunchLatency = RequiredMeasurement
+ .<Float>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_LATENCY)
+ .setPredicate(RequirementConstants.FLOAT_LTE)
+ .addRequiredValue(Build.VERSION_CODES.R, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.S, 600.0f)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 600.0f)
+ .build();
+
+ return new CameraLatencyRequirement(RequirementConstants.R7_5__H_1_6,
+ rearLaunchLatency, frontLaunchLatency);
+ }
+ }
+
+ public static class CameraRawRequirement extends Requirement {
+ private static final String TAG = CameraRawRequirement.class.getSimpleName();
+
+ private CameraRawRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearRawSupported(boolean rearRawSupported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_RAW_SUPPORTED,
+ rearRawSupported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-8] MUST support CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW and
+ * android.graphics.ImageFormat.RAW_SENSOR for the primary back camera.
+ */
+ public static CameraRawRequirement createRawReq() {
+ RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_RAW_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.S, true)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new CameraRawRequirement(RequirementConstants.R7_5__H_1_8, requirement);
+ }
+ }
+
+ public static class Camera240FpsRequirement extends Requirement {
+ private static final String TAG = Camera240FpsRequirement.class.getSimpleName();
+
+ private Camera240FpsRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRear240FpsSupported(boolean rear240FpsSupported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_240FPS_SUPPORTED,
+ rear240FpsSupported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-9] MUST have a rear-facing primary camera supporting 720p or 1080p @ 240fps.
+ */
+ public static Camera240FpsRequirement create240FpsReq() {
+ RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_240FPS_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new Camera240FpsRequirement(RequirementConstants.R7_5__H_1_9, requirement);
+ }
+ }
+
+ public static class UltraWideZoomRatioRequirement extends Requirement {
+ private static final String TAG =
+ UltraWideZoomRatioRequirement.class.getSimpleName();
+
+ private UltraWideZoomRatioRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearUltraWideZoomRatioReqMet(boolean ultrawideZoomRatioReqMet) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET,
+ ultrawideZoomRatioReqMet);
+ }
+
+ public void setFrontUltraWideZoomRatioReqMet(boolean ultrawideZoomRatioReqMet) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET,
+ ultrawideZoomRatioReqMet);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-10] MUST have min ZOOM_RATIO < 1.0 for the primary cameras if
+ * there is an ultrawide RGB camera facing the same direction.
+ */
+ public static UltraWideZoomRatioRequirement createUltrawideZoomRatioReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new UltraWideZoomRatioRequirement(RequirementConstants.R7_5__H_1_10,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public static class ConcurrentRearFrontRequirement extends Requirement {
+ private static final String TAG = ConcurrentRearFrontRequirement.class.getSimpleName();
+
+ private ConcurrentRearFrontRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setConcurrentRearFrontSupported(boolean concurrentRearFrontSupported) {
+ this.setMeasuredValue(RequirementConstants.CONCURRENT_REAR_FRONT_SUPPORTED,
+ concurrentRearFrontSupported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-11] MUST implement concurrent front-back streaming on primary cameras.
+ */
+ public static ConcurrentRearFrontRequirement createConcurrentRearFrontReq() {
+ RequiredMeasurement<Boolean> requirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.CONCURRENT_REAR_FRONT_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new ConcurrentRearFrontRequirement(RequirementConstants.R7_5__H_1_11,
+ requirement);
+ }
+ }
+
+ public static class PreviewStabilizationRequirement extends Requirement {
+ private static final String TAG =
+ PreviewStabilizationRequirement.class.getSimpleName();
+
+ private PreviewStabilizationRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearPreviewStabilizationSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED,
+ supported);
+ }
+
+ public void setFrontPreviewStabilizationSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED,
+ supported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-12] MUST support CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION
+ * for both primary front and primary back camera.
+ */
+ public static PreviewStabilizationRequirement createPreviewStabilizationReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new PreviewStabilizationRequirement(RequirementConstants.R7_5__H_1_12,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public static class LogicalMultiCameraRequirement extends Requirement {
+ private static final String TAG =
+ LogicalMultiCameraRequirement.class.getSimpleName();
+
+ private LogicalMultiCameraRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearLogicalMultiCameraReqMet(boolean reqMet) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET,
+ reqMet);
+ }
+
+ public void setFrontLogicalMultiCameraReqMet(boolean reqMet) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET,
+ reqMet);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-13] MUST support LOGICAL_MULTI_CAMERA capability for the primary
+ * cameras if there are greater than 1 RGB cameras facing the same direction.
+ */
+ public static LogicalMultiCameraRequirement createLogicalMultiCameraReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new LogicalMultiCameraRequirement(RequirementConstants.R7_5__H_1_13,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public static class StreamUseCaseRequirement extends Requirement {
+ private static final String TAG =
+ StreamUseCaseRequirement.class.getSimpleName();
+
+ private StreamUseCaseRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setRearStreamUseCaseSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.REAR_CAMERA_STREAM_USECASE_SUPPORTED,
+ supported);
+ }
+
+ public void setFrontStreamUseCaseSupported(boolean supported) {
+ this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_STREAM_USECASE_SUPPORTED,
+ supported);
+ }
+
+ /**
+ * [2.2.7.2/7.5/H-1-14] MUST support STREAM_USE_CASE capability for both primary
+ * front and primary back camera.
+ */
+ public static StreamUseCaseRequirement createStreamUseCaseReq() {
+ RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.REAR_CAMERA_STREAM_USECASE_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+ RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement
+ .<Boolean>builder()
+ .setId(RequirementConstants.FRONT_CAMERA_STREAM_USECASE_SUPPORTED)
+ .setPredicate(RequirementConstants.BOOLEAN_EQ)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true)
+ .build();
+
+ return new StreamUseCaseRequirement(RequirementConstants.R7_5__H_1_14,
+ rearRequirement, frontRequirement);
+ }
+ }
+
+ public <R extends Requirement> R addRequirement(R req) {
if (!this.mRequirements.add(req)) {
throw new IllegalStateException("Requirement " + req.id() + " already added");
}
@@ -1000,16 +1487,69 @@ public class PerformanceClassEvaluator {
return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_10());
}
+ public PrimaryCameraRequirement addPrimaryRearCameraReq() {
+ return this.addRequirement(PrimaryCameraRequirement.createRearPrimaryCamera());
+ }
+
+ public PrimaryCameraRequirement addPrimaryFrontCameraReq() {
+ return this.addRequirement(PrimaryCameraRequirement.createFrontPrimaryCamera());
+ }
+
+ public CameraTimestampSourceRequirement addR7_5__H_1_4() {
+ return this.addRequirement(CameraTimestampSourceRequirement.createTimestampSourceReq());
+ }
+
+ public CameraLatencyRequirement addR7_5__H_1_5() {
+ return this.addRequirement(CameraLatencyRequirement.createJpegLatencyReq());
+ }
+
+ public CameraLatencyRequirement addR7_5__H_1_6() {
+ return this.addRequirement(CameraLatencyRequirement.createLaunchLatencyReq());
+ }
+
+ public CameraRawRequirement addR7_5__H_1_8() {
+ return this.addRequirement(CameraRawRequirement.createRawReq());
+ }
+
+ public Camera240FpsRequirement addR7_5__H_1_9() {
+ return this.addRequirement(Camera240FpsRequirement.create240FpsReq());
+ }
+
+ public UltraWideZoomRatioRequirement addR7_5__H_1_10() {
+ return this.addRequirement(UltraWideZoomRatioRequirement.createUltrawideZoomRatioReq());
+ }
+
+ public ConcurrentRearFrontRequirement addR7_5__H_1_11() {
+ return this.addRequirement(ConcurrentRearFrontRequirement.createConcurrentRearFrontReq());
+ }
+
+ public PreviewStabilizationRequirement addR7_5__H_1_12() {
+ return this.addRequirement(PreviewStabilizationRequirement.createPreviewStabilizationReq());
+ }
+
+ public LogicalMultiCameraRequirement addR7_5__H_1_13() {
+ return this.addRequirement(LogicalMultiCameraRequirement.createLogicalMultiCameraReq());
+ }
+
+ public StreamUseCaseRequirement addR7_5__H_1_14() {
+ return this.addRequirement(StreamUseCaseRequirement.createStreamUseCaseReq());
+ }
+
public void submitAndCheck() {
- boolean perfClassMet = true;
- for (Requirement req: this.mRequirements) {
- perfClassMet &= req.writeLogAndCheck(this.mTestName);
- }
+ boolean perfClassMet = submit();
// check performance class
assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass());
assertThat(perfClassMet).isTrue();
+ }
+ public boolean submit() {
+ boolean perfClassMet = true;
+ for (Requirement req: this.mRequirements) {
+ perfClassMet &= req.writeLogAndCheck(this.mTestName);
+ }
this.mRequirements.clear(); // makes sure report isn't submitted twice
+ return perfClassMet;
}
+
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
index d93cb2e0a00..ad0d0d5694f 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -16,8 +16,6 @@
package android.mediapc.cts.common;
-import android.os.Build;
-
import java.util.function.BiPredicate;
public class RequirementConstants {
@@ -54,8 +52,13 @@ public class RequirementConstants {
public static final String R7_5__H_1_4 = "r7_5__h_1_4"; // 7.5/H-1-4
public static final String R7_5__H_1_5 = "r7_5__h_1_5"; // 7.5/H-1-5
public static final String R7_5__H_1_6 = "r7_5__h_1_6"; // 7.5/H-1-6
- public static final String R7_5__H_1_7 = "r7_5__h_1_7"; // 7.5/H-1-7
public static final String R7_5__H_1_8 = "r7_5__h_1_8"; // 7.5/H-1-8
+ public static final String R7_5__H_1_9 = "r7_5__h_1_9"; // 7.5/H-1-9
+ public static final String R7_5__H_1_10 = "r7_5__h_1_10"; // 7.5/H-1-10
+ public static final String R7_5__H_1_11 = "r7_5__h_1_11"; // 7.5/H-1-11
+ public static final String R7_5__H_1_12 = "r7_5__h_1_12"; // 7.5/H-1-12
+ public static final String R7_5__H_1_13 = "r7_5__h_1_13"; // 7.5/H-1-13
+ public static final String R7_5__H_1_14 = "r7_5__h_1_14"; // 7.5/H-1-14
public static final String R7_1_1_1__H_1_1 = "r7_1_1_1__h_1_1"; // 7.1.1.1/H-1-1
public static final String R7_1_1_3__H_1_1 = "r7_1_1_3__h_1_1"; // 7.1.1.3/H-1-1
public static final String R7_6_1__H_1_1 = "r7_6_1__h_1_1"; // 7.6.1/H-1-1
@@ -90,14 +93,50 @@ public class RequirementConstants {
public static final String NUM_CRYPTO_HW_SECURE_ALL_SUPPORT =
"number_crypto_hw_secure_all_support";
+ public static final String PRIMARY_CAMERA_AVAILABLE = "primary_camera_available";
+ public static final String PRIMARY_CAMERA_RESOLUTION = "primary_camera_resolution";
+ public static final String PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED =
+ "primary_camera_video_size_req_satisfied";
+ public static final String PRIMARY_CAMERA_VIDEO_FPS =
+ "primary_camera_video_fps";
+ public static final String REAR_CAMERA_HWL_LEVEL = "rear_primary_camera_hwl_level";
+ public static final String FRONT_CAMERA_HWL_LEVEL = "front_primary_camera_hwl_level";
+ public static final String REAR_CAMERA_TIMESTAMP_SOURCE =
+ "rear_primary_camera_timestamp_source";
+ public static final String FRONT_CAMERA_TIMESTAMP_SOURCE =
+ "front_primary_camera_timestamp_source";
+ public static final String REAR_CAMERA_LATENCY = "rear_camera_latency";
+ public static final String FRONT_CAMERA_LATENCY = "front_camera_latency";
+ public static final String REAR_CAMERA_RAW_SUPPORTED = "rear_camera_raw_supported";
+ public static final String REAR_CAMERA_240FPS_SUPPORTED = "rear_camera_240fps_supported";
+ public static final String REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET =
+ "rear_camera_ultrawide_zoom_req_met";
+ public static final String FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET =
+ "front_camera_ultrawide_zoom_req_met";
+ public static final String CONCURRENT_REAR_FRONT_SUPPORTED = "rear_front_concurrent_camera";
+ public static final String REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED =
+ "rear_camera_preview_stabilization_supported";
+ public static final String FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED =
+ "front_camera_preview_stabilization_supported";
+ public static final String REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET =
+ "rear_camera_logical_multi_camera_req_met";
+ public static final String FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET =
+ "front_camera_logical_multi_camera_req_met";
+ public static final String REAR_CAMERA_STREAM_USECASE_SUPPORTED =
+ "rear_camera_stream_usecase_supported";
+ public static final String FRONT_CAMERA_STREAM_USECASE_SUPPORTED =
+ "front_camera_stream_usecase_supported";
+
public enum Result {
NA, MET, UNMET
}
public static final BiPredicate<Long, Long> LONG_GTE = RequirementConstants.gte();
public static final BiPredicate<Long, Long> LONG_LTE = RequirementConstants.lte();
+ public static final BiPredicate<Float, Float> FLOAT_LTE = RequirementConstants.lte();
public static final BiPredicate<Integer, Integer> INTEGER_GTE = RequirementConstants.gte();
public static final BiPredicate<Integer, Integer> INTEGER_LTE = RequirementConstants.lte();
+ public static final BiPredicate<Integer, Integer> INTEGER_EQ = RequirementConstants.eq();
public static final BiPredicate<Double, Double> DOUBLE_EQ = RequirementConstants.eq();
public static final BiPredicate<Boolean, Boolean> BOOLEAN_EQ = RequirementConstants.eq();
public static final BiPredicate<Double, Double> DOUBLE_GTE = RequirementConstants.gte();
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
index ac03705a1a2..28a122b4521 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -73,16 +73,24 @@ public class Utils {
Context context = InstrumentationRegistry.getInstrumentation().getContext();
DisplayMetrics metrics = new DisplayMetrics();
- WindowManager windowManager = context.getSystemService(WindowManager.class);
- windowManager.getDefaultDisplay().getMetrics(metrics);
- DISPLAY_DPI = metrics.densityDpi;
- DISPLAY_LONG_PIXELS = Math.max(metrics.widthPixels, metrics.heightPixels);
- DISPLAY_SHORT_PIXELS = Math.min(metrics.widthPixels, metrics.heightPixels);
-
- ActivityManager activityManager = context.getSystemService(ActivityManager.class);
- ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
- activityManager.getMemoryInfo(memoryInfo);
- TOTAL_MEMORY_MB = memoryInfo.totalMem / 1024 / 1024;
+ // When used from ItsService, context will be null
+ if (context != null) {
+ WindowManager windowManager = context.getSystemService(WindowManager.class);
+ windowManager.getDefaultDisplay().getMetrics(metrics);
+ DISPLAY_DPI = metrics.densityDpi;
+ DISPLAY_LONG_PIXELS = Math.max(metrics.widthPixels, metrics.heightPixels);
+ DISPLAY_SHORT_PIXELS = Math.min(metrics.widthPixels, metrics.heightPixels);
+
+ ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+ ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
+ activityManager.getMemoryInfo(memoryInfo);
+ TOTAL_MEMORY_MB = memoryInfo.totalMem / 1024 / 1024;
+ } else {
+ DISPLAY_DPI = 0;
+ DISPLAY_LONG_PIXELS = 0;
+ DISPLAY_SHORT_PIXELS = 0;
+ TOTAL_MEMORY_MB = 0;
+ }
}
/**
diff --git a/tests/tests/assist/common/src/android/assist/common/Utils.java b/tests/tests/assist/common/src/android/assist/common/Utils.java
index 0ffcb271093..98e857689cf 100755
--- a/tests/tests/assist/common/src/android/assist/common/Utils.java
+++ b/tests/tests/assist/common/src/android/assist/common/Utils.java
@@ -56,6 +56,7 @@ public class Utils {
public static final String COMPARE_SCREENSHOT_KEY = "compare_screenshot";
public static final String DISPLAY_WIDTH_KEY = "display_width";
public static final String DISPLAY_HEIGHT_KEY = "dislay_height";
+ public static final String DISPLAY_AREA_BOUNDS_KEY = "display_area_bounds";
public static final String SCROLL_X_POSITION = "scroll_x_position";
public static final String SCROLL_Y_POSITION = "scroll_y_position";
public static final String SHOW_SESSION_FLAGS_TO_SET = "show_session_flags_to_set";
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
index 7f35367333a..25c080b9c0c 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -56,6 +56,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
private int mCurColor;
private int mDisplayHeight;
private int mDisplayWidth;
+ private Rect mDisplayAreaBounds;
private BroadcastReceiver mReceiver;
private String mTestName;
private View mContentView;
@@ -106,7 +107,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
public void onPrepareShow(Bundle args, int showFlags) {
if (Utils.LIFECYCLE_NOUI.equals(args.getString(Utils.TESTCASE_TYPE, ""))) {
setUiEnabled(false);
- } else {
+ } else {
setUiEnabled(true);
}
}
@@ -122,6 +123,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
mCurColor = args.getInt(Utils.SCREENSHOT_COLOR_KEY);
mDisplayHeight = args.getInt(Utils.DISPLAY_HEIGHT_KEY);
mDisplayWidth = args.getInt(Utils.DISPLAY_WIDTH_KEY);
+ mDisplayAreaBounds = args.getParcelable(Utils.DISPLAY_AREA_BOUNDS_KEY);
mRemoteCallback = args.getParcelable(Utils.EXTRA_REMOTE_CALLBACK);
super.onShow(args, showFlags);
if (mContentView == null) return; // Happens when ui is not enabled.
@@ -256,6 +258,11 @@ public class MainInteractionSession extends VoiceInteractionSession {
int[] pixels = new int[size.x * size.y];
screenshot.getPixels(pixels, 0, size.x, 0, 0, size.x, size.y);
+ // screenshot bitmap contains the screenshot for the entire physical display. A single
+ // physical display could have multiple display area with different applications.
+ // Let's grab the region of the display area from the original screenshot.
+ Bitmap displayAreaScreenshot = Bitmap.createBitmap(screenshot, mDisplayAreaBounds.left,
+ mDisplayAreaBounds.top, mDisplayAreaBounds.width(), mDisplayAreaBounds.height());
int expectedColor = 0;
for (int pixel : pixels) {
// Check for roughly the same because there are rounding errors converting from the
@@ -267,7 +274,7 @@ public class MainInteractionSession extends VoiceInteractionSession {
}
}
- int pixelCount = screenshot.getWidth() * screenshot.getHeight();
+ int pixelCount = displayAreaScreenshot.getWidth() * displayAreaScreenshot.getHeight();
double colorRatio = (double) expectedColor / pixelCount;
Log.i(TAG, "the ratio is " + colorRatio);
return colorRatio >= 0.6;
diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
index 44a3109a740..c89119bdea1 100644
--- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
+++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java
@@ -35,9 +35,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.LocaleList;
import android.os.RemoteCallback;
import android.provider.Settings;
@@ -341,6 +341,8 @@ abstract class AssistTestBase {
Display.Mode dMode = mTestActivity.getWindowManager().getDefaultDisplay().getMode();
mDisplaySize = new Point(dMode.getPhysicalWidth(), dMode.getPhysicalHeight());
}
+ Rect bounds = mTestActivity.getWindowManager().getMaximumWindowMetrics().getBounds();
+ intent.putExtra(Utils.DISPLAY_AREA_BOUNDS_KEY, bounds);
intent.putExtra(Utils.DISPLAY_WIDTH_KEY, mDisplaySize.x);
intent.putExtra(Utils.DISPLAY_HEIGHT_KEY, mDisplaySize.y);
}
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
index 9a3075beee6..98189620bab 100644
--- a/tests/tests/bluetooth/AndroidTest.xml
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -33,6 +33,6 @@
<!-- Only run Cts Tests in MTS if the Bluetooth Mainline module is installed. -->
<object type="module_controller"
class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController">
- <option name="mainline-module-package-name" value="com.google.android.bluetooth" />
+ <option name="mainline-module-package-name" value="com.android.btservices" />
</object>
</configuration>
diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
index 49b72549b7e..8bd1bb8fb33 100644
--- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
+++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java
@@ -43,6 +43,9 @@ import android.content.res.Configuration;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.UiObjectNotFoundException;
+import android.support.test.uiautomator.UiScrollable;
+import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.util.Log;
@@ -140,7 +143,7 @@ public class CtsSyncAccountAccessOtherCertTestCases {
} catch (Throwable t) {
if (scrollUps < 10) {
// The notification we search for is below the fold, scroll to find it
- swipeUp(uiDevice);
+ scrollNotifications();
scrollUps++;
continue;
}
@@ -200,6 +203,18 @@ public class CtsSyncAccountAccessOtherCertTestCases {
50 /* numberOfSteps */);
}
+ private boolean scrollNotifications() {
+ UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
+ if (!scrollable.exists()) {
+ return false;
+ }
+ try {
+ return scrollable.scrollForward(50);
+ } catch (UiObjectNotFoundException e) {
+ return false;
+ }
+ }
+
private boolean isRunningInVR() {
final Context context = InstrumentationRegistry.getTargetContext();
return ((context.getResources().getConfiguration().uiMode &
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index 47662682d36..ef44528cbff 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -41,6 +41,7 @@ import android.media.MediaFormat;
import android.os.Build;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
+import android.os.SystemProperties;
import android.platform.test.annotations.LargeTest;
import android.platform.test.annotations.RequiresDevice;
import android.system.ErrnoException;
@@ -1012,6 +1013,9 @@ public class BitmapFactoryTest {
public void testDecode10BitHEIFTo10BitBitmap() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
+ assumeTrue(
+ "Test needs VNDK at least T.",
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
BitmapFactory.Options opt = new BitmapFactory.Options();
@@ -1028,6 +1032,9 @@ public class BitmapFactoryTest {
public void testDecode10BitHEIFTo8BitBitmap() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
+ assumeTrue(
+ "Test needs VNDK at least T.",
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
BitmapFactory.Options opt = new BitmapFactory.Options();
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index 6741c07ec21..b6689d87f54 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -49,6 +49,7 @@ import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.net.Uri;
import android.os.Build;
+import android.os.SystemProperties;
import android.util.DisplayMetrics;
import android.util.Size;
import android.util.TypedValue;
@@ -246,6 +247,9 @@ public class ImageDecoderTest {
public void testDecode10BitHeif() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
+ assumeTrue(
+ "Test needs VNDK at least T.",
+ SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
try {
diff --git a/tests/tests/media/common/src/android/media/cts/CodecState.java b/tests/tests/media/common/src/android/media/cts/CodecState.java
index 3565fc85e2b..4aa9db47312 100644
--- a/tests/tests/media/common/src/android/media/cts/CodecState.java
+++ b/tests/tests/media/common/src/android/media/cts/CodecState.java
@@ -169,13 +169,15 @@ public class CodecState {
}
}
- public void start() {
+ public void startCodec() {
mCodec.start();
mCodecInputBuffers = mCodec.getInputBuffers();
if (!mIsTunneled || mIsAudio) {
mCodecOutputBuffers = mCodec.getOutputBuffers();
}
+ }
+ public void play() {
if (mAudioTrack != null) {
mAudioTrack.play();
}
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java b/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
index 5e4df7f6c08..888cf235560 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
@@ -487,11 +487,13 @@ public class MediaCodecClearKeyPlayer implements MediaTimeProvider {
}
for (CodecState state : mVideoCodecStates.values()) {
- state.start();
+ state.startCodec();
+ state.play();
}
for (CodecState state : mAudioCodecStates.values()) {
- state.start();
+ state.startCodec();
+ state.play();
}
mDeltaTimeUs = -1;
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
index 0b495dd8fd9..879f561af6e 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java
@@ -44,11 +44,13 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
/** State the player starts in, before configuration. */
private static final int STATE_IDLE = 1;
/** State of the player during initial configuration. */
- private static final int STATE_PREPARING = 2;
+ private static final int STATE_PREPARED = 2;
+ /** State of the player after starting the codecs */
+ private static final int STATE_STARTED = 3;
/** State of the player during playback. */
- private static final int STATE_PLAYING = 3;
- /** State of the player when configured but not playing. */
- private static final int STATE_PAUSED = 4;
+ private static final int STATE_PLAYING = 4;
+ /** State of the player when playback is paused. */
+ private static final int STATE_PAUSED = 5;
private Boolean mThreadStarted = false;
private byte[] mSessionId;
@@ -194,7 +196,12 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return true;
}
+ // Creates the extractors, identifies tracks and formats, and then calls MediaCodec.configure
public boolean prepare() throws IOException {
+ if (mState != STATE_IDLE) {
+ throw new IllegalStateException("Expected STATE_IDLE, got " + mState);
+ }
+
if (null == mAudioExtractor) {
mAudioExtractor = new MediaExtractor();
if (null == mAudioExtractor) {
@@ -237,9 +244,7 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return false;
}
- synchronized (mState) {
- mState = STATE_PAUSED;
- }
+ mState = STATE_PREPARED;
return true;
}
@@ -306,70 +311,56 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return format.containsKey(key) ? format.getInteger(key) : 0;
}
- public boolean start() {
+ // Calls MediaCodec.start
+ public void startCodec() {
Log.d(TAG, "start");
- synchronized (mState) {
- if (mState == STATE_PLAYING || mState == STATE_PREPARING) {
- return true;
- } else if (mState == STATE_IDLE) {
- mState = STATE_PREPARING;
- return true;
- } else if (mState != STATE_PAUSED) {
- throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
- }
-
- for (CodecState state : mVideoCodecStates.values()) {
- state.start();
- }
+ if (mState != STATE_PREPARED) {
+ throw new IllegalStateException("Expected STATE_PREAPRED, got " + mState);
+ }
- for (CodecState state : mAudioCodecStates.values()) {
- state.start();
- }
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.startCodec();
+ }
- mDeltaTimeUs = -1;
- mState = STATE_PLAYING;
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.startCodec();
}
- return false;
+
+ mDeltaTimeUs = -1;
+ mState = STATE_STARTED;
}
- public void startWork() throws IOException, Exception {
- try {
- // Just change state from STATE_IDLE to STATE_PREPARING.
- start();
- // Extract media information from uri asset, and change state to STATE_PAUSED.
- prepare();
- // Start CodecState, and change from STATE_PAUSED to STATE_PLAYING.
- start();
- } catch (IOException e) {
- throw e;
+ // Starts the decoding threads and then starts AudioTrack playback
+ public void play() {
+ if (mState != STATE_STARTED) {
+ throw new IllegalStateException("Expected STATE_STARTED, got " + mState);
}
+ mState = STATE_PLAYING;
synchronized (mThreadStarted) {
mThreadStarted = true;
mThread.start();
}
- }
- public void startThread() {
- start();
- synchronized (mThreadStarted) {
- mThreadStarted = true;
- mThread.start();
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.play();
+ }
+
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.play();
}
}
- // Pauses the audio track
+ // Pauses playback by pausing the AudioTrack
public void pause() {
Log.d(TAG, "pause");
- synchronized (mState) {
- if (mState == STATE_PAUSED) {
- return;
- } else if (mState != STATE_PLAYING) {
- throw new IllegalStateException();
- }
+ if (mState != STATE_PLAYING) {
+ throw new IllegalStateException("Expected STATE_PLAYING, got " + mState);
+ }
+ synchronized (mState) {
for (CodecState state : mVideoCodecStates.values()) {
state.pause();
}
@@ -382,43 +373,60 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
}
}
- public void flush() {
- Log.d(TAG, "flush");
+ // Resume playback when paused
+ public void resume() {
+ Log.d(TAG, "resume");
+
+ if (mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
+ }
synchronized (mState) {
- if (mState == STATE_PLAYING || mState == STATE_PREPARING) {
- return;
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.play();
}
for (CodecState state : mAudioCodecStates.values()) {
- state.flush();
+ state.play();
}
- for (CodecState state : mVideoCodecStates.values()) {
- state.flush();
- }
+ mState = STATE_PLAYING;
}
}
- /** Seek all tracks to their very beginning.
+ public void flush() {
+ Log.d(TAG, "flush");
+
+ if (mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
+ }
+
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.flush();
+ }
+
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.flush();
+ }
+ }
+
+ /** Seek all tracks to the first sample time.
*
* @param presentationTimeOffsetUs The offset for the presentation time to start at.
* @throws IllegalStateException if the player is not paused
*/
public void seekToBeginning(long presentationTimeOffsetUs) {
Log.d(TAG, "seekToBeginning");
- synchronized (mState) {
- if (mState != STATE_PAUSED) {
- throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
- }
+ if (mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
+ }
- for (CodecState state : mVideoCodecStates.values()) {
- state.seekToBeginning(presentationTimeOffsetUs);
- }
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.seekToBeginning(presentationTimeOffsetUs);
+ }
- for (CodecState state : mAudioCodecStates.values()) {
- state.seekToBeginning(presentationTimeOffsetUs);
- }
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.seekToBeginning(presentationTimeOffsetUs);
}
}
@@ -426,53 +434,50 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
* Enables or disables looping. Should be called after {@link #prepare()}.
*/
public void setLoopEnabled(boolean enabled) {
- synchronized (mState) {
- if (mVideoCodecStates != null) {
- for (CodecState state : mVideoCodecStates.values()) {
- state.setLoopEnabled(enabled);
- }
- }
+ if (mState != STATE_PREPARED) {
+ throw new IllegalStateException("Expected STATE_PREPARED, got " + mState);
+ }
- if (mAudioCodecStates != null) {
- for (CodecState state : mAudioCodecStates.values()) {
- state.setLoopEnabled(enabled);
- }
- }
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.setLoopEnabled(enabled);
+ }
+
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.setLoopEnabled(enabled);
}
}
public void reset() {
- synchronized (mState) {
- if (mState == STATE_PLAYING) {
- pause();
- }
- if (mVideoCodecStates != null) {
- for (CodecState state : mVideoCodecStates.values()) {
- state.release();
- }
- mVideoCodecStates = null;
- }
-
- if (mAudioCodecStates != null) {
- for (CodecState state : mAudioCodecStates.values()) {
- state.release();
- }
- mAudioCodecStates = null;
+ if (mState == STATE_PLAYING) {
+ pause();
+ }
+ if (mVideoCodecStates != null) {
+ for (CodecState state : mVideoCodecStates.values()) {
+ state.release();
}
+ mVideoCodecStates = null;
+ }
- if (mAudioExtractor != null) {
- mAudioExtractor.release();
- mAudioExtractor = null;
+ if (mAudioCodecStates != null) {
+ for (CodecState state : mAudioCodecStates.values()) {
+ state.release();
}
+ mAudioCodecStates = null;
+ }
- if (mVideoExtractor != null) {
- mVideoExtractor.release();
- mVideoExtractor = null;
- }
+ if (mAudioExtractor != null) {
+ mAudioExtractor.release();
+ mAudioExtractor = null;
+ }
- mDurationUs = -1;
- mState = STATE_IDLE;
+ if (mVideoExtractor != null) {
+ mVideoExtractor.release();
+ mVideoExtractor = null;
}
+
+ mDurationUs = -1;
+ mState = STATE_IDLE;
+
synchronized (mThreadStarted) {
mThreadStarted = false;
}
@@ -607,6 +612,14 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
return mVideoCodecStates.get(0).getVideoTimeUs();
}
+ public long getVideoSystemTimeNs() {
+ if (mVideoCodecStates == null || mVideoCodecStates.get(0) == null) {
+ return -1;
+ }
+ return mVideoCodecStates.get(0).getVideoTimeUs();
+
+ }
+
/**
* Returns the ordered list of video frame timestamps rendered in tunnel mode.
*
@@ -643,39 +656,23 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider {
public Long queueOneVideoFrame() {
Log.d(TAG, "queueOneVideoFrame");
- if (mVideoCodecStates == null || !(mState == STATE_PLAYING || mState == STATE_PAUSED)) {
- return null;
+ if (mState != STATE_STARTED && mState != STATE_PAUSED) {
+ throw new IllegalStateException("Expected STARTED or PAUSED, got " + mState);
}
Long result = null;
- for (CodecState state : mVideoCodecStates.values()) {
- Long timestamp = state.doSomeWork(true /* mustWait */);
- if (timestamp != null) {
- result = timestamp;
+ if (mVideoCodecStates != null) {
+ for (CodecState state : mVideoCodecStates.values()) {
+ Long timestamp = state.doSomeWork(true /* mustWait */);
+ if (timestamp != null) {
+ result = timestamp;
+ }
}
}
return result;
}
/**
- * Resume playback when paused.
- *
- * @throws IllegalStateException if playback is not paused or if there is no configured audio
- * track.
- */
- public void resume() {
- Log.d(TAG, "resume");
- if (mAudioTrackState == null) {
- throw new IllegalStateException("Resuming playback with no audio track");
- }
- if (mState != STATE_PAUSED) {
- throw new IllegalStateException("Expected STATE_PAUSED, got " + mState);
- }
- mAudioTrackState.playAudioTrack();
- mState = STATE_PLAYING;
- }
-
- /**
* Configure video peek for the video codecs attached to the player.
*/
public void setVideoPeek(boolean enable) {
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
index 145cfaf96fd..c9823760671 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecodeAccuracyTest.java
@@ -25,7 +25,6 @@ import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.media.MediaFormat;
-import android.media.cts.MediaCodecTunneledPlayer;
import android.media.cts.MediaHeavyPresubmitTest;
import android.media.cts.TestArgs;
import android.os.Environment;
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
index a424edbd8c5..9926f04378f 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java
@@ -73,6 +73,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SdkSuppress;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.DynamicConfigDeviceSide;
@@ -124,10 +125,10 @@ public class DecoderTest extends MediaTestBase {
private static final int CONFIG_MODE_NONE = 0;
private static final int CONFIG_MODE_QUEUE = 1;
- private static final int CODEC_ALL = 0; // All codecs must support
- private static final int CODEC_ANY = 1; // At least one codec must support
- private static final int CODEC_DEFAULT = 2; // Default codec must support
- private static final int CODEC_OPTIONAL = 3; // Codec support is optional
+ public static final int CODEC_ALL = 0; // All codecs must support
+ public static final int CODEC_ANY = 1; // At least one codec must support
+ public static final int CODEC_DEFAULT = 2; // Default codec must support
+ public static final int CODEC_OPTIONAL = 3; // Codec support is optional
short[] mMasterBuffer;
static final String mInpPrefix = WorkDir.getMediaDirString();
@@ -141,8 +142,6 @@ public class DecoderTest extends MediaTestBase {
private DisplayManager mDisplayManager;
static final Map<String, String> sDefaultDecoders = new HashMap<>();
- private static boolean mIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
-
protected static AssetFileDescriptor getAssetFileDescriptorFor(final String res)
throws FileNotFoundException {
File inpFile = new File(mInpPrefix + res);
@@ -3884,11 +3883,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -3921,8 +3919,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback mode with HEVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoPlaybackHevc() throws Exception {
tunneledVideoPlayback(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
@@ -3931,8 +3929,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback mode with AVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoPlaybackAvc() throws Exception {
tunneledVideoPlayback(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
@@ -3941,8 +3939,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback mode with VP9 if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoPlaybackVp9() throws Exception {
tunneledVideoPlayback(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
@@ -3966,11 +3964,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -3990,8 +3987,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback flush with HEVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoFlushHevc() throws Exception {
testTunneledVideoFlush(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
@@ -4000,8 +3997,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback flush with AVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoFlushAvc() throws Exception {
testTunneledVideoFlush(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
@@ -4010,23 +4007,19 @@ public class DecoderTest extends MediaTestBase {
/**
* Test tunneled video playback flush with VP9 if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledVideoFlushVp9() throws Exception {
testTunneledVideoFlush(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
/**
- * Test tunneled video peek renders the first frame when on
+ * Test that the first frame is rendered when video peek is on in tunneled mode.
*
* TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
*/
private void testTunneledVideoPeekOn(String mimeType, String videoName) throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledVideoPeekOn requires Android 12")) {
- return;
- }
-
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4040,9 +4033,8 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
- mMediaCodecPlayer.start();
+ mMediaCodecPlayer.startCodec();
mMediaCodecPlayer.setVideoPeek(true); // Enable video peek
// Assert that onFirstTunnelFrameReady is called
@@ -4061,30 +4053,30 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test tunneled video peek with HEVC renders the first frame when on
+ * Test that the first frame is rendered when video peek is on for HEVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOnHevc() throws Exception {
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled video peek with AVC renders the first frame when on
+ * Test that the first frame is rendered when video peek is on for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOnAvc() throws Exception {
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled video peek with VP9 renders the first frame when on
+ * Test that the first frame is rendered when video peek is on for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOnVp9() throws Exception {
testTunneledVideoPeekOn(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
@@ -4092,15 +4084,11 @@ public class DecoderTest extends MediaTestBase {
/**
- * Test tunneled video peek doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on in tunneled mode.
*
* TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
*/
private void testTunneledVideoPeekOff(String mimeType, String videoName) throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledVideoPeekOff requires Android 12")) {
- return;
- }
-
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4114,9 +4102,8 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
- mMediaCodecPlayer.start();
+ mMediaCodecPlayer.startCodec();
mMediaCodecPlayer.setVideoPeek(false); // Disable video peek
// Assert that onFirstTunnelFrameReady is called
@@ -4142,75 +4129,40 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test tunneled video peek with HEVC doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on for HEC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOffHevc() throws Exception {
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled video peek with AVC doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOffAvc() throws Exception {
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled video peek with VP9 doesn't render the first frame when off and then turned on
+ * Test that peek off doesn't render the first frame until turned on for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodec#PARAMETER_KEY_TUNNEL_PEEK"})
public void testTunneledVideoPeekOffVp9() throws Exception {
testTunneledVideoPeekOff(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
- /**
- * Test tunneled audio PTS gaps with HEVC if supported.
- * If there exist PTS Gaps in AudioTrack playback, the framePosition returned by
- * AudioTrack#getTimestamp must not advance for any silent frames rendered to fill the
- * gap.
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioPtsGapsHevc() throws Exception {
- testTunneledAudioPtsGaps(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test tunneled audio PTS gaps with AVC if supported
- * If there exist PTS Gaps in AudioTrack playback, the framePosition returned by
- * AudioTrack#getTimestamp must not advance for any silent frames rendered to fill the
- * gap.
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioPtsGapsAvc() throws Exception {
- testTunneledAudioPtsGaps(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test tunneled audio PTS gaps with VP9 if supported
- * If there exist PTS Gaps in AudioTrack playback, the framePosition returned by
- * AudioTrack#getTimestamp must not advance for any silent frames rendered to fill the
- * gap.
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioPtsGapsVp9() throws Exception {
- testTunneledAudioPtsGaps(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- private void testTunneledAudioPtsGaps(String mimeType, String fileName) throws Exception {
+ /**
+ * Test that audio timestamps don't progress during audio PTS gaps in tunneled mode.
+ */
+ private void testTunneledAudioProgressWithPtsGaps(String mimeType, String fileName)
+ throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4224,11 +4176,10 @@ public class DecoderTest extends MediaTestBase {
final Uri mediaUri = Uri.fromFile(new File(mInpPrefix, fileName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4291,37 +4242,40 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test tunneled audioTimestamp progress with underrun, with HEVC if supported
+ * Test that audio timestamps don't progress during audio PTS gaps for HEVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
- public void testTunneledAudioTimestampProgressWithUnderrunHevc() throws Exception {
- testTunneledAudioTimestampProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPtsGapsHevc() throws Exception {
+ testTunneledAudioProgressWithPtsGaps(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled audioTimestamp progress with underrun, with AVC if supported.
+ * Test that audio timestamps don't progress during audio PTS gaps for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
- public void testTunneledAudioTimestampProgressWithUnderrunAvc() throws Exception {
- testTunneledAudioTimestampProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_AVC,
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPtsGapsAvc() throws Exception {
+ testTunneledAudioProgressWithPtsGaps(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled audioTimestamp progress with underrun, with VP9 if supported.
+ * Test that audio timestamps don't progress during audio PTS gaps for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
- public void testTunneledAudioTimestampProgressWithUnderrunVp9() throws Exception {
- testTunneledAudioTimestampProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_VP9,
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPtsGapsVp9() throws Exception {
+ testTunneledAudioProgressWithPtsGaps(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
- private void testTunneledAudioTimestampProgressWithUnderrun(
- String mimeType, String fileName) throws Exception {
+ /**
+ * Test that audio timestamps stop progressing during underrun in tunneled mode.
+ */
+ private void testTunneledAudioProgressWithUnderrun(String mimeType, String fileName)
+ throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4335,11 +4289,10 @@ public class DecoderTest extends MediaTestBase {
final Uri mediaUri = Uri.fromFile(new File(mInpPrefix, fileName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4380,9 +4333,39 @@ public class DecoderTest extends MediaTestBase {
}
/**
- * Test accurate video rendering after a video MediaCodec flush.
+ * Test that audio timestamps stop progressing during underrun for HEVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithUnderrunHevc() throws Exception {
+ testTunneledAudioProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during underrun for AVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithUnderrunAvc() throws Exception {
+ testTunneledAudioProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_AVC,
+ "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during underrun for VP9 in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithUnderrunVp9() throws Exception {
+ testTunneledAudioProgressWithUnderrun(MediaFormat.MIMETYPE_VIDEO_VP9,
+ "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
+ }
+
+ /**
+ * Test accurate video rendering after a flush in tunneled mode.
*
- * On some devices, queuing content when the player is paused, then triggering a flush, then
+ * Test On some devices, queuing content when the player is paused, then triggering a flush, then
* queuing more content does not behave as expected. The queued content gets lost and the flush
* is really only applied once playback has resumed.
*
@@ -4390,10 +4373,6 @@ public class DecoderTest extends MediaTestBase {
*/
private void testTunneledAccurateVideoFlush(String mimeType, String videoName)
throws Exception {
- if (!MediaUtils.check(mIsAtLeastS, "testTunneledAccurateVideoFlush requires Android 12")) {
- return;
- }
-
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4414,15 +4393,14 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
// Video peek might interfere with the test: we want to ensure that queuing more data during
// a pause does not cause displaying more video frames, which is precisely what video peek
// does.
mMediaCodecPlayer.setVideoPeek(false);
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4434,22 +4412,72 @@ public class DecoderTest extends MediaTestBase {
assertNotEquals("Audio timestamp has a zero frame position",
mMediaCodecPlayer.getTimestamp().framePosition, 0);
+ // Allow some time for playback to commence
+ Thread.sleep(500);
+
// Pause playback
mMediaCodecPlayer.pause();
- // Allow some time for playback to pause
- Thread.sleep(maxDrainTimeMs);
-
- // Verify that playback has paused
- long pauseAudioFramePositionUs = mMediaCodecPlayer.getTimestamp().framePosition;
- long pauseVideoPositionUs = mMediaCodecPlayer.getVideoTimeUs();
- Thread.sleep(maxDrainTimeMs);
- assertEquals(mMediaCodecPlayer.getTimestamp().framePosition, pauseAudioFramePositionUs);
+
+ // Wait for audio to pause
+ AudioTimestamp pauseAudioTimestamp;
+ {
+ AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ // If it takes longer to pause, the UX won't feel responsive to the user
+ int audioPauseTimeoutMs = 250;
+ assertTrue(String.format("No audio pause after %d milliseconds",
+ audioPauseTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < audioPauseTimeoutMs);
+ pauseAudioTimestamp = currentAudioTimestamp;
+ Thread.sleep(50);
+ currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ } while (currentAudioTimestamp.framePosition != pauseAudioTimestamp.framePosition);
+ }
+ long pauseAudioSystemTimeMs = pauseAudioTimestamp.nanoTime / 1000 / 1000;
+
+ // Wait for video to pause
+ long pauseVideoSystemTimeNs;
+ long pauseVideoPositionUs;
+ {
+ long currentVideoSystemTimeNs = mMediaCodecPlayer.getCurrentRenderedSystemTimeNano();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int videoUnderrunTimeoutMs = 2000;
+ assertTrue(String.format("No video pause after %d milliseconds",
+ videoUnderrunTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs);
+ pauseVideoSystemTimeNs = currentVideoSystemTimeNs;
+ Thread.sleep(250); // onFrameRendered can get delayed in the Framework
+ currentVideoSystemTimeNs = mMediaCodecPlayer.getCurrentRenderedSystemTimeNano();
+ } while (currentVideoSystemTimeNs != pauseVideoSystemTimeNs);
+ pauseVideoPositionUs = mMediaCodecPlayer.getVideoTimeUs();
+ }
+ long pauseVideoSystemTimeMs = pauseVideoSystemTimeNs / 1000 / 1000;
+
+ // Video should not continue running for a long period of time after audio pauses
+ long pauseVideoToleranceMs = 500;
+ assertTrue(String.format(
+ "Video ran %d milliseconds longer than audio (video:%d audio:%d)",
+ pauseVideoToleranceMs, pauseVideoSystemTimeMs, pauseAudioSystemTimeMs),
+ pauseVideoSystemTimeMs - pauseAudioSystemTimeMs < pauseVideoToleranceMs);
+
+ // Verify that playback stays paused
+ Thread.sleep(500);
+ assertEquals(mMediaCodecPlayer.getTimestamp().framePosition, pauseAudioTimestamp.framePosition);
+ assertEquals(mMediaCodecPlayer.getCurrentRenderedSystemTimeNano(), pauseVideoSystemTimeNs);
assertEquals(mMediaCodecPlayer.getVideoTimeUs(), pauseVideoPositionUs);
- // Verify audio and video are in sync
- assertTrue(String.format("Video pts (%d) is ahead of audio pts (%d)",
- pauseVideoPositionUs, pauseAudioFramePositionUs),
- pauseVideoPositionUs <= pauseAudioFramePositionUs);
+ // Verify audio and video are roughly in sync when paused
+ long framePosition = mMediaCodecPlayer.getTimestamp().framePosition;
+ long playbackRateFps = mMediaCodecPlayer.getAudioTrack().getPlaybackRate();
+ long pauseAudioPositionMs = pauseAudioTimestamp.framePosition * 1000 / playbackRateFps;
+ long pauseVideoPositionMs = pauseVideoPositionUs / 1000;
+ long deltaMs = pauseVideoPositionMs - pauseAudioPositionMs;
+ assertTrue(String.format(
+ "Video is %d milliseconds out of sync from audio (video:%d audio:%d)",
+ deltaMs, pauseVideoPositionMs, pauseAudioPositionMs),
+ deltaMs > -80 && deltaMs < pauseVideoToleranceMs);
// Flush both audio and video pipelines
mMediaCodecPlayer.flush();
@@ -4493,8 +4521,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test accurate video rendering after a video MediaCodec flush with HEVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAccurateVideoFlushHevc() throws Exception {
testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_HEVC,
"video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
@@ -4503,8 +4531,8 @@ public class DecoderTest extends MediaTestBase {
/**
* Test accurate video rendering after a video MediaCodec flush with AVC if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAccurateVideoFlushAvc() throws Exception {
testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
@@ -4513,49 +4541,18 @@ public class DecoderTest extends MediaTestBase {
/**
* Test accurate video rendering after a video MediaCodec flush with VP9 if supported
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAccurateVideoFlushVp9() throws Exception {
testTunneledAccurateVideoFlush(MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
/**
- * Test tunneled audioTimestamp progress with HEVC if supported
+ * Test that audio timestamps stop progressing during pause in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioTimestampProgressHevc() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
- }
-
- /**
- * Test tunneled audioTimestamp progress with AVC if supported
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioTimestampProgressAvc() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
- }
-
- /**
- * Test tunneled audioTimestamp progress with VP9 if supported
- */
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
- @Test
- public void testTunneledAudioTimestampProgressVp9() throws Exception {
- testTunneledAudioTimestampProgress(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
- }
-
- /**
- * Test that AudioTrack timestamps don't advance after pause.
- */
- private void
- testTunneledAudioTimestampProgress(String mimeType, String videoName) throws Exception
- {
+ private void testTunneledAudioProgressWithPause(String mimeType, String videoName)
+ throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
return;
@@ -4568,11 +4565,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4604,14 +4600,43 @@ public class DecoderTest extends MediaTestBase {
assertEquals(audioTimestampAfterPause.nanoTime, mMediaCodecPlayer.getTimestamp().nanoTime);
}
+
/**
- * Test tunneled audio underrun, if supported.
- *
- * Underrun test with lower pts after underrun.
+ * Test that audio timestamps stop progressing during pause for HEVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPauseHevc() throws Exception {
+ testTunneledAudioProgressWithPause(MediaFormat.MIMETYPE_VIDEO_HEVC,
+ "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during pause for AVC in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPauseAvc() throws Exception {
+ testTunneledAudioProgressWithPause(MediaFormat.MIMETYPE_VIDEO_AVC,
+ "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
+ }
+
+ /**
+ * Test that audio timestamps stop progressing during pause for VP9 in tunneled mode.
+ */
+ @Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
+ public void testTunneledAudioProgressWithPauseVp9() throws Exception {
+ testTunneledAudioProgressWithPause(MediaFormat.MIMETYPE_VIDEO_VP9,
+ "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
+ }
+
+ /**
+ * Test that audio underrun pauses video and resumes in-sync in tunneled mode.
*
* TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content
*/
- private void tunneledAudioUnderrun(String mimeType, String videoName, int frameRate)
+ private void tunneledAudioUnderrun(String mimeType, String videoName)
throws Exception {
if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback),
"No tunneled video playback codec found for MIME " + mimeType)) {
@@ -4625,11 +4650,10 @@ public class DecoderTest extends MediaTestBase {
Uri mediaUri = Uri.fromFile(new File(mInpPrefix, videoName));
mMediaCodecPlayer.setAudioDataSource(mediaUri, null);
mMediaCodecPlayer.setVideoDataSource(mediaUri, null);
- assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start());
assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare());
+ mMediaCodecPlayer.startCodec();
- // Starts video playback
- mMediaCodecPlayer.startThread();
+ mMediaCodecPlayer.play();
sleepUntil(() ->
mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP
&& mMediaCodecPlayer.getTimestamp() != null
@@ -4645,36 +4669,39 @@ public class DecoderTest extends MediaTestBase {
mMediaCodecPlayer.simulateAudioUnderrun(true);
// Wait for audio underrun
- final int audioUnderrunTimeoutMs = 1000; // Arbitrary upper time limit on loop time duration
- long startTimeMs = System.currentTimeMillis();
- AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
AudioTimestamp underrunAudioTimestamp;
- do {
- assertTrue(String.format("No audio underrun after %d milliseconds",
- System.currentTimeMillis() - startTimeMs),
- System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
- underrunAudioTimestamp = currentAudioTimestamp;
- Thread.sleep(50);
- currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
- } while (currentAudioTimestamp.framePosition != underrunAudioTimestamp.framePosition);
-
+ {
+ AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int audioUnderrunTimeoutMs = 1000;
+ assertTrue(String.format("No audio underrun after %d milliseconds",
+ System.currentTimeMillis() - startTimeMs),
+ System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs);
+ underrunAudioTimestamp = currentAudioTimestamp;
+ Thread.sleep(50);
+ currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ } while (currentAudioTimestamp.framePosition != underrunAudioTimestamp.framePosition);
+ }
- // Wait until video playback stalls
- final int videoUnderrunTimeoutMs = 1000;
- startTimeMs = System.currentTimeMillis();
- long currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- long underrunVideoTimeUs = -1;
- do {
- assertTrue(String.format("No video underrun after %d milliseconds",
- videoUnderrunTimeoutMs),
- System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs);
- underrunVideoTimeUs = currentVideoTimeUs;
- Thread.sleep(50);
- currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- } while (currentVideoTimeUs != underrunVideoTimeUs);
+ // Wait until video playback pauses due to underrunning audio
+ long pausedVideoTimeUs = -1;
+ {
+ long currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int videoPauseTimeoutMs = 2000;
+ assertTrue(String.format("No video pause after %d milliseconds",
+ videoPauseTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < videoPauseTimeoutMs);
+ pausedVideoTimeUs = currentVideoTimeUs;
+ Thread.sleep(250); // onFrameRendered messages can get delayed in the Framework
+ currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ } while (currentVideoTimeUs != pausedVideoTimeUs);
+ }
- // Retrieve index for the video rendered frame at the time of underrun
- int underrunVideoRenderedTimestampIndex =
+ // Retrieve index for the video rendered frame at the time of video pausing
+ int pausedVideoRenderedTimestampIndex =
mMediaCodecPlayer.getRenderedVideoFrameTimestampList().size() - 1;
// Resume audio buffering with a negative offset, in order to simulate a desynchronisation.
@@ -4683,35 +4710,38 @@ public class DecoderTest extends MediaTestBase {
mMediaCodecPlayer.simulateAudioUnderrun(false);
// Wait until audio playback resumes
- final int audioResumeTimeoutMs = 1000;
- startTimeMs = System.currentTimeMillis();
- currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
AudioTimestamp postResumeAudioTimestamp;
- do {
- assertTrue(String.format("Audio has not resumed after %d milliseconds",
- audioResumeTimeoutMs),
- System.currentTimeMillis() - startTimeMs < audioResumeTimeoutMs);
- postResumeAudioTimestamp = currentAudioTimestamp;
- Thread.sleep(50);
- currentAudioTimestamp = mMediaCodecPlayer.getTimestamp();
- } while(currentAudioTimestamp.framePosition == postResumeAudioTimestamp.framePosition);
+ {
+ AudioTimestamp previousAudioTimestamp;
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int audioResumeTimeoutMs = 1000;
+ assertTrue(String.format("Audio has not resumed after %d milliseconds",
+ audioResumeTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < audioResumeTimeoutMs);
+ previousAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ Thread.sleep(50);
+ postResumeAudioTimestamp = mMediaCodecPlayer.getTimestamp();
+ } while (postResumeAudioTimestamp.framePosition == previousAudioTimestamp.framePosition);
+ }
// Now that audio playback has resumed, wait until video playback resumes
- // We care about the timestamp of the first output frame, rather than the exact time the
- // video resumed, which is why we only start polling after we are sure audio playback has
- // resumed.
- final int videoResumeTimeoutMs = 1000;
- startTimeMs = System.currentTimeMillis();
- currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- long resumeVideoTimeUs = -1;
- do {
- assertTrue(String.format("Video has not resumed after %d milliseconds",
- videoResumeTimeoutMs),
- System.currentTimeMillis() - startTimeMs < videoResumeTimeoutMs);
- resumeVideoTimeUs = currentVideoTimeUs;
- Thread.sleep(50);
- currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
- } while (currentVideoTimeUs == resumeVideoTimeUs);
+ {
+ // We actually don't care about trying to capture the exact time video resumed, because
+ // we can just look at the historical list of rendered video timestamps
+ long postResumeVideoTimeUs;
+ long previousVideoTimeUs;
+ long startTimeMs = System.currentTimeMillis();
+ do {
+ int videoResumeTimeoutMs = 2000;
+ assertTrue(String.format("Video has not resumed after %d milliseconds",
+ videoResumeTimeoutMs),
+ System.currentTimeMillis() - startTimeMs < videoResumeTimeoutMs);
+ previousVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ Thread.sleep(50);
+ postResumeVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs();
+ } while (postResumeVideoTimeUs == previousVideoTimeUs);
+ }
// The system time when rendering the first audio frame after the resume
long playbackRateFps = mMediaCodecPlayer.getAudioTrack().getPlaybackRate();
@@ -4721,52 +4751,74 @@ public class DecoderTest extends MediaTestBase {
long resumeAudioSystemTimeNs = postResumeAudioTimestamp.nanoTime - (long) elapsedTimeNs;
long resumeAudioSystemTimeMs = resumeAudioSystemTimeNs / 1000 / 1000;
- // The system time when rendering the first video frame after the resume
+ // The system time when rendering the first video frame after video playback resumes
long resumeVideoSystemTimeMs = mMediaCodecPlayer.getRenderedVideoFrameSystemTimeList()
- .get(underrunVideoRenderedTimestampIndex + 1) / 1000 / 1000;
+ .get(pausedVideoRenderedTimestampIndex + 1) / 1000 / 1000;
- // Verify that audio and video are in-sync after resume time
+ // Verify that video resumes in a reasonable amount of time after audio resumes
// Note: Because a -100ms PTS gap is introduced, the video should resume 100ms later
resumeAudioSystemTimeMs += 100;
- long vsyncMs = 1000 / frameRate;
- long avSyncOffsetMs = resumeAudioSystemTimeMs - resumeVideoSystemTimeMs;
+ long resumeDeltaMs = resumeVideoSystemTimeMs - resumeAudioSystemTimeMs;
+ assertTrue(String.format("Video started %s milliseconds before audio resumed "
+ + "(video:%d audio:%d)", resumeDeltaMs * -1, resumeVideoSystemTimeMs,
+ resumeAudioSystemTimeMs),
+ resumeDeltaMs > 0); // video is expected to start after audio resumes
assertTrue(String.format(
- "Audio is %d milliseconds out of sync of video (audio:%d video:%d)",
- avSyncOffsetMs, resumeAudioSystemTimeMs, resumeVideoSystemTimeMs),
- Math.abs(avSyncOffsetMs) <= vsyncMs);
+ "Video started %d milliseconds after audio resumed (video:%d audio:%d)",
+ resumeDeltaMs, resumeVideoSystemTimeMs, resumeAudioSystemTimeMs),
+ resumeDeltaMs <= 600); // video starting 300ms after audio is barely noticeable
+
+ // Determine the system time of the audio frame that matches the presentation timestamp of
+ // the resumed video frame
+ long resumeVideoPresentationTimeUs = mMediaCodecPlayer.getRenderedVideoFrameTimestampList()
+ .get(pausedVideoRenderedTimestampIndex + 1);
+ long matchingAudioFramePosition = resumeVideoPresentationTimeUs * playbackRateFps / 1000 / 1000;
+ playedFrames = matchingAudioFramePosition - postResumeAudioTimestamp.framePosition;
+ elapsedTimeNs = playedFrames * (1000.0 * 1000.0 * 1000.0 / playbackRateFps);
+ long matchingAudioSystemTimeNs = postResumeAudioTimestamp.nanoTime + (long) elapsedTimeNs;
+ long matchingAudioSystemTimeMs = matchingAudioSystemTimeNs / 1000 / 1000;
+
+ // Verify that video and audio are in sync at the time when video resumes
+ // Note: Because a -100ms PTS gap is introduced, the video should resume 100ms later
+ matchingAudioSystemTimeMs += 100;
+ long avSyncOffsetMs = resumeVideoSystemTimeMs - matchingAudioSystemTimeMs;
+ assertTrue(String.format("Video is %d milliseconds out of sync of audio after resuming "
+ + "(video:%d, audio:%d)", avSyncOffsetMs, resumeVideoSystemTimeMs,
+ matchingAudioSystemTimeMs),
+ // some leniency in AV sync is required because Android TV STB/OTT OEMs often have
+ // to tune for imperfect downstream TVs (that have processing delays on the video)
+ // by knowingly producing HDMI output that has audio and video mildly out of sync
+ Math.abs(avSyncOffsetMs) <= 80);
}
/**
- * Test tunneled audio underrun with HEVC if supported
+ * Test that audio underrun pauses video and resumes in-sync for HEVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAudioUnderrunHevc() throws Exception {
tunneledAudioUnderrun(MediaFormat.MIMETYPE_VIDEO_HEVC,
- "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv",
- 25);
+ "video_1280x720_mkv_h265_500kbps_25fps_aac_stereo_128kbps_44100hz.mkv");
}
/**
- * Test tunneled audio underrun with AVC if supported
+ * Test that audio underrun pauses video and resumes in-sync for AVC in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAudioUnderrunAvc() throws Exception {
tunneledAudioUnderrun(MediaFormat.MIMETYPE_VIDEO_AVC,
- "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
- 25);
+ "video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
/**
- * Test tunneled audio underrun with VP9 if supported
+ * Test that audio underrun pauses video and resumes in-sync for VP9 in tunneled mode.
*/
- @SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
@Test
+ @ApiTest(apis={"android.media.MediaCodecInfo.CodecCapabilities#FEATURE_TunneledPlayback"})
public void testTunneledAudioUnderrunVp9() throws Exception {
tunneledAudioUnderrun(MediaFormat.MIMETYPE_VIDEO_VP9,
- "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
- 30);
+ "bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
private void sleepUntil(Supplier<Boolean> supplier, Duration maxWait) throws Exception {
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java
index f34f9e23146..0857809211e 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java
@@ -81,9 +81,9 @@ public class DecoderTestAacFormat {
AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER},
{"noise_6ch_44khz_aot5_dr_sbr_sig2_mp4.m4a", 6, AudioFormat.CHANNEL_OUT_5POINT1},
};
-
- for (Object [] sample: samples) {
- for (String codecName : DecoderTest.codecsFor((String)sample[0] /* resource */)) {
+ for (Object[] sample: samples) {
+ for (String codecName : DecoderTest.codecsFor((String)sample[0] /* resource */,
+ DecoderTest.CODEC_DEFAULT)) {
// verify correct number of channels is observed without downmixing
AudioParameter chanParams = new AudioParameter();
decodeUpdateFormat(codecName, (String) sample[0] /*resource*/, chanParams,
diff --git a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index 1a1a46f5383..2c1d9c5edc4 100644
--- a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -26,7 +26,6 @@ import android.media.ResourceBusyException;
import android.media.UnsupportedSchemeException;
import android.media.cts.AudioManagerStub;
import android.media.cts.AudioManagerStubHelper;
-import android.media.cts.CodecState;
import android.media.cts.ConnectionStatus;
import android.media.cts.IConnectionStatus;
import android.media.cts.InputSurface;
diff --git a/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt b/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt
index f057b21a849..931ecd1bc6b 100644
--- a/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt
+++ b/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt
@@ -67,7 +67,7 @@ object SafetyCenterUtils {
@JvmStatic
fun assertSafetyCenterStarted() {
// CollapsingToolbar title can't be found by text, so using description instead.
- waitFindObject(By.desc("Security & Privacy"))
+ waitFindObject(By.desc("Security & privacy"))
}
@JvmStatic
diff --git a/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt
index 6693aa325e3..8bd15373101 100644
--- a/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/MediaPermissionTest.kt
@@ -20,6 +20,7 @@ import android.Manifest
import android.os.Build
import androidx.test.filters.SdkSuppress
import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assume
import org.junit.Test
/**
@@ -96,6 +97,8 @@ class MediaPermissionTest : BaseUsePermissionTest() {
@Test
fun testWhenVisualIsDeniedManuallyThenShouldDenyAllPermissions() {
+ // TODO: Re-enable after b/239249703 is fixed
+ Assume.assumeFalse("skip on TV due to flaky", isTv)
installPackage(APP_APK_PATH_23)
grantAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
revokeAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index 5355fdc6860..d3310990b89 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -45,6 +45,7 @@ private const val MORE_OPTIONS = "More options"
private const val TIMELINE_7_DAYS_DESCRIPTION = "in the past 7 days"
private const val DASHBOARD_7_DAYS_DESCRIPTION = "7 days"
private const val PRIV_DASH_7_DAY_ENABLED = "privacy_dashboard_7_day_toggle"
+private const val REFRESH = "Refresh"
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
class PermissionHistoryTest : BasePermissionHubTest() {
@@ -100,9 +101,21 @@ class PermissionHistoryTest : BasePermissionHubTest() {
waitFindObject(By.textContains(APP_LABEL_1))
openPermissionDashboard()
- waitFindObject(By.res("android:id/title").textContains("Microphone")).click()
- waitFindObject(By.textContains(micLabel))
- waitFindObject(By.textContains(APP_LABEL_1))
+
+ SystemUtil.eventually {
+ try {
+ waitFindObject(By.res("android:id/title")
+ .textContains("Microphone")).click()
+ waitFindObject(By.textContains(micLabel))
+ waitFindObject(By.textContains(APP_LABEL_1))
+ } catch (e: Exception) {
+ // Sometimes the dashboard was in the state from previous failed tests.
+ // Clicking the refresh button to get the most recent access.
+ waitFindObject(By.textContains(REFRESH)).click()
+ throw e
+ }
+ }
+
pressBack()
pressBack()
}
diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
index 598a59a1727..872a243ce2e 100644
--- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
+++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt
@@ -78,6 +78,8 @@ private const val IDLE_TIMEOUT_MILLIS: Long = 1000
private const val UNEXPECTED_TIMEOUT_MILLIS = 1000
private const val TIMEOUT_MILLIS: Long = 20000
private const val TV_MIC_INDICATOR_WINDOW_TITLE = "MicrophoneCaptureIndicator"
+private const val MIC_LABEL_NAME = "microphone_toggle_label_qs"
+private const val CAMERA_LABEL_NAME = "camera_toggle_label_qs"
class CameraMicIndicatorsPermissionTest {
private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -90,11 +92,9 @@ class CameraMicIndicatorsPermissionTest {
private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
private val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ private val micLabel = getPermissionControllerString(MIC_LABEL_NAME)
+ private val cameraLabel = getPermissionControllerString(CAMERA_LABEL_NAME)
private var wasEnabled = false
- private val micLabel = packageManager.getPermissionGroupInfo(
- Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString()
- private val cameraLabel = packageManager.getPermissionGroupInfo(
- Manifest.permission_group.CAMERA, 0).loadLabel(packageManager).toString()
private var isScreenOn = false
private var screenTimeoutBeforeTest: Long = 0L
@@ -520,4 +520,18 @@ class CameraMicIndicatorsPermissionTest {
automatorMethod(remainingTime)
}
}
+
+ private fun getPermissionControllerString(resourceName: String): String {
+ val permissionControllerPkg = context.packageManager.permissionControllerPackageName
+ try {
+ val permissionControllerContext =
+ context.createPackageContext(permissionControllerPkg, 0)
+ val resourceId =
+ permissionControllerContext.resources.getIdentifier(
+ resourceName, "string", "com.android.permissioncontroller")
+ return permissionControllerContext.getString(resourceId)
+ } catch (e: PackageManager.NameNotFoundException) {
+ throw RuntimeException(e)
+ }
+ }
} \ No newline at end of file
diff --git a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
index 8cff38a67a9..67fa1bc3207 100644
--- a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
+++ b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt
@@ -25,6 +25,7 @@ import android.content.Context
import android.content.ContextParams
import android.content.Intent
import android.content.pm.PackageManager.FEATURE_LEANBACK
+import android.content.pm.PackageManager.FEATURE_TELEPHONY
import android.net.Uri
import android.os.Bundle
import android.os.Process
@@ -44,6 +45,7 @@ import com.android.compatibility.common.util.SystemUtil
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.Test
import org.mockito.ArgumentMatcher
@@ -105,6 +107,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testSelfSmsAccess() {
assumeNotTv()
+ assumeHasTelephony()
testSelfAccess(Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
}
@@ -178,6 +181,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testUntrustedSmsAccessAttributeToAnother() {
assumeNotTv()
+ assumeHasTelephony()
testUntrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
}
@@ -225,6 +229,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testUntrustedSmsAccessAttributeToAnotherThroughIntermediary() {
assumeNotTv()
+ assumeHasTelephony()
testUntrustedAccessAttributeToAnotherThroughIntermediary(
Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
@@ -323,6 +328,7 @@ class RuntimePermissionsAppOpTrackingTest {
@Throws(Exception::class)
fun testTrustedAccessSmsAttributeToAnother() {
assumeNotTv()
+ assumeHasTelephony()
testTrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI,
Manifest.permission.READ_SMS)
}
@@ -666,6 +672,7 @@ class RuntimePermissionsAppOpTrackingTest {
get() = InstrumentationRegistry.getInstrumentation()
private val isTv = context.packageManager.hasSystemFeature(FEATURE_LEANBACK)
+ private val isTel = context.packageManager.hasSystemFeature(FEATURE_TELEPHONY)
fun ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() {
SystemUtil.runShellCommand("am force-stop $RECEIVER_PACKAGE_NAME")
@@ -1178,5 +1185,6 @@ class RuntimePermissionsAppOpTrackingTest {
}
private fun assumeNotTv() = assumeFalse(isTv)
+ private fun assumeHasTelephony() = assumeTrue(isTel)
}
}
diff --git a/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java b/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java
index 29cf672a829..782f30c6508 100644
--- a/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java
+++ b/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java
@@ -103,7 +103,8 @@ public class PreferenceActivityLegacyFlowTest {
}
private void assertScreenshotsAreEqual(Bitmap before, Bitmap after) {
- assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after));
+ // TODO(b/227553681): remove the precision=0.99 arg so it does a pixel-by-pixel check
+ assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after, 0.99));
}
private void assertTextShown(String text) {
diff --git a/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java b/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java
new file mode 100644
index 00000000000..c6b7e35b4ef
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 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.security.cts;
+
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
+
+import static com.android.compatibility.common.util.SystemUtil.eventually;
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.location.LocationManager;
+import android.os.PackageTagsList;
+import android.os.Process;
+import android.os.UserHandle;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class LocationDisabledAppOpsTest extends StsExtraBusinessLogicTestCase {
+
+ private final Context mContext = InstrumentationRegistry.getContext();
+ private LocationManager mLm;
+ private AppOpsManager mAom;
+
+ @Before
+ public void setUp() {
+ mLm = mContext.getSystemService(LocationManager.class);
+ mAom = mContext.getSystemService(AppOpsManager.class);
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 231496105)
+ public void testLocationAppOpIsIgnoredForAppsWhenLocationIsDisabled() {
+ PackageTagsList ignoreList = mLm.getIgnoreSettingsAllowlist();
+
+ UserHandle[] userArr = {UserHandle.SYSTEM};
+ runWithShellPermissionIdentity(() -> {
+ userArr[0] = UserHandle.of(ActivityManager.getCurrentUser());
+ });
+
+ UserHandle user = userArr[0];
+
+ boolean wasEnabled = mLm.isLocationEnabledForUser(user);
+
+ try {
+ runWithShellPermissionIdentity(() -> {
+ mLm.setLocationEnabledForUser(false, user);
+ });
+ List<PackageInfo> pkgs =
+ mContext.getPackageManager().getInstalledPackagesAsUser(
+ 0, user.getIdentifier());
+
+ eventually(() -> {
+ List<String> bypassedNoteOps = new ArrayList<>();
+ List<String> bypassedCheckOps = new ArrayList<>();
+ for (PackageInfo pi : pkgs) {
+ ApplicationInfo ai = pi.applicationInfo;
+ if (ai.uid != Process.SYSTEM_UID) {
+ final int[] mode = {MODE_ALLOWED};
+ runWithShellPermissionIdentity(() -> {
+ mode[0] = mAom.noteOpNoThrow(
+ OPSTR_FINE_LOCATION, ai.uid, ai.packageName);
+ });
+ if (mode[0] == MODE_ALLOWED && !ignoreList.containsAll(pi.packageName)) {
+ bypassedNoteOps.add(pi.packageName);
+ }
+
+
+ mode[0] = MODE_ALLOWED;
+ runWithShellPermissionIdentity(() -> {
+ mode[0] = mAom
+ .checkOpNoThrow(OPSTR_FINE_LOCATION, ai.uid, ai.packageName);
+ });
+ if (mode[0] == MODE_ALLOWED && !ignoreList.includes(pi.packageName)) {
+ bypassedCheckOps.add(pi.packageName);
+ }
+
+ }
+ }
+
+ String msg = "";
+ if (!bypassedNoteOps.isEmpty()) {
+ msg += "Apps which still have access from noteOp " + bypassedNoteOps;
+ }
+ if (!bypassedCheckOps.isEmpty()) {
+ msg += (msg.isEmpty() ? "" : "\n\n")
+ + "Apps which still have access from checkOp " + bypassedCheckOps;
+ }
+ if (!msg.isEmpty()) {
+ Assert.fail(msg);
+ }
+ });
+ } finally {
+ runWithShellPermissionIdentity(() -> {
+ mLm.setLocationEnabledForUser(wasEnabled, user);
+ });
+ }
+ }
+
+}
+
diff --git a/tests/tests/systemui/Android.bp b/tests/tests/systemui/Android.bp
index e33d8fc7966..3a68e4df1dd 100644
--- a/tests/tests/systemui/Android.bp
+++ b/tests/tests/systemui/Android.bp
@@ -39,6 +39,7 @@ android_test {
"androidx.test.ext.junit",
"androidx.test.uiautomator",
"cts-wm-util",
+ "permission-test-util-lib",
"ub-uiautomator",
],
srcs: [
diff --git a/tests/tests/systemui/AndroidManifest.xml b/tests/tests/systemui/AndroidManifest.xml
index f55ed3f13c5..d4ba3b3d4fe 100644
--- a/tests/tests/systemui/AndroidManifest.xml
+++ b/tests/tests/systemui/AndroidManifest.xml
@@ -26,6 +26,7 @@
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<!-- Required by flickerlib to dump window states -->
<uses-permission android:name="android.permission.DUMP"/>
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application android:requestLegacyExternalStorage="true">
<activity android:name=".LightBarActivity"
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index ffa58bafc97..50792176d28 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -16,6 +16,9 @@
package android.systemui.cts;
+import static android.Manifest.permission.POST_NOTIFICATIONS;
+import static android.Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL;
+import static android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS;
import static android.server.wm.BarTestUtils.assumeHasColoredNavigationBar;
import static android.server.wm.BarTestUtils.assumeHasColoredStatusBar;
import static android.server.wm.BarTestUtils.assumeStatusBarContainsCutout;
@@ -33,7 +36,10 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Insets;
+import android.os.Process;
import android.os.SystemClock;
+import android.permission.PermissionManager;
+import android.permission.cts.PermissionUtils;
import android.platform.test.annotations.AppModeFull;
import android.view.Gravity;
import android.view.InputDevice;
@@ -45,6 +51,7 @@ import android.view.WindowMetrics;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThrowingRunnable;
import org.junit.Rule;
@@ -244,22 +251,23 @@ public class LightBarTests extends LightBarTestBase {
}
private void runInNotificationSession(ThrowingRunnable task) throws Exception {
+ Context context = getInstrumentation().getContext();
+ String packageName = getInstrumentation().getTargetContext().getPackageName();
try {
- mNm = (NotificationManager) getInstrumentation().getContext()
- .getSystemService(Context.NOTIFICATION_SERVICE);
+ PermissionUtils.grantPermission(packageName, POST_NOTIFICATIONS);
+ mNm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel1 = new NotificationChannel(NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW);
mNm.createNotificationChannel(channel1);
// post 10 notifications to ensure enough icons in the status bar
for (int i = 0; i < 10; i++) {
- Notification.Builder noti1 = new Notification.Builder(
- getInstrumentation().getContext(),
- NOTIFICATION_CHANNEL_ID)
- .setSmallIcon(R.drawable.ic_save)
- .setChannelId(NOTIFICATION_CHANNEL_ID)
- .setPriority(Notification.PRIORITY_LOW)
- .setGroup(NOTIFICATION_GROUP_KEY);
+ Notification.Builder noti1 =
+ new Notification.Builder(context, NOTIFICATION_CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_save)
+ .setChannelId(NOTIFICATION_CHANNEL_ID)
+ .setPriority(Notification.PRIORITY_LOW)
+ .setGroup(NOTIFICATION_GROUP_KEY);
mNm.notify(NOTIFICATION_TAG, i, noti1.build());
}
@@ -267,6 +275,16 @@ public class LightBarTests extends LightBarTestBase {
} finally {
mNm.cancelAll();
mNm.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID);
+
+ // Use test API to prevent PermissionManager from killing the test process when revoking
+ // permission.
+ SystemUtil.runWithShellPermissionIdentity(
+ () -> context.getSystemService(PermissionManager.class)
+ .revokePostNotificationPermissionWithoutKillForTest(
+ packageName,
+ Process.myUserHandle().getIdentifier()),
+ REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL,
+ REVOKE_RUNTIME_PERMISSIONS);
}
}
diff --git a/tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java b/tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java
deleted file mode 100644
index b74678bc3af..00000000000
--- a/tests/tests/systemui/src/android/systemui/cts/MediaOutputDialogTest.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2022 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.systemui.cts;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assume.assumeFalse;
-import static org.junit.Assume.assumeTrue;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.server.wm.WindowManagerStateHelper;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.Until;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.compatibility.common.util.SystemUtil;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Tests related MediaOutputDialog:
- *
- * atest MediaDialogTest
- */
-@RunWith(AndroidJUnit4.class)
-public class MediaOutputDialogTest {
-
- private static final int TIMEOUT = 5000;
- private static final String ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG =
- "com.android.systemui.action.LAUNCH_MEDIA_OUTPUT_DIALOG";
- private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
- public static final String EXTRA_PACKAGE_NAME = "package_name";
- public static final String TEST_PACKAGE_NAME = "com.android.package.test";
- private static final BySelector MEDIA_DIALOG_SELECTOR = By.res(SYSTEMUI_PACKAGE_NAME,
- "media_output_dialog");
- private WindowManagerStateHelper mWmState = new WindowManagerStateHelper();
-
- private Context mContext;
- private UiDevice mDevice;
- private String mLauncherPackage;
- private boolean mHasTouchScreen;
- private ActivityManager mActivityManager;
- private static final int DURATION_SCREEN_TOGGLE = 2000;
-
- @Before
- public void setUp() {
- mContext = InstrumentationRegistry.getTargetContext();
- mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
- final PackageManager packageManager = mContext.getPackageManager();
-
- mHasTouchScreen = packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
- || packageManager.hasSystemFeature(PackageManager.FEATURE_FAKETOUCH);
-
- Intent launcherIntent = new Intent(Intent.ACTION_MAIN);
- launcherIntent.addCategory(Intent.CATEGORY_HOME);
- ResolveInfo resolveInfo = packageManager.resolveActivity(launcherIntent,
- PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
- assumeFalse("Skipping test: can't get resolve info", resolveInfo == null);
- assumeFalse("Skipping test: not supported on automotive yet",
- packageManager.hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE));
- mLauncherPackage = resolveInfo.activityInfo.packageName;
- mActivityManager = mContext.getSystemService(ActivityManager.class);
- }
-
- @Test
- public void mediaOutputDialog_correctDialog() throws Exception {
- prepareDevice();
- assumeTrue(mHasTouchScreen);
- try {
- if (mActivityManager.isLowRamDevice()) {
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "appops set " + SYSTEMUI_PACKAGE_NAME + " SYSTEM_ALERT_WINDOW allow");
- }
-
- launchMediaOutputDialog();
-
- assertThat(mDevice.wait(Until.hasObject(MEDIA_DIALOG_SELECTOR), TIMEOUT)).isTrue();
- } finally {
- if (mActivityManager.isLowRamDevice()) {
- SystemUtil.runShellCommand(InstrumentationRegistry.getInstrumentation(),
- "appops set " + SYSTEMUI_PACKAGE_NAME + " SYSTEM_ALERT_WINDOW ignore");
- }
- }
- }
-
- private void prepareDevice() throws Exception {
- mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
- mDevice.executeShellCommand("wm dismiss-keyguard");
- // Since the screen on/off intent is ordered, they will not be sent right now.
- mWmState.waitForKeyguardGone();
- }
-
- private void launchMediaOutputDialog() {
- mDevice.pressHome();
- mDevice.wait(Until.hasObject(By.pkg(mLauncherPackage).depth(0)), TIMEOUT);
-
- Intent intent = new Intent();
- intent.setPackage(SYSTEMUI_PACKAGE_NAME)
- .setAction(ACTION_LAUNCH_MEDIA_OUTPUT_DIALOG)
- .putExtra(EXTRA_PACKAGE_NAME, TEST_PACKAGE_NAME);
-
- mContext.sendBroadcast(intent);
- }
-
-}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index 3757b632d28..4df93b20398 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -109,6 +109,7 @@ import android.util.Pair;
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CarrierPrivilegeUtils;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.ShellIdentityUtils;
@@ -283,6 +284,7 @@ public class TelephonyManagerTest {
private static final int RADIO_HAL_VERSION_1_3 = makeRadioVersion(1, 3);
private static final int RADIO_HAL_VERSION_1_5 = makeRadioVersion(1, 5);
private static final int RADIO_HAL_VERSION_1_6 = makeRadioVersion(1, 6);
+ private static final int RADIO_HAL_VERSION_2_0 = makeRadioVersion(2, 0);
static {
EMERGENCY_NUMBER_SOURCE_SET = new HashSet<Integer>();
@@ -1250,24 +1252,50 @@ public class TelephonyManagerTest {
private static final String ISO_COUNTRY_CODE_PATTERN = "[a-z]{2}";
@Test
+ @ApiTest(apis = "android.telephony.TelephonyManager#getNetworkCountryIso")
public void testGetNetworkCountryIso() {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
String countryCode = mTelephonyManager.getNetworkCountryIso();
- assertTrue("Country code '" + countryCode + "' did not match "
- + ISO_COUNTRY_CODE_PATTERN,
- Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
+ ServiceState serviceState = mTelephonyManager.getServiceState();
+ if (serviceState != null && (serviceState.getState()
+ == ServiceState.STATE_IN_SERVICE || serviceState.getState()
+ == ServiceState.STATE_EMERGENCY_ONLY)) {
+ assertTrue("Country code '" + countryCode + "' did not match "
+ + ISO_COUNTRY_CODE_PATTERN,
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
+ } else {
+ assertTrue("Country code could be empty when out of service",
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
+ || TextUtils.isEmpty(countryCode));
+ }
- for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
- SubscriptionInfo subscriptionInfo =
- mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(i);
- if (subscriptionInfo != null) {
- countryCode = mTelephonyManager.getNetworkCountryIso(i);
+ int[] allSubs = ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mSubscriptionManager, (sm) -> sm.getActiveSubscriptionIdList());
+ for (int i : allSubs) {
+ countryCode = mTelephonyManager.getNetworkCountryIso(
+ SubscriptionManager.getSlotIndex(i));
+ serviceState = mTelephonyManager.createForSubscriptionId(i).getServiceState();
+
+ if (serviceState != null && (serviceState.getState()
+ == ServiceState.STATE_IN_SERVICE || serviceState.getState()
+ == ServiceState.STATE_EMERGENCY_ONLY)) {
assertTrue("Country code '" + countryCode + "' did not match "
- + ISO_COUNTRY_CODE_PATTERN + " for slot " + i,
+ + ISO_COUNTRY_CODE_PATTERN + " for slot " + i,
Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode));
+ } else {
+ assertTrue("Country code could be empty when out of service",
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
+ || TextUtils.isEmpty(countryCode));
}
}
+
+ for (int i = 0; i < mTelephonyManager.getPhoneCount(); i++) {
+ countryCode = mTelephonyManager.getNetworkCountryIso(i);
+ assertTrue("Country code must match " + ISO_COUNTRY_CODE_PATTERN + "or empty",
+ Pattern.matches(ISO_COUNTRY_CODE_PATTERN, countryCode)
+ || TextUtils.isEmpty(countryCode));
+ }
}
@Test
@@ -1729,6 +1757,10 @@ public class TelephonyManagerTest {
@Test
public void testRebootRadio() throws Throwable {
assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS));
+ if (mRadioVersion < RADIO_HAL_VERSION_2_0) {
+ Log.d(TAG, "Skipping test since rebootModem is not supported.");
+ return;
+ }
TestThread t = new TestThread(() -> {
Looper.prepare();
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 7d73da9dad1..f00f0b13b5c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java
@@ -125,6 +125,8 @@ public class ExactCanvasTests extends ActivityTestBase {
canvas.drawColor(Color.WHITE);
p.setColor(Color.BLACK);
p.setAntiAlias(false);
+ // ensure the lines do not hit pixel edges
+ canvas.translate(0.05f, 0.05f);
float[] pts = {
0, 0, 80, 80, 80, 0, 0, 80, 40, 50, 60, 50
};
diff --git a/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java b/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java
index a4ef244f232..a86a9f5b3d7 100644
--- a/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/BackInvokedOnWidgetsTest.java
@@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue;
import android.app.Instrumentation;
import android.graphics.Color;
+import android.platform.test.annotations.AppModeFull;
import android.support.test.uiautomator.UiDevice;
import android.view.Gravity;
import android.view.ViewGroup;
@@ -40,7 +41,10 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+// @AppModeFull because GestureNavRule does not work for
+// instant mode tests (b/238975931)
@MediumTest
+@AppModeFull
@RunWith(AndroidJUnit4.class)
public class BackInvokedOnWidgetsTest {
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
index f7322dde5e1..464fb4c40b8 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java
@@ -274,6 +274,29 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
new LinkedList<Integer>(Arrays.asList(waitSingleSync)));
}
+ private NetworkInfo.DetailedState waitForNextNetworkState() {
+ assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
+ assertNotNull(mMySync.expectedNetworkInfo);
+ return mMySync.expectedNetworkInfo.getDetailedState();
+ }
+
+ private boolean waitForConnectedNetworkState() {
+ // The possible orders of network states are:
+ // * IDLE > CONNECTING > CONNECTED for lazy initialization
+ // * DISCONNECTED > CONNECTING > CONNECTED for previous group removal
+ // * CONNECTING > CONNECTED
+ NetworkInfo.DetailedState state = waitForNextNetworkState();
+ if (state == NetworkInfo.DetailedState.IDLE
+ || state == NetworkInfo.DetailedState.DISCONNECTED) {
+ state = waitForNextNetworkState();
+ }
+ if (state != NetworkInfo.DetailedState.CONNECTING) {
+ return false;
+ }
+ state = waitForNextNetworkState();
+ return state == NetworkInfo.DetailedState.CONNECTED;
+ }
+
private boolean waitForServiceResponse(MyResponse waitResponse) {
synchronized (waitResponse) {
long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
@@ -508,21 +531,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
-
- // The first network state might be IDLE due to
- // lazy initialization, but not CONNECTED.
- for (int i = 0; i < 2; i++) {
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- if (NetworkInfo.DetailedState.CONNECTED ==
- mMySync.expectedNetworkInfo.getDetailedState()) {
- break;
- }
- assertEquals(NetworkInfo.DetailedState.IDLE,
- mMySync.expectedNetworkInfo.getDetailedState());
- }
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
mWifiP2pManager.requestNetworkInfo(mWifiP2pChannel,
@@ -660,21 +669,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
-
- // The first network state might be IDLE due to
- // lazy initialization, but not CONNECTED.
- for (int i = 0; i < 2; i++) {
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- if (NetworkInfo.DetailedState.CONNECTED ==
- mMySync.expectedNetworkInfo.getDetailedState()) {
- break;
- }
- assertEquals(NetworkInfo.DetailedState.IDLE,
- mMySync.expectedNetworkInfo.getDetailedState());
- }
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
@@ -707,10 +702,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener);
@@ -812,21 +804,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase {
mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener);
assertTrue(waitForServiceResponse(mMyResponse));
assertTrue(mMyResponse.success);
-
- // The first network state might be IDLE due to
- // lazy initialization, but not CONNECTED.
- for (int i = 0; i < 2; i++) {
- assertTrue(waitForBroadcasts(MySync.NETWORK_INFO));
- assertNotNull(mMySync.expectedNetworkInfo);
- if (NetworkInfo.DetailedState.CONNECTED
- == mMySync.expectedNetworkInfo.getDetailedState()) {
- break;
- }
- assertEquals(NetworkInfo.DetailedState.IDLE,
- mMySync.expectedNetworkInfo.getDetailedState());
- }
- assertEquals(NetworkInfo.DetailedState.CONNECTED,
- mMySync.expectedNetworkInfo.getDetailedState());
+ assertTrue(waitForConnectedNetworkState());
resetResponse(mMyResponse);
MacAddress peerMacAddress = MacAddress.fromString(mTestWifiP2pPeerConfig.deviceAddress);