diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-10 16:16:42 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-06-10 16:16:42 +0000 |
commit | f77a00c53f15ee8499c32a72fcd9d7cf9f003b0c (patch) | |
tree | 8e7dbd9b66a5162d98b2bb1d8e260aba6d8124b5 | |
parent | 3c6bfa5771c64232370c967d240f032afc281d81 (diff) | |
parent | fb9a587335ce035687ca8a7bffb1acf5ee6c0aee (diff) | |
download | cts-android13-mainline-go-adservices-release.tar.gz |
Snap for 8708169 from fb9a587335ce035687ca8a7bffb1acf5ee6c0aee to mainline-go-adservices-releaseaml_go_ads_330915100aml_go_ads_330915000aml_go_ads_330913000android13-mainline-go-adservices-release
Change-Id: I88653d47cd2d686036c0957a51c7ad5605903853
101 files changed, 2651 insertions, 1031 deletions
diff --git a/apps/CameraITS/build/scripts/gpylint_rcfile b/apps/CameraITS/build/scripts/gpylint_rcfile index fe9f3d1175a..38c169344b5 100644 --- a/apps/CameraITS/build/scripts/gpylint_rcfile +++ b/apps/CameraITS/build/scripts/gpylint_rcfile @@ -61,9 +61,6 @@ test-mode=test # Inject some known modules. inject-known-modules=no -# The import path resolver -resolver=blaze - [REPORTS] diff --git a/apps/CameraITS/tests/its_base_test.py b/apps/CameraITS/tests/its_base_test.py index 0240682be2c..9b29ab72365 100644 --- a/apps/CameraITS/tests/its_base_test.py +++ b/apps/CameraITS/tests/its_base_test.py @@ -171,6 +171,7 @@ class ItsBaseTest(base_test.BaseTestClass): self.tablet.adb.shell('am force-stop com.google.android.apps.photos') self.tablet.adb.shell('am force-stop com.android.gallery3d') self.tablet.adb.shell('am force-stop com.sec.android.gallery3d') + self.tablet.adb.shell('am force-stop com.miui.gallery') def set_tablet_landscape_orientation(self): """Sets the screen orientation to landscape. diff --git a/apps/CameraITS/tests/scene1_1/test_ae_af.py b/apps/CameraITS/tests/scene1_1/test_ae_af.py index 09a1470c234..852c7867582 100644 --- a/apps/CameraITS/tests/scene1_1/test_ae_af.py +++ b/apps/CameraITS/tests/scene1_1/test_ae_af.py @@ -67,8 +67,8 @@ class SingleATest(its_base_test.ItsBaseTest): do_awb=three_a_req[2], mono_camera=mono_camera) - except error_util.CameraItsError: - raise AssertionError(f'{k} did not converge.') + except error_util.CameraItsError as e_util: + raise AssertionError(f'{k} did not converge.') from e_util logging.debug('AWB gains: %s, xform: %s', str(awb_gains), str(awb_xform)) diff --git a/apps/CameraITS/tests/scene1_1/test_capture_result.py b/apps/CameraITS/tests/scene1_1/test_capture_result.py index 304a7376c02..f3a9e9d994a 100644 --- a/apps/CameraITS/tests/scene1_1/test_capture_result.py +++ b/apps/CameraITS/tests/scene1_1/test_capture_result.py @@ -213,7 +213,7 @@ def test_manual(cam, props, log_path): metadata['android.tonemap.curve']['green'], metadata['android.tonemap.curve']['blue']] logging.debug('Tonemap: %s', str(curves[0][1::16])) - for j, c in enumerate(curves): + for _, c in enumerate(curves): if not c: raise AssertionError('c in curves is empty.') if not all([np.isclose(c[i], c[i+1], atol=ISCLOSE_ATOL) diff --git a/apps/CameraITS/tests/scene1_2/test_raw_exposure.py b/apps/CameraITS/tests/scene1_2/test_raw_exposure.py index 5bd44e8f1a5..bcf426d8cfc 100644 --- a/apps/CameraITS/tests/scene1_2/test_raw_exposure.py +++ b/apps/CameraITS/tests/scene1_2/test_raw_exposure.py @@ -85,15 +85,16 @@ def create_plot(exps, means, sens, log_path): gb = [m[2] for m in means[1:]] b = [m[3] for m in means[1:]] pylab.figure('%s_%s' % (NAME, sens)) - pylab.plot(exps, r, 'r.-') - pylab.plot(exps, b, 'b.-') - pylab.plot(exps, gr, 'g.-') - pylab.plot(exps, gb, 'k.-') + pylab.plot(exps, r, 'r.-', label='R') + pylab.plot(exps, gr, 'g.-', label='Gr') + pylab.plot(exps, gb, 'k.-', label='Gb') + pylab.plot(exps, b, 'b.-', label='B') pylab.xscale('log') pylab.yscale('log') pylab.title('%s ISO=%d' % (NAME, sens)) pylab.xlabel('Exposure time (ms)') pylab.ylabel('Center patch pixel mean') + pylab.legend(loc='lower right', numpoints=1, fancybox=True) matplotlib.pyplot.savefig( '%s_s=%d.png' % (os.path.join(log_path, NAME), sens)) pylab.clf() diff --git a/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py b/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py index 8c542ab9cc4..62a017b8f68 100644 --- a/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py +++ b/apps/CameraITS/tests/scene1_2/test_raw_sensitivity.py @@ -63,7 +63,6 @@ class RawSensitivityTest(its_base_test.ItsBaseTest): camera_properties_utils.per_frame_control(props) and not camera_properties_utils.mono_camera(props)) name_with_log_path = os.path.join(self.log_path, NAME) - camera_fov = float(cam.calc_camera_fov(props)) # Load chart for scene (chart_distance=0 for no chart scaling) its_session_utils.load_scene( diff --git a/apps/CameraITS/tests/scene2_a/test_format_combos.py b/apps/CameraITS/tests/scene2_a/test_format_combos.py index 7568da796e2..c05301b261b 100644 --- a/apps/CameraITS/tests/scene2_a/test_format_combos.py +++ b/apps/CameraITS/tests/scene2_a/test_format_combos.py @@ -147,7 +147,7 @@ class FormatCombosTest(its_base_test.ItsBaseTest): if STOP_AT_FIRST_FAILURE: raise AssertionError( f'Capture fail at combo req: {req_str}, fmt: {fmt_combo}, ' - f'burst: {burst_len}') + f'burst: {burst_len}') from e n += 1 num_fail = len(failures) diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py index e77a702d3b3..3959b42ef27 100644 --- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py +++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py @@ -148,7 +148,7 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest): camera_properties_utils.skip_unless( first_api_level >= its_session_utils.ANDROID13_API_LEVEL, 'First API level should be {} or higher. Found {}.'.format( - its_session_utils.ANDROID13_API_LEVEL, first_api_level)) + its_session_utils.ANDROID13_API_LEVEL, first_api_level)) supported_stabilization_modes = props[ 'android.control.availableVideoStabilizationModes' 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 eca64ef9b5c..06f3f129f53 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 @@ -182,7 +182,8 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): for hlg10_param in hlg10_params: video_recording_obj = cam.do_basic_recording( - profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS, 0, hlg10_param) + profile_id, quality, _VIDEO_RECORDING_DURATION_SECONDS, 0, + hlg10_param) logging.debug('video_recording_obj: %s', video_recording_obj) # TODO(ruchamk): Modify video recording object to send videoFrame # width and height instead of videoSize to avoid string operation @@ -196,7 +197,8 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): self.log_path]) logging.debug('Recorded video is available at: %s', self.log_path) - video_file_name = video_recording_obj['recordedOutputPath'].split('/')[-1] + video_file_name = video_recording_obj[ + 'recordedOutputPath'].split('/')[-1] logging.debug('video_file_name: %s', video_file_name) key_frame_files = [] @@ -208,7 +210,8 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): last_key_frame_file = video_processing_utils.get_key_frame_to_process( key_frame_files) logging.debug('last_key_frame: %s', last_key_frame_file) - last_key_frame_path = os.path.join(self.log_path, last_key_frame_file) + last_key_frame_path = os.path.join( + self.log_path, last_key_frame_file) # Convert lastKeyFrame to numpy array np_image = image_processing_utils.convert_image_to_numpy_array( @@ -222,7 +225,7 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): max_img_value = _MAX_8BIT_IMGS if hlg10_param: - max_img_value = _MAX_10BIT_IMGS + max_img_value = _MAX_10BIT_IMGS # Check pass/fail for fov coverage for all fmts in AR_CHECKED fov_chk_msg = image_fov_utils.check_fov( @@ -232,7 +235,8 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): os.path.join(self.log_path, _NAME), quality, width, height) fov_chk_quality_msg = f'Quality: {quality} {fov_chk_msg}' failed_fov.append(fov_chk_quality_msg) - image_processing_utils.write_image(np_image/max_img_value, img_name, True) + image_processing_utils.write_image( + np_image/max_img_value, img_name, True) # Check pass/fail for aspect ratio. ar_chk_msg = image_fov_utils.check_ar( @@ -242,14 +246,16 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): img_name = '%s_%s_w%d_h%d_ar.png' % ( os.path.join(self.log_path, _NAME), quality, width, height) failed_ar.append(ar_chk_msg) - image_processing_utils.write_image(np_image/max_img_value, img_name, True) + image_processing_utils.write_image( + np_image/max_img_value, img_name, True) # Check pass/fail for crop. if run_crop_test: # Normalize the circle size to 1/4 of the image size, so that # circle size won't affect the crop test result crop_thresh_factor = ((min(ref_fov['w'], ref_fov['h']) / 4.0) / - max(ref_fov['circle_w'], ref_fov['circle_h'])) + max(ref_fov['circle_w'], + ref_fov['circle_h'])) crop_chk_msg = image_fov_utils.check_crop( circle, cc_ct_gt, width, height, f'{quality}', crop_thresh_factor) diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py index c828ad5798b..d4fa21c3c29 100644 --- a/apps/CameraITS/tests/scene6/test_zoom.py +++ b/apps/CameraITS/tests/scene6/test_zoom.py @@ -273,13 +273,13 @@ class ZoomTest(its_base_test.ItsBaseTest): if circle_cropped(circle, size): logging.debug('zoom %.2f is too large! Skip further captures', z) break - except AssertionError: + except AssertionError as e: if z/z_list[0] >= ZOOM_MAX_THRESH: break else: raise AssertionError( f'No circle was detected for zoom ratio <= {ZOOM_MAX_THRESH}. ' - 'Please take pictures according to instructions carefully!') + 'Take pictures according to instructions carefully!') from e test_data[i] = {'z': z, 'circle': circle, 'r_tol': radius_tol, 'o_tol': offset_tol, 'fl': cap_fl} diff --git a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py index 64b22d908ce..c6b852c5378 100644 --- a/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py +++ b/apps/CameraITS/tests/sensor_fusion/test_preview_stabilization.py @@ -20,9 +20,9 @@ import time from mobly import test_runner +import its_base_test import camera_properties_utils import image_processing_utils -import its_base_test import its_session_utils import sensor_fusion_utils import video_processing_utils @@ -33,11 +33,11 @@ _ARDUINO_SERVO_SPEED = 10 _IMG_FORMAT = 'png' _MIN_PHONE_MOVEMENT_ANGLE = 5 # degrees _NAME = os.path.splitext(os.path.basename(__file__))[0] -_NUM_ROTATIONS = 25 +_NUM_ROTATIONS = 12 _START_FRAME = 30 # give 3A some frames to warm up _VIDEO_DELAY_TIME = 5.5 # seconds _VIDEO_DURATION = 5.5 # seconds -_VIDEO_STABILIZATION_FACTOR = 0.6 # 60% of gyro movement allowed +_VIDEO_STABILIZATION_FACTOR = 0.7 # 70% of gyro movement allowed _PREVIEW_STABILIZATION_MODE_PREVIEW = 2 @@ -86,7 +86,7 @@ def _collect_data(cam, video_size, rot_rig): return recording_obj -class PreviewStabilityTest(its_base_test.ItsBaseTest): +class PreviewStabilizationTest(its_base_test.ItsBaseTest): """Tests if preview is stabilized. Camera is moved in sensor fusion rig on an arc of 15 degrees. @@ -115,7 +115,7 @@ class PreviewStabilityTest(its_base_test.ItsBaseTest): camera_properties_utils.skip_unless( first_api_level >= its_session_utils.ANDROID13_API_LEVEL, 'First API level should be {} or higher. Found {}.'.format( - its_session_utils.ANDROID13_API_LEVEL, first_api_level)) + its_session_utils.ANDROID13_API_LEVEL, first_api_level)) supported_stabilization_modes = props[ 'android.control.availableVideoStabilizationModes' @@ -124,7 +124,7 @@ class PreviewStabilityTest(its_base_test.ItsBaseTest): camera_properties_utils.skip_unless( supported_stabilization_modes is not None and _PREVIEW_STABILIZATION_MODE_PREVIEW - in supported_stabilization_modes, + in supported_stabilization_modes, 'Preview Stabilization not supported', ) @@ -137,9 +137,12 @@ class PreviewStabilityTest(its_base_test.ItsBaseTest): # Initialize rotation rig rot_rig['cntl'] = self.rotator_cntl rot_rig['ch'] = self.rotator_ch + if rot_rig['cntl'].lower() != 'arduino': + raise AssertionError(f'You must use the arduino controller for {_NAME}.') # List of video resolutions to test supported_preview_sizes = cam.get_supported_preview_sizes(self.camera_id) + supported_preview_sizes.remove(video_processing_utils.QCIF_SIZE) logging.debug('Supported preview resolutions: %s', supported_preview_sizes) @@ -201,10 +204,9 @@ class PreviewStabilityTest(its_base_test.ItsBaseTest): sensor_fusion_utils.calc_max_rotation_angle(gyro_rots, 'Gyro') ) logging.debug( - 'Max deflection (degrees): gyro: %.2f, camera: %.2f', - max_gyro_angles[-1], - max_camera_angles[-1], - ) + 'Max deflection (degrees) %s: video: %.3f, gyro: %.3f ratio: %.4f', + video_size, max_camera_angles[-1], max_gyro_angles[-1], + max_camera_angles[-1] / max_gyro_angles[-1]) # Assert phone is moved enough during test if max_gyro_angles[-1] < _MIN_PHONE_MOVEMENT_ANGLE: @@ -218,9 +220,10 @@ class PreviewStabilityTest(its_base_test.ItsBaseTest): if max_camera_angle >= max_gyro_angles[i] * _VIDEO_STABILIZATION_FACTOR: test_failures.append( f'{supported_preview_sizes[i]} video not stabilized enough! ' - f'Max gyro angle: {max_gyro_angles[i]:.2f}, Max camera angle: ' - f'{max_camera_angle:.2f}, stabilization factor THRESH: ' - f'{_VIDEO_STABILIZATION_FACTOR}.') + f'Max video angle: {max_camera_angle:.3f}, ' + f'Max gyro angle: {max_gyro_angles[i]:.3f}, ' + f'ratio: {max_camera_angle/max_gyro_angles[i]:.4f} ' + f'THRESH: {_VIDEO_STABILIZATION_FACTOR}.') if test_failures: raise AssertionError(test_failures) diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py index e6eec9fa48a..193993524de 100644 --- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py +++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py @@ -337,7 +337,7 @@ class SensorFusionTest(its_base_test.ItsBaseTest): " smaller values of 'w', 'h', 'fps', or 'test_length'.") if replay: - events, frames, _, h = load_data() + events, frames, _, _ = load_data() else: with its_session_utils.ItsSession( device_id=self.dut.serial, diff --git a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py index 3a71fda4c32..0be38b56d11 100644 --- a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py +++ b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py @@ -22,9 +22,9 @@ import time from mobly import test_runner import numpy as np +import its_base_test import camera_properties_utils import image_processing_utils -import its_base_test import its_session_utils import sensor_fusion_utils import video_processing_utils @@ -35,7 +35,7 @@ _ARDUINO_SERVO_SPEED = 10 _IMG_FORMAT = 'png' _MIN_PHONE_MOVEMENT_ANGLE = 5 # degrees _NAME = os.path.splitext(os.path.basename(__file__))[0] -_NUM_ROTATIONS = 25 +_NUM_ROTATIONS = 12 _RADS_TO_DEGS = 180/math.pi _SEC_TO_NSEC = 1E9 _START_FRAME = 30 # give 3A 1s to warm up @@ -115,7 +115,7 @@ def _collect_data(cam, video_profile, video_quality, rot_rig): return recording_obj -class VideoStabilityTest(its_base_test.ItsBaseTest): +class VideoStabilizationTest(its_base_test.ItsBaseTest): """Tests if video is stabilized. Camera is moved in sensor fusion rig on an arc of 15 degrees. @@ -156,6 +156,8 @@ class VideoStabilityTest(its_base_test.ItsBaseTest): # Initialize rotation rig rot_rig['cntl'] = self.rotator_cntl rot_rig['ch'] = self.rotator_ch + if rot_rig['cntl'].lower() != 'arduino': + raise AssertionError(f'You must use the arduino controller for {_NAME}.') # Create list of video qualities to test supported_video_qualities = cam.get_supported_video_qualities( @@ -220,8 +222,10 @@ class VideoStabilityTest(its_base_test.ItsBaseTest): gyro_rots = _conv_acceleration_to_movement(gyro_events) max_gyro_angles.append(sensor_fusion_utils.calc_max_rotation_angle( gyro_rots, 'Gyro')) - logging.debug('Max deflection (degrees): gyro: %.2f, camera: %.2f', - max_gyro_angles[-1], max_camera_angles[-1]) + logging.debug( + 'Max deflection (degrees) %s: video: %.3f, gyro: %.3f, ratio: %.4f', + video_quality, max_camera_angles[-1], max_gyro_angles[-1], + max_camera_angles[-1] / max_gyro_angles[-1]) # Assert phone is moved enough during test if max_gyro_angles[-1] < _MIN_PHONE_MOVEMENT_ANGLE: @@ -235,9 +239,10 @@ class VideoStabilityTest(its_base_test.ItsBaseTest): if max_camera_angle >= max_gyro_angles[i] * _VIDEO_STABILIZATION_FACTOR: test_failures.append( f'{tested_video_qualities[i]} video not stabilized enough! ' - f'Max gyro angle: {max_gyro_angles[i]:.2f}, Max camera angle: ' - f'{max_camera_angle:.2f}, stabilization factor THRESH: ' - f'{_VIDEO_STABILIZATION_FACTOR}.') + f'Max video angle: {max_camera_angle:.3f}, ' + f'Max gyro angle: {max_gyro_angles[i]:.3f}, ' + f'ratio: {max_camera_angle}/{max_gyro_angles[-1]:.3f}, ' + f'THRESH: {_VIDEO_STABILIZATION_FACTOR}.') if test_failures: raise AssertionError(test_failures) diff --git a/apps/CameraITS/utils/image_processing_utils.py b/apps/CameraITS/utils/image_processing_utils.py index d0bf08e5e6e..19d76c3fa88 100644 --- a/apps/CameraITS/utils/image_processing_utils.py +++ b/apps/CameraITS/utils/image_processing_utils.py @@ -137,7 +137,7 @@ def unpack_raw10_image(img): # Cut out the 4x2b LSBs and put each in bits [1:0] of their own 8b words. lsbs = img[::, 4::5].reshape(h, w // 4) lsbs = numpy.right_shift( - numpy.packbits(numpy.unpackbits(lsbs).reshape(h, w // 4, 4, 2), 3), 6) + numpy.packbits(numpy.unpackbits(lsbs).reshape((h, w // 4, 4, 2)), 3), 6) # Pair the LSB bits group to 0th pixel instead of 3rd pixel lsbs = lsbs.reshape(h, w // 4, 4)[:, :, ::-1] lsbs = lsbs.reshape(h, w) @@ -190,7 +190,7 @@ def unpack_raw12_image(img): # Cut out the 2x4b LSBs and put each in bits [3:0] of their own 8b words. lsbs = img[::, 2::3].reshape(h, w // 2) lsbs = numpy.right_shift( - numpy.packbits(numpy.unpackbits(lsbs).reshape(h, w // 2, 2, 4), 3), 4) + numpy.packbits(numpy.unpackbits(lsbs).reshape((h, w // 2, 2, 4)), 3), 4) # Pair the LSB bits group to pixel 0 instead of pixel 1 lsbs = lsbs.reshape(h, w // 2, 2)[:, :, ::-1] lsbs = lsbs.reshape(h, w) @@ -243,7 +243,7 @@ def decompress_jpeg_to_rgb_image(jpeg_buffer): img = Image.open(io.BytesIO(jpeg_buffer)) w = img.size[0] h = img.size[1] - return numpy.array(img).reshape(h, w, 3) / 255.0 + return numpy.array(img).reshape((h, w, 3)) / 255.0 def convert_image_to_numpy_array(image_path): @@ -453,7 +453,7 @@ def convert_raw_to_rgb_image(r_plane, gr_plane, gb_plane, b_plane, props, img = (((img.reshape(h, w, 3) - black_levels) * scale) * gains).clip(0.0, 1.0) if apply_ccm_raw_to_rgb: img = numpy.dot( - img.reshape(w * h, 3), ccm.T).reshape(h, w, 3).clip(0.0, 1.0) + img.reshape(w * h, 3), ccm.T).reshape((h, w, 3)).clip(0.0, 1.0) return img @@ -938,7 +938,7 @@ class ImageProcessingUtilsTest(unittest.TestCase): ref_image = [0.1, 0.2, 0.3] lut_max = 65536 lut = numpy.array([i*2 for i in range(lut_max)]) - x = numpy.array(ref_image).reshape(1, 1, 3) + x = numpy.array(ref_image).reshape((1, 1, 3)) y = apply_lut_to_image(x, lut).reshape(3).tolist() y_ref = [i*2 for i in ref_image] self.assertTrue(numpy.allclose(y, y_ref, atol=1/lut_max)) diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py index 722f5860bdc..4a6cbf9af01 100644 --- a/apps/CameraITS/utils/its_session_utils.py +++ b/apps/CameraITS/utils/its_session_utils.py @@ -134,10 +134,10 @@ class ItsSession(object): try: socket_lock.bind((ItsSession.IPADDR, ItsSession.LOCK_PORT)) break - except (socket.error, socket.timeout): + except (socket.error, socket.timeout) as socket_issue: if i == num_retries - 1: - raise error_util.CameraItsError(self._device_id, - 'socket lock returns error') + raise error_util.CameraItsError( + self._device_id, 'socket lock returns error') from socket_issue else: time.sleep(retry_wait_time_sec) @@ -545,8 +545,9 @@ class ItsSession(object): VideoRecordingObject: { 'tag': 'recordingResponse', 'objValue': { - 'recordedOutputPath': '/storage/emulated/0/Android/data/com.android.cts.verifier' - '/files/VideoITS/VID_20220324_080414_0_CIF_352x288.mp4', + 'recordedOutputPath': '/storage/emulated/0/Android/data/' + 'com.android.cts.verifier/files/VideoITS/' + 'VID_20220324_080414_0_CIF_352x288.mp4', 'quality': 'preview', 'videoSize': '352x288' } @@ -1478,8 +1479,8 @@ def get_build_sdk_version(device_id): try: build_sdk_version = int(subprocess.check_output(cmd.split()).rstrip()) logging.debug('Build SDK version: %d', build_sdk_version) - except (subprocess.CalledProcessError, ValueError): - raise AssertionError('No build_sdk_version.') + except (subprocess.CalledProcessError, ValueError) as exp_errors: + raise AssertionError('No build_sdk_version.') from exp_errors return build_sdk_version diff --git a/apps/CameraITS/utils/sensor_fusion_utils.py b/apps/CameraITS/utils/sensor_fusion_utils.py index 0f83af96cda..327b2333e52 100644 --- a/apps/CameraITS/utils/sensor_fusion_utils.py +++ b/apps/CameraITS/utils/sensor_fusion_utils.py @@ -146,8 +146,9 @@ def canakit_cmd_send(canakit_serial_port, cmd_str): time.sleep(CANAKIT_CMD_TIME) # This is critical for relay. canakit_serial_port.write(cmd_str.encode()) - except IOError: - raise IOError(f'Port {CANAKIT_VID}:{CANAKIT_PID} is not open!') + except IOError as io_error: + raise IOError( + f'Port {CANAKIT_VID}:{CANAKIT_PID} is not open!') from io_error def canakit_set_relay_channel_state(canakit_port, ch, state): diff --git a/apps/CameraITS/utils/video_processing_utils.py b/apps/CameraITS/utils/video_processing_utils.py index b82e6c557fb..98d930bc90b 100644 --- a/apps/CameraITS/utils/video_processing_utils.py +++ b/apps/CameraITS/utils/video_processing_utils.py @@ -33,6 +33,7 @@ ITS_SUPPORTED_QUALITIES = ( 'LOW', 'VGA' ) +QCIF_SIZE = '176x144' def extract_key_frames_from_video(log_path, video_file_name): @@ -83,7 +84,7 @@ def extract_key_frames_from_video(log_path, video_file_name): logging.debug('Extracted key frames: %s', key_frame_files) logging.debug('Length of key_frame_files: %d', len(key_frame_files)) - if not len(key_frame_files): + if not key_frame_files: raise AssertionError('No key frames extracted. Check source video.') return key_frame_files @@ -142,7 +143,7 @@ def extract_all_frames_from_video(log_path, video_file_name, img_format): file_list = sorted( [_ for _ in os.listdir(log_path) if (_.endswith(img_format) and ffmpeg_image_name in _)]) - if not len(file_list): + if not file_list: raise AssertionError('No frames extracted. Check source video.') return file_list diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml index 0b3e811b9fb..35afa207584 100644 --- a/apps/CtsVerifier/AndroidManifest.xml +++ b/apps/CtsVerifier/AndroidManifest.xml @@ -105,7 +105,9 @@ <uses-permission android:name="android.permission.USE_EXACT_ALARM" /> <!-- Needed for Wi-Fi Direct tests from T --> - <uses-permission android:name="android.permission.NEARBY_WIFI_DEVICES" /> + <uses-permission + android:name="android.permission.NEARBY_WIFI_DEVICES" + android:usesPermissionFlags="neverForLocation" /> <!-- READ_LOGS User Consent Test from T --> <uses-permission android:name="android.permission.READ_LOGS" /> diff --git a/apps/CtsVerifier/res/layout-port/camera_video.xml b/apps/CtsVerifier/res/layout-port/camera_video.xml new file mode 100644 index 00000000000..2a90e67530a --- /dev/null +++ b/apps/CtsVerifier/res/layout-port/camera_video.xml @@ -0,0 +1,136 @@ +<?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. +--> + +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="fill_parent" + android:layout_height="fill_parent"> + + <LinearLayout + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" > + + <LinearLayout + android:orientation="vertical" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="2" > + + <Spinner + android:id="@+id/cameras_selection" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> + <Spinner + android:id="@+id/resolution_selection" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> + + <LinearLayout + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" > + + <Button + android:id="@+id/record_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/record_button_text"/> + <Button + android:id="@+id/next_button" + android:layout_height="wrap_content" + android:layout_width="wrap_content" + android:text="@string/next_button_text" /> + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="2" > + + <TextView + android:id="@+id/status_label" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/status_ready" + android:padding="2dp" + android:textSize="16sp" + android:gravity="center" /> + </LinearLayout> + + </LinearLayout> + + </LinearLayout> + + <LinearLayout + android:orientation="horizontal" + android:layout_width="fill_parent" + android:layout_height="0dp" + android:layout_weight="1" > + + <LinearLayout + android:orientation="vertical" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="3" + android:gravity="center" > + + <TextureView + android:id="@+id/video_capture" + android:layout_height="0dp" + android:layout_width="fill_parent" + android:layout_weight="3" /> + <TextView + android:id="@+id/camera_video_capture_label" + android:layout_height="wrap_content" + android:layout_width="fill_parent" + android:text="@string/video_capture_label" + android:padding="2dp" + android:textSize="16sp" + android:gravity="center" /> + + </LinearLayout> + <LinearLayout + android:orientation="vertical" + android:layout_width="0dp" + android:layout_height="fill_parent" + android:layout_weight="3" + android:gravity="center" > + + <VideoView + android:id="@+id/video_playback" + android:layout_height="0dp" + android:layout_width="fill_parent" + android:layout_weight="3" /> + <TextView + android:id="@+id/camera_video_playback_label" + android:layout_height="wrap_content" + android:layout_width="fill_parent" + android:text="@string/video_playback_label" + android:padding="2dp" + android:textSize="16sp" + android:gravity="center" /> + + </LinearLayout> + + </LinearLayout> + + <include layout="@layout/pass_fail_buttons" /> + +</LinearLayout> diff --git a/apps/CtsVerifier/res/layout/audio_dev_notify.xml b/apps/CtsVerifier/res/layout/audio_dev_notify.xml index e8f49ceaa93..6fa178df62a 100644 --- a/apps/CtsVerifier/res/layout/audio_dev_notify.xml +++ b/apps/CtsVerifier/res/layout/audio_dev_notify.xml @@ -38,6 +38,12 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> + <Button + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:id="@+id/audio_dev_notification_connect_clearmsgs_btn" + android:text="@string/audio_dev_notification_clearmsgs"/> + <TextView android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml index fd5eab1e781..d595bef2e78 100644 --- a/apps/CtsVerifier/res/values/strings.xml +++ b/apps/CtsVerifier/res/values/strings.xml @@ -6590,6 +6590,11 @@ Follow the instructions on the screen to measure the frequency response for the The Presence tests check whether or not a device is properly calibrated for BLE, NAN and UWB based on Presence requirements. \nAll tests are required to pass on every device, if the radio technology is supported </string> + <string name="presence_test_tv_info"> + The Presence tests check whether or not a device is properly calibrated for BLE, NAN and UWB based on Presence requirements. + \nAll tests are required to pass on all Android T+ launched TV devices, if the radio technology is supported. + \nIf the TV device is launched on older Android letters, all tests will be disabled. Press Pass to pass this case. + </string> <string name="uwb_precision">Uwb Precision Test</string> <string name="uwb_short_range">Uwb Short Range Test</string> <string name="uwb_precision_instruction"> diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/Utils.java new file mode 100644 index 00000000000..b6071d87be1 --- /dev/null +++ b/apps/CtsVerifier/src/com/android/cts/verifier/Utils.java @@ -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 com.android.cts.verifier; + +import android.content.ComponentName; + +/** + * Provides common helper methods. + */ +public final class Utils { + + /** + * Helper to get {@link #flattenToShortString()} in a {@link ComponentName} reference that can + * be {@code null}. + * + * @hide + */ + public static String flattenToShortString(ComponentName componentName) { + return componentName == null ? null : componentName.flattenToShortString(); + } + + private Utils() { + throw new UnsupportedOperationException("contains only static methods"); + } +} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java index a6709e786ad..9a5f314f07a 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputDeviceNotificationsActivity.java @@ -81,6 +81,17 @@ public class AudioInputDeviceNotificationsActivity extends AudioWiredDeviceBaseA mInfoView.setText(mContext.getResources().getString( R.string.audio_devices_notification_instructions)); + findViewById(R.id.audio_dev_notification_connect_clearmsgs_btn) + .setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mConnectView.setText(""); + mConnectReceived = false; + mDisconnectView.setText(""); + mDisconnectReceived = false; + calculatePass(); + } + }); + AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null); @@ -90,6 +101,8 @@ public class AudioInputDeviceNotificationsActivity extends AudioWiredDeviceBaseA setInfoResources(R.string.audio_in_devices_notifications_test, R.string.audio_in_devices_infotext, -1); setPassFailButtonClickListeners(); + + calculatePass(); } @Override diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java index 7399f33faeb..38d99b4b827 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioInputRoutingNotificationsActivity.java @@ -129,6 +129,7 @@ public class AudioInputRoutingNotificationsActivity extends AudioWiredDeviceBase AudioDeviceInfo routedDevice = audioRecord.getRoutedDevice(); CharSequence deviceName = routedDevice != null ? routedDevice.getProductName() : "none"; mConnectedPeripheralName = deviceName.toString(); + int deviceType = routedDevice != null ? routedDevice.getType() : -1; textView.setText(msg + " - " + deviceName + " [0x" + Integer.toHexString(deviceType) + "]" + @@ -156,8 +157,6 @@ public class AudioInputRoutingNotificationsActivity extends AudioWiredDeviceBase R.id.audio_routingnotification_testresult)).setText( "Test PASSES - No peripheral support"); } - - stopRecording(); } protected void storeTestResults() { diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java index c0f98d1c6b3..5fb51c4ebb0 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputDeviceNotificationsActivity.java @@ -81,6 +81,17 @@ public class AudioOutputDeviceNotificationsActivity extends AudioWiredDeviceBase mInfoView.setText(mContext.getResources().getString( R.string.audio_devices_notification_instructions)); + findViewById(R.id.audio_dev_notification_connect_clearmsgs_btn) + .setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + mConnectView.setText(""); + mConnectReceived = false; + mDisconnectView.setText(""); + mDisconnectReceived = false; + calculatePass(); + } + }); + AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); audioManager.registerAudioDeviceCallback(new TestAudioDeviceCallback(), null); @@ -90,6 +101,8 @@ public class AudioOutputDeviceNotificationsActivity extends AudioWiredDeviceBase setInfoResources(R.string.audio_out_devices_notifications_test, R.string.audio_out_devices_infotext, -1); setPassFailButtonClickListeners(); + + calculatePass(); } @Override diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java index e23ee17f25d..591fe9b6bd4 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioOutputRoutingNotificationsActivity.java @@ -160,8 +160,6 @@ public class AudioOutputRoutingNotificationsActivity extends AudioWiredDeviceBas R.id.audio_routingnotification_testresult)).setText( "Test PASSES - No peripheral support"); } - - stopPlayback(); } protected void storeTestResults() { diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java index 834839398e6..97813afe874 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioWiredDeviceBaseActivity.java @@ -35,7 +35,7 @@ abstract class AudioWiredDeviceBaseActivity extends PassFailButtons.Activity { private Button mSupportsBtn; private Button mDoesntSupportBtn; - protected boolean mSupportsWiredPeripheral; + protected boolean mSupportsWiredPeripheral = true; protected String mConnectedPeripheralName; protected abstract void enableTestButtons(boolean enabled); diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java index 406a3051c5d..e27ae0a0f11 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; +import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.hardware.Camera.PictureCallback; @@ -183,8 +184,9 @@ public class PhotoCaptureActivity extends Activity SelectableResolution resolution = mSupportedResolutions.get(position); switchToCamera(resolution, false); - // It should be guaranteed that the FOV is correctly updated after setParameters(). - mReportedFovPrePictureTaken = mCamera.getParameters().getHorizontalViewAngle(); + // It should be guaranteed that the FOV is correctly updated after + // setParameters(). + mReportedFovPrePictureTaken = getCameraFov(resolution.cameraId); mResolutionSpinnerIndex = position; startPreview(); @@ -271,8 +273,8 @@ public class PhotoCaptureActivity extends Activity @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getPictureFile(this); - Camera.Parameters params = mCamera.getParameters(); - mReportedFovDegrees = params.getHorizontalViewAngle(); + + mReportedFovDegrees = getCameraFov(mSelectedResolution.cameraId); // Show error if FOV does not match the value reported before takePicture(). if (mReportedFovPrePictureTaken != mReportedFovDegrees) { @@ -436,6 +438,36 @@ public class PhotoCaptureActivity extends Activity initializeCamera(true); } + private void setPreviewTransform(Size previewSize) { + int sensorRotation = mPreviewOrientation; + float selectedPreviewAspectRatio; + if (sensorRotation == 0 || sensorRotation == 180) { + selectedPreviewAspectRatio = (float) previewSize.width + / (float) previewSize.height; + } else { + selectedPreviewAspectRatio = (float) previewSize.height + / (float) previewSize.width; + } + + Matrix transform = new Matrix(); + float viewAspectRatio = (float) mPreviewView.getMeasuredWidth() + / (float) mPreviewView.getMeasuredHeight(); + float scaleX = 1.0f, scaleY = 1.0f; + float translateX = 0, translateY = 0; + if (selectedPreviewAspectRatio > viewAspectRatio) { + scaleY = viewAspectRatio / selectedPreviewAspectRatio; + translateY = (float) mPreviewView.getMeasuredHeight() / 2 + - (float) mPreviewView.getMeasuredHeight() * scaleY / 2; + } else { + scaleX = selectedPreviewAspectRatio / viewAspectRatio; + translateX = (float) mPreviewView.getMeasuredWidth() / 2 + - (float) mPreviewView.getMeasuredWidth() * scaleX / 2; + } + transform.postScale(scaleX, scaleY); + transform.postTranslate(translateX, translateY); + mPreviewView.setTransform(transform); + } + private void initializeCamera(boolean startPreviewAfterInit) { if (mCamera == null || mPreviewTexture == null) { return; @@ -470,6 +502,7 @@ public class PhotoCaptureActivity extends Activity if (selectedPreviewSize != null) { params.setPreviewSize(selectedPreviewSize.width, selectedPreviewSize.height); mCamera.setParameters(params); + setPreviewTransform(selectedPreviewSize); mCameraInitialized = true; } @@ -561,21 +594,25 @@ public class PhotoCaptureActivity extends Activity return result; } + private int getDisplayRotation() { + int displayRotation = getDisplay().getRotation(); + int displayRotationDegrees = 0; + switch (displayRotation) { + case Surface.ROTATION_0: displayRotationDegrees = 0; break; + case Surface.ROTATION_90: displayRotationDegrees = 90; break; + case Surface.ROTATION_180: displayRotationDegrees = 180; break; + case Surface.ROTATION_270: displayRotationDegrees = 270; break; + } + return displayRotationDegrees; + } + private void calculateOrientations(Activity activity, int cameraId, android.hardware.Camera camera) { android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(cameraId, info); - int rotation = activity.getWindowManager().getDefaultDisplay() - .getRotation(); - int degrees = 0; - switch (rotation) { - case Surface.ROTATION_0: degrees = 0; break; - case Surface.ROTATION_90: degrees = 90; break; - case Surface.ROTATION_180: degrees = 180; break; - case Surface.ROTATION_270: degrees = 270; break; - } + int degrees = getDisplayRotation(); if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { mJpegOrientation = (info.orientation + degrees) % 360; mPreviewOrientation = (360 - mJpegOrientation) % 360; // compensate the mirror @@ -603,4 +640,12 @@ public class PhotoCaptureActivity extends Activity } return false; } + + private float getCameraFov(int cameraId) { + if (mPreviewOrientation == 0 || mPreviewOrientation == 180) { + return mCamera.getParameters().getHorizontalViewAngle(); + } else { + return mCamera.getParameters().getVerticalViewAngle(); + } + } } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java index 5706610df0b..ef66b533a0e 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java @@ -20,6 +20,8 @@ import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME; import static android.app.admin.DevicePolicyManager.MAKE_USER_EPHEMERAL; import static android.app.admin.DevicePolicyManager.SKIP_SETUP_WIZARD; +import static com.android.cts.verifier.Utils.flattenToShortString; + import android.Manifest; import android.app.Activity; import android.app.ActivityManager; @@ -262,9 +264,9 @@ public class CommandReceiverActivity extends Activity { } break; case COMMAND_SET_STATUSBAR_DISABLED: { boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false); - Log.d(TAG, "calling setStatusBarDisabled(" - + ComponentName.flattenToShortString(mAdmin) + ", " + enforced - + ") using " + mDpm + " on user " + UserHandle.myUserId()); + Log.d(TAG, "calling setStatusBarDisabled(" + flattenToShortString(mAdmin) + + ", " + enforced + ") using " + mDpm + " on user " + + UserHandle.myUserId()); mDpm.setStatusBarDisabled(mAdmin, enforced); } break; case COMMAND_SET_LOCK_TASK_FEATURES: { diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java index e8a0cccfdab..67766931591 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java @@ -16,12 +16,18 @@ 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 @@ -29,8 +35,26 @@ public class PresenceTestActivity extends PassFailButtons.TestListActivity { super.onCreate(savedInstanceState); setContentView(R.layout.pass_fail_list); setPassFailButtonClickListeners(); - setInfoResources(R.string.presence_test, R.string.presence_test_info, -1); - setTestListAdapter( - new ManifestTestListAdapter(this, PresenceTestActivity.class.getName())); + + 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/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt index 2d109ba7a02..a3e391d231a 100644 --- a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt +++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/InputDeviceInfo.kt @@ -16,9 +16,7 @@ package com.android.compatibility.common.deviceinfo import android.content.Context - import androidx.test.core.app.ApplicationProvider - import com.android.compatibility.common.util.DeviceConfigStateManager import com.android.compatibility.common.util.DeviceInfoStore @@ -35,10 +33,11 @@ public final class InputDeviceInfo : DeviceInfo() { collectInputInfo(store, "input") } - private fun readDeviceConfig(namespace: String, name: String): String { + private fun readDeviceConfig(namespace: String, name: String, default: String): String { val context: Context = ApplicationProvider.getApplicationContext() val stateManager = DeviceConfigStateManager(context, namespace, name) - return stateManager.get()!! + val value = stateManager.get() + return if (value != null) value else default } /** @@ -47,10 +46,15 @@ public final class InputDeviceInfo : DeviceInfo() { private fun collectInputInfo(store: DeviceInfoStore, groupName: String) { store.startGroup(groupName) - val palmRejectionValue = readDeviceConfig("input_native_boot", "palm_rejection_enabled") + val palmRejectionValue = readDeviceConfig("input_native_boot", "palm_rejection_enabled", "") val palmRejectionEnabled = palmRejectionValue == "1" || palmRejectionValue == "true" store.addResult("palm_rejection_enabled", palmRejectionEnabled) + val velocityTrackerStrategyValue = readDeviceConfig( + "input_native_boot", "velocitytracker_strategy", "default" + ) + store.addResult("velocitytracker_strategy", velocityTrackerStrategyValue) + store.endGroup() } } diff --git a/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java b/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java index e7d954fa23a..9affccb9e35 100644 --- a/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java +++ b/hostsidetests/compilation/src/android/compilation/cts/BackgroundDexOptimizationTest.java @@ -82,6 +82,8 @@ public final class BackgroundDexOptimizationTest extends BaseHostJUnit4Test { // Uses internal consts defined in BackgroundDexOptService only for testing purpose. private static final int STATUS_OK = 0; private static final int STATUS_CANCELLED = 1; + // We allow package level failure in dexopt, which will lead into this error state. + private static final int STATUS_DEX_OPT_FAILED = 5; private ITestDevice mDevice; @@ -124,7 +126,7 @@ public final class BackgroundDexOptimizationTest extends BaseHostJUnit4Test { () -> getLastExecutionTime().duration >= 0); int status = getLastDexOptStatus(); - assertThat(status).isAnyOf(STATUS_OK, STATUS_CANCELLED); + assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED, STATUS_CANCELLED); if (status == STATUS_CANCELLED) { assertThat(checkFinishedPostBootUpdate()).isFalse(); // If cancelled, we can complete it by running it again. @@ -177,7 +179,7 @@ public final class BackgroundDexOptimizationTest extends BaseHostJUnit4Test { () -> getLastExecutionTime().duration >= 0); int status = getLastDexOptStatus(); - assertThat(status).isAnyOf(STATUS_OK, STATUS_CANCELLED); + assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED, STATUS_CANCELLED); if (status == STATUS_CANCELLED) { // If cancelled, we can complete it by running it again. completeIdleOptimization(); @@ -204,7 +206,7 @@ public final class BackgroundDexOptimizationTest extends BaseHostJUnit4Test { assertThat(timeAfter.startTime).isAtLeast(timeBefore.deviceCurrentTime); assertThat(timeAfter.duration).isAtLeast(0); int status = getLastDexOptStatus(); - assertThat(status).isEqualTo(STATUS_OK); + assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED); } private void completeIdleOptimization() throws Exception { @@ -220,7 +222,7 @@ public final class BackgroundDexOptimizationTest extends BaseHostJUnit4Test { }); int status = getLastDexOptStatus(); - assertThat(status).isEqualTo(STATUS_OK); + assertThat(status).isAnyOf(STATUS_OK, STATUS_DEX_OPT_FAILED); } @After diff --git a/hostsidetests/cpptools/Android.bp b/hostsidetests/cpptools/Android.bp index 90bf3a75ea2..f2a9ee5ec69 100644 --- a/hostsidetests/cpptools/Android.bp +++ b/hostsidetests/cpptools/Android.bp @@ -29,4 +29,10 @@ java_test_host { "cts", "general-tests", ], + data: [ + ":CtsCppToolsApp", + ":CtsDomainSocket", + ], + data_device_bins_both: ["connector"], + per_testcase_directory: true, } diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java index 0d0bd8f899a..c87a7f8d7f4 100644 --- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java +++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/DeviceOwnerTest.java @@ -32,6 +32,7 @@ import android.stats.devicepolicy.EventId; import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.RequiresAdditionalFeatures; +import com.android.cts.devicepolicy.DeviceAdminFeaturesCheckerRule.TemporarilyIgnoreOnHeadlessSystemUserMode; import com.android.cts.devicepolicy.metrics.DevicePolicyEventWrapper; import com.android.tradefed.log.LogUtil.CLog; @@ -342,6 +343,8 @@ public class DeviceOwnerTest extends BaseDeviceOwnerTest { executeCreateAndManageUserTest("testCreateAndManageUser_RemoveRestrictionSet"); } + @TemporarilyIgnoreOnHeadlessSystemUserMode(bugId = "220386262", + reason = "Often fails on automotive due to race condition") @Test public void testCreateAndManageUser_newUserDisclaimer() throws Exception { assumeCanStartNewUser(); diff --git a/hostsidetests/graphics/gpuprofiling/Android.bp b/hostsidetests/graphics/gpuprofiling/Android.bp index ff441bc21ac..b57dc9dd7e3 100644 --- a/hostsidetests/graphics/gpuprofiling/Android.bp +++ b/hostsidetests/graphics/gpuprofiling/Android.bp @@ -30,4 +30,9 @@ java_test_host { "perfetto_config-full", "platform-test-annotations-host", ], + data: [ + ":CtsGraphicsProfilingDataApp", + ], + data_device_bins_both: ["ctsgraphicsgpucountersinit"], + per_testcase_directory: true, } diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2022-20147/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2022-20147/Android.bp new file mode 100644 index 00000000000..62741e711c5 --- /dev/null +++ b/hostsidetests/securitybulletin/securityPatch/CVE-2022-20147/Android.bp @@ -0,0 +1,44 @@ +/* + * 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"], +} + +cc_test { + name: "CVE-2022-20147", + defaults: ["cts_hostsidetests_securitybulletin_defaults"], + srcs: [ + "poc.cpp", + ":cts_hostsidetests_securitybulletin_memutils", + ], + compile_multilib: "64", + shared_libs: [ + "libnfc-nci", + ], + include_dirs: [ + "system/nfc/src/nfa/include/", + "system/nfc/src/nfc/include/", + "system/nfc/src/include/", + "system/nfc/src/gki/common/", + "system/nfc/src/gki/ulinux/", + ], + cflags: [ + "-DCHECK_OVERFLOW", + "-DENABLE_SELECTIVE_OVERLOADING", + ], +} diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2022-20147/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2022-20147/poc.cpp new file mode 100644 index 00000000000..3d114e2592c --- /dev/null +++ b/hostsidetests/securitybulletin/securityPatch/CVE-2022-20147/poc.cpp @@ -0,0 +1,67 @@ +/* + * 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. + */ +#include "../includes/common.h" +#include "../includes/memutils.h" + +#include <nfa_dm_int.h> +#include <rw_int.h> +#include <unistd.h> + +constexpr size_t kBufferSize = 2; +constexpr size_t kLengthVal = 0x30; +char enable_selective_overload = ENABLE_NONE; +bool testInProgress = false; + +struct sigaction new_action, old_action; + +void sigsegv_handler(int signum, siginfo_t *info, void *context) { + if (testInProgress && info->si_signo == SIGSEGV) { + (*old_action.sa_sigaction)(signum, info, context); + return; + } + _exit(EXIT_FAILURE); +} + +void poc_cback(tRW_EVENT, tRW_DATA*) { +} + +int main() { + sigemptyset(&new_action.sa_mask); + new_action.sa_flags = SA_SIGINFO; + new_action.sa_sigaction = sigsegv_handler; + sigaction(SIGSEGV, &new_action, &old_action); + + tNFC_ACTIVATE_DEVT p_activate_params = { }; + p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP; + p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A; + RW_SetActivatedTagType(&p_activate_params, &poc_cback); + FAIL_CHECK(rw_cb.p_cback == &poc_cback); + + enable_selective_overload = ENABLE_ALL; + uint8_t *buffer = (uint8_t *)malloc(kBufferSize * sizeof(uint8_t)); + FAIL_CHECK(buffer); + buffer[0] = NFC_PMID_ATR_RES_GEN_BYTES; + buffer[1] = kLengthVal; + + testInProgress = true; + nfa_dm_check_set_config(kBufferSize, buffer, false); + enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK; + testInProgress = false; + + free(buffer); + + return EXIT_SUCCESS; +} 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 b2ed808c2f5..5532e4602a4 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java @@ -53,6 +53,6 @@ public class CVE_2021_0954 extends BaseHostJUnit4Test { installPackage(TEST_APP); AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW", device); - Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testVulnerableActivityPresence")); + runDeviceTests(TEST_PKG, TEST_CLASS, "testVulnerableActivityPresence"); } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java new file mode 100644 index 00000000000..41a727f857e --- /dev/null +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20147.java @@ -0,0 +1,63 @@ +/* + * 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.compatibility.common.util.CrashUtils; +import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern; +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; + +import java.util.regex.Pattern; + +import org.junit.runner.RunWith; +import org.junit.Test; + +@RunWith(DeviceJUnit4ClassRunner.class) +public class CVE_2022_20147 extends SecurityTestCase { + /** + * b/221216105 + * Vulnerability Behaviour: SIGSEGV in self + * Vulnerable Library: libnfc-nci (As per AOSP code) + * Vulnerable Function: nfa_dm_check_set_config (As per AOSP code) + */ + @AsbSecurityTest(cveBugId = 221216105) + @Test + public void testPocCVE_2022_20147() { + try { + AdbUtils.assumeHasNfc(getDevice()); + assumeIsSupportedNfcDevice(getDevice()); + pocPusher.only64(); + String signals[] = { CrashUtils.SIGSEGV }; + String binaryName = "CVE-2022-20147"; + AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, + getDevice()); + testConfig.config = new CrashUtils.Config() + .setProcessPatterns(Pattern.compile(binaryName)) + .setBacktraceIncludes(new BacktraceFilterPattern( + "libnfc-nci", "nfa_dm_check_set_config")); + testConfig.config.setBacktraceExcludes( + new BacktraceFilterPattern("libdl", "__cfi_slowpath")); + testConfig.config.setSignals(signals); + AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig); + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java index 06cf21a7068..c4d37b0ecb5 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/TestMedia.java @@ -238,7 +238,7 @@ public class TestMedia extends SecurityTestCase { @Test @AsbSecurityTest(cveBugId = 36104177) public void testPocCVE_2017_0670() throws Exception { - AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2017-0670", null, getDevice()); + AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2017-0670", getDevice(), 60); } /** 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 6e36fb32b79..f98690625e9 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 @@ -20,7 +20,9 @@ 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.Assume.assumeNoException; +import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.provider.Settings; @@ -70,7 +72,11 @@ public class DeviceTest { Intent intent = new Intent(); intent.setClassName(TEST_VULNERABLE_PKG, TEST_VULNERABLE_ACTIVITY); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); + try { + context.startActivity(intent); + } catch (ActivityNotFoundException e) { + assumeNoException("Activity not found on device", e); + } } @Before diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appcompatstate/AppCompatStateStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appcompatstate/AppCompatStateStatsTests.java index e192e72c5d7..9648d8cd4f9 100644 --- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appcompatstate/AppCompatStateStatsTests.java +++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appcompatstate/AppCompatStateStatsTests.java @@ -183,8 +183,9 @@ public class AppCompatStateStatsTests extends DeviceTestCase implements IBuildRe private void testAppCompatFlow(String activity, @Nullable String secondActivity, boolean switchToOpened, List<AppCompatStateChanged.State>... expectedStatesOptions) throws Exception { - if (!isOpenedDeviceStateAvailable()) { - CLog.i("Device doesn't support OPENED device state."); + if (!isDeviceStateAvailable(DEVICE_STATE_OPENED) + || !isDeviceStateAvailable(DEVICE_STATE_CLOSED)) { + CLog.i("Device doesn't support OPENED or CLOSED device states."); return; } @@ -238,10 +239,10 @@ public class AppCompatStateStatsTests extends DeviceTestCase implements IBuildRe return result; } - private boolean isOpenedDeviceStateAvailable() throws Exception { + private boolean isDeviceStateAvailable(int state) throws Exception { return Arrays.stream( getDevice().executeShellCommand(CMD_GET_AVAILABLE_DEVICE_STATES).split(",")) .map(Integer::valueOf) - .anyMatch(state -> state == DEVICE_STATE_OPENED); + .anyMatch(availableState -> availableState == state); } -}
\ No newline at end of file +} diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java index c7feda651c3..f07f9d34e64 100644 --- a/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java +++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/appops/AppOpsTests.java @@ -61,12 +61,13 @@ public class AppOpsTests extends DeviceTestCase implements IBuildReceiver { protected void setUp() throws Exception { super.setUp(); - mTransformedFromOp.clear(); - // The hotword op is allowed to all UIDs on TV and Auto devices. - if (!(DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE) - || DeviceUtils.hasFeature(getDevice(), FEATURE_LEANBACK_ONLY))) { - mTransformedFromOp.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD); - } + // Temporarily commented out until the Trusted Hotword requirement is enforced again. + // mTransformedFromOp.clear(); + // // The hotword op is allowed to all UIDs on TV and Auto devices. + // if (!(DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE) + // || DeviceUtils.hasFeature(getDevice(), FEATURE_LEANBACK_ONLY))) { + // mTransformedFromOp.put(APP_OP_RECORD_AUDIO, APP_OP_RECORD_AUDIO_HOTWORD); + // } assertThat(mCtsBuild).isNotNull(); ConfigUtils.removeConfig(getDevice()); diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java index b797e687cd7..a6aaebf9916 100644 --- a/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java +++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/sizecompatrestartbutton/SizeCompatRestartButtonStatsTests.java @@ -98,8 +98,9 @@ public class SizeCompatRestartButtonStatsTests extends DeviceTestCase implements } public void testSizeCompatRestartButtonAppearedButNotClicked() throws Exception { - if (!isOpenedDeviceStateAvailable()) { - CLog.i("Device doesn't support OPENED device state."); + if (!isDeviceStateAvailable(DEVICE_STATE_OPENED) + || !isDeviceStateAvailable(DEVICE_STATE_CLOSED)) { + CLog.i("Device doesn't support OPENED or CLOSED device states."); return; } @@ -120,11 +121,10 @@ public class SizeCompatRestartButtonStatsTests extends DeviceTestCase implements assertThat(atom.getEvent()).isEqualTo(Event.APPEARED); } - private boolean isOpenedDeviceStateAvailable() throws Exception { + private boolean isDeviceStateAvailable(int state) throws Exception { return Arrays.stream( getDevice().executeShellCommand(CMD_GET_AVAILABLE_DEVICE_STATES).split(",")) .map(Integer::valueOf) - .anyMatch(state -> state == DEVICE_STATE_OPENED); + .anyMatch(availableState -> availableState == state); } } - diff --git a/hostsidetests/sustainedperf/Android.bp b/hostsidetests/sustainedperf/Android.bp index 4d887e13ef6..97e101f239c 100644 --- a/hostsidetests/sustainedperf/Android.bp +++ b/hostsidetests/sustainedperf/Android.bp @@ -30,4 +30,10 @@ java_test_host { "tradefed", "compatibility-host-util", ], + data: [ + ":CtsSustainedPerformanceDeviceTestApp", + ":CtsSustainedPerformanceTestCases", + ], + data_device_bins_both: ["dhry"], + per_testcase_directory: true, } diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java index 7507d0abb7d..11b5fd40842 100644 --- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java +++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java @@ -1177,6 +1177,7 @@ public final class DevicePolicyManagerTest { @Test @EnsureHasPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS) @RequireDoesNotHaveFeature(FEATURE_MANAGED_USERS) + @RequireFeature(FEATURE_DEVICE_ADMIN) public void checkProvisioningPreCondition_actionPO_withoutManagedUserFeature_returnsManagedUsersNotSupported() { assertThat( sDevicePolicyManager.checkProvisioningPrecondition( diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java index 31bb8bf7f49..7e87fb40134 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java @@ -304,7 +304,7 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { EdgeExtensionActivity.class, extras); final Rect appBounds = getTopAppBounds(); assertColorChangeXIndex(screenshots, - (appBounds.left + appBounds.right) / 4 * 3, testBounds); + appBounds.left + (appBounds.right - appBounds.left) * 3 / 4, testBounds); } /** @@ -355,7 +355,7 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { EdgeExtensionActivity.class, extras); final Rect appBounds = getTopAppBounds(); assertColorChangeXIndex(screenshots, - (appBounds.left + appBounds.right) / 4, testBounds); + appBounds.left + (appBounds.right - appBounds.left) / 4, testBounds); } /** @@ -422,9 +422,7 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { boolean isTransitioning; do { getWmState().computeState(); - isTransitioning = - getWmState().getDefaultDisplayLastTransition().equals("TRANSIT_ACTIVITY_OPEN") - && getWmState().getDefaultDisplayAppTransitionState() + isTransitioning = getWmState().getDefaultDisplayAppTransitionState() .equals("APP_STATE_RUNNING"); SystemClock.sleep(10); } while (!isTransitioning); @@ -530,11 +528,15 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { } private boolean arrayEquals(float[] array1, float[] array2) { + return arrayEquals(array1, array2, COLOR_VALUE_VARIANCE_TOLERANCE); + } + + private boolean arrayEquals(float[] array1, float[] array2, float varianceTolerance) { if (array1.length != array2.length) { return true; } for (int i = 0; i < array1.length; i++) { - if (Math.abs(array1[i] - array2[i]) > COLOR_VALUE_VARIANCE_TOLERANCE) { + if (Math.abs(array1[i] - array2[i]) > varianceTolerance) { return true; } } @@ -593,13 +595,6 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { private AssertionResult assertColorChangeXIndex(Bitmap screen, int xIndex, TestBounds testBounds) { - final int colorChangeXIndex = getColorChangeXIndex(screen); - - if (xIndex != colorChangeXIndex) { - return new AssertionResult(true, "Expected color to change at x index " + xIndex - + " instead of " + colorChangeXIndex); - } - // The activity we are extending is a half red, half blue. // We are scaling the activity in the animation so if the extension doesn't work we should // have a blue, then red, then black section, and if it does work we should see on a blue, @@ -631,9 +626,13 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { sRgbColor = rawColor; } + // Increase tolerance on edge pixels since blending might occur there + final float varianceTolerance = Math.abs(x - xIndex) <= 1 + ? 0.5f : COLOR_VALUE_VARIANCE_TOLERANCE; if (arrayEquals(new float[]{ expectedColor.red(), expectedColor.green(), expectedColor.blue()}, - new float[]{sRgbColor.red(), sRgbColor.green(), sRgbColor.blue()})) { + new float[]{sRgbColor.red(), sRgbColor.green(), sRgbColor.blue()}, + varianceTolerance)) { return new ColorCheckResult(new Point(x, y), expectedColor, sRgbColor); } } @@ -642,25 +641,6 @@ public class ActivityTransitionTests extends ActivityManagerTestBase { return AssertionResult.SUCCESS; } - private int getColorChangeXIndex(Bitmap screen) { - // Look for color changing index at middle of app - final int y = - (getTopAppBounds().top + getTopAppBounds().bottom) / 2; - - Color prevColor = screen.getColor(0, y) - .convert(ColorSpace.get(ColorSpace.Named.SRGB)); - for (int x = 0; x < screen.getWidth(); x++) { - final Color c = screen.getColor(x, y) - .convert(ColorSpace.get(ColorSpace.Named.SRGB)); - - if (!colorsEqual(prevColor, c)) { - return x; - } - } - - return -1; - } - private boolean colorsEqual(Color c1, Color c2) { return almostEquals(c1.red(), c2.red(), COLOR_VALUE_VARIANCE_TOLERANCE) && almostEquals(c1.green(), c2.green(), COLOR_VALUE_VARIANCE_TOLERANCE) diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java index a667c9644e0..6e9d910d7e0 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentOrganizerTest.java @@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertThrows; +import static org.junit.Assume.assumeTrue; import android.app.Activity; import android.content.ComponentName; @@ -62,6 +63,7 @@ public class TaskFragmentOrganizerTest extends TaskFragmentOrganizerTestBase { */ @Test public void testCreateTaskFragment() { + assumeTrue("MultiWindow is not supported.", supportsMultiWindow()); mWmState.computeState(mOwnerActivityName); Task parentTask = mWmState.getRootTask(mOwnerActivity.getTaskId()); final int originalTaskFragCount = parentTask.getTaskFragments().size(); diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java index 669594d8428..e73ae81999d 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java @@ -756,8 +756,16 @@ public class WindowInputTests { final ExecutorService executor = Executors.newSingleThreadExecutor(); boolean[] securityExceptionCaught = new boolean[1]; + Exception[] illegalArgumentException = new Exception[1]; executor.execute(() -> { - mInstrumentation.sendPointerSync(eventDown); + try { + mInstrumentation.sendPointerSync(eventDown); + } catch (IllegalArgumentException e) { + // InputManagerService throws IllegalArgumentException when input target mismatch. + // Store the exception, and raise test failure later to avoid cts thread crash. + illegalArgumentException[0] = e; + return; + } for (int i = 0; i < 20; i++) { final long eventTime = SystemClock.uptimeMillis(); final MotionEvent eventMove = MotionEvent.obtain( @@ -766,8 +774,13 @@ public class WindowInputTests { mInstrumentation.sendPointerSync(eventMove); } catch (SecurityException e) { securityExceptionCaught[0] = true; + return; + } catch (IllegalArgumentException e) { + illegalArgumentException[0] = e; + return; } } + }); // Launch another activity, should not crash the process. @@ -783,6 +796,11 @@ public class WindowInputTests { // so the failure is thrown in the test thread. fail("Should be allowed to inject event."); } + + if (illegalArgumentException[0] != null) { + fail("Failed to inject event due to input target mismatch: " + + illegalArgumentException[0].getMessage()); + } } private void waitForWindow(String name) { diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java index 63956791808..8cc0b8efb54 100644 --- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java +++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java @@ -582,8 +582,8 @@ public class StylusHandwritingTest extends EndToEndImeTestBase { NOT_EXPECT_TIMEOUT); final int touchSlop = getTouchSlop(); - final int startX = 50; - final int startY = 50; + final int startX = editText.getWidth() / 2; + final int startY = editText.getHeight() / 2; final int endX = startX + 2 * touchSlop; final int endY = startY + 2 * touchSlop; final int number = 5; diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java index a687b6b46f8..a8d7947f98b 100644 --- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java +++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java @@ -1036,6 +1036,7 @@ public class LocationManagerFineTest { } @Test + @AppModeFull(reason = "Instant apps can't hold INTERACT_ACROSS_USERS permission") public void testAddProviderRequestListener() throws Exception { InstrumentationRegistry.getInstrumentation().getUiAutomation() .adoptShellPermissionIdentity(Manifest.permission.LOCATION_HARDWARE); diff --git a/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java b/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java new file mode 100644 index 00000000000..990d1deb11f --- /dev/null +++ b/tests/location/location_none/src/android/location/cts/none/LocationDisabledAppOpsTest.java @@ -0,0 +1,120 @@ +/* + * 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.location.cts.none; + +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.OPSTR_FINE_LOCATION; + +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.content.pm.PackageManager; +import android.location.LocationManager; +import android.os.PackageTagsList; +import android.os.Process; +import android.os.UserHandle; + +import androidx.test.InstrumentationRegistry; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class LocationDisabledAppOpsTest { + + 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 + 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<String> bypassedNoteOps = new ArrayList<>(); + List<String> bypassedCheckOps = new ArrayList<>(); + for (PackageInfo pi : mContext.getPackageManager().getInstalledPackagesAsUser( + 0, user.getIdentifier())) { + 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/media/src/android/mediav2/cts/CodecEncoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java index 5f176783d59..932af636d95 100644 --- a/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java +++ b/tests/media/src/android/mediav2/cts/CodecEncoderValidationTest.java @@ -142,6 +142,10 @@ public class CodecEncoderValidationTest extends CodecEncoderTestBase { if (!mIsAudio) { int colorFormat = mFormats.get(0).getInteger(MediaFormat.KEY_COLOR_FORMAT); Assume.assumeTrue(hasSupportForColorFormat(mCodecName, mMime, colorFormat)); + if (mUseHBD) { + Assume.assumeTrue("Codec doesn't support high bit depth profile encoding", + doesCodecSupportHDRProfile(mCodecName, mMime)); + } } checkFormatSupport(mCodecName, mMime, true, mFormats, null, CODEC_OPTIONAL); setUpSource(inputFile); diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java index 945a7dbf890..5f9aa09c891 100644 --- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java +++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java @@ -91,40 +91,31 @@ public class CodecInfoTest { /** * Tests if the devices on T or later, if decoder for a mediaType supports HDR profiles then - * it should be capable of displaying the same + * it should be capable of displaying the same. Since HLG profiles can't be distinguished from + * default 10-bit profiles, those are excluded from this test. */ @Test - @Ignore("TODO(b/228237404) Enable once display capabilities can be queried at codec2 level") public void testHDRDisplayCapabilities() { Assume.assumeTrue("Test needs Android 13", IS_AT_LEAST_T); Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/")); - Assume.assumeTrue("Test is applicable for codecs with HDR profiles", - mProfileHdrMap.containsKey(mMediaType)); - int[] HdrProfiles = mProfileHdrMap.get(mMediaType); + int[] Hdr10Profiles = mProfileHdr10Map.get(mMediaType); + int[] Hdr10PlusProfiles = mProfileHdr10PlusMap.get(mMediaType); + Assume.assumeTrue("Test is applicable for codecs with HDR10/HDR10+ profiles", + Hdr10Profiles != null || Hdr10PlusProfiles != null); + MediaCodecInfo.CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mMediaType); for (CodecProfileLevel pl : caps.profileLevels) { - if (IntStream.of(HdrProfiles).anyMatch(x -> x == pl.profile)) { - if (pl.profile == AV1ProfileMain10 || pl.profile == AVCProfileHigh10 || - pl.profile == HEVCProfileMain10 || pl.profile == VP9Profile2) { - assertTrue("Advertises support for HLG technology without HLG display", - IntStream.of(DISPLAY_HDR_TYPES).anyMatch(x -> x == HDR_TYPE_HLG)); - } else if (pl.profile == AV1ProfileMain10HDR10 || - pl.profile == HEVCProfileMain10HDR10 || pl.profile == VP9Profile2HDR) { - assertTrue(mCodecInfo.getName() + " Advertises support for HDR10 profile " + - pl.profile + " without HDR10 display", - IntStream.of(DISPLAY_HDR_TYPES).anyMatch(x -> x == HDR_TYPE_HDR10)); - } else if (pl.profile == AV1ProfileMain10HDR10Plus || - pl.profile == HEVCProfileMain10HDR10Plus || - pl.profile == VP9Profile2HDR10Plus) { - assertTrue(mCodecInfo.getName() + " Advertises support for HDR10+ profile " + - pl.profile + " without HDR10+ display", - IntStream.of(DISPLAY_HDR_TYPES) - .anyMatch(x -> x == HDR_TYPE_HDR10_PLUS)); - } else { - fail("Unhandled HDR profile" + pl.profile + " for type " + mMediaType); - } + boolean isHdr10Profile = Hdr10Profiles != null && + IntStream.of(Hdr10Profiles).anyMatch(x -> x == pl.profile); + boolean isHdr10PlusProfile = Hdr10PlusProfiles != null && + IntStream.of(Hdr10PlusProfiles).anyMatch(x -> x == pl.profile); + // TODO (b/228237404) Once there is a way to query support for HDR10/HDR10+ display at + // native level, separate the following to independent checks for HDR10 and HDR10+ + if (isHdr10Profile || isHdr10PlusProfile) { + assertTrue(mCodecInfo.getName() + " Advertises support for HDR10/HDR10+ profile " + + pl.profile + " without any HDR display", DISPLAY_HDR_TYPES.length > 0); } } } @@ -160,8 +151,8 @@ public class CodecInfoTest { // COLOR_FormatSurface support is an existing requirement, but we did not // test for it before T. We can not retroactively apply the higher standard to - // devices that are already certified, so only test on T or later devices. - if (IS_AT_LEAST_T) { + // devices that are already certified, so only test on VNDK T or later devices. + if (VNDK_IS_AT_LEAST_T) { assertFalse(mCodecInfo.getName() + " does not support COLOR_FormatSurface", IntStream.of(caps.colorFormats) .noneMatch(x -> x == COLOR_FormatSurface)); diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java index 11057991cb1..0368d882d36 100644 --- a/tests/media/src/android/mediav2/cts/CodecTestBase.java +++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java @@ -32,6 +32,7 @@ import android.media.MediaExtractor; import android.media.MediaFormat; import android.os.Build; import android.os.PersistableBundle; +import android.os.SystemProperties; import android.util.Log; import android.util.Pair; import android.view.Display; @@ -597,6 +598,8 @@ abstract class CodecTestBase { // TIRAMISU is set correctly public static final boolean FIRST_SDK_IS_AT_LEAST_T = ApiLevelUtil.isFirstApiAfter(Build.VERSION_CODES.S_V2); + public static final boolean VNDK_IS_AT_LEAST_T = + SystemProperties.getInt("ro.vndk.version", 0) > Build.VERSION_CODES.S_V2; private static final String LOG_TAG = CodecTestBase.class.getSimpleName(); enum SupportClass { CODEC_ALL, // All codecs must support diff --git a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java index e9a74faa359..9c722c4f03c 100644 --- a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java +++ b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java @@ -20,8 +20,11 @@ import android.media.MediaCodec; import android.media.MediaCodecList; import android.media.MediaFormat; import android.media.MediaMuxer; +import android.opengl.GLES20; import android.os.Build; import android.util.Log; +import android.util.Pair; +import android.view.Surface; import androidx.test.filters.SmallTest; @@ -39,7 +42,9 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface; import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010; +import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -54,22 +59,31 @@ public class EncoderColorAspectsTest extends CodecEncoderTestBase { private int mStandard; private int mTransferCurve; private boolean mUseHighBitDepth; + private boolean mSurfaceMode; + + private Surface mInpSurface; + private EGLWindowSurface mEGLWindowInpSurface; private MediaFormat mConfigFormat; private MediaMuxer mMuxer; private int mTrackID = -1; + private int mLatency; + private boolean mReviseLatency; + private ArrayList<String> mCheckESList = new ArrayList<>(); private static boolean sIsAtLeastR = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R); public EncoderColorAspectsTest(String encoderName, String mime, int width, int height, - int range, int standard, int transferCurve, boolean useHighBitDepth) { + int range, int standard, int transferCurve, boolean useHighBitDepth, + boolean surfaceMode) { super(encoderName, mime, new int[]{64000}, new int[]{width}, new int[]{height}); mRange = range; mStandard = standard; mTransferCurve = transferCurve; mUseHighBitDepth = useHighBitDepth; + mSurfaceMode = surfaceMode; mWidth = width; mHeight = height; setUpParams(1); @@ -113,7 +127,10 @@ public class EncoderColorAspectsTest extends CodecEncoderTestBase { if (!stringArgsList.contains(currentObject)) { exhaustiveArgsList .add(new Object[]{mediaType, 176, 144, range, standard, - transfer, useHighBitDepth}); + transfer, useHighBitDepth, false}); + exhaustiveArgsList + .add(new Object[]{mediaType, 176, 144, range, standard, + transfer, useHighBitDepth, true}); stringArgsList.add(currentObject); } } @@ -122,7 +139,7 @@ public class EncoderColorAspectsTest extends CodecEncoderTestBase { } } - @Parameterized.Parameters(name = "{index}({0}_{1}_{4}_{5}_{6})") + @Parameterized.Parameters(name = "{index}({0}_{1}_{4}_{5}_{6}_{7}_{8})") public static Collection<Object[]> input() { final boolean isEncoder = true; final boolean needAudio = false; @@ -170,19 +187,109 @@ public class EncoderColorAspectsTest extends CodecEncoderTestBase { return CodecTestBase .prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false); } + private long computePresentationTime(int frameIndex) { + return frameIndex * 1000000 / mFrameRate; + } + + private void generateSurfaceFrame() { + GLES20.glViewport(0, 0, mWidth, mHeight); + GLES20.glEnable(GLES20.GL_SCISSOR_TEST); + GLES20.glClearColor(128.0f, 128.0f, 128.0f, 1.0f); + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + } + + private void tryEncoderOutput(long timeOutUs) throws InterruptedException { + if (!mAsyncHandle.hasSeenError() && !mSawOutputEOS) { + int retry = 0; + while (mReviseLatency) { + if (mAsyncHandle.hasOutputFormatChanged()) { + mReviseLatency = false; + int actualLatency = mAsyncHandle.getOutputFormat() + .getInteger(MediaFormat.KEY_LATENCY, mLatency); + if (mLatency < actualLatency) { + mLatency = actualLatency; + return; + } + } else { + if (retry > RETRY_LIMIT) { + throw new InterruptedException( + "did not receive output format changed for encoder after " + + Q_DEQ_TIMEOUT_US * RETRY_LIMIT + " us"); + } + Thread.sleep(Q_DEQ_TIMEOUT_US / 1000); + retry++; + } + } + Pair<Integer, MediaCodec.BufferInfo> element = mAsyncHandle.getOutput(); + if (element != null) { + dequeueOutput(element.first, element.second); + } + } + } + + void queueEOS() throws InterruptedException { + if (!mSurfaceMode) { + super.queueEOS(); + } else { + if (!mAsyncHandle.hasSeenError() && !mSawInputEOS) { + mCodec.signalEndOfInputStream(); + mSawInputEOS = true; + if (ENABLE_LOGS) Log.d(LOG_TAG, "signalled end of stream"); + } + } + } + + void doWork(int frameLimit) throws IOException, InterruptedException { + if (!mSurfaceMode) { + super.doWork(frameLimit); + } else { + while (!mAsyncHandle.hasSeenError() && !mSawInputEOS && + mInputCount < frameLimit) { + if (mInputCount - mOutputCount > mLatency) { + tryEncoderOutput(CodecTestBase.Q_DEQ_TIMEOUT_US); + } + mEGLWindowInpSurface.makeCurrent(); + generateSurfaceFrame(); + mEGLWindowInpSurface + .setPresentationTime(computePresentationTime(mInputCount) * 1000); + if (ENABLE_LOGS) Log.d(LOG_TAG, "inputSurface swapBuffers"); + mEGLWindowInpSurface.swapBuffers(); + mInputCount++; + } + } + } @SmallTest @Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS) public void testColorAspects() throws IOException, InterruptedException { Assume.assumeTrue("Test introduced with Android 11", sIsAtLeastR); - String inputTestFile = mInputFile; if (mUseHighBitDepth) { - Assume.assumeTrue(hasSupportForColorFormat(mCodecName, mMime, COLOR_FormatYUVP010)); - mConfigFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUVP010); - mBytesPerSample = 2; - inputTestFile = INPUT_VIDEO_FILE_HBD; + // Check if encoder is capable of supporting HDR profiles. + // Previous check doesn't verify this as profile isn't set in the format + Assume.assumeTrue(mCodecName + " doesn't support HDR encoding", + CodecTestBase.doesCodecSupportHDRProfile(mCodecName, mMime)); + + // Encoder surface mode tests are to be enabled only if an encoder supports + // COLOR_Format32bitABGR2101010 + if (mSurfaceMode) { + Assume.assumeTrue(mCodecName + " doesn't support RGBA1010102", + hasSupportForColorFormat(mCodecName, mMime, COLOR_Format32bitABGR2101010)); + } + } + + if (mSurfaceMode) { + mConfigFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface); + } else { + String inputTestFile = mInputFile; + if (mUseHighBitDepth) { + Assume.assumeTrue(hasSupportForColorFormat(mCodecName, mMime, COLOR_FormatYUVP010)); + mConfigFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUVP010); + mBytesPerSample = 2; + inputTestFile = INPUT_VIDEO_FILE_HBD; + } + setUpSource(inputTestFile); } - setUpSource(inputTestFile); + mOutputBuff = new OutputManager(); { mCodec = MediaCodec.createByCodecName(mCodecName); @@ -205,7 +312,19 @@ public class EncoderColorAspectsTest extends CodecEncoderTestBase { tmpFile = File.createTempFile("tmp" + (mUseHighBitDepth ? "10bit" : ""), ".mp4"); } mMuxer = new MediaMuxer(tmpFile.getAbsolutePath(), muxerFormat); - configureCodec(mConfigFormat, false, true, true); + // When in surface mode, encoder needs to be configured in async mode + boolean isAsync = mSurfaceMode; + configureCodec(mConfigFormat, isAsync, true, true); + + if (mSurfaceMode) { + mInpSurface = mCodec.createInputSurface(); + assertTrue("Surface is not valid", mInpSurface.isValid()); + mEGLWindowInpSurface = new EGLWindowSurface(mInpSurface, mUseHighBitDepth); + if (mCodec.getInputFormat().containsKey(MediaFormat.KEY_LATENCY)) { + mReviseLatency = true; + mLatency = mCodec.getInputFormat().getInteger(MediaFormat.KEY_LATENCY); + } + } mCodec.start(); doWork(4); queueEOS(); @@ -218,6 +337,16 @@ public class EncoderColorAspectsTest extends CodecEncoderTestBase { mMuxer.release(); mMuxer = null; } + + if (mEGLWindowInpSurface != null) { + mEGLWindowInpSurface.release(); + mEGLWindowInpSurface = null; + } + if (mInpSurface != null) { + mInpSurface.release(); + mInpSurface = null; + } + assertTrue(log + "unexpected error", !mAsyncHandle.hasSeenError()); assertTrue(log + "no input sent", 0 != mInputCount); assertTrue(log + "output received", 0 != mOutputCount); diff --git a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java index a6a36882fd6..26c6eb55920 100644 --- a/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java +++ b/tests/media/src/android/mediav2/cts/EncoderHDRInfoTest.java @@ -82,11 +82,12 @@ public class EncoderHDRInfoTest extends CodecEncoderTestBase { super.enqueueInput(bufferIndex); } void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { + MediaFormat bufferFormat = mCodec.getOutputFormat(bufferIndex); if (info.size > 0) { ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex); if (mMuxer != null) { if (mTrackID == -1) { - mTrackID = mMuxer.addTrack(mCodec.getOutputFormat()); + mTrackID = mMuxer.addTrack(bufferFormat); mMuxer.start(); } mMuxer.writeSampleData(mTrackID, buf, info); @@ -95,7 +96,7 @@ public class EncoderHDRInfoTest extends CodecEncoderTestBase { super.dequeueOutput(bufferIndex, info); // verify if the out fmt contains HDR Dynamic metadata as expected if (mTestDynamicMetadata && mOutputCount > 0) { - validateHDRDynamicMetaData(mCodec.getOutputFormat(), + validateHDRDynamicMetaData(bufferFormat, ByteBuffer.wrap(loadByteArrayFromString(HDR_DYNAMIC_INFO[mOutputCount - 1]))); } } 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 1c3a4ddfc83..327fb9cf6c9 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java @@ -20,10 +20,13 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assume.assumeTrue; +import android.media.MediaFormat; import android.os.Build; import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Arrays; import org.junit.rules.TestName; import java.util.HashSet; @@ -90,36 +93,17 @@ public class PerformanceClassEvaluator { .setId(RequirementConstants.LONG_RESOLUTION) .setPredicate(RequirementConstants.INTEGER_GTE) .addRequiredValue(Build.VERSION_CODES.S, 1920) - .build(); - RequiredMeasurement<Integer> short_resolution = RequiredMeasurement - .<Integer>builder() - .setId(RequirementConstants.SHORT_RESOLUTION) - .setPredicate(RequirementConstants.INTEGER_GTE) - .addRequiredValue(Build.VERSION_CODES.S, 1080) - .build(); - - return new ResolutionRequirement(RequirementConstants.R7_1_1_1__H_2_1, long_resolution, - short_resolution); - } - - /** - * [7.1.1.1/?] MUST have screen resolution of at least 1080p. - */ - public static ResolutionRequirement createR7_1_1_1__TBD1() { - RequiredMeasurement<Integer> long_resolution = RequiredMeasurement - .<Integer>builder() - .setId(RequirementConstants.LONG_RESOLUTION) - .setPredicate(RequirementConstants.INTEGER_GTE) .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1920) .build(); RequiredMeasurement<Integer> short_resolution = RequiredMeasurement .<Integer>builder() .setId(RequirementConstants.SHORT_RESOLUTION) .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.S, 1080) .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1080) .build(); - return new ResolutionRequirement(RequirementConstants.RTBD, long_resolution, + return new ResolutionRequirement(RequirementConstants.R7_1_1_1__H_2_1, long_resolution, short_resolution); } } @@ -159,27 +143,14 @@ public class PerformanceClassEvaluator { .setId(RequirementConstants.DISPLAY_DENSITY) .setPredicate(RequirementConstants.INTEGER_GTE) .addRequiredValue(Build.VERSION_CODES.S, 400) - .build(); - - return new DensityRequirement(RequirementConstants.R7_1_1_3__H_2_1, display_density); - } - - /** - * [7.1.1.3/?] MUST have screen density of at least 400 dpi. - */ - public static DensityRequirement createR7_1_1_3__TBD2() { - RequiredMeasurement<Integer> display_density = RequiredMeasurement - .<Integer>builder() - .setId(RequirementConstants.DISPLAY_DENSITY) - .setPredicate(RequirementConstants.INTEGER_GTE) .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 400) .build(); - return new DensityRequirement(RequirementConstants.RTBD, display_density); + return new DensityRequirement(RequirementConstants.R7_1_1_3__H_2_1, display_density); } } - // used for requirements [7.6.1/H-1-1], [7.6.1/H-2-1], [7.6.1/H-3-1] + // used for requirements [7.6.1/H-1-1], [7.6.1/H-2-1] public static class MemoryRequirement extends Requirement { private static final String TAG = MemoryRequirement.class.getSimpleName(); @@ -208,39 +179,23 @@ public class PerformanceClassEvaluator { } /** - * [7.6.1/H-2-1] MUST have at least 6 GB of physical memory. + * [7.6.1/H-2-1] MUST have at least 6/8 GB of physical memory. */ public static MemoryRequirement createR7_6_1__H_2_1() { RequiredMeasurement<Long> physical_memory = RequiredMeasurement .<Long>builder() .setId(RequirementConstants.PHYSICAL_MEMORY) .setPredicate(RequirementConstants.LONG_GTE) - // Media performance requires 6 GB minimum RAM, but keeping the following to 5 GB - // as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device. + // Media performance requires 6/8 GB minimum RAM, but keeping the following to + // 5/7 GB as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device. .addRequiredValue(Build.VERSION_CODES.S, 5L * 1024L) - .build(); - - return new MemoryRequirement(RequirementConstants.R7_6_1__H_2_1, physical_memory); - } - - /** - * [7.6.1/H-3-1] MUST have at least 8 GB of physical memory. - */ - public static MemoryRequirement createR7_6_1__H_3_1() { - RequiredMeasurement<Long> physical_memory = RequiredMeasurement - .<Long>builder() - .setId(RequirementConstants.PHYSICAL_MEMORY) - .setPredicate(RequirementConstants.LONG_GTE) - // Media performance requires 8 GB minimum RAM, but keeping the following to 7 GB - // as activityManager.getMemoryInfo() returns around 7.4 GB on a 8 GB device. .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 7L * 1024L) .build(); - return new MemoryRequirement(RequirementConstants.R7_6_1__H_3_1, physical_memory); + return new MemoryRequirement(RequirementConstants.R7_6_1__H_2_1, physical_memory); } } - // used for requirements [2.2.7.1/5.1/H-1-7], [2.2.7.1/5.1/H-1-8], [2.2.7.1/5.1/H-1-?] public static class CodecInitLatencyRequirement extends Requirement { private static final String TAG = CodecInitLatencyRequirement.class.getSimpleName(); @@ -293,40 +248,38 @@ public class PerformanceClassEvaluator { codec_init_latency); } - // TODO(b/218771970): Update CDD section, change RequirementConstants.RTBD to appropirate - // requirement id once finalized, ex: RequirementConstants.R5_1__H_1_<something> /** - * [2.2.7.1/5.1/H-1-?] Codec initialization latency of 40ms or less for a 1080p or + * [2.2.7.1/5.1/H-1-12] Codec initialization latency of 40ms or less for a 1080p or * smaller video decoding session for all hardware video encoders when under load. Load * here is defined as a concurrent 1080p to 720p video-only transcoding session using * hardware video codecs together with the 1080p audio-video recording initialization. */ - public static CodecInitLatencyRequirement createR5_1__H_1_TBD1() { + public static CodecInitLatencyRequirement createR5_1__H_1_12() { RequiredMeasurement<Long> codec_init_latency = RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY) .setPredicate(RequirementConstants.LONG_LTE) .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 40L) .build(); - return new CodecInitLatencyRequirement(RequirementConstants.RTBD, codec_init_latency); + return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_12, + codec_init_latency); } - // TODO(b/218771970): Update CDD section, change RequirementConstants.RTBD to appropirate - // requirement id once finalized, ex: RequirementConstants.R5_1__H_1_<something> /** - * [2.2.7.1/5.1/H-1-?] Codec initialization latency of 30ms or less for a 128kbps or + * [2.2.7.1/5.1/H-1-13] Codec initialization latency of 30ms or less for a 128kbps or * lower bitrate audio decoding session for all audio encoders when under load. Load here * is defined as a concurrent 1080p to 720p video-only transcoding session using hardware * video codecs together with the 1080p audio-video recording initialization. */ - public static CodecInitLatencyRequirement createR5_1__H_1_TBD2() { + public static CodecInitLatencyRequirement createR5_1__H_1_13() { RequiredMeasurement<Long> codec_init_latency = RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY) .setPredicate(RequirementConstants.LONG_LTE) .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 30L) .build(); - return new CodecInitLatencyRequirement(RequirementConstants.RTBD, codec_init_latency); + return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_13, + codec_init_latency); } } @@ -455,9 +408,6 @@ public class PerformanceClassEvaluator { } } - // TODO(b/218771970): Add cdd annotation, change RequirementConstants.RTBD to appropirate - // requirement id once finalized - // used for requirements [?] public static class VideoCodecRequirement extends Requirement { private static final String TAG = VideoCodecRequirement.class.getSimpleName(); @@ -478,7 +428,7 @@ public class PerformanceClassEvaluator { } /** - * [?] Must have at least 1 HW video decoder supporting 4K60 + * [2.2.7.1/5.1/H-1-15] Must have at least 1 HW video decoder supporting 4K60 */ public static VideoCodecRequirement createR4k60HwDecoder() { RequiredMeasurement<Integer> requirement = RequiredMeasurement @@ -488,11 +438,11 @@ public class PerformanceClassEvaluator { .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1) .build(); - return new VideoCodecRequirement(RequirementConstants.RTBD, requirement); + return new VideoCodecRequirement(RequirementConstants.R5_1__H_1_15, requirement); } /** - * [?] Must have at least 1 HW video encoder supporting 4K60 + * [2.2.7.1/5.1/H-1-16] Must have at least 1 HW video encoder supporting 4K60 */ public static VideoCodecRequirement createR4k60HwEncoder() { RequiredMeasurement<Integer> requirement = RequiredMeasurement @@ -502,11 +452,11 @@ public class PerformanceClassEvaluator { .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1) .build(); - return new VideoCodecRequirement(RequirementConstants.RTBD, requirement); + return new VideoCodecRequirement(RequirementConstants.R5_1__H_1_16, requirement); } /** - * [?] AV1 Hardware decoder: Main 10, Level 4.1, Film Grain + * [2.2.7.1/5.1/H-1-14] AV1 Hardware decoder: Main 10, Level 4.1, Film Grain */ public static VideoCodecRequirement createRAV1DecoderReq() { RequiredMeasurement<Boolean> requirement = RequiredMeasurement @@ -516,87 +466,378 @@ public class PerformanceClassEvaluator { .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) .build(); - return new VideoCodecRequirement(RequirementConstants.RTBD, requirement); + return new VideoCodecRequirement(RequirementConstants.R5_1__H_1_14, requirement); } } - // TODO(b/218771970): Add cdd annotation - // used for requirements [?] - public static class SecureCodecRequirement extends Requirement { - private static final String TAG = SecureCodecRequirement.class.getSimpleName(); + // used for requirements [2.2.7.1/5.1/H-1-1], [2.2.7.1/5.1/H-1-2], [2.2.7.1/5.1/H-1-3], + // [2.2.7.1/5.1/H-1-4], [2.2.7.1/5.1/H-1-5], [2.2.7.1/5.1/H-1-6], [2.2.7.1/5.1/H-1-9], + // [2.2.7.1/5.1/H-1-10] + public static class ConcurrentCodecRequirement extends Requirement { + private static final String TAG = ConcurrentCodecRequirement.class.getSimpleName(); + // allowed tolerance in measured fps vs expected fps in percentage, i.e. codecs achieving + // fps that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as + // passing the test + private static final double FPS_TOLERANCE_FACTOR = 0.95; + private static final double FPS_30_TOLERANCE = 30.0 * FPS_TOLERANCE_FACTOR; + static final int REQUIRED_MIN_CONCURRENT_INSTANCES = 6; + static final int REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 = 2; - private SecureCodecRequirement(String id, RequiredMeasurement<?> ... reqs) { + private ConcurrentCodecRequirement(String id, RequiredMeasurement<?> ... reqs) { super(id, reqs); } - public void setSecureReqSatisfied(boolean secureReqSatisfied) { - this.setMeasuredValue(RequirementConstants.SECURE_REQ_SATISFIED, secureReqSatisfied); + public void setConcurrentInstances(int concurrentInstances) { + this.setMeasuredValue(RequirementConstants.CONCURRENT_SESSIONS, + concurrentInstances); + } + + public void setConcurrentFps(double achievedFps) { + this.setMeasuredValue(RequirementConstants.CONCURRENT_FPS, achievedFps); + } + + // copied from android.mediapc.cts.getReqMinConcurrentInstances due to build issues on aosp + public static int getReqMinConcurrentInstances(int performanceClass, String mimeType1, + String mimeType2, int resolution) { + ArrayList<String> MEDIAPC_CONCURRENT_CODECS_R = new ArrayList<>( + Arrays.asList(MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC)); + ArrayList<String> MEDIAPC_CONCURRENT_CODECS = new ArrayList<>(Arrays + .asList(MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC, + MediaFormat.MIMETYPE_VIDEO_VP9, MediaFormat.MIMETYPE_VIDEO_AV1)); + + if (performanceClass >= Build.VERSION_CODES.TIRAMISU) { + return resolution >= 1080 ? REQUIRED_MIN_CONCURRENT_INSTANCES : 0; + } else if (performanceClass == Build.VERSION_CODES.S) { + if (resolution >= 1080) { + return 0; + } + if (MEDIAPC_CONCURRENT_CODECS.contains(mimeType1) && MEDIAPC_CONCURRENT_CODECS + .contains(mimeType2)) { + if (MediaFormat.MIMETYPE_VIDEO_VP9.equalsIgnoreCase(mimeType1) + || MediaFormat.MIMETYPE_VIDEO_VP9.equalsIgnoreCase(mimeType2)) { + return REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9; + } else { + return REQUIRED_MIN_CONCURRENT_INSTANCES; + } + } else { + return 0; + } + } else if (performanceClass == Build.VERSION_CODES.R) { + if (resolution >= 1080) { + return 0; + } + if (MEDIAPC_CONCURRENT_CODECS_R.contains(mimeType1) && MEDIAPC_CONCURRENT_CODECS_R + .contains(mimeType2)) { + return REQUIRED_MIN_CONCURRENT_INSTANCES; + } else { + return 0; + } + } else { + return 0; + } + } + + private static double getReqMinConcurrentFps(int performanceClass, String mimeType1, + String mimeType2, int resolution) { + return FPS_30_TOLERANCE * getReqMinConcurrentInstances(performanceClass, mimeType1, + mimeType2, resolution); } - public void setWidevineSupported(boolean isWidevineSupported) { - this.setMeasuredValue(RequirementConstants.WIDEWINE_SUPPORT, isWidevineSupported); + /** + * [2.2.7.1/5.1/H-1-1] MUST advertise the maximum number of hardware video decoder + * sessions that can be run concurrently in any codec combination via the + * CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities + * .getSupportedPerformancePoints() methods. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_1_720p(String mimeType1, + String mimeType2, int resolution) { + RequiredMeasurement<Integer> maxInstances = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.CONCURRENT_SESSIONS) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.R, + getReqMinConcurrentInstances(Build.VERSION_CODES.R, mimeType1, mimeType2, + resolution)) + .addRequiredValue(Build.VERSION_CODES.S, + getReqMinConcurrentInstances(Build.VERSION_CODES.S, mimeType1, mimeType2, + resolution)) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_1, maxInstances); } - public void setWidevineL1Supported(boolean isL1Supported) { - this.setMeasuredValue(RequirementConstants.WIDEWINE_L1, isL1Supported); + /** + * [2.2.7.1/5.1/H-1-1] MUST advertise the maximum number of hardware video decoder + * sessions that can be run concurrently in any codec combination via the + * CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities + * .getSupportedPerformancePoints() methods. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_1_1080p() { + RequiredMeasurement<Integer> maxInstances = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.CONCURRENT_SESSIONS) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_1, maxInstances); } - public void setWidevineL1Tier3Supported(boolean isL1Tier3Supported) { - this.setMeasuredValue(RequirementConstants.WIDEWINE_L1_TIER3, isL1Tier3Supported); + /** + * [2.2.7.1/5.1/H-1-2] MUST support 6 instances of hardware video decoder sessions (AVC, + * HEVC, VP9* or later) in any codec combination running concurrently at 720p(R,S) + * resolution@30 fps. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_2_720p(String mimeType1, + String mimeType2, int resolution) { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + .addRequiredValue(Build.VERSION_CODES.R, + getReqMinConcurrentFps(Build.VERSION_CODES.R, mimeType1, mimeType2, resolution)) + .addRequiredValue(Build.VERSION_CODES.S, + getReqMinConcurrentFps(Build.VERSION_CODES.S, mimeType1, mimeType2, resolution)) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_2, + reqConcurrentFps); } - public void setOemCrypto17Plus(boolean isOemCrypto17Plus) { - this.setMeasuredValue(RequirementConstants.OEM_CRYPTO_17_PLUS, isOemCrypto17Plus); + /** + * [2.2.7.1/5.1/H-1-2] MUST support 6 instances of hardware video decoder sessions (AVC, + * HEVC, VP9* or later) in any codec combination running concurrently at 1080p(T) + * resolution@30 fps. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_2_1080p() { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6 * FPS_30_TOLERANCE) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_2, + reqConcurrentFps); } - public void setWidevineCdm17Plus(boolean isWidevineCdm17Plus) { - this.setMeasuredValue(RequirementConstants.WIDEWINE_CDM_17_PLUS, isWidevineCdm17Plus); + /** + * [2.2.7.1/5.1/H-1-3] MUST advertise the maximum number of hardware video encoder + * sessions that can be run concurrently in any codec combination via the + * CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities + * .getSupportedPerformancePoints() methods. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_3_720p(String mimeType1, + String mimeType2, int resolution) { + RequiredMeasurement<Integer> maxInstances = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.CONCURRENT_SESSIONS) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.R, + getReqMinConcurrentInstances(Build.VERSION_CODES.R, mimeType1, mimeType2, + resolution)) + .addRequiredValue(Build.VERSION_CODES.S, + getReqMinConcurrentInstances(Build.VERSION_CODES.S, mimeType1, mimeType2, + resolution)) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_3, maxInstances); } /** - * [?] Support for Widevine L1 Tier 3, WidevineCdmVersion >= 17, OemCryptoVersion >= 17 + * [2.2.7.1/5.1/H-1-3] MUST advertise the maximum number of hardware video encoder + * sessions that can be run concurrently in any codec combination via the + * CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities + * .getSupportedPerformancePoints() methods. */ - public static SecureCodecRequirement createRWidevineSupport() { - RequiredMeasurement<Boolean> widevineSupport = RequiredMeasurement - .<Boolean>builder() - .setId(RequirementConstants.WIDEWINE_SUPPORT) - .setPredicate(RequirementConstants.BOOLEAN_EQ) - .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + public static ConcurrentCodecRequirement createR5_1__H_1_3_1080p() { + RequiredMeasurement<Integer> maxInstances = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.CONCURRENT_SESSIONS) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6) .build(); - RequiredMeasurement<Boolean> widevineL1 = - RequiredMeasurement.<Boolean>builder().setId(RequirementConstants.WIDEWINE_L1) - .setPredicate(RequirementConstants.BOOLEAN_EQ) - .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) - .build(); + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_3, maxInstances); + } - RequiredMeasurement<Boolean> widevineL1Tier3 = - RequiredMeasurement.<Boolean>builder().setId(RequirementConstants.WIDEWINE_L1_TIER3) - .setPredicate(RequirementConstants.BOOLEAN_EQ) - .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) - .build(); + /** + * [2.2.7.1/5.1/H-1-4] MUST support 6 instances of hardware video encoder sessions (AVC, + * HEVC, VP9* or later) in any codec combination running concurrently at 720p(R,S) + * resolution@30 fps. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_4_720p() { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + // Requirement not asserted since encoder test runs in byte buffer mode + .addRequiredValue(Build.VERSION_CODES.R, 0.0) + .addRequiredValue(Build.VERSION_CODES.S, 0.0) + .build(); - RequiredMeasurement<Boolean> oemCryptoReq = RequiredMeasurement.<Boolean>builder() - .setId(RequirementConstants.OEM_CRYPTO_17_PLUS) - .setPredicate(RequirementConstants.BOOLEAN_EQ) - .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_4, + reqConcurrentFps); + } + + /** + * [2.2.7.1/5.1/H-1-4] MUST support 6 instances of hardware video encoder sessions (AVC, + * HEVC, VP9* or later) in any codec combination running concurrently at 1080p(T) + * resolution@30 fps. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_4_1080p() { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + // Requirement not asserted since encoder test runs in byte buffer mode + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 0.0) .build(); - RequiredMeasurement<Boolean> widevineCdmReq = RequiredMeasurement.<Boolean>builder() - .setId(RequirementConstants.WIDEWINE_CDM_17_PLUS) - .setPredicate(RequirementConstants.BOOLEAN_EQ) - .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_4, + reqConcurrentFps); + } + + /** + * [2.2.7.1/5.1/H-1-5] MUST advertise the maximum number of hardware video encoder and + * decoder sessions that can be run concurrently in any codec combination via the + * CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities + * .getSupportedPerformancePoints() methods. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_5_720p(String mimeType1, + String mimeType2, int resolution) { + RequiredMeasurement<Integer> maxInstances = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.CONCURRENT_SESSIONS) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.R, + getReqMinConcurrentInstances(Build.VERSION_CODES.R, mimeType1, mimeType2, + resolution)) + .addRequiredValue(Build.VERSION_CODES.S, + getReqMinConcurrentInstances(Build.VERSION_CODES.S, mimeType1, mimeType2, + resolution)) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_5, maxInstances); + } + + /** + * [2.2.7.1/5.1/H-1-5] MUST advertise the maximum number of hardware video encoder and + * decoder sessions that can be run concurrently in any codec combination via the + * CodecCapabilities.getMaxSupportedInstances() and VideoCapabilities + * .getSupportedPerformancePoints() methods. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_5_1080p() { + RequiredMeasurement<Integer> maxInstances = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.CONCURRENT_SESSIONS) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_5, maxInstances); + } + + /** + * [2.2.7.1/5.1/H-1-6] Support 6 instances of hardware video decoder and hardware video + * encoder sessions (AVC, HEVC, VP9 or AV1) in any codec combination running concurrently + * at 720p(R,S) /1080p(T) @30fps resolution. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_6_720p(String mimeType1, + String mimeType2, int resolution) { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + // Test transcoding, fps calculated for encoder and decoder combined so req / 2 + .addRequiredValue(Build.VERSION_CODES.R, + getReqMinConcurrentFps(Build.VERSION_CODES.R, mimeType1, mimeType2, resolution) + / 2) + .addRequiredValue(Build.VERSION_CODES.S, + getReqMinConcurrentFps(Build.VERSION_CODES.S, mimeType1, mimeType2, resolution) + / 2) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_6, + reqConcurrentFps); + } + + /** + * [2.2.7.1/5.1/H-1-6] Support 6 instances of hardware video decoder and hardware video + * encoder sessions (AVC, HEVC, VP9 or AV1) in any codec combination running concurrently + * at 720p(R,S) /1080p(T) @30fps resolution. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_6_1080p() { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + // Test transcoding, fps calculated for encoder and decoder combined so req / 2 + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 6 * FPS_30_TOLERANCE / 2) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_6, + reqConcurrentFps); + } + + /** + * [2.2.7.1/5.1/H-1-9] Support 2 instances of secure hardware video decoder sessions + * (AVC, HEVC, VP9 or AV1) in any codec combination running concurrently at 1080p + * resolution@30fps. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_9() { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 2 * FPS_30_TOLERANCE) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_9, + reqConcurrentFps); + } + + /** + * [2.2.7.1/5.1/H-1-10] Support 3 instances of non-secure hardware video decoder sessions + * together with 1 instance of secure hardware video decoder session (4 instances total) + * (AVC, HEVC, VP9 or AV1) in any codec combination running concurrently at 1080p + * resolution@30fps. + */ + public static ConcurrentCodecRequirement createR5_1__H_1_10() { + RequiredMeasurement<Double> reqConcurrentFps = RequiredMeasurement.<Double>builder() + .setId(RequirementConstants.CONCURRENT_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 4 * FPS_30_TOLERANCE) + .build(); + + return new ConcurrentCodecRequirement(RequirementConstants.R5_1__H_1_10, + reqConcurrentFps); + } + } + + // used for requirements [2.2.7.1/5.1/H-1-11], [2.2.7.1/5.7/H-1-2] + public static class SecureCodecRequirement extends Requirement { + private static final String TAG = SecureCodecRequirement.class.getSimpleName(); + + private SecureCodecRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setSecureReqSatisfied(boolean secureReqSatisfied) { + this.setMeasuredValue(RequirementConstants.SECURE_REQ_SATISFIED, secureReqSatisfied); + } + + public void setNumCryptoHwSecureAllDec(int numCryptoHwSecureAllDec) { + this.setMeasuredValue(RequirementConstants.NUM_CRYPTO_HW_SECURE_ALL_SUPPORT, + numCryptoHwSecureAllDec); + } + + /** + * [2.2.7.1/5.7/H-1-2] MUST support MediaDrm.SECURITY_LEVEL_HW_SECURE_ALL with the below + * content decryption capabilities. + */ + public static SecureCodecRequirement createR5_7__H_1_2() { + RequiredMeasurement<Integer> hw_secure_all = RequiredMeasurement.<Integer>builder() + .setId(RequirementConstants.NUM_CRYPTO_HW_SECURE_ALL_SUPPORT) + .setPredicate(RequirementConstants.INTEGER_GTE) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1) .build(); - return new SecureCodecRequirement(RequirementConstants.RTBD, widevineSupport, - widevineL1, widevineL1Tier3, oemCryptoReq, widevineCdmReq); + return new SecureCodecRequirement(RequirementConstants.R5_7__H_1_2, hw_secure_all); } /** - * [?] Must support secure decoder when a corresponding AVC/VP9/HEVC or AV1 hardware - * decoder is available + * [2.2.7.1/5.1/H-1-11] Must support secure decoder when a corresponding AVC/VP9/HEVC or AV1 + * hardware decoder is available */ - public static SecureCodecRequirement createRSecureDecodeSupport() { + public static SecureCodecRequirement createR5_1__H_1_11() { RequiredMeasurement<Boolean> requirement = RequiredMeasurement .<Boolean>builder() .setId(RequirementConstants.SECURE_REQ_SATISFIED) @@ -604,7 +845,7 @@ public class PerformanceClassEvaluator { .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) .build(); - return new SecureCodecRequirement(RequirementConstants.RTBD, requirement); + return new SecureCodecRequirement(RequirementConstants.R5_1__H_1_11, requirement); } } @@ -633,25 +874,13 @@ public class PerformanceClassEvaluator { ResolutionRequirement.createR7_1_1_1__H_2_1()); } - public ResolutionRequirement addR7_1_1_1__TBD1() { - return this.<ResolutionRequirement>addRequirement( - ResolutionRequirement.createR7_1_1_1__TBD1()); - } - public DensityRequirement addR7_1_1_3__H_2_1() { return this.<DensityRequirement>addRequirement(DensityRequirement.createR7_1_1_3__H_2_1()); } - public DensityRequirement addR7_1_1_3__TBD2() { - return this.<DensityRequirement>addRequirement(DensityRequirement.createR7_1_1_3__TBD2()); - } - public MemoryRequirement addR7_6_1__H_2_1() { return this.<MemoryRequirement>addRequirement(MemoryRequirement.createR7_6_1__H_2_1()); } - public MemoryRequirement addR7_6_1__H_3_1() { - return this.<MemoryRequirement>addRequirement(MemoryRequirement.createR7_6_1__H_3_1()); - } public FrameDropRequirement addR5_3__H_1_1_R() { return this.addRequirement(FrameDropRequirement.createR5_3__H_1_1_R()); @@ -677,12 +906,12 @@ public class PerformanceClassEvaluator { return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_8()); } - public CodecInitLatencyRequirement addR5_1__H_1_TBD1() { - return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_TBD1()); + public CodecInitLatencyRequirement addR5_1__H_1_12() { + return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_12()); } - public CodecInitLatencyRequirement addR5_1__H_1_TBD2() { - return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_TBD2()); + public CodecInitLatencyRequirement addR5_1__H_1_13() { + return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_13()); } public VideoCodecRequirement addR4k60HwEncoder() { @@ -697,12 +926,78 @@ public class PerformanceClassEvaluator { return this.addRequirement(VideoCodecRequirement.createRAV1DecoderReq()); } - public SecureCodecRequirement addRSecureDecodeSupport() { - return this.addRequirement(SecureCodecRequirement.createRSecureDecodeSupport()); + public SecureCodecRequirement addR5_1__H_1_11() { + return this.addRequirement(SecureCodecRequirement.createR5_1__H_1_11()); + } + + public SecureCodecRequirement addR5_7__H_1_2() { + return this.addRequirement(SecureCodecRequirement.createR5_7__H_1_2()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_1_720p(String mimeType1, String mimeType2, + int resolution) { + return this.addRequirement( + ConcurrentCodecRequirement.createR5_1__H_1_1_720p(mimeType1, mimeType2, resolution)); + } + + public ConcurrentCodecRequirement addR5_1__H_1_1_1080p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_1_1080p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_2_720p(String mimeType1, String mimeType2, + int resolution) { + return this.addRequirement( + ConcurrentCodecRequirement.createR5_1__H_1_2_720p(mimeType1, mimeType2, resolution)); + } + + public ConcurrentCodecRequirement addR5_1__H_1_2_1080p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_2_1080p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_3_720p(String mimeType1, String mimeType2, + int resolution) { + return this.addRequirement( + ConcurrentCodecRequirement.createR5_1__H_1_3_720p(mimeType1, mimeType2, resolution)); + } + + public ConcurrentCodecRequirement addR5_1__H_1_3_1080p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_3_1080p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_4_720p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_4_720p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_4_1080p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_4_1080p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_5_720p(String mimeType1, String mimeType2, + int resolution) { + return this.addRequirement( + ConcurrentCodecRequirement.createR5_1__H_1_5_720p(mimeType1, mimeType2, resolution)); + } + + public ConcurrentCodecRequirement addR5_1__H_1_5_1080p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_5_1080p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_6_720p(String mimeType1, String mimeType2, + int resolution) { + return this.addRequirement( + ConcurrentCodecRequirement.createR5_1__H_1_6_720p(mimeType1, mimeType2, resolution)); + } + + public ConcurrentCodecRequirement addR5_1__H_1_6_1080p() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_6_1080p()); + } + + public ConcurrentCodecRequirement addR5_1__H_1_9() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_9()); } - public SecureCodecRequirement addRWidevineSupport() { - return this.addRequirement(SecureCodecRequirement.createRWidevineSupport()); + public ConcurrentCodecRequirement addR5_1__H_1_10() { + return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_10()); } public void submitAndCheck() { 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 0de6a99d610..d93cb2e0a00 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java @@ -35,9 +35,19 @@ public class RequirementConstants { public static final String R5_1__H_1_6 = "r5_1__h_1_6"; // 5.1/H-1-6 public static final String R5_1__H_1_7 = "r5_1__h_1_7"; // 5.1/H-1-7 public static final String R5_1__H_1_8 = "r5_1__h_1_8"; // 5.1/H-1-8 + public static final String R5_1__H_1_9 = "r5_1__h_1_9"; // 5.1/H-1-9 + public static final String R5_1__H_1_10 = "r5_1__h_1_10"; // 5.1/H-1-10 + public static final String R5_1__H_1_11 = "r5_1__h_1_11"; // 5.1/H-1-11 + public static final String R5_1__H_1_12 = "r5_1__h_1_12"; // 5.1/H-1-12 + public static final String R5_1__H_1_13 = "r5_1__h_1_13"; // 5.1/H-1-13 + public static final String R5_1__H_1_14 = "r5_1__h_1_14"; // 5.1/H-1-14 + public static final String R5_1__H_1_15 = "r5_1__h_1_15"; // 5.1/H-1-16 + public static final String R5_1__H_1_16 = "r5_1__h_1_16"; // 5.1/H-1-16 public static final String R5_3__H_1_1 = "r5_3__h_1_1"; // 5.3/H-1-1 public static final String R5_3__H_1_2 = "r5_3__h_1_2"; // 5.3/H-1-2 public static final String R5_6__H_1_1 = "r5_6__h_1_1"; // 5.6/H-1-1 + public static final String R5_7__H_1_1 = "r5_7__h_1_1"; // 5.7/H-1-1 + public static final String R5_7__H_1_2 = "r5_7__h_1_2"; // 5.7/H-1-2 public static final String R7_5__H_1_1 = "r7_5__h_1_1"; // 7.5/H-1-1 public static final String R7_5__H_1_2 = "r7_5__h_1_2"; // 7.5/H-1-2 public static final String R7_5__H_1_3 = "r7_5__h_1_3"; // 7.5/H-1-3 @@ -63,7 +73,8 @@ public class RequirementConstants { public static final String R8_2__H_2_4 = "r8_2__h_2_4"; // 8.2/H-2-4 public static final String RTBD = "tbd"; // placeholder for requirements without a set id - public static final String MAX_CONCURRENT_SESSIONS = "max_concurrent_sessions"; + public static final String CONCURRENT_SESSIONS = "concurrent_sessions"; + public static final String CONCURRENT_FPS = "concurrent_fps"; public static final String SUPPORTED_PERFORMANCE_POINTS = "supported_performance_points"; public static final String FRAMES_DROPPED = "frame_drops_per_30sec"; public static final String FRAME_RATE = "frame_rate"; @@ -76,11 +87,8 @@ public class RequirementConstants { public static final String NUM_4k_HW_DEC = "number_4k_hw_decoders"; public static final String NUM_4k_HW_ENC = "number_4k_hw_encoders"; public static final String SECURE_REQ_SATISFIED = "secure_requirement_satisfied_boolean"; - public static final String WIDEWINE_SUPPORT = "widevine_support_boolean"; - public static final String WIDEWINE_L1 = "widevine_l1_support_boolean"; - public static final String WIDEWINE_L1_TIER3 = "widevine_l1_tier3_support_boolean"; - public static final String OEM_CRYPTO_17_PLUS = "oem_crypto_version_17plus_boolean"; - public static final String WIDEWINE_CDM_17_PLUS = "widevine_cdm_version_17plus_boolean"; + public static final String NUM_CRYPTO_HW_SECURE_ALL_SUPPORT = + "number_crypto_hw_secure_all_support"; public enum Result { NA, MET, UNMET @@ -92,6 +100,7 @@ public class RequirementConstants { public static final BiPredicate<Integer, Integer> INTEGER_LTE = RequirementConstants.lte(); 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(); /** * Creates a >= predicate. diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java index 03790901307..5a4822dd281 100644 --- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java +++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java @@ -37,6 +37,7 @@ import android.media.MediaFormat; import android.media.MediaRecorder; import android.mediapc.cts.common.PerformanceClassEvaluator; import android.mediapc.cts.common.Utils; +import android.os.SystemClock; import android.util.Log; import android.util.Pair; import android.view.Surface; @@ -269,7 +270,6 @@ public class CodecInitializationLatencyTest { } } - // TODO(b/218771970): Add cdd annotation /** * This test validates the initialization latency (time for codec create + configure) for * audio and hw video codecs. @@ -282,7 +282,9 @@ public class CodecInitializationLatencyTest { @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) @CddTest(requirements = { "2.2.7.1/5.1/H-1-7", - "2.2.7.1/5.1/H-1-8",}) + "2.2.7.1/5.1/H-1-8", + "2.2.7.1/5.1/H-1-12", + "2.2.7.1/5.1/H-1-13",}) public void testInitializationLatency() throws Exception { MediaCodec codec = MediaCodec.createByCodecName(mCodecName); boolean isEncoder = codec.getCodecInfo().isEncoder(); @@ -347,7 +349,7 @@ public class CodecInitializationLatencyTest { PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); PerformanceClassEvaluator.CodecInitLatencyRequirement r5_1__H_1_Latency = isEncoder ? isAudio ? pce.addR5_1__H_1_8() : pce.addR5_1__H_1_7() - : isAudio ? pce.addR5_1__H_1_TBD2() : pce.addR5_1__H_1_TBD1(); + : isAudio ? pce.addR5_1__H_1_13() : pce.addR5_1__H_1_12(); r5_1__H_1_Latency.setCodecInitLatencyMs(initializationLatency); @@ -435,14 +437,14 @@ public class CodecInitializationLatencyTest { MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo(); long enqueueTimeStamp = 0; long dequeueTimeStamp = 0; - long baseTimeStamp = System.nanoTime(); + long baseTimeStamp = SystemClock.elapsedRealtimeNanos(); mCodec = MediaCodec.createByCodecName(mEncoderName); resetContext(mIsAsync, false); mAsyncHandle.setCallBack(mCodec, mIsAsync); mCodec.configure(format, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null); - long configureTimeStamp = System.nanoTime(); + long configureTimeStamp = SystemClock.elapsedRealtimeNanos(); mCodec.start(); - long startTimeStamp = System.nanoTime(); + long startTimeStamp = SystemClock.elapsedRealtimeNanos(); if (mIsAsync) { // We will keep on feeding the input to encoder until we see the first dequeued // frame. @@ -452,12 +454,12 @@ public class CodecInitializationLatencyTest { int bufferID = element.first; MediaCodec.BufferInfo info = element.second; if (info != null) { - dequeueTimeStamp = System.nanoTime(); + dequeueTimeStamp = SystemClock.elapsedRealtimeNanos(); dequeueOutput(bufferID, info); break; } else { if (enqueueTimeStamp == 0) { - enqueueTimeStamp = System.nanoTime(); + enqueueTimeStamp = SystemClock.elapsedRealtimeNanos(); } enqueueInput(bufferID); } @@ -469,14 +471,14 @@ public class CodecInitializationLatencyTest { int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US); if (inputBufferId > 0) { if (enqueueTimeStamp == 0) { - enqueueTimeStamp = System.nanoTime(); + enqueueTimeStamp = SystemClock.elapsedRealtimeNanos(); } enqueueInput(inputBufferId); } } int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US); if (outputBufferId >= 0) { - dequeueTimeStamp = System.nanoTime(); + dequeueTimeStamp = SystemClock.elapsedRealtimeNanos(); dequeueOutput(outputBufferId, outInfo); break; } @@ -531,14 +533,14 @@ public class CodecInitializationLatencyTest { MediaFormat format = setUpSource(mTestFile); long enqueueTimeStamp = 0; long dequeueTimeStamp = 0; - long baseTimeStamp = System.nanoTime(); + long baseTimeStamp = SystemClock.elapsedRealtimeNanos(); mCodec = MediaCodec.createByCodecName(mDecoderName); resetContext(mIsAsync, false); mAsyncHandle.setCallBack(mCodec, mIsAsync); mCodec.configure(format, mSurface, 0, null); - long configureTimeStamp = System.nanoTime(); + long configureTimeStamp = SystemClock.elapsedRealtimeNanos(); mCodec.start(); - long startTimeStamp = System.nanoTime(); + long startTimeStamp = SystemClock.elapsedRealtimeNanos(); if (mIsAsync) { // We will keep on feeding the input to decoder until we see the first dequeued // frame. @@ -548,12 +550,12 @@ public class CodecInitializationLatencyTest { int bufferID = element.first; MediaCodec.BufferInfo info = element.second; if (info != null) { - dequeueTimeStamp = System.nanoTime(); + dequeueTimeStamp = SystemClock.elapsedRealtimeNanos(); dequeueOutput(bufferID, info); break; } else { if (enqueueTimeStamp == 0) { - enqueueTimeStamp = System.nanoTime(); + enqueueTimeStamp = SystemClock.elapsedRealtimeNanos(); } enqueueInput(bufferID); } @@ -565,14 +567,14 @@ public class CodecInitializationLatencyTest { int inputBufferId = mCodec.dequeueInputBuffer(Q_DEQ_TIMEOUT_US); if (inputBufferId >= 0) { if (enqueueTimeStamp == 0) { - enqueueTimeStamp = System.nanoTime(); + enqueueTimeStamp = SystemClock.elapsedRealtimeNanos(); } enqueueInput(inputBufferId); } } int outputBufferId = mCodec.dequeueOutputBuffer(outInfo, Q_DEQ_TIMEOUT_US); if (outputBufferId >= 0) { - dequeueTimeStamp = System.nanoTime(); + dequeueTimeStamp = SystemClock.elapsedRealtimeNanos(); dequeueOutput(outputBufferId, outInfo); break; } diff --git a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java index 98c33475065..ca7a17a1484 100644 --- a/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java +++ b/tests/mediapc/src/android/mediapc/cts/MultiCodecPerfTestBase.java @@ -44,10 +44,7 @@ public class MultiCodecPerfTestBase { static final int REQUIRED_MIN_CONCURRENT_INSTANCES = 6; static final int REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9 = 2; static final int REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES = 2; - // allowed tolerance in measured fps vs expected fps in percentage, i.e. codecs achieving fps - // that is greater than (FPS_TOLERANCE_FACTOR * expectedFps) will be considered as - // passing the test - static final double FPS_TOLERANCE_FACTOR = 0.95; + static ArrayList<String> mMimeList = new ArrayList<>(); static Map<String, String> mTestFiles = new HashMap<>(); static Map<String, String> m720pTestFiles = new HashMap<>(); @@ -89,8 +86,6 @@ public class MultiCodecPerfTestBase { String mTestFile; final boolean mIsAsync; - double mMaxFrameRate; - @Before public void isPerformanceClassCandidate() { Utils.assumeDeviceMeetsPerformanceClassPreconditions(); @@ -120,9 +115,11 @@ public class MultiCodecPerfTestBase { } // Returns the max number of 30 fps instances that the given list of mimeCodecPairs - // supports. It also checks that the each codec supports 180 fps PerformancePoint. + // supports. It also checks that the each codec supports a PerformancePoint that covers + // required number of 30 fps instances. public int checkAndGetMaxSupportedInstancesForCodecCombinations(int height, int width, - ArrayList<Pair<String, String>> mimeCodecPairs) throws IOException { + ArrayList<Pair<String, String>> mimeCodecPairs, int requiredMinInstances) + throws IOException { int[] maxInstances = new int[mimeCodecPairs.size()]; int[] maxFrameRates = new int[mimeCodecPairs.size()]; int[] maxMacroBlockRates = new int[mimeCodecPairs.size()]; @@ -135,8 +132,7 @@ public class MultiCodecPerfTestBase { assertTrue(pps.size() > 0); boolean hasVP9 = mimeCodecPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9); - int requiredFrameRate = getRequiredMinConcurrentInstances(hasVP9, mimeCodecPair.second, - mimeCodecPair.first) * 30; + int requiredFrameRate = requiredMinInstances * 30; maxInstances[loopCount] = cap.getMaxSupportedInstances(); PerformancePoint PPRes = new PerformancePoint(width, height, requiredFrameRate); @@ -168,26 +164,13 @@ public class MultiCodecPerfTestBase { int minOfMaxFrameRates = maxFrameRates[0]; int minOfMaxMacroBlockRates = maxMacroBlockRates[0]; - // Allow a tolerance in expected frame rate - mMaxFrameRate = minOfMaxFrameRates * FPS_TOLERANCE_FACTOR; - // Calculate how many 30fps max instances it can support from it's mMaxFrameRate // amd maxMacroBlockRate. (assuming 16x16 macroblocks) return Math.min(minOfMaxInstances, Math.min((int) (minOfMaxFrameRates / 30.0), (int) (minOfMaxMacroBlockRates / ((width / 16) * (height / 16)) / 30.0))); } - public int getRequiredMinConcurrentInstances(boolean hasVP9) throws IOException { - return getRequiredMinConcurrentInstances(hasVP9, null, null); - } - - public int getRequiredMinConcurrentInstances(boolean hasVP9, String codecName, String mime) - throws IOException { - if (codecName != null && mime != null) { - if (isSecureSupportedCodec(codecName, mime)) { - return REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES; - } - } + public int getRequiredMinConcurrentInstances720p(boolean hasVP9) throws IOException { // Below T, VP9 requires 60 fps at 720p and minimum of 2 instances if (!Utils.isTPerfClass() && hasVP9) { return REQUIRED_MIN_CONCURRENT_INSTANCES_FOR_VP9; @@ -203,21 +186,4 @@ public class MultiCodecPerfTestBase { codec.release(); return isSecureSupported; } - - boolean codecSupportsPP(String codecName, String mime, PerformancePoint reqPP) - throws IOException { - MediaCodec codec = MediaCodec.createByCodecName(codecName); - List<PerformancePoint> suppPPs = - codec.getCodecInfo().getCapabilitiesForType(mime).getVideoCapabilities() - .getSupportedPerformancePoints(); - assertTrue("Performance point not published by codec: " + codecName, suppPPs != null); - boolean codecSupportsReqPP = false; - for (PerformancePoint pp : suppPPs) { - if (pp.covers(reqPP)) { - codecSupportsReqPP = true; - } - } - codec.release(); - return codecSupportsReqPP; - } } diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java index 6694a46a41c..0c69346825a 100644 --- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java +++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPairPerfTest.java @@ -20,8 +20,8 @@ import static org.junit.Assert.assertTrue; import android.media.MediaCodecInfo; import android.media.MediaFormat; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.mediapc.cts.common.Utils; -import android.os.Build; import android.util.Pair; import androidx.test.filters.LargeTest; @@ -33,7 +33,9 @@ import com.android.compatibility.common.util.ResultType; import com.android.compatibility.common.util.ResultUnit; import org.junit.Assume; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -68,6 +70,9 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { mSecondPair = secondPair; } + @Rule + public final TestName mTestName = new TestName(); + // Returns the list of params with two hardware (mime - decoder) pairs in both // sync and async modes. // Parameters {0}_{1}_{2} -- Pair(Mime DecoderName)_Pair(Mime DecoderName)_isAsync @@ -110,7 +115,7 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { boolean hasVP9 = mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9) || mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9); - int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9); + int requiredMinInstances = getRequiredMinConcurrentInstances720p(hasVP9); testCodec(m720pTestFiles, 720, 1280, requiredMinInstances); } @@ -122,99 +127,25 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { */ @LargeTest @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - @CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2") + @CddTest(requirements = { + "2.2.7.1/5.1/H-1-1", + "2.2.7.1/5.1/H-1-2", + "2.2.7.1/5.1/H-1-9", + "2.2.7.1/5.1/H-1-10",}) public void test1080p() throws Exception { Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass()); - Assume.assumeFalse("Skipping regular performance tests for secure codecs", - isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) || - isSecureSupportedCodec(mSecondPair.second, mSecondPair.first)); - testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES); - } - - /** - * Validates if hardware decoder pairs where one supports secure decode and required - * perf are present and tests with concurrent unsecure decoders - */ - @LargeTest - @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - // TODO(b/218771970) Add @CddTest annotation - public void testReqSecureWithUnsecureDecodeSupport() throws Exception { - Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass()); - Assume.assumeTrue("Testing if only one of the pair is secure", - isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) ^ - isSecureSupportedCodec(mSecondPair.second, mSecondPair.first)); - - MediaCodecInfo.VideoCapabilities.PerformancePoint reqSecurePP = - new MediaCodecInfo.VideoCapabilities.PerformancePoint(1920, 1080, 30); - - MediaCodecInfo.VideoCapabilities.PerformancePoint reqNonSecurePP = - new MediaCodecInfo.VideoCapabilities.PerformancePoint(1920, 1080, - 30 * REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE); - - boolean codecSupportsReqPP = codecSupportsPP(mFirstPair.second, mFirstPair.first, - isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) ? reqSecurePP : - reqNonSecurePP); - - codecSupportsReqPP &= codecSupportsPP(mSecondPair.second, mSecondPair.first, - isSecureSupportedCodec(mSecondPair.second, mSecondPair.first) ? reqSecurePP : - reqNonSecurePP); - - testCodec(m1080pTestFiles, 1080, 1920, - REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE + 1, true); - - if (Utils.isTPerfClass()) { - assertTrue( - "Required Secure Decode Support required for MPC >= Android T, unsupported " + - "codec pair: " + mFirstPair.second + "," + mSecondPair.second, - codecSupportsReqPP); - } else { - DeviceReportLog log = - new DeviceReportLog("MediaPerformanceClassLogs", "SecureDecodeSupport"); - log.addValue("Req Secure Decode Support pair: " + mFirstPair.second + "," + - mSecondPair.second, codecSupportsReqPP, ResultType.NEUTRAL, ResultUnit.NONE); - // TODO(b/218771970) Log CDD sections - log.setSummary("MPC 13: Secure Decode requirements", 0, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); - } - } - - /** - * Validates if hardware decoder pairs where both supports secure decode and required - * perf is present - */ - @LargeTest - @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - // TODO(b/218771970) Add @CddTest annotation - public void testReqMultiSecureDecodeSupport() throws Exception { - Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass()); - Assume.assumeTrue("Run test if both are secure codecs", - isSecureSupportedCodec(mFirstPair.second, mFirstPair.first) && - isSecureSupportedCodec(mSecondPair.second, mSecondPair.first)); - - MediaCodecInfo.VideoCapabilities.PerformancePoint reqSecurePP = - new MediaCodecInfo.VideoCapabilities.PerformancePoint(1920, 1080, 30); - - boolean codecSupportsReqPP = - codecSupportsPP(mFirstPair.second, mFirstPair.first, reqSecurePP); - codecSupportsReqPP &= codecSupportsPP(mSecondPair.second, mSecondPair.first, reqSecurePP); - - testCodec(null, 1080, 1920, REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES); - - if (Utils.isTPerfClass()) { - assertTrue( - "Required Secure Decode Support required for MPC >= Android T, unsupported " + - "codec pair: " + mFirstPair.second + "," + mSecondPair.second, - codecSupportsReqPP); + boolean isFirstSecure = isSecureSupportedCodec(mFirstPair.second, mFirstPair.first); + boolean isSecondSecure = isSecureSupportedCodec(mSecondPair.second, mSecondPair.first); + boolean onlyOneSecure = isFirstSecure ^ isSecondSecure; + boolean bothSecure = isFirstSecure & isSecondSecure; + + if (bothSecure) { + testCodec(null, 1080, 1920, REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES); + } else if (onlyOneSecure) { + testCodec(m1080pTestFiles, 1080, 1920, + REQUIRED_CONCURRENT_NON_SECURE_INSTANCES_WITH_SECURE + 1, true); } else { - DeviceReportLog log = - new DeviceReportLog("MediaPerformanceClassLogs", "SecureDecodeSupport"); - log.addValue("Req Secure Decode Support pair: " + mFirstPair.second + "," + - mSecondPair.second, codecSupportsReqPP, ResultType.NEUTRAL, ResultUnit.NONE); - // TODO(b/218771970) Log CDD sections - log.setSummary("MPC 13: Secure Decode requirements", 0, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES); } } @@ -229,8 +160,9 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { ArrayList<Pair<String, String>> mimeDecoderPairs = new ArrayList<>(); mimeDecoderPairs.add(mFirstPair); mimeDecoderPairs.add(mSecondPair); + boolean bothSecure = true; int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, - mimeDecoderPairs); + mimeDecoderPairs, requiredMinInstances); double achievedFrameRate = 0.0; // secure test should not reach this point if secure codec doesn't support PP if (maxInstances >= requiredMinInstances || secureWithUnsecure) { @@ -245,6 +177,7 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { List<Decode> testList = new ArrayList<>(); for (int i = 0; i < firstPairInstances; i++) { boolean isSecure = isSecureSupportedCodec(mFirstPair.second, mFirstPair.first); + bothSecure &= isSecure; String testFile = isSecure ? m1080pWidevineTestFiles.get(mFirstPair.first) : mTestFiles.get(mFirstPair.first); Assume.assumeTrue("Add " + (isSecure ? "secure" : "") + " test vector for mime: " + @@ -254,6 +187,7 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { } for (int i = 0; i < secondPairInstances; i++) { boolean isSecure = isSecureSupportedCodec(mSecondPair.second, mSecondPair.first); + bothSecure &= isSecure; String testFile = isSecure ? m1080pWidevineTestFiles.get(mSecondPair.first) : mTestFiles.get(mSecondPair.first); Assume.assumeTrue("Add " + (isSecure ? "secure" : "") + " test vector for mime: " + @@ -267,29 +201,30 @@ public class MultiDecoderPairPerfTest extends MultiCodecPerfTestBase { achievedFrameRate += result.get(); } } - if (Utils.isPerfClass()) { - assertTrue("Decoder pair " + mFirstPair.second + " and " + mSecondPair.second - + " unable to support minimum concurrent " + - "instances. act/exp: " + maxInstances + "/" + requiredMinInstances, - maxInstances >= requiredMinInstances); - assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate - + "/" + mMaxFrameRate + " for " + maxInstances + " instances.", - achievedFrameRate >= mMaxFrameRate); + PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); + if (secureWithUnsecure) { + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_10 = + pce.addR5_1__H_1_10(); + r5_1__H_1_10.setConcurrentFps(achievedFrameRate); + } else if (bothSecure) { + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_9 = pce.addR5_1__H_1_9(); + r5_1__H_1_9.setConcurrentFps(achievedFrameRate); } else { - int pc = maxInstances >= requiredMinInstances && achievedFrameRate >= mMaxFrameRate - ? Build.VERSION_CODES.R : 0; - DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", - "MultiDecoderPairPerf_" + mFirstPair.second); - log.addValue("decoders", - mFirstPair.first + "_" + mFirstPair.second + "_" + mSecondPair.first + "_" - + mSecondPair.second, ResultType.NEUTRAL, ResultUnit.NONE); - log.addValue("achieved_framerate", achievedFrameRate, ResultType.HIGHER_BETTER, - ResultUnit.NONE); - log.addValue("expected_framerate", mMaxFrameRate, ResultType.NEUTRAL, ResultUnit.NONE); - log.setSummary("CDD 2.2.7.1/5.1/H-1-1,H-1-2 performance_class", pc, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_1; + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_2; + if (height >= 1080) { + r5_1__H_1_1 = pce.addR5_1__H_1_1_1080p(); + r5_1__H_1_2 = pce.addR5_1__H_1_2_1080p(); + r5_1__H_1_1.setConcurrentInstances(maxInstances); + r5_1__H_1_2.setConcurrentFps(achievedFrameRate); + } else { + r5_1__H_1_1 = pce.addR5_1__H_1_1_720p(mMime, mMime, height); + r5_1__H_1_2 = pce.addR5_1__H_1_2_720p(mMime, mMime, height); + r5_1__H_1_1.setConcurrentInstances(maxInstances); + r5_1__H_1_2.setConcurrentFps(achievedFrameRate); + } } + pce.submitAndCheck(); } } diff --git a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java index 62c7f832142..13203cc77ce 100644 --- a/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java +++ b/tests/mediapc/src/android/mediapc/cts/MultiDecoderPerfTest.java @@ -18,10 +18,9 @@ package android.mediapc.cts; import static org.junit.Assert.assertTrue; -import android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint; import android.media.MediaFormat; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.mediapc.cts.common.Utils; -import android.os.Build; import android.util.Pair; import androidx.test.filters.LargeTest; @@ -33,7 +32,9 @@ import com.android.compatibility.common.util.ResultType; import com.android.compatibility.common.util.ResultUnit; import org.junit.Assume; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -62,6 +63,9 @@ public class MultiDecoderPerfTest extends MultiCodecPerfTestBase { mDecoderName = decoderName; } + @Rule + public final TestName mTestName = new TestName(); + // Returns the params list with the mime and corresponding hardware decoders in // both sync and async modes. // Parameters {0}_{1}_{2} -- Mime_DecoderName_isAsync @@ -92,56 +96,28 @@ public class MultiDecoderPerfTest extends MultiCodecPerfTestBase { Assume.assumeFalse("Skipping regular performance tests for secure codecs", isSecureSupportedCodec(mDecoderName, mMime)); boolean hasVP9 = mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9); - int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9); + int requiredMinInstances = getRequiredMinConcurrentInstances720p(hasVP9); testCodec(m720pTestFiles, 720, 1280, requiredMinInstances); } /** - * This test validates that the decoder can support at least 6 concurrent 1080p 30fps - * decoder instances. Also ensures that all the concurrent sessions succeed in decoding - * with meeting the expected frame rate. + * This test validates that the decoder can support at least 6 non-secure/2 secure concurrent + * 1080p 30fps decoder instances. Also ensures that all the concurrent sessions succeed in + * decoding with meeting the expected frame rate. */ @LargeTest @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - @CddTest(requirement = "2.2.7.1/5.1/H-1-1,H-1-2") + @CddTest(requirements = { + "2.2.7.1/5.1/H-1-1", + "2.2.7.1/5.1/H-1-2", + "2.2.7.1/5.1/H-1-9",}) public void test1080p() throws Exception { Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass()); - Assume.assumeFalse("Skipping regular performance tests for secure codecs", - isSecureSupportedCodec(mDecoderName, mMime)); - testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES); - } - - /** - * Validates if hardware decoder that supports required secure decode perf is present - */ - @LargeTest - @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - // TODO(b/218771970) Add @CddTest annotation - public void testReqSecureDecodeSupport() throws Exception { - Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass()); - Assume.assumeTrue("Skipping secure decode support tests for non-secure codecs", - isSecureSupportedCodec(mDecoderName, mMime)); - - PerformancePoint reqPP = - new PerformancePoint(1920, 1080, 30 * REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES); - - boolean codecSupportsReqPP = codecSupportsPP(mDecoderName, mMime, reqPP); - - testCodec(m1080pWidevineTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES); - - if (Utils.isTPerfClass()) { - assertTrue( - "Required Secure Decode Support required for MPC >= Android T, unsupported " + - "codec: " + mDecoderName, codecSupportsReqPP); + if (isSecureSupportedCodec(mDecoderName, mMime)) { + testCodec(m1080pWidevineTestFiles, 1080, 1920, + REQUIRED_MIN_CONCURRENT_SECURE_INSTANCES); } else { - DeviceReportLog log = - new DeviceReportLog("MediaPerformanceClassLogs", "SecureDecodeSupport"); - log.addValue("Req Secure Decode Support: " + mDecoderName, codecSupportsReqPP, - ResultType.NEUTRAL, ResultUnit.NONE); - // TODO(b/218771970) Log CDD sections - log.setSummary("MPC 13: Secure Decode requirements", 0, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES); } } @@ -151,15 +127,15 @@ public class MultiDecoderPerfTest extends MultiCodecPerfTestBase { Assume.assumeTrue("Add test vector for mime: " + mMime, mTestFile != null); ArrayList<Pair<String, String>> mimeDecoderPairs = new ArrayList<>(); mimeDecoderPairs.add(Pair.create(mMime, mDecoderName)); + boolean isSecure = isSecureSupportedCodec(mDecoderName, mMime); int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, - mimeDecoderPairs); + mimeDecoderPairs, requiredMinInstances); double achievedFrameRate = 0.0; if (maxInstances >= requiredMinInstances) { ExecutorService pool = Executors.newFixedThreadPool(maxInstances); List<Decode> testList = new ArrayList<>(); for (int i = 0; i < maxInstances; i++) { - boolean isSecure = isSecureSupportedCodec(mDecoderName, mMime); testList.add(new Decode(mMime, mTestFile, mDecoderName, mIsAsync, isSecure)); } List<Future<Double>> resultList = pool.invokeAll(testList); @@ -167,26 +143,26 @@ public class MultiDecoderPerfTest extends MultiCodecPerfTestBase { achievedFrameRate += result.get(); } } - if (Utils.isPerfClass()) { - assertTrue("Decoder " + mDecoderName + " unable to support minimum concurrent " + - "instances. act/exp: " + maxInstances + "/" + requiredMinInstances, - maxInstances >= requiredMinInstances); - assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate - + "/" + mMaxFrameRate + " for " + maxInstances + " instances.", - achievedFrameRate >= mMaxFrameRate); + + PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); + if (isSecure) { + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_9 = pce.addR5_1__H_1_9(); + r5_1__H_1_9.setConcurrentFps(achievedFrameRate); } else { - int pc = maxInstances >= requiredMinInstances && achievedFrameRate >= mMaxFrameRate - ? Build.VERSION_CODES.R : 0; - DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", - "MultiDecoderPerf_" + mDecoderName); - log.addValue("decoders", mMime + "_" + mDecoderName, ResultType.NEUTRAL, - ResultUnit.NONE); - log.addValue("achieved_framerate", achievedFrameRate, ResultType.HIGHER_BETTER, - ResultUnit.NONE); - log.addValue("expected_framerate", mMaxFrameRate, ResultType.NEUTRAL, ResultUnit.NONE); - log.setSummary("CDD 2.2.7.1/5.1/H-1-1,H-1-2 performance_class", pc, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_1; + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_2; + if (height >= 1080) { + r5_1__H_1_1 = pce.addR5_1__H_1_1_1080p(); + r5_1__H_1_2 = pce.addR5_1__H_1_2_1080p(); + r5_1__H_1_1.setConcurrentInstances(maxInstances); + r5_1__H_1_2.setConcurrentFps(achievedFrameRate); + } else { + r5_1__H_1_1 = pce.addR5_1__H_1_1_720p(mMime, mMime, height); + r5_1__H_1_2 = pce.addR5_1__H_1_2_720p(mMime, mMime, height); + r5_1__H_1_1.setConcurrentInstances(maxInstances); + r5_1__H_1_2.setConcurrentFps(achievedFrameRate); + } } + pce.submitAndCheck(); } } diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java index 01e68d3b7e3..1997c6beac9 100644 --- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java +++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPairPerfTest.java @@ -16,24 +16,19 @@ package android.mediapc.cts; -import static org.junit.Assert.assertTrue; - import android.media.MediaFormat; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.mediapc.cts.common.Utils; -import android.os.Build; -import android.util.Log; import android.util.Pair; import androidx.test.filters.LargeTest; -import androidx.test.platform.app.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.Assume; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -66,6 +61,9 @@ public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase { mSecondPair = secondPair; } + @Rule + public final TestName mTestName = new TestName(); + // Returns the list of params with two hardware (mime - encoder) pairs in both // sync and async modes. // Parameters {0}_{1}_{2} -- Pair(Mime EncoderName)_Pair(Mime EncoderName)_isAsync @@ -105,7 +103,7 @@ public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase { boolean hasVP9 = mFirstPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9) || mSecondPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9); - int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9); + int requiredMinInstances = getRequiredMinConcurrentInstances720p(hasVP9); testCodec(720, 1280, 4000000, requiredMinInstances); } @@ -129,7 +127,7 @@ public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase { mimeEncoderPairs.add(mFirstPair); mimeEncoderPairs.add(mSecondPair); int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, - mimeEncoderPairs); + mimeEncoderPairs, requiredMinInstances); double achievedFrameRate = 0.0; if (maxInstances >= requiredMinInstances) { int secondPairInstances = maxInstances / 2; @@ -151,22 +149,22 @@ public class MultiEncoderPairPerfTest extends MultiCodecPerfTestBase { achievedFrameRate += result.get(); } } - if (Utils.isPerfClass()) { - assertTrue("Encoder pair " + mFirstPair.second + " and " + mSecondPair.second - + " unable to support minimum concurrent instances. act/exp: " + maxInstances - + "/" + requiredMinInstances, maxInstances >= requiredMinInstances); - Log.v(LOG_TAG, "Achieved fps: " + achievedFrameRate + - "\nAchieved frame rate is not compared as this test runs in byte buffer mode"); + PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_3; + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_4; + // Achieved frame rate is not compared as this test runs in byte buffer mode. + if (height >= 1080) { + r5_1__H_1_3 = pce.addR5_1__H_1_3_1080p(); + r5_1__H_1_4 = pce.addR5_1__H_1_4_1080p(); + r5_1__H_1_3.setConcurrentInstances(maxInstances); + r5_1__H_1_4.setConcurrentFps(achievedFrameRate); } else { - int pc = maxInstances >= requiredMinInstances ? Build.VERSION_CODES.R : 0; - DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", - "MultiEncoderPairPerf_" + mFirstPair.second); - log.addValue("encoders", - mFirstPair.first + "_" + mFirstPair.second + "_" + mSecondPair.first + "_" - + mSecondPair.second, ResultType.NEUTRAL, ResultUnit.NONE); - log.setSummary("CDD 2.2.7.1/5.1/H-1-3,H-1-4 performance_class", pc, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + r5_1__H_1_3 = pce.addR5_1__H_1_3_720p(mMime, mMime, height); + r5_1__H_1_4 = pce.addR5_1__H_1_4_720p(); + r5_1__H_1_3.setConcurrentInstances(maxInstances); + r5_1__H_1_4.setConcurrentFps(achievedFrameRate); } + + pce.submitAndCheck(); } } diff --git a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java index 28c7fbd9307..66afa892425 100644 --- a/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java +++ b/tests/mediapc/src/android/mediapc/cts/MultiEncoderPerfTest.java @@ -16,24 +16,19 @@ package android.mediapc.cts; -import static org.junit.Assert.assertTrue; - import android.media.MediaFormat; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.mediapc.cts.common.Utils; -import android.os.Build; -import android.util.Log; import android.util.Pair; import androidx.test.filters.LargeTest; -import androidx.test.platform.app.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.Assume; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -62,6 +57,9 @@ public class MultiEncoderPerfTest extends MultiCodecPerfTestBase { mEncoderName = encoderName; } + @Rule + public final TestName mTestName = new TestName(); + // Returns the params list with the mime and their hardware encoders in // both sync and async modes. // Parameters {0}_{2}_{3} -- Mime_EncoderName_isAsync @@ -90,7 +88,7 @@ public class MultiEncoderPerfTest extends MultiCodecPerfTestBase { Assume.assumeTrue(Utils.isSPerfClass() || Utils.isRPerfClass() || !Utils.isPerfClass()); boolean hasVP9 = mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9); - int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9); + int requiredMinInstances = getRequiredMinConcurrentInstances720p(hasVP9); testCodec(720, 1280, 4000000, requiredMinInstances); } @@ -111,7 +109,7 @@ public class MultiEncoderPerfTest extends MultiCodecPerfTestBase { ArrayList<Pair<String, String>> mimeEncoderPairs = new ArrayList<>(); mimeEncoderPairs.add(Pair.create(mMime, mEncoderName)); int maxInstances = checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, - mimeEncoderPairs); + mimeEncoderPairs, requiredMinInstances); double achievedFrameRate = 0.0; if (maxInstances >= requiredMinInstances) { ExecutorService pool = Executors.newFixedThreadPool(maxInstances); @@ -124,22 +122,22 @@ public class MultiEncoderPerfTest extends MultiCodecPerfTestBase { achievedFrameRate += result.get(); } } + PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_3; + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_4; // Achieved frame rate is not compared as this test runs in byte buffer mode. - if (Utils.isPerfClass()) { - assertTrue("Encoder " + mEncoderName + " unable to support minimum concurrent " + - "instances. act/exp: " + maxInstances + "/" + requiredMinInstances, - maxInstances >= requiredMinInstances); - Log.v(LOG_TAG, "Achieved fps: " + achievedFrameRate + - "\nAchieved frame rate is not compared as this test runs in byte buffer mode"); + if (height >= 1080) { + r5_1__H_1_3 = pce.addR5_1__H_1_3_1080p(); + r5_1__H_1_4 = pce.addR5_1__H_1_4_1080p(); + r5_1__H_1_3.setConcurrentInstances(maxInstances); + r5_1__H_1_4.setConcurrentFps(achievedFrameRate); } else { - int pc = maxInstances >= requiredMinInstances ? Build.VERSION_CODES.R : 0; - DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", - "MultiEncoderPerf_" + mEncoderName); - log.addValue("encoder", mMime + "_" + mEncoderName, ResultType.NEUTRAL, - ResultUnit.NONE); - log.setSummary("CDD 2.2.7.1/5.1/H-1-3,H-1-4 performance_class", pc, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + r5_1__H_1_3 = pce.addR5_1__H_1_3_720p(mMime, mMime, height); + r5_1__H_1_4 = pce.addR5_1__H_1_4_720p(); + r5_1__H_1_3.setConcurrentInstances(maxInstances); + r5_1__H_1_4.setConcurrentFps(achievedFrameRate); } + + pce.submitAndCheck(); } } diff --git a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java index 9312637450e..34ffc9b8814 100644 --- a/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java +++ b/tests/mediapc/src/android/mediapc/cts/MultiTranscoderPerfTest.java @@ -19,23 +19,20 @@ package android.mediapc.cts; import static org.junit.Assert.assertTrue; import android.media.MediaFormat; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.mediapc.cts.common.Utils; -import android.os.Build; import android.util.Pair; import android.view.Surface; import androidx.test.filters.LargeTest; -import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; 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.Assume; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -73,6 +70,9 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase { mEncoderPair = encoderPair; } + @Rule + public final TestName mTestName = new TestName(); + // Parameters {0}_{1}_{2} -- Pair(Mime DecoderName)_Pair(Mime EncoderName)_isAsync @Parameterized.Parameters(name = "{index}({0}_{1}_{2})") public static Collection<Object[]> inputParams() { @@ -115,7 +115,7 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase { boolean hasVP9 = mDecoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9) || mEncoderPair.first.equals(MediaFormat.MIMETYPE_VIDEO_VP9); - int requiredMinInstances = getRequiredMinConcurrentInstances(hasVP9) / 2; + int requiredMinInstances = getRequiredMinConcurrentInstances720p(hasVP9); testCodec(m720pTestFiles, 720, 1280, requiredMinInstances); } @@ -131,7 +131,7 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase { @CddTest(requirement = "2.2.7.1/5.1/H-1-5,H-1-6") public void test1080p() throws Exception { Assume.assumeTrue(Utils.isTPerfClass() || !Utils.isPerfClass()); - testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES / 2); + testCodec(m1080pTestFiles, 1080, 1920, REQUIRED_MIN_CONCURRENT_INSTANCES); } private void testCodec(Map<String, String> testFiles, int height, int width, @@ -141,7 +141,8 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase { mimeCodecPairs.add(mDecoderPair); mimeCodecPairs.add(mEncoderPair); int maxInstances = - checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, mimeCodecPairs); + checkAndGetMaxSupportedInstancesForCodecCombinations(height, width, mimeCodecPairs, + requiredMinInstances); double achievedFrameRate = 0.0; if (maxInstances >= requiredMinInstances) { ExecutorService pool = @@ -175,29 +176,22 @@ public class MultiTranscoderPerfTest extends MultiCodecPerfTestBase { } } } - if (Utils.isPerfClass()) { - assertTrue("DecodeMime: " + mDecoderPair.first + ", Decoder " + mDecoderPair.second + - ", EncodeMime: " + mEncoderPair.first + ", Encoder: " + mEncoderPair.second + - ", unable to support minimum concurrent instances. act/exp: " + maxInstances + - "/" + requiredMinInstances, maxInstances >= requiredMinInstances); - - assertTrue("Unable to achieve the maxFrameRate supported. act/exp: " + achievedFrameRate - + "/" + mMaxFrameRate / 2 + " for " + maxInstances + " instances.", - achievedFrameRate >= mMaxFrameRate / 2); + + PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_5; + PerformanceClassEvaluator.ConcurrentCodecRequirement r5_1__H_1_6; + if (height >= 1080) { + r5_1__H_1_5 = pce.addR5_1__H_1_5_1080p(); + r5_1__H_1_6 = pce.addR5_1__H_1_6_1080p(); + r5_1__H_1_5.setConcurrentInstances(maxInstances); + r5_1__H_1_6.setConcurrentFps(achievedFrameRate); } else { - int pc = maxInstances >= requiredMinInstances && achievedFrameRate >= mMaxFrameRate / 2 - ? Build.VERSION_CODES.R : 0; - DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", - "MultiTranscoderPairPerf_" + mDecoderPair.second); - log.addValue("decoders", mDecoderPair.first + "_" + mDecoderPair.second + "_" - + mEncoderPair.first + "_" + mEncoderPair.second, ResultType.NEUTRAL, - ResultUnit.NONE); - log.addValue("achieved_framerate", achievedFrameRate, ResultType.HIGHER_BETTER, - ResultUnit.NONE); - log.addValue("expected_framerate", mMaxFrameRate, ResultType.NEUTRAL, ResultUnit.NONE); - log.setSummary("CDD 2.2.7.1/5.1/H-1-5,H-1-6 performance_class", pc, ResultType.NEUTRAL, - ResultUnit.NONE); - log.submit(InstrumentationRegistry.getInstrumentation()); + r5_1__H_1_5 = pce.addR5_1__H_1_5_720p(mDecoderPair.first, mEncoderPair.first, height); + r5_1__H_1_6 = pce.addR5_1__H_1_6_720p(mDecoderPair.first, mEncoderPair.first, height); + r5_1__H_1_5.setConcurrentInstances(maxInstances); + r5_1__H_1_6.setConcurrentFps(achievedFrameRate); } + + pce.submitAndCheck(); } } diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java index 24b22eae1b6..2508845049b 100644 --- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java +++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java @@ -17,7 +17,7 @@ package android.mediapc.cts; import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback; - +import static android.media.MediaDrm.SECURITY_LEVEL_HW_SECURE_ALL; import static org.junit.Assert.assertTrue; import android.app.ActivityManager; @@ -33,30 +33,26 @@ import android.mediapc.cts.common.Utils; import android.util.DisplayMetrics; import android.util.Log; import android.view.WindowManager; - import androidx.test.filters.SmallTest; import androidx.test.platform.app.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 java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; import org.junit.Assume; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; -import java.io.IOException; -import java.util.ArrayList; -import java.util.UUID; - /** * Tests the basic aspects of the media performance class. */ public class PerformanceClassTest { private static final String TAG = "PerformanceClassTest"; - private static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL); + public static final String[] VIDEO_CONTAINER_MEDIA_TYPES = + {"video/mp4", "video/webm", "video/3gpp", "video/3gpp2", "video/avi", "video/x-ms-wmv", + "video/x-ms-asf"}; static ArrayList<String> mMimeSecureSupport = new ArrayList<>(); @Rule @@ -83,8 +79,8 @@ public class PerformanceClassTest { @SmallTest @Test - // TODO(b/218771970) Add @CddTest annotation - public void testSecureHwDecodeSupport() throws IOException { + @CddTest(requirements = {"2.2.7.1/5.1/H-1-11"}) + public void testSecureHwDecodeSupport() { ArrayList<String> noSecureHwDecoderForMimes = new ArrayList<>(); for (String mime : mMimeSecureSupport) { boolean isSecureHwDecoderFoundForMime = false; @@ -110,46 +106,35 @@ public class PerformanceClassTest { boolean secureDecodeSupportIfHwDecoderPresent = noSecureHwDecoderForMimes.isEmpty(); PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); - PerformanceClassEvaluator.SecureCodecRequirement rSecureDecodeSupport = - pce.addRSecureDecodeSupport(); - rSecureDecodeSupport.setSecureReqSatisfied(secureDecodeSupportIfHwDecoderPresent); + PerformanceClassEvaluator.SecureCodecRequirement r5_1__H_1_11 = pce.addR5_1__H_1_11(); + r5_1__H_1_11.setSecureReqSatisfied(secureDecodeSupportIfHwDecoderPresent); pce.submitAndCheck(); } @SmallTest @Test - // TODO(b/218771970) Add @CddTest annotation - public void testWidevineSupport() throws UnsupportedSchemeException { - boolean isWidevineSupported = MediaDrm.isCryptoSchemeSupported(WIDEVINE_UUID); - boolean isL1Supported = false; - boolean isL1Tier3Supported = false; - boolean isOemCrypto17Plus = false; - boolean isWidevineCdm17Plus = false; - if (isWidevineSupported) { - MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID); - isL1Supported = mediaDrm.getPropertyString("securityLevel").equals("L1"); - int tier = Integer.parseInt(mediaDrm.getPropertyString("resourceRatingTier")); - isL1Tier3Supported = tier >= 3; - - String oemCryptoVersionProperty = mediaDrm.getPropertyString("oemCryptoApiVersion"); - int oemCryptoVersion = Integer.parseInt(oemCryptoVersionProperty); - isOemCrypto17Plus = oemCryptoVersion >= 17; - - String cdmVersionProperty = mediaDrm.getPropertyString(MediaDrm.PROPERTY_VERSION); - int cdmMajorVersion = Integer.parseInt(cdmVersionProperty.split("\\.", 2)[0]); - isWidevineCdm17Plus = cdmMajorVersion >= 17; + @CddTest(requirements = {"2.2.7.1/5.7/H-1-2"}) + public void testMediaDrmSecurityLevelHwSecureAll() throws UnsupportedSchemeException { + List<UUID> drmList = MediaDrm.getSupportedCryptoSchemes(); + List<UUID> supportedHwSecureAllSchemes = new ArrayList<>(); + + for (UUID cryptoSchemeUUID : drmList) { + boolean cryptoSchemeSupportedForAtleastOneMediaType = false; + for (String mediaType : VIDEO_CONTAINER_MEDIA_TYPES) { + cryptoSchemeSupportedForAtleastOneMediaType |= MediaDrm + .isCryptoSchemeSupported(cryptoSchemeUUID, mediaType, + SECURITY_LEVEL_HW_SECURE_ALL); + } + if (cryptoSchemeSupportedForAtleastOneMediaType) { + supportedHwSecureAllSchemes.add(cryptoSchemeUUID); + } } PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); - PerformanceClassEvaluator.SecureCodecRequirement rWidevineReqSupport = - pce.addRWidevineSupport(); + PerformanceClassEvaluator.SecureCodecRequirement r5_7__H_1_2 = pce.addR5_7__H_1_2(); - rWidevineReqSupport.setWidevineSupported(isWidevineSupported); - rWidevineReqSupport.setWidevineL1Supported(isL1Supported); - rWidevineReqSupport.setWidevineL1Tier3Supported(isL1Tier3Supported); - rWidevineReqSupport.setOemCrypto17Plus(isOemCrypto17Plus); - rWidevineReqSupport.setWidevineCdm17Plus(isWidevineCdm17Plus); + r5_7__H_1_2.setNumCryptoHwSecureAllDec(supportedHwSecureAllSchemes.size()); pce.submitAndCheck(); } @@ -190,19 +175,15 @@ public class PerformanceClassTest { PerformanceClassEvaluator.DensityRequirement r7_1_1_3__h_1_1 = pce.addR7_1_1_3__H_1_1(); PerformanceClassEvaluator.ResolutionRequirement r7_1_1_1__h_2_1 = pce.addR7_1_1_1__H_2_1(); PerformanceClassEvaluator.DensityRequirement r7_1_1_3__h_2_1 = pce.addR7_1_1_3__H_2_1(); - PerformanceClassEvaluator.ResolutionRequirement r7_1_1_1__tbd1 = pce.addR7_1_1_1__TBD1(); - PerformanceClassEvaluator.DensityRequirement r7_1_1_3__tbd2 = pce.addR7_1_1_3__TBD2(); r7_1_1_1__h_1_1.setLongResolution(longPix); r7_1_1_1__h_2_1.setLongResolution(longPix); - r7_1_1_1__tbd1.setLongResolution(longPix); + r7_1_1_1__h_1_1.setShortResolution(shortPix); r7_1_1_1__h_2_1.setShortResolution(shortPix); - r7_1_1_1__tbd1.setShortResolution(shortPix); r7_1_1_3__h_1_1.setDisplayDensity(density); r7_1_1_3__h_2_1.setDisplayDensity(density); - r7_1_1_3__tbd2.setDisplayDensity(density); pce.submitAndCheck(); } @@ -210,8 +191,7 @@ public class PerformanceClassTest { @Test @CddTest(requirements={ "2.2.7.3/7.6.1/H-1-1", - "2.2.7.3/7.6.1/H-2-1", - "2.2.7.3/7.6.1/H-3-1"}) + "2.2.7.3/7.6.1/H-2-1",}) public void testMinimumMemory() { Context context = InstrumentationRegistry.getInstrumentation().getContext(); @@ -224,11 +204,9 @@ public class PerformanceClassTest { PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_1_1 = pce.addR7_6_1__H_1_1(); PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_2_1 = pce.addR7_6_1__H_2_1(); - PerformanceClassEvaluator.MemoryRequirement r7_6_1_h_3_1 = pce.addR7_6_1__H_3_1(); r7_6_1_h_1_1.setPhysicalMemory(totalMemoryMb); r7_6_1_h_2_1.setPhysicalMemory(totalMemoryMb); - r7_6_1_h_3_1.setPhysicalMemory(totalMemoryMb); pce.submitAndCheck(); } diff --git a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java index 4a9d39f127d..bbe26dce0ac 100644 --- a/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java +++ b/tests/mediapc/src/android/mediapc/cts/VideoCodecRequirementsTest.java @@ -29,6 +29,7 @@ import android.media.MediaFormat; import android.mediapc.cts.common.PerformanceClassEvaluator; import android.util.Log; import androidx.test.filters.LargeTest; +import com.android.compatibility.common.util.CddTest; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -78,7 +79,7 @@ public class VideoCodecRequirementsTest { */ @LargeTest @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - // TODO(b/218771970) Add @CddTest annotation + @CddTest(requirement = "2.2.7.1/5.1/H-1-14") public void testAV1HwDecoderRequirements() throws Exception { MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AV1, 1920, 1080); format.setInteger(MediaFormat.KEY_FRAME_RATE, 60); @@ -107,7 +108,7 @@ public class VideoCodecRequirementsTest { */ @LargeTest @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - // TODO(b/218771970) Add @CddTest annotation + @CddTest(requirement = "2.2.7.1/5.1/H-1-15") public void test4k60Decoder() throws IOException { Set<String> decoderSet = get4k60HwCodecSet(false); @@ -123,7 +124,7 @@ public class VideoCodecRequirementsTest { */ @LargeTest @Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS) - // TODO(b/218771970) Add @CddTest annotation + @CddTest(requirement = "2.2.7.1/5.1/H-1-16") public void test4k60Encoder() throws IOException { Set<String> encoderSet = get4k60HwCodecSet(true); diff --git a/tests/musicrecognition/Android.bp b/tests/musicrecognition/Android.bp index 1b7298a6898..ecda10b2926 100644 --- a/tests/musicrecognition/Android.bp +++ b/tests/musicrecognition/Android.bp @@ -31,4 +31,8 @@ android_test { "cts", "general-tests", ], + data: [ + ":CtsOutsideOfPackageService", + ], + per_testcase_directory: true, } diff --git a/tests/net/src/android/net/cts/LocalSocketTest.java b/tests/net/src/android/net/cts/LocalSocketTest.java index 39b5dbcdb46..c302f818528 100644 --- a/tests/net/src/android/net/cts/LocalSocketTest.java +++ b/tests/net/src/android/net/cts/LocalSocketTest.java @@ -30,12 +30,9 @@ import android.net.Credentials; import android.net.LocalServerSocket; import android.net.LocalSocket; import android.net.LocalSocketAddress; -import android.os.ParcelFileDescriptor; -import android.os.SystemClock; import android.system.Os; import android.system.OsConstants; import android.system.StructTimeval; -import android.system.UnixSocketAddress; import androidx.test.runner.AndroidJUnit4; @@ -196,7 +193,7 @@ public class LocalSocketTest { } // http://b/31205169 - @Test + @Test @IgnoreUpTo(SC_V2) // Crashes on pre-T due to a JNI bug. See http://r.android.com/2096720 public void testSetSoTimeout_readTimeout() throws Exception { String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout"; diff --git a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java index 542b3aa9db6..0e1bcd1da66 100644 --- a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java +++ b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java @@ -405,7 +405,8 @@ public class MediaStoreUiTest { private boolean supportsHardware() { final PackageManager pm = mContext.getPackageManager(); return !pm.hasSystemFeature("android.hardware.type.television") - && !pm.hasSystemFeature("android.hardware.type.watch"); + && !pm.hasSystemFeature("android.hardware.type.watch") + && !pm.hasSystemFeature("android.hardware.type.automotive"); } public File getVolumePath(String volumeName) { 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 671078dbdeb..7f35367333a 100644 --- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java +++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java @@ -196,6 +196,15 @@ public class MainInteractionSession extends VoiceInteractionSession { return; } + if (structure != null && structure.isHomeActivity() && !state.isFocused()) { + // If the system has multiple display areas, the launcher may be visible and resumed + // when the tests are in progress, so the tests might fail if they receives unexpected + // state from the launcher. Ignore the states from unfocused launcher to avoid this + // failure. + Log.i(TAG, "Ignoring the state from unfocused launcher"); + return; + } + // send to test to verify that this is accurate. mAssistData.putBoolean(Utils.ASSIST_IS_ACTIVITY_ID_NULL, state.getActivityId() == null); mAssistData.putParcelable(Utils.ASSIST_STRUCTURE_KEY, structure); diff --git a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java index e4fbee6805d..5afdbb118a6 100644 --- a/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java +++ b/tests/tests/carrierapi/src/android/carrierapi/cts/CarrierApiTest.java @@ -525,10 +525,9 @@ public class CarrierApiTest extends BaseCarrierApiTest { mTelephonyManager.getServiceState(); mTelephonyManager.getManualNetworkSelectionPlmn(); mTelephonyManager.setForbiddenPlmns(new ArrayList<String>()); - int activeModemCount = mTelephonyManager.getActiveModemCount(); - for (int i = 0; i < activeModemCount; i++) { - mTelephonyManager.isModemEnabledForSlot(i); - } + // TODO(b/235490259): test all slots once TM#isModemEnabledForSlot allows + mTelephonyManager.isModemEnabledForSlot( + SubscriptionManager.getSlotIndex(mTelephonyManager.getSubscriptionId())); } catch (SecurityException e) { fail(NO_CARRIER_PRIVILEGES_FAILURE_MESSAGE); } @@ -1105,7 +1104,7 @@ public class CarrierApiTest extends BaseCarrierApiTest { } // Set subscription group with current sub Id. - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + int subId = SubscriptionManager.getDefaultSubscriptionId(); if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return; ParcelUuid uuid = ShellIdentityUtils.invokeMethodWithShellPermissions(mSubscriptionManager, (sm) -> sm.createSubscriptionGroup(Arrays.asList(subId))); @@ -1142,7 +1141,7 @@ public class CarrierApiTest extends BaseCarrierApiTest { @Test public void testAddSubscriptionToExistingGroupForEsim() { // Set subscription group with current sub Id. - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + int subId = SubscriptionManager.getDefaultSubscriptionId(); if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return; ParcelUuid uuid = mSubscriptionManager.createSubscriptionGroup(Arrays.asList(subId)); @@ -1172,7 +1171,7 @@ public class CarrierApiTest extends BaseCarrierApiTest { */ @Test public void testOpportunistic() { - int subId = SubscriptionManager.getDefaultDataSubscriptionId(); + int subId = SubscriptionManager.getDefaultSubscriptionId(); if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return; SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId); boolean oldOpportunistic = info.isOpportunistic(); diff --git a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt index 8c03abd8c53..ef9d958dfb9 100644 --- a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt +++ b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt @@ -79,8 +79,7 @@ abstract class TestBase { }) // Make sure CompanionDeviceServices are not bound. - assertFalse(PrimaryCompanionService.isBound) - assertFalse(SecondaryCompanionService.isBound) + assertValidCompanionDeviceServicesUnbind() setUp() } diff --git a/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java b/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java index 5cb59c24c3f..4359d7d171a 100644 --- a/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java +++ b/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java @@ -52,10 +52,12 @@ import android.content.pm.PackageInstaller.SessionParams; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.cts.util.AbandonAllPackageSessionsRule; +import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.IBinder; import android.os.ParcelFileDescriptor; +import android.os.SystemProperties; import android.platform.test.annotations.AppModeFull; import android.util.ExceptionUtils; @@ -71,6 +73,7 @@ import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata; import org.junit.After; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -152,6 +155,11 @@ public class ChecksumsTest { new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(TEST_FIXED_APK_SHA256)), new Checksum(TYPE_WHOLE_MD5, hexStringToBytes(TEST_FIXED_APK_MD5))}; + /** Default is to not use fs-verity since it depends on kernel support. */ + private static final int FSVERITY_DISABLED = 0; + + /** Standard fs-verity. */ + private static final int FSVERITY_ENABLED = 2; private static final byte[] NO_SIGNATURE = null; @@ -315,6 +323,7 @@ public class ChecksumsTest { @LargeTest @Test public void testFixedFSVerityDefaultChecksums() throws Exception { + Assume.assumeTrue(isApkVerityEnabled()); installApkWithFSVerity(TEST_FIXED_APK_FSVERITY, TEST_FIXED_APK_FSVERITY_FSVSIG); assertTrue(isAppInstalled(FIXED_FSVERITY_PACKAGE_NAME)); @@ -1513,6 +1522,13 @@ public class ChecksumsTest { return getPackageManager().hasSystemFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY); } + // From PackageManagerServiceUtils. + private static boolean isApkVerityEnabled() { + return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R + || SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED) + == FSVERITY_ENABLED; + } + private byte[] readSignature() throws IOException { return readSignature(TEST_FIXED_APK_DIGESTS_SIGNATURE); } diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt index cf9dde09e22..416d19f7615 100644 --- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt +++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandMultiUserTest.kt @@ -237,19 +237,21 @@ class PackageManagerShellCommandMultiUserTest { val intentFilter = IntentFilter() intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED) intentFilter.addDataScheme("package") - context.registerReceiver( - broadcastReceiverForPrimaryUser, - intentFilter, - null, - backgroundHandler, - RECEIVER_EXPORTED - ) uiAutomation.adoptShellPermissionIdentity( Manifest.permission.INTERACT_ACROSS_USERS, Manifest.permission.INTERACT_ACROSS_USERS_FULL ) + val contextPrimaryUser = context.createContextAsUser(primaryUser.userHandle(), 0) + val contextSecondaryUser = context.createContextAsUser(secondaryUser.userHandle(), 0) try { - context.createContextAsUser(secondaryUser.userHandle(), 0).registerReceiver( + contextPrimaryUser.registerReceiver( + broadcastReceiverForPrimaryUser, + intentFilter, + null, + backgroundHandler, + RECEIVER_EXPORTED + ) + contextSecondaryUser.registerReceiver( broadcastReceiverForSecondaryUser, intentFilter, null, diff --git a/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java b/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java index 227c81ec7ee..166227ab916 100644 --- a/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java +++ b/tests/tests/dreams/src/android/service/dreams/cts/DreamServiceTest.java @@ -16,8 +16,10 @@ package android.service.dreams.cts; import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeFalse; import android.content.ComponentName; +import android.content.pm.PackageManager; import android.server.wm.ActivityManagerTestBase; import android.server.wm.DreamCoordinator; import android.service.dreams.DreamService; @@ -65,6 +67,9 @@ public class DreamServiceTest extends ActivityManagerTestBase { @Test public void testDreamInSeparateProcess() { + assumeFalse(mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_AUTOMOTIVE)); + final ComponentName dreamService = ComponentName.unflattenFromString(DREAM_SERVICE_COMPONENT); final ComponentName dreamActivity = mDreamCoordinator.setActiveDream(dreamService); diff --git a/tests/tests/graphics/AndroidManifest.xml b/tests/tests/graphics/AndroidManifest.xml index 64061339025..9a1c59142d6 100644 --- a/tests/tests/graphics/AndroidManifest.xml +++ b/tests/tests/graphics/AndroidManifest.xml @@ -55,6 +55,23 @@ <activity android:name="android.graphics.drawable.cts.DrawableStubActivity" android:theme="@style/WhiteBackgroundNoWindowAnimation" android:screenOrientation="locked"/> + + <activity android:name="android.graphics.cts.EmptyActivity" + android:label="Empty Activity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <activity android:name="android.graphics.cts.EmptyActivity2" + android:label="Empty Activity 2" + android:exported="true"> + <intent-filter> + <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/> + </intent-filter> + </activity> <activity android:name="android.graphics.drawable.cts.AnimatedImageActivity" android:theme="@style/WhiteBackgroundNoWindowAnimation" android:screenOrientation="locked"> diff --git a/tests/tests/graphics/res/xml/valid_themes.xml b/tests/tests/graphics/res/xml/valid_themes.xml index a7619d46a56..a7e230417a3 100644 --- a/tests/tests/graphics/res/xml/valid_themes.xml +++ b/tests/tests/graphics/res/xml/valid_themes.xml @@ -19,7 +19,7 @@ <theme color="ffb9577a"> <spritz>ffffff,fffbff,ffecf0,f9dbe2,dcbfc6,c0a4ab,a48a90,887076,6f595e,564147,3e2b31,27171c,000000,ffffff,fffbff,ffecf0,f2dde1,d5c2c6,b9a7aa,9e8c90,827276,6a5b5e,514347,3a2d30,24191c,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000,ffffff,fffbff,f7efef,e8e1e1,ccc5c5,b0aaaa,958f90,7a7575,625d5e,4a4646,332f30,1e1b1b,000000,ffffff,fffbff,f7efef,e8e1e1,ccc5c5,b0aaaa,958f90,7a7575,625d5e,4a4646,332f30,1e1b1b,000000</spritz> <tonal_spot>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,e494ad,c67b92,a76178,8c4a60,703348,541d32,3a071d,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000,ffffff,fffbff,ffeee2,ffdcc1,efbd94,d1a27b,b48862,976d4a,7c5635,613f20,48290b,2e1500,000000,ffffff,fffbff,faeeef,ebe0e1,cfc4c5,b3a9aa,988e90,7d7475,645c5e,4c4546,352f30,201a1b,000000,ffffff,fffbff,ffecf0,f2dde1,d5c2c6,b9a7aa,9e8c90,827276,6a5b5e,514347,3a2d30,24191c,000000</tonal_spot> - <vibrant>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,ff84ae,ff4896,e5007b,b90063,8e004a,650033,3e001d,000000,ffffff,fffbff,ffedec,ffdad9,f5b7b7,d79c9c,ba8382,9c6968,815252,663b3b,4c2526,331112,000000,ffffff,fffbff,ffede8,ffdbd1,ffb59f,e49982,c67f6a,a76551,8b4e3c,6e3726,532212,370d02,000000,ffffff,fffbff,ffecf0,f2dde1,d5c2c6,b9a7aa,9e8c90,827276,6a5b5e,514347,3a2d30,24191c,000000,ffffff,fffbff,ffecf0,f9dbe2,dcbfc6,c0a4ab,a48a90,887076,6f595e,564147,3e2b31,27171c,000000</vibrant> + <vibrant>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,ff84ae,ff4896,e5007b,b90063,8e004a,650033,3e001d,000000,ffffff,fffbff,ffedec,ffdad9,f5b7b7,d79c9c,ba8382,9c6968,815252,663b3b,4c2526,331112,000000,ffffff,fffbff,ffede8,ffdbd1,ffb59f,e49982,c67f6a,a76551,8b4e3c,6e3726,532212,370d02,000000,ffffff,fffbff,ffecf0,f6dce2,d9c0c6,bca5ab,a18b90,857176,6c5a5e,534247,3c2c30,25181c,000000,ffffff,fffbff,ffecf0,f9dbe2,dcbfc6,c0a4ab,a48a90,887076,6f595e,564147,3e2b31,27171c,000000</vibrant> <expressive>ffffff,fbfcff,e5f2ff,c8e6ff,8bcefd,6fb2e0,5298c4,337da8,0c648e,004c6d,00344d,001e2e,000000,ffffff,fffbff,ffede6,ffdbcb,f4ba9e,d69f85,b9856c,9b6b53,80543e,653d28,4b2714,311303,000000,ffffff,fcffdd,ebf8ad,dde9a0,c1cd86,a6b16e,8b9656,717b3e,596329,424b13,2c3400,181e00,000000,ffffff,fffbff,ffedec,f4dddd,d7c1c2,bba6a7,9f8c8c,847272,6b5a5b,524343,3b2d2d,241819,000000,ffffff,fffbff,ffedec,fcdbdb,debfc0,c2a4a5,a68a8b,8a7070,715859,584142,3f2b2c,281718,000000</expressive> <rainbow>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,f48bae,d57193,b55779,984061,7b2949,5e1132,3e001d,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000,ffffff,fffbff,ffeee2,ffdcc1,efbd94,d1a27b,b48862,976d4a,7c5635,613f20,48290b,2e1500,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow> <fruit_salad>ffffff,fffbff,f9ecff,f0dbff,dcb8ff,c598f1,a97ed4,8d64b7,744c9d,5b3383,431a6b,2c0051,000000,ffffff,fffbff,f9ecff,f0dbff,dab9f9,be9edc,a384c0,876aa4,6e528a,553b71,3e2459,280d42,000000,ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,e494ad,c67b92,a76178,8c4a60,703348,541d32,3a071d,000000,ffffff,fffbff,ffecf0,f6dce2,d9c0c6,bca5ab,a18b90,857176,6c5a5e,534247,3c2c30,25181c,000000,ffffff,fffbff,ffecf0,ffd9e2,e3bdc6,c6a2ab,aa8891,8d6e76,74565f,5b3f47,422931,2b151c,000000</fruit_salad> @@ -27,7 +27,7 @@ <theme color="ffb16407"> <spritz>ffffff,fffbff,ffeee2,f9ddc9,dcc2ae,c0a793,a48c7a,887261,6f5a4a,564334,3d2d1f,27190c,000000,ffffff,fffbff,ffeee2,f2dfd1,d6c3b6,b9a89b,9e8e82,827368,6a5c51,51443a,3a2e25,231a11,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000,ffffff,fffbff,f7efec,e8e1dd,ccc5c2,b0aaa7,95908d,7a7572,625d5b,4a4644,33302e,1e1b19,000000,ffffff,fffbff,f7efec,e8e1dd,ccc5c2,b0aaa7,95908d,7a7572,625d5b,4a4644,33302e,1e1b19,000000</spritz> <tonal_spot>ffffff,fffbff,ffeee2,ffdcc1,ffb778,e09d60,c28349,a36931,87521c,6b3b04,4c2700,2e1500,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000,ffffff,fcffde,edf6bf,dfe7b2,c3cb98,a8b07e,8d9566,727a4d,5b6238,434a22,2d330e,181e00,000000,ffffff,fffbff,faefe8,ece0da,cfc4be,b3a9a3,988f89,7d746f,655d58,4c4541,352f2b,201b17,000000,ffffff,fffbff,ffeee2,f2dfd1,d6c3b6,b9a89b,9e8e82,827368,6a5c51,51443a,3a2e25,231a11,000000</tonal_spot> - <vibrant>ffffff,fffbff,ffeee2,ffdcc1,ffb778,fd9000,d77900,b06200,8e4e00,6c3a00,4c2700,2e1500,000000,ffffff,fffbff,ffeedc,ffddb2,e6c08d,c9a574,ad8b5c,907144,76592f,5c421a,432c06,291800,000000,ffffff,fffbff,ffefcf,ffe090,e1c477,c4a85f,a88e48,8c7330,725c1a,584401,3d2e00,241a00,000000,ffffff,fffbff,ffeee2,f2dfd1,d6c3b6,b9a89b,9e8e82,827368,6a5c51,51443a,3a2e25,231a11,000000,ffffff,fffbff,ffeee2,f9ddc9,dcc2ae,c0a793,a48c7a,887261,6f5a4a,564334,3d2d1f,27190c,000000</vibrant> + <vibrant>ffffff,fffbff,ffeee2,ffdcc1,ffb778,fd9000,d77900,b06200,8e4e00,6c3a00,4c2700,2e1500,000000,ffffff,fffbff,ffeedc,ffddb2,e6c08d,c9a574,ad8b5c,907144,76592f,5c421a,432c06,291800,000000,ffffff,fffbff,ffefcf,ffe090,e1c477,c4a85f,a88e48,8c7330,725c1a,584401,3d2e00,241a00,000000,ffffff,fffbff,ffeee2,f6decd,d9c2b2,bda797,a18d7e,857364,6c5b4e,534437,3c2e22,25190f,000000,ffffff,fffbff,ffeee2,f9ddc9,dcc2ae,c0a793,a48c7a,887261,6f5a4a,564334,3d2d1f,27190c,000000</vibrant> <expressive>ffffff,fffbff,f6edff,eaddff,d1bcff,b6a0e8,9b85cb,7f6baf,675395,4f3b7b,382463,220b4d,000000,ffffff,fffbff,fbf2b7,ece4aa,cfc890,b3ad77,98925f,7d7747,656031,4c481c,353107,1f1c00,000000,ffffff,fffbff,ffeed9,ffdeaa,ebc078,cda55f,b08b48,937030,79591b,5e4102,422c00,271900,000000,ffffff,fffbff,feeedd,efe0cf,d3c4b4,b7a99a,9b8f80,807466,675d50,4f4539,382f24,221a10,000000,ffffff,fffbff,ffeedc,f5dfc6,d8c3ab,bba891,a08e77,84735e,6b5c48,524432,3b2e1d,241a0a,000000</expressive> <rainbow>ffffff,fffbff,ffeee2,ffdcc1,ffb778,ee9743,ce7d2b,ae640f,8e4e00,6c3a00,4c2700,2e1500,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000,ffffff,fcffde,edf6bf,dfe7b2,c3cb98,a8b07e,8d9566,727a4d,5b6238,434a22,2d330e,181e00,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow> <fruit_salad>ffffff,fffbff,ffeced,ffd9dd,ffb2bb,f98a9b,d97181,b95767,9b4051,7d293a,5f1125,400012,000000,ffffff,fffbff,ffeced,ffd9dd,ffb2bb,e8949f,c97a85,aa606b,8e4954,72333d,561d28,3b0714,000000,ffffff,fffbff,ffeee2,ffdcc1,ffb778,e09d60,c28349,a36931,87521c,6b3b04,4c2700,2e1500,000000,ffffff,fffbff,ffeee2,f6decd,d9c2b2,bda797,a18d7e,857364,6c5b4e,534437,3c2e22,25190f,000000,ffffff,fffbff,ffeee2,ffdcc1,e2c0a5,c6a58b,a98b72,8d7159,735943,5a422d,412c19,2a1706,000000</fruit_salad> @@ -35,7 +35,7 @@ <theme color="ff6e7f10"> <spritz>ffffff,fdfee4,f1f3d8,e3e4cb,c6c8b0,abad95,90937c,757862,5d604c,464835,2f3220,1a1d0d,000000,ffffff,fefdec,f2f2e1,e4e3d3,c7c7b7,acac9d,919283,767769,5e5f52,46483b,303126,1b1c12,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000,ffffff,fcffdd,f4f0ec,e5e2de,c9c6c2,adaba7,92908d,777672,5f5e5b,474744,31302e,1c1c19,000000,ffffff,fcffdd,f4f0ec,e5e2de,c9c6c2,adaba7,92908d,777672,5f5e5b,474744,31302e,1c1c19,000000</spritz> <tonal_spot>ffffff,fcffdd,eaf8a4,dcea97,c0ce7e,a5b265,8a974e,707c36,586420,414b08,2c3400,181e00,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000,ffffff,f3fffa,cbfbed,bdecdf,a2d0c3,87b4a8,6d998e,527e74,3a665c,224e45,05372f,00201a,000000,ffffff,fffcf4,f3f1e8,e5e2da,c8c7bf,adaba4,92918a,77766f,5f5f58,474741,31312b,1b1c17,000000,ffffff,fefdec,f2f2e1,e4e3d3,c7c7b7,acac9d,919283,767769,5e5f52,46483b,303126,1b1c12,000000</tonal_spot> - <vibrant>ffffff,fcffdd,e9f99b,d0f100,b7d300,9db600,859a00,6c7e00,566500,404c00,2c3400,181e00,000000,ffffff,f9ffe9,e4f8c7,d6e9ba,bacd9f,9fb286,85976d,6a7c54,53643e,3c4c28,263514,111f03,000000,ffffff,f6ffef,d0fdc6,c2eeb9,a7d29e,8cb685,729b6c,588053,41673d,2a4f28,133813,002203,000000,ffffff,fefdec,f2f2e1,e4e3d3,c7c7b7,acac9d,919283,767769,5e5f52,46483b,303126,1b1c12,000000,ffffff,fdfee4,f1f3d8,e3e4cb,c6c8b0,abad95,90937c,757862,5d604c,464835,2f3220,1a1d0d,000000</vibrant> + <vibrant>ffffff,fcffdd,e9f99b,d0f100,b7d300,9db600,859a00,6c7e00,566500,404c00,2c3400,181e00,000000,ffffff,f9ffe9,e4f8c7,d6e9ba,bacd9f,9fb286,85976d,6a7c54,53643e,3c4c28,263514,111f03,000000,ffffff,f6ffef,d0fdc6,c2eeb9,a7d29e,8cb685,729b6c,588053,41673d,2a4f28,133813,002203,000000,ffffff,fdfee8,f2f2dd,e3e4cf,c7c8b3,abad99,91927f,767766,5e604f,464838,2f3223,1b1d10,000000,ffffff,fdfee4,f1f3d8,e3e4cb,c6c8b0,abad95,90937c,757862,5d604c,464835,2f3220,1a1d0d,000000</vibrant> <expressive>ffffff,fffbff,ffecf0,ffd9e2,ffb1c8,e991ad,cb7893,ac5e78,904760,733049,581932,3c031d,000000,ffffff,f4fff6,d0fbe1,c2ecd4,a6d0b8,8bb49e,719984,577e6a,406653,284e3c,0f3726,002114,000000,ffffff,f7ffed,d5fcc1,c7eeb3,acd199,91b580,779a67,5d7f4f,466739,2f4e23,19370f,042100,000000,ffffff,fafeef,eff2e4,e0e4d6,c4c8ba,a9ada0,8e9286,73786c,5b6055,44483e,2d3228,191d14,000000,ffffff,f8ffeb,ebf4dd,dde6d0,c1cab4,a6ae9a,8b9480,717966,596150,414939,2b3324,171e10,000000</expressive> <rainbow>ffffff,fcffdd,e9f99b,d9ec7b,bdd062,a2b44a,879932,6d7d17,566500,404c00,2c3400,181e00,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000,ffffff,f3fffa,cbfbed,bdecdf,a2d0c3,87b4a8,6d998e,527e74,3a665c,224e45,05372f,00201a,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow> <fruit_salad>ffffff,fffbff,ffeede,ffddb8,ffb960,e59c37,c7821d,a66800,865300,653e00,472a00,2b1700,000000,ffffff,fffbff,ffeede,ffddb8,f8bb71,daa059,bc8642,9e6c2a,825513,653e00,472a00,2b1700,000000,ffffff,fcffdd,eaf8a4,dcea97,c0ce7e,a5b265,8a974e,707c36,586420,414b08,2c3400,181e00,000000,ffffff,fdfee8,f2f2dd,e3e4cf,c7c8b3,abad99,91927f,767766,5e604f,464838,2f3223,1b1d10,000000,ffffff,fcffdd,f0f4d0,e2e5c2,c5c9a8,aaae8e,8f9375,74795b,5d6145,45492f,2e321b,1a1d08,000000</fruit_salad> @@ -43,7 +43,7 @@ <theme color="ff008673"> <spritz>ffffff,f3fffa,e2f5ee,d4e7e0,b8cbc4,9dafa9,83958f,687a74,51625d,3a4a46,23342f,0e1e1b,000000,ffffff,f4fffa,e9f3ef,dbe5e0,bec9c5,a3ada9,89938f,6e7875,57605d,3f4946,293230,141d1b,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000,ffffff,fdfcfa,f2f0ef,e3e2e1,c7c6c5,ababaa,91918f,767675,5e5e5d,464746,2f3130,1b1c1b,000000,ffffff,fdfcfa,f2f0ef,e3e2e1,c7c6c5,ababaa,91918f,767675,5e5e5d,464746,2f3130,1b1c1b,000000</spritz> <tonal_spot>ffffff,f3fffa,b6ffed,a0f2de,84d6c2,69baa7,4d9f8d,2e8373,056b5b,005144,00382f,00201a,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000,ffffff,fcfcff,e5f2ff,c8e6ff,abcae4,90afc8,7594ac,5b7a91,436278,2b4a5f,113348,001e2f,000000,ffffff,fafdfa,eff1ef,e0e3e1,c4c7c5,a9acaa,8e918f,737775,5c5f5d,444746,2e3130,191c1b,000000,ffffff,f4fffa,e9f3ef,dbe5e0,bec9c5,a3ada9,89938f,6e7875,57605d,3f4946,293230,141d1b,000000</tonal_spot> - <vibrant>ffffff,f3fffa,b6ffed,00fedc,00dfc1,00c1a6,00a38c,008572,006b5b,005144,00382f,00201a,000000,ffffff,f1fffe,c9faf8,bbecea,a0cfce,85b4b2,6b9998,507e7d,386665,1e4e4d,003736,00201f,000000,ffffff,f6feff,d1f8ff,a9eefa,8dd1dd,72b6c1,579ba6,3a808b,1b6772,004f58,00363d,001f24,000000,ffffff,f4fffa,e9f3ef,dbe5e0,bec9c5,a3ada9,89938f,6e7875,57605d,3f4946,293230,141d1b,000000,ffffff,f3fffa,e2f5ee,d4e7e0,b8cbc4,9dafa9,83958f,687a74,51625d,3a4a46,23342f,0e1e1b,000000</vibrant> + <vibrant>ffffff,f3fffa,b6ffed,00fedc,00dfc1,00c1a6,00a38c,008572,006b5b,005144,00382f,00201a,000000,ffffff,f1fffe,c9faf8,bbecea,a0cfce,85b4b2,6b9998,507e7d,386665,1e4e4d,003736,00201f,000000,ffffff,f6feff,d1f8ff,a9eefa,8dd1dd,72b6c1,579ba6,3a808b,1b6772,004f58,00363d,001f24,000000,ffffff,f3fffa,e6f4ee,d7e6e0,bbcac4,a0aea9,86948f,6b7975,54615d,3c4946,26332f,111e1b,000000,ffffff,f3fffa,e2f5ee,d4e7e0,b8cbc4,9dafa9,83958f,687a74,51625d,3a4a46,23342f,0e1e1b,000000</vibrant> <expressive>ffffff,fffbff,ffeee2,ffdcc1,ffb779,e59b57,c68140,a76728,8b5011,6c3a00,4c2700,2e1500,000000,ffffff,fafdff,def4ff,c0e9fb,a5cdde,8ab1c2,7096a7,557b8b,3d6473,244c5a,063543,001f29,000000,ffffff,f1ffff,bbfcff,a8eff2,8cd2d5,70b7ba,559c9f,388183,19686b,004f52,003739,002021,000000,ffffff,f4fefd,e8f3f2,dae5e3,bec9c8,a3adac,889392,6e7877,566060,3f4948,293232,141d1d,000000,ffffff,f1fffe,e2f5f3,d3e6e5,b8cac9,9dafae,829493,687979,506261,394a49,233333,0e1e1e,000000</expressive> <rainbow>ffffff,f3fffa,b6ffed,78f8dd,59dbc1,35bfa6,00a38c,008572,006b5b,005144,00382f,00201a,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000,ffffff,fcfcff,e5f2ff,c8e6ff,abcae4,90afc8,7594ac,5b7a91,436278,2b4a5f,113348,001e2f,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow> <fruit_salad>ffffff,f9ffe7,dafca7,c6f08a,abd471,90b759,779c41,5d8128,466810,324f00,213600,111f00,000000,ffffff,f9ffe7,ddfbaf,cfeda2,b3d088,98b56f,7e9a57,647e3f,4d662a,364e14,213600,111f00,000000,ffffff,f3fffa,b6ffed,a0f2de,84d6c2,69baa7,4d9f8d,2e8373,056b5b,005144,00382f,00201a,000000,ffffff,f3fffa,e6f4ee,d7e6e0,bbcac4,a0aea9,86948f,6b7975,54615d,3c4946,26332f,111e1b,000000,ffffff,f3fffa,dbf7ee,cde8e0,b1ccc4,96b1a9,7c968f,627b74,4a635d,334b45,1d352f,06201b,000000</fruit_salad> @@ -51,7 +51,7 @@ <theme color="ff007fb4"> <spritz>ffffff,fbfcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7781,546069,3d4851,26323a,121d25,000000,ffffff,fbfcff,ebf1f8,dde3ea,c1c7ce,a6acb2,8b9198,70777d,595f65,41484d,2b3136,161c21,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000,ffffff,fefcfc,f2f0f1,e4e2e3,c7c6c7,acabac,919091,767677,5e5e5f,464748,303031,1b1c1c,000000,ffffff,fefcfc,f2f0f1,e4e2e3,c7c6c7,acabac,919091,767677,5e5e5f,464748,303031,1b1c1c,000000</spritz> <tonal_spot>ffffff,fbfcff,e5f2ff,c8e6ff,94cdf6,78b2da,5d97be,407ca1,246488,004c6d,00344d,001e2e,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000,ffffff,fffbff,f6edff,e9ddff,cdc0e8,b2a5cc,978bb1,7c7095,63597c,4b4163,342b4b,1f1635,000000,ffffff,fcfcff,f0f0f3,e2e2e5,c5c6c9,aaabae,8f9193,747679,5d5e61,454749,2e3133,191c1e,000000,ffffff,fbfcff,ebf1f8,dde3ea,c1c7ce,a6acb2,8b9198,70777d,595f65,41484d,2b3136,161c21,000000</tonal_spot> - <vibrant>ffffff,fbfcff,e5f2ff,c8e6ff,87ceff,0eb6ff,009ad9,007eb2,006590,004c6d,00344d,001e2e,000000,ffffff,fdfcff,ebf1ff,d4e3ff,b3c8e9,98accc,7e92b1,637795,4c5f7c,344863,1d314b,051c35,000000,ffffff,fefbff,efefff,dce1ff,b8c4fa,9da9dd,838ec1,6874a4,505c8b,384472,212e5a,0a1844,000000,ffffff,fbfcff,ebf1f8,dde3ea,c1c7ce,a6acb2,8b9198,70777d,595f65,41484d,2b3136,161c21,000000,ffffff,fbfcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7781,546069,3d4851,26323a,121d25,000000</vibrant> + <vibrant>ffffff,fbfcff,e5f2ff,c8e6ff,87ceff,0eb6ff,009ad9,007eb2,006590,004c6d,00344d,001e2e,000000,ffffff,fdfcff,ebf1ff,d4e3ff,b3c8e9,98accc,7e92b1,637795,4c5f7c,344863,1d314b,051c35,000000,ffffff,fefbff,efefff,dce1ff,b8c4fa,9da9dd,838ec1,6874a4,505c8b,384472,212e5a,0a1844,000000,ffffff,fbfcff,e9f2fb,dbe4ed,bfc8d0,a3acb5,89929a,6e777f,575f67,3f484f,293138,141d23,000000,ffffff,fbfcff,e6f2fe,d8e4ef,bcc8d3,a1adb7,86929d,6c7781,546069,3d4851,26323a,121d25,000000</vibrant> <expressive>ffffff,fcffdd,e9f99a,dbeb8e,bfce75,a4b35c,8a9845,6f7c2d,586416,414c00,2c3400,191e00,000000,ffffff,fffbff,ffebfa,fed7f9,e0bbdd,c4a0c1,a886a6,8c6c8a,735572,593d59,412742,2a122c,000000,ffffff,fdfcff,eaf1ff,d2e4ff,a7c9f6,8caed9,7293bd,5778a1,3f6088,25496f,073257,001c37,000000,ffffff,fdfcff,edf1fa,dfe2eb,c3c6cf,a7abb4,8d9199,72767e,5a5f66,43474e,2c3137,171c22,000000,ffffff,fdfcff,eaf1ff,dbe3f1,bfc7d5,a4acb9,89919e,6f7783,575f6b,3f4753,29313c,141c26,000000</expressive> <rainbow>ffffff,fbfcff,e5f2ff,c8e6ff,87ceff,55b4ed,3399d1,007eb2,006590,004c6d,00344d,001e2e,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000,ffffff,fffbff,f6edff,e9ddff,cdc0e8,b2a5cc,978bb1,7c7095,63597c,4b4163,342b4b,1f1635,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow> <fruit_salad>ffffff,f2fffc,b1fff7,71f7ec,50dbd0,25beb5,00a299,00847d,006a64,00504b,003734,00201e,000000,ffffff,f2fffc,b1fff7,9df2e9,81d5cd,65b9b2,489e97,28837c,006a64,00504b,003734,00201e,000000,ffffff,fbfcff,e5f2ff,c8e6ff,94cdf6,78b2da,5d97be,407ca1,246488,004c6d,00344d,001e2e,000000,ffffff,fbfcff,e9f2fb,dbe4ed,bfc8d0,a3acb5,89929a,6e777f,575f67,3f484f,293138,141d23,000000,ffffff,fbfcff,e5f2ff,d2e5f5,b7c9d8,9cadbd,8193a2,677886,4f606e,384956,21323f,0b1d29,000000</fruit_salad> @@ -59,7 +59,7 @@ <theme color="ff8267c2"> <spritz>ffffff,fffbff,f6edff,e8dff2,cbc3d5,afa8b9,958e9e,797383,615c6b,494453,332e3c,1d1a26,000000,ffffff,fffbff,f5eefa,e7e0eb,cac4cf,afa9b4,948f99,79747e,615d66,49454e,322f37,1d1a22,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000,ffffff,fffbff,f4eff1,e6e1e3,c9c5c7,aeaaac,939092,787577,605e5f,484648,313031,1c1b1d,000000,ffffff,fffbff,f4eff1,e6e1e3,c9c5c7,aeaaac,939092,787577,605e5f,484648,313031,1c1b1d,000000</spritz> <tonal_spot>ffffff,fffbff,f6edff,e9ddff,d0bcfe,b5a1e1,9987c4,7e6ca8,66558e,4e3d75,37265d,210f47,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000,ffffff,fffbff,ffecef,ffd9e2,f0b8c7,d29dac,b58391,986977,7e525f,633b47,4a2531,31101c,000000,ffffff,fffbff,f5eff4,e6e1e6,cac5ca,aeaaae,938f94,787579,605d61,48464a,323033,1c1b1e,000000,ffffff,fffbff,f5eefa,e7e0eb,cac4cf,afa9b4,948f99,79747e,615d66,49454e,322f37,1d1a22,000000</tonal_spot> - <vibrant>ffffff,fffbff,f6edff,e9ddff,d1bcff,b89bff,a078ff,884fff,7212ff,5700c9,3c0090,23005b,000000,ffffff,fffbff,fbecff,f4daff,d7bde4,bba2c8,a088ac,846e90,6c5778,533f5f,3b2947,251431,000000,ffffff,fffbff,ffebfa,ffd6fa,e9b6e6,cc9cc9,b082ae,936792,7a5079,603960,472348,2f0d32,000000,ffffff,fffbff,f5eefa,e7e0eb,cac4cf,afa9b4,948f99,79747e,615d66,49454e,322f37,1d1a22,000000,ffffff,fffbff,f6edff,e8dff2,cbc3d5,afa8b9,958e9e,797383,615c6b,494453,332e3c,1d1a26,000000</vibrant> + <vibrant>ffffff,fffbff,f6edff,e9ddff,d1bcff,b89bff,a078ff,884fff,7212ff,5700c9,3c0090,23005b,000000,ffffff,fffbff,fbecff,f4daff,d7bde4,bba2c8,a088ac,846e90,6c5778,533f5f,3b2947,251431,000000,ffffff,fffbff,ffebfa,ffd6fa,e9b6e6,cc9cc9,b082ae,936792,7a5079,603960,472348,2f0d32,000000,ffffff,fffbff,f6eefd,e7e0ee,cbc4d2,afa9b7,948e9c,797481,615c69,494551,322f3a,1d1a24,000000,ffffff,fffbff,f6edff,e8dff2,cbc3d5,afa8b9,958e9e,797383,615c6b,494453,332e3c,1d1a26,000000</vibrant> <expressive>ffffff,f3fffa,b7ffed,94f4de,78d7c2,5bbba7,3da08d,168572,006b5b,005144,00382f,00201a,000000,ffffff,fffbff,ffecf4,ffd8ec,e9b9d3,cc9eb7,b0849c,936a81,795369,5f3c51,46263a,2f1124,000000,ffffff,fffbff,feebff,f8d8ff,e1b9ed,c49ed0,a984b5,8c6998,73527f,5a3b66,42244e,2b0e38,000000,ffffff,fffbff,f8edf8,eadfea,cdc3ce,b2a8b2,978e98,7b737d,635c65,4b454d,342e36,1f1a21,000000,ffffff,fffbff,fbecfe,ecdeef,d0c2d3,b4a7b7,998d9d,7d7281,655b69,4d4351,362d3a,201925,000000</expressive> <rainbow>ffffff,fffbff,f6edff,e9ddff,d1bcff,b79cf7,9c82da,8167bd,684fa3,50378a,391e72,23005b,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000,ffffff,fffbff,ffecef,ffd9e2,f0b8c7,d29dac,b58391,986977,7e525f,633b47,4a2531,31101c,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000,ffffff,fcfcfc,f1f1f1,e2e2e2,c6c6c6,ababab,919191,767676,5e5e5e,474747,303030,1b1b1b,000000</rainbow> <fruit_salad>ffffff,fcfcff,e8f1ff,cfe5ff,99cbff,68b1f4,4a96d8,277bbb,00629e,004a78,003355,001d34,000000,ffffff,fcfcff,e8f1ff,cfe5ff,9dcbfb,82afdf,6794c2,4b7aa6,31628d,124a73,003355,001d34,000000,ffffff,fffbff,f6edff,e9ddff,d0bcfe,b5a1e1,9987c4,7e6ca8,66558e,4e3d75,37265d,210f47,000000,ffffff,fffbff,f6eefd,e7e0ee,cbc4d2,afa9b7,948e9c,797481,615c69,494551,322f3a,1d1a24,000000,ffffff,fffbff,f6edff,e8def8,ccc2db,b0a7bf,958da4,7a7289,625b70,4a4458,332d41,1e192b,000000</fruit_salad> diff --git a/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java b/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java new file mode 100644 index 00000000000..b21edd501b6 --- /dev/null +++ b/tests/tests/graphics/src/android/graphics/cts/AnimatorLeakTest.java @@ -0,0 +1,255 @@ +/* + * 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.graphics.cts; + +import static androidx.test.InstrumentationRegistry.getInstrumentation; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; +import android.support.test.uiautomator.UiDevice; + +import androidx.test.filters.MediumTest; +import androidx.test.rule.ActivityTestRule; +import androidx.test.runner.AndroidJUnit4; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +@MediumTest +@RunWith(AndroidJUnit4.class) +public class AnimatorLeakTest { + + @Rule + public ActivityTestRule<EmptyActivity> mActivityRule = + new ActivityTestRule<>(EmptyActivity.class, false, true); + public ActivityTestRule<EmptyActivity2> mActivityRule2 = + new ActivityTestRule<>(EmptyActivity2.class, false, false); + + boolean mPaused = false; + boolean mPausedSet = false; + boolean mFinitePaused = false; + boolean mFinitePausedSet = false; + boolean mResumed = false; + + @After + public void cleanup() { + Animator.setAnimatorPausingEnabled(true); + } + + /** + * The approach of this test is to start animators in the main activity for the test. + * That activity is forced into the background and the test checks whether the animators + * are paused appropriately. The activity is then forced back into the foreground again + * and the test checks whether the animators previously paused are resumed. There are also + * checks to make sure that animators which should not have been paused are handled + * correctly. + */ + @Test + public void testPauseResume() { + // Latches used to wait for each of the appropriate lifecycle events + final CountDownLatch animatorStartedLatch = new CountDownLatch(1); + // There are 2 animators which should be paused and resumed, thus a countdown of 2 + final CountDownLatch animatorPausedLatch = new CountDownLatch(2); + final CountDownLatch animatorResumedLatch = new CountDownLatch(2); + + // The first of these (infinite) should get paused, the second (finite) should not + ValueAnimator infiniteAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(1000); + infiniteAnimator.setRepeatCount(ValueAnimator.INFINITE); + ValueAnimator finiteAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(5000); + + // Now create infinite and finite AnimatorSets + // As above, the infinite set should get paused, the finite one should not + ValueAnimator infiniteAnimator1 = ValueAnimator.ofFloat(0f, 1f).setDuration(1000); + infiniteAnimator1.setRepeatCount(ValueAnimator.INFINITE); + AnimatorSet infiniteSet = new AnimatorSet(); + infiniteSet.play(infiniteAnimator1); + ValueAnimator finiteAnimator1 = ValueAnimator.ofFloat(0f, 1f).setDuration(5000); + AnimatorSet finiteSet = new AnimatorSet(); + finiteSet.play(finiteAnimator1); + + // This listener tracks which animators get paused and resumed + AnimatorListenerAdapter listener = new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + // Wait until animators start to trigger the lifecycle changes + animatorStartedLatch.countDown(); + } + + @Override + public void onAnimationPause(Animator animation) { + if (animation == infiniteAnimator) { + mPaused = true; + } else if (animation == infiniteSet) { + mPausedSet = true; + } else if (animation == finiteAnimator) { + mFinitePaused = true; + // end it to avoid having it interfere with future resume latch + animation.end(); + return; + } else if (animation == finiteSet) { + mFinitePausedSet = true; + // end it to avoid having it interfere with future resume latch + animation.end(); + return; + } + animatorPausedLatch.countDown(); + } + + @Override + public void onAnimationResume(Animator animation) { + mResumed = true; + animatorResumedLatch.countDown(); + } + }; + infiniteAnimator.addListener(listener); + infiniteAnimator.addPauseListener(listener); + finiteAnimator.addPauseListener(listener); + infiniteSet.addPauseListener(listener); + finiteSet.addPauseListener(listener); + + getInstrumentation().runOnMainSync(new Runnable() { + public void run() { + Animator.setBackgroundPauseDelay(500); + try { + infiniteAnimator.start(); + finiteAnimator.start(); + infiniteSet.start(); + finiteSet.start(); + } catch (Throwable throwable) { + } + } + }); + try { + // Wait until the animators are running to start changing the activity lifecycle + animatorStartedLatch.await(5, TimeUnit.SECONDS); + + // First, test that animators are *not* paused when an activity goes to the background + // if there is another activity in the same process which is now in the foreground. + mActivityRule2.launchActivity(null); + animatorPausedLatch.await(1, TimeUnit.SECONDS); + Assert.assertFalse("Animator was paused", mPaused); + mActivityRule2.finishActivity(); + + // Send the activity to the background. This should cause the animators to be paused + // after Animator.getBackgroundPauseDelay() + UiDevice uiDevice = UiDevice.getInstance(getInstrumentation()); + uiDevice.pressHome(); + + animatorPausedLatch.await(5, TimeUnit.SECONDS); + + // It is not possible (or obvious) how to bring the activity back into the foreground. + // However, AnimationHandler pauses/resumes all animators for the process based on + // *any* visible activities in that process. So it is sufficient to launch a second + // activity, which should resume the animators paused when the first activity went + // into the background. + mActivityRule2.launchActivity(null); + animatorResumedLatch.await(5, TimeUnit.SECONDS); + } catch (Exception e) { } + Assert.assertTrue("Animator was not paused", mPaused); + Assert.assertTrue("AnimatorSet was not paused", mPausedSet); + Assert.assertFalse("Non-infinite Animator was paused", mFinitePaused); + Assert.assertFalse("Non-infinite AnimatorSet was paused", mFinitePausedSet); + Assert.assertTrue("Animator was not resumed", mResumed); + Assert.assertTrue("AnimatorSet was not resumed", mResumed); + } + + /** + * The approach of this test is to start animators in the main activity for the test. + * That activity is forced into the background and the test checks whether the animators + * are paused appropriately. The activity is then forced back into the foreground again + * and the test checks whether the animators previously paused are resumed. There are also + * checks to make sure that animators which should not have been paused are handled + * correctly. + */ + @Test + public void testPauseDisablement() { + // Latches used to wait for each of the appropriate lifecycle events + final CountDownLatch animatorStartedLatch = new CountDownLatch(1); + // There are 2 animators which should be paused and resumed, thus a countdown of 2 + final CountDownLatch animatorPausedLatch = new CountDownLatch(1); + final CountDownLatch animatorResumedLatch = new CountDownLatch(1); + + // The first of these (infinite) should get paused, the second (finite) should not + ValueAnimator infiniteAnimator = ValueAnimator.ofFloat(0f, 1f).setDuration(1000); + infiniteAnimator.setRepeatCount(ValueAnimator.INFINITE); + + // This listener tracks which animators get paused and resumed + AnimatorListenerAdapter listener = new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + // Wait until animators start to trigger the lifecycle changes + animatorStartedLatch.countDown(); + } + + @Override + public void onAnimationPause(Animator animation) { + mPaused = true; + animatorPausedLatch.countDown(); + } + + @Override + public void onAnimationResume(Animator animation) { + mResumed = true; + animatorResumedLatch.countDown(); + } + }; + infiniteAnimator.addListener(listener); + infiniteAnimator.addPauseListener(listener); + + getInstrumentation().runOnMainSync(new Runnable() { + public void run() { + Animator.setBackgroundPauseDelay(500); + Animator.setAnimatorPausingEnabled(false); + try { + infiniteAnimator.start(); + } catch (Throwable throwable) { + } + } + }); + try { + // Wait until the animators are running to start changing the activity lifecycle + animatorStartedLatch.await(5, TimeUnit.SECONDS); + + // Send the activity to the background. This should cause the animators to be paused + // after Animator.getBackgroundPauseDelay() + UiDevice uiDevice = UiDevice.getInstance(getInstrumentation()); + uiDevice.pressHome(); + + animatorPausedLatch.await(2, TimeUnit.SECONDS); + + // It is not possible (or obvious) how to bring the activity back into the foreground. + // However, AnimationHandler pauses/resumes all animators for the process based on + // *any* visible activities in that process. So it is sufficient to launch a second + // activity, which should resume the animators paused when the first activity went + // into the background. + mActivityRule2.launchActivity(null); + animatorResumedLatch.await(2, TimeUnit.SECONDS); + } catch (Exception e) { } + Assert.assertFalse("Animator paused when pausing disabled", mPaused); + Assert.assertFalse("Animator resumed when pausing disabled", mResumed); + } + +} diff --git a/tests/tests/graphics/src/android/graphics/cts/EmptyActivity.java b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity.java new file mode 100644 index 00000000000..5ae6cd30e89 --- /dev/null +++ b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity.java @@ -0,0 +1,36 @@ +/* + * 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.graphics.cts; + +import android.app.Activity; +import android.os.Bundle; +import android.view.ViewGroup; +import android.widget.Button; + +/** + * Empty activity + */ +public final class EmptyActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Button b = new Button(this); + b.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); + b.setText("My Button 1111"); + setContentView(b); + } +} diff --git a/tests/tests/graphics/src/android/graphics/cts/EmptyActivity2.java b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity2.java new file mode 100644 index 00000000000..da0b8a64b13 --- /dev/null +++ b/tests/tests/graphics/src/android/graphics/cts/EmptyActivity2.java @@ -0,0 +1,37 @@ +/* + * 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.graphics.cts; + +import android.app.Activity; +import android.os.Bundle; +import android.view.ViewGroup; +import android.widget.Button; + +/** + * Empty activity - this one exists in addition to EmptyActivity when an app + * needs two launch 2 separate activities. + */ +public final class EmptyActivity2 extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Button b = new Button(this); + b.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); + b.setText("My Button 22222"); + setContentView(b); + } +} diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java index ba192c42bd8..8ad13dfdcb6 100644 --- a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java +++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualDeviceTestCase.java @@ -57,8 +57,8 @@ public abstract class VirtualDeviceTestCase extends InputTestCase { private static final int ARBITRARY_SURFACE_TEX_ID = 1; - static final int DISPLAY_WIDTH = 100; - static final int DISPLAY_HEIGHT = 100; + protected static final int DISPLAY_WIDTH = 100; + protected static final int DISPLAY_HEIGHT = 100; // Uses: // Manifest.permission.CREATE_VIRTUAL_DEVICE, @@ -140,10 +140,6 @@ public abstract class VirtualDeviceTestCase extends InputTestCase { } // Tap to gain window focus on the activity tapActivityToFocus(); - // Wait for everything to settle. Like see in InputHidTestCase, registered input devices - // don't always seem to produce events right away. Adding a bit of slack here decreases - // the flake rate. - SystemClock.sleep(1000L); } abstract void onSetUpVirtualInputDevice(); diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java index eb54097e2b0..6ca80e57de5 100644 --- a/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java +++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/VirtualMouseTest.java @@ -40,11 +40,7 @@ public class VirtualMouseTest extends VirtualDeviceTestCase { private static final String DEVICE_NAME = "CtsVirtualMouseTestDevice"; - // TODO(b/216792538): while the start position is deterministic, it would be nice to test it at - // runtime. The virtual display is 100x100px, running from [0,99]. Half of this is 49.5, and - // we assume the pointer for a new display begins at the center. - private static final PointF START_POSITION = new PointF((DISPLAY_WIDTH - 1) / 2f, - (DISPLAY_HEIGHT - 1) / 2f); + private static final float EPSILON = 0.001f; private VirtualMouse mVirtualMouse; @@ -63,6 +59,7 @@ public class VirtualMouseTest extends VirtualDeviceTestCase { @Test public void sendButtonEvent() { + final PointF startPosition = mVirtualMouse.getCursorPosition(); mVirtualMouse.sendButtonEvent(new VirtualMouseButtonEvent.Builder() .setAction(VirtualMouseButtonEvent.ACTION_BUTTON_PRESS) .setButtonCode(VirtualMouseButtonEvent.BUTTON_PRIMARY) @@ -72,59 +69,78 @@ public class VirtualMouseTest extends VirtualDeviceTestCase { .setButtonCode(VirtualMouseButtonEvent.BUTTON_PRIMARY) .build()); final MotionEvent buttonPressEvent = createMotionEvent(MotionEvent.ACTION_BUTTON_PRESS, - START_POSITION.x, START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + startPosition.x, startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, MotionEvent.BUTTON_PRIMARY, /* pressure= */ 1.0f); buttonPressEvent.setActionButton(MotionEvent.BUTTON_PRIMARY); final MotionEvent buttonReleaseEvent = createMotionEvent(MotionEvent.ACTION_BUTTON_RELEASE, - START_POSITION.x, START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + startPosition.x, startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f); buttonReleaseEvent.setActionButton(MotionEvent.BUTTON_PRIMARY); verifyEvents(Arrays.asList( - createMotionEvent(MotionEvent.ACTION_DOWN, START_POSITION.x, START_POSITION.y, + createMotionEvent(MotionEvent.ACTION_DOWN, startPosition.x, startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, MotionEvent.BUTTON_PRIMARY, /* pressure= */ 1.0f), buttonPressEvent, buttonReleaseEvent, - createMotionEvent(MotionEvent.ACTION_UP, START_POSITION.x, START_POSITION.y, + createMotionEvent(MotionEvent.ACTION_UP, startPosition.x, startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f), - createMotionEvent(MotionEvent.ACTION_HOVER_ENTER, START_POSITION.x, - START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + createMotionEvent(MotionEvent.ACTION_HOVER_ENTER, startPosition.x, + startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f))); } @Test public void sendRelativeEvent() { + final PointF startPosition = mVirtualMouse.getCursorPosition(); final float relativeChangeX = 25f; final float relativeChangeY = 35f; mVirtualMouse.sendRelativeEvent(new VirtualMouseRelativeEvent.Builder() .setRelativeY(relativeChangeY) .setRelativeX(relativeChangeX) .build()); - mVirtualMouse.sendRelativeEvent(new VirtualMouseRelativeEvent.Builder() - .setRelativeY(-relativeChangeY) - .setRelativeX(-relativeChangeX) - .build()); - final float firstStopPositionX = START_POSITION.x + relativeChangeX; - final float firstStopPositionY = START_POSITION.y + relativeChangeY; - final float secondStopPositionX = firstStopPositionX - relativeChangeX; - final float secondStopPositionY = firstStopPositionY - relativeChangeY; + final float firstStopPositionX = startPosition.x + relativeChangeX; + final float firstStopPositionY = startPosition.y + relativeChangeY; verifyEvents(Arrays.asList( createMotionEvent(MotionEvent.ACTION_HOVER_ENTER, firstStopPositionX, firstStopPositionY, relativeChangeX, relativeChangeY, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f), createMotionEvent(MotionEvent.ACTION_HOVER_MOVE, firstStopPositionX, firstStopPositionY, relativeChangeX, relativeChangeY, /* vScroll= */ 0f, + /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f))); + final PointF cursorPosition1 = mVirtualMouse.getCursorPosition(); + assertEquals("getCursorPosition() should return the updated x position", + firstStopPositionX, cursorPosition1.x, EPSILON); + assertEquals("getCursorPosition() should return the updated y position", + firstStopPositionY, cursorPosition1.y, EPSILON); + + final float secondStopPositionX = firstStopPositionX - relativeChangeX; + final float secondStopPositionY = firstStopPositionY - relativeChangeY; + mVirtualMouse.sendRelativeEvent(new VirtualMouseRelativeEvent.Builder() + .setRelativeY(-relativeChangeY) + .setRelativeX(-relativeChangeX) + .build()); + verifyEvents(Arrays.asList( + createMotionEvent(MotionEvent.ACTION_HOVER_ENTER, secondStopPositionX, + secondStopPositionY, -relativeChangeX, + -relativeChangeY, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f), createMotionEvent(MotionEvent.ACTION_HOVER_MOVE, secondStopPositionX, - secondStopPositionY, -relativeChangeX, -relativeChangeY, /* vScroll= */ 0f, + secondStopPositionY, -relativeChangeX, + -relativeChangeY, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0.0f))); + final PointF cursorPosition2 = mVirtualMouse.getCursorPosition(); + assertEquals("getCursorPosition() should return the updated x position", + secondStopPositionX, cursorPosition2.x, EPSILON); + assertEquals("getCursorPosition() should return the updated y position", + secondStopPositionY, cursorPosition2.y, EPSILON); } @Test public void sendScrollEvent() { + final PointF startPosition = mVirtualMouse.getCursorPosition(); final float moveX = 0f; final float moveY = 1f; mVirtualMouse.sendScrollEvent(new VirtualMouseScrollEvent.Builder() @@ -132,42 +148,46 @@ public class VirtualMouseTest extends VirtualDeviceTestCase { .setXAxisMovement(moveX) .build()); verifyEvents(Arrays.asList( - createMotionEvent(MotionEvent.ACTION_HOVER_ENTER, START_POSITION.x, - START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + createMotionEvent(MotionEvent.ACTION_HOVER_ENTER, startPosition.x, + startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0f), - createMotionEvent(MotionEvent.ACTION_HOVER_MOVE, START_POSITION.x, - START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + createMotionEvent(MotionEvent.ACTION_HOVER_MOVE, startPosition.x, + startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0f), - createMotionEvent(MotionEvent.ACTION_SCROLL, START_POSITION.x, - START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + createMotionEvent(MotionEvent.ACTION_SCROLL, startPosition.x, + startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 1f, /* hScroll= */ 0f, /* buttonState= */ 0, /* pressure= */ 0f))); } @Test - public void getCursorPosition() { + public void testStartingCursorPosition() { + // The virtual display is 100x100px, running from [0,99]. Half of this is 49.5, and + // we assume the pointer for a new display begins at the center. + final PointF startPosition = new PointF((DISPLAY_WIDTH - 1) / 2f, + (DISPLAY_HEIGHT - 1) / 2f); // Trigger a position update without moving the cursor off the starting position. mVirtualMouse.sendButtonEvent(new VirtualMouseButtonEvent.Builder() .setAction(VirtualMouseButtonEvent.ACTION_BUTTON_PRESS) .setButtonCode(VirtualMouseButtonEvent.BUTTON_PRIMARY) .build()); final MotionEvent buttonPressEvent = createMotionEvent(MotionEvent.ACTION_BUTTON_PRESS, - START_POSITION.x, START_POSITION.y, /* relativeX= */ 0f, /* relativeY= */ 0f, + startPosition.x, startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, MotionEvent.BUTTON_PRIMARY, /* pressure= */ 1.0f); buttonPressEvent.setActionButton(MotionEvent.BUTTON_PRIMARY); verifyEvents(Arrays.asList( - createMotionEvent(MotionEvent.ACTION_DOWN, START_POSITION.x, START_POSITION.y, + createMotionEvent(MotionEvent.ACTION_DOWN, startPosition.x, startPosition.y, /* relativeX= */ 0f, /* relativeY= */ 0f, /* vScroll= */ 0f, /* hScroll= */ 0f, MotionEvent.BUTTON_PRIMARY, /* pressure= */ 1.0f), buttonPressEvent)); final PointF position = mVirtualMouse.getCursorPosition(); - assertEquals("Cursor position x differs", START_POSITION.x, position.x, 0.0001f); - assertEquals("Cursor position y differs", START_POSITION.y, position.y, 0.0001f); + assertEquals("Cursor position x differs", startPosition.x, position.x, EPSILON); + assertEquals("Cursor position y differs", startPosition.y, position.y, EPSILON); } private MotionEvent createMotionEvent(int action, float x, float y, float relativeX, diff --git a/tests/tests/keystore/src/android/keystore/cts/BlockCipherTestBase.java b/tests/tests/keystore/src/android/keystore/cts/BlockCipherTestBase.java index be2ecc5a5b2..6057e457fb8 100644 --- a/tests/tests/keystore/src/android/keystore/cts/BlockCipherTestBase.java +++ b/tests/tests/keystore/src/android/keystore/cts/BlockCipherTestBase.java @@ -842,19 +842,19 @@ abstract class BlockCipherTestBase { int ciphertextIndex = 0; for (int plaintextIndex = 0; plaintextIndex < plaintext.length; plaintextIndex++) { byte[] output = update(new byte[] {plaintext[plaintextIndex]}); - if ((plaintextIndex % blockSize) == blockSize - 1) { - String additionalInformation = ""; - boolean compareOutput = true; - if (isStrongbox() && output == null) { - // This is known to be broken on older vendor implementations. - if (Build.VERSION_CODES.TIRAMISU - > SystemProperties.getInt("ro.vendor.api_level", 0)) { - compareOutput = false; - } else { - additionalInformation = " (b/194134359)"; - } + String additionalInformation = ""; + boolean compareOutput = true; + if (isStrongbox()) { + // This is known to be broken on older vendor implementations. + if (Build.VERSION_CODES.TIRAMISU + > SystemProperties.getInt("ro.vendor.api_level", 0)) { + compareOutput = false; + } else { + additionalInformation = " (b/194134359)"; } - if (compareOutput) { + } + if (compareOutput) { + if ((plaintextIndex % blockSize) == blockSize - 1) { // Cipher.update is expected to have output a new block assertArrayEquals( "plaintext index: " + plaintextIndex + additionalInformation, @@ -863,10 +863,12 @@ abstract class BlockCipherTestBase { ciphertextIndex, ciphertextIndex + blockSize), output); + } else { + // Cipher.update is expected to have produced no output + assertArrayEquals( + "plaintext index: " + plaintextIndex + additionalInformation, + null, output); } - } else { - // Cipher.update is expected to have produced no output - assertArrayEquals("plaintext index: " + plaintextIndex, null, output); } if (output != null) { ciphertextIndex += output.length; @@ -943,27 +945,28 @@ abstract class BlockCipherTestBase { && (ciphertextIndex > 0) && ((ciphertextIndex % blockSize) == 0)) || ((!paddingEnabled) && ((ciphertextIndex % blockSize) == blockSize - 1)); - if (outputExpected) { - String additionalInformation = ""; - boolean compareOutput = true; - if (isStrongbox()) { - // This is known to be broken on older vendor implementations. - if (Build.VERSION_CODES.TIRAMISU - > SystemProperties.getInt("ro.vendor.api_level", 0)) { - compareOutput = false; - } else { - additionalInformation = " (b/194134040)"; - } + String additionalInformation = ""; + boolean compareOutput = true; + if (isStrongbox()) { + // This is known to be broken on older vendor implementations. + if (Build.VERSION_CODES.TIRAMISU + > SystemProperties.getInt("ro.vendor.api_level", 0)) { + compareOutput = false; + } else { + additionalInformation = " (b/194134040)"; } - if (compareOutput) { + } + if (compareOutput) { + if (outputExpected) { assertArrayEquals( "ciphertext index: " + ciphertextIndex + additionalInformation, subarray(expectedPlaintext, plaintextIndex, plaintextIndex + blockSize), output); + } else { + assertEquals("ciphertext index: " + ciphertextIndex + additionalInformation, + null, output); } - } else { - assertEquals("ciphertext index: " + ciphertextIndex, null, output); } if (output != null) { @@ -1322,7 +1325,6 @@ abstract class BlockCipherTestBase { System.arraycopy(input, 0, buffer, inputOffsetInBuffer, input.length); createCipher(); initKat(opmode); - String additionalInformation = ""; int outputLength = update(buffer, inputOffsetInBuffer, input.length, buffer, outputOffsetInBuffer); if (isStrongbox()) { diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java index d899b04739c..56b5aaf24eb 100644 --- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java +++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java @@ -815,6 +815,10 @@ public class KeyAttestationTest { if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.S) { return; } + // ID attestation is not implemented on the goldfish emulator. + if (Build.BOARD.startsWith("goldfish")) { + return; + } // ID attestation is tested by other tests (outside of this class), including negative // tests that ID attestation is failing if the platform does not declare support. // Hence, it's safe to only test here that the feature is supported. 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 e0cae51fc93..3e90992f777 100644 --- a/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java +++ b/tests/tests/media/common/src/android/media/cts/MediaCodecTunneledPlayer.java @@ -615,6 +615,9 @@ public class MediaCodecTunneledPlayer implements MediaTimeProvider { * Note: This assumes there is exactly one video codec running in the player. */ public long getVideoTimeUs() { + if (mVideoCodecStates == null || mVideoCodecStates.get(0) == null) { + return CodecState.UNINITIALIZED_TIMESTAMP; + } return mVideoCodecStates.get(0).getVideoTimeUs(); } 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 cde71e7a113..73ba7c309ff 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 @@ -16,6 +16,7 @@ package android.media.decoder.cts; +import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_TunneledPlayback; import static android.media.MediaCodecInfo.CodecProfileLevel.AVCLevel31; import static android.media.MediaCodecInfo.CodecProfileLevel.AVCLevel32; import static android.media.MediaCodecInfo.CodecProfileLevel.AVCLevel4; @@ -40,7 +41,6 @@ import android.hardware.display.DisplayManager; import android.media.AudioFormat; import android.media.AudioManager; import android.media.AudioTimestamp; -import android.media.AudioTrack; import android.media.Image; import android.media.MediaCodec; import android.media.MediaCodec.BufferInfo; @@ -3872,11 +3872,8 @@ public class DecoderTest extends MediaTestBase { * TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content */ private void tunneledVideoPlayback(String mimeType, String videoName) throws Exception { - if (!isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback)) { - MediaUtils.skipTest( - TAG, - "No tunneled video playback codec found for MIME " + mimeType); + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -3892,6 +3889,16 @@ public class DecoderTest extends MediaTestBase { // starts video playback mMediaCodecPlayer.startThread(); + sleepUntil(() -> + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, + Duration.ofSeconds(1)); + assertNotEquals("onFrameRendered was not called", + mMediaCodecPlayer.getVideoTimeUs(), CodecState.UNINITIALIZED_TIMESTAMP); + assertNotEquals("Audio timestamp is null", mMediaCodecPlayer.getTimestamp(), null); + assertNotEquals("Audio timestamp has a zero frame position", + mMediaCodecPlayer.getTimestamp().framePosition, 0); final long durationMs = mMediaCodecPlayer.getDuration(); final long timeOutMs = System.currentTimeMillis() + durationMs + 5 * 1000; // add 5 sec @@ -3947,11 +3954,8 @@ public class DecoderTest extends MediaTestBase { * TODO(b/182915887): Test all the codecs advertised by the DUT for the provided test content */ private void testTunneledVideoFlush(String mimeType, String videoName) throws Exception { - if (!isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback)) { - MediaUtils.skipTest( - TAG, - "No tunneled video playback codec found for MIME " + mimeType); + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -3967,7 +3971,17 @@ public class DecoderTest extends MediaTestBase { // starts video playback mMediaCodecPlayer.startThread(); - Thread.sleep(SLEEP_TIME_MS); + sleepUntil(() -> + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, + Duration.ofSeconds(1)); + assertNotEquals("onFrameRendered was not called", + mMediaCodecPlayer.getVideoTimeUs(), CodecState.UNINITIALIZED_TIMESTAMP); + assertNotEquals("Audio timestamp is null", mMediaCodecPlayer.getTimestamp(), null); + assertNotEquals("Audio timestamp has a zero frame position", + mMediaCodecPlayer.getTimestamp().framePosition, 0); + mMediaCodecPlayer.pause(); mMediaCodecPlayer.flush(); // mMediaCodecPlayer.reset() handled in TearDown(); @@ -4013,9 +4027,8 @@ public class DecoderTest extends MediaTestBase { return; } - if (!MediaUtils.check(isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback), - "No tunneled video playback codec found for MIME " + mimeType)){ + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4088,9 +4101,8 @@ public class DecoderTest extends MediaTestBase { return; } - if (!MediaUtils.check(isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback), - "No tunneled video playback codec found for MIME " + mimeType)){ + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4199,9 +4211,8 @@ public class DecoderTest extends MediaTestBase { } private void testTunneledAudioPtsGaps(String mimeType, String fileName) throws Exception { - if (!MediaUtils.check(isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback), - "No tunneled video playback codec found for MIME " + mimeType)) { + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4212,52 +4223,71 @@ 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()); + // starts video playback mMediaCodecPlayer.startThread(); - sleepUntil(() -> mMediaCodecPlayer.getTimestamp() != null - && mMediaCodecPlayer.getTimestamp().framePosition > 0, Duration.ofSeconds(1)); - // After 30 ms, Changing the presentation offset for audio track - Thread.sleep(30); + sleepUntil(() -> + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, + Duration.ofSeconds(1)); + assertNotEquals("onFrameRendered was not called", + mMediaCodecPlayer.getVideoTimeUs(), CodecState.UNINITIALIZED_TIMESTAMP); + assertNotEquals("Audio timestamp is null", mMediaCodecPlayer.getTimestamp(), null); + assertNotEquals("Audio timestamp has a zero frame position", + mMediaCodecPlayer.getTimestamp().framePosition, 0); // Requirement: If the audio presentation timestamp header sent by the app is greater than // the current audio clock by less than 100ms, the framePosition returned by // AudioTrack#getTimestamp (per get_presentation_position) must not advance for any silent // frames rendered to fill the gap. // TODO: add link to documentation when available - mMediaCodecPlayer.setAudioTrackOffsetMs(100); - // Wait for 20 ms so that whatever was buffered before offset is played - Thread.sleep(20); - long initialFramePosition = mMediaCodecPlayer.getTimestamp().framePosition; - // Verify that the framePosition did not advance after 30 ms. This ensures framePosition - // returned by AudioTrack#getTimestamp did not advance for any silent frames rendered to - // fill PTS gaps. + // Simulate a PTS gap of 100ms after 30ms Thread.sleep(30); - assertEquals( - "Initial frame position != Final frame position after introducing PTS gaps", - initialFramePosition, mMediaCodecPlayer.getTimestamp().framePosition); + mMediaCodecPlayer.setAudioTrackOffsetMs(100); + // Verify that at some point in time in the future, the framePosition stopped advancing. + // This verifies that when silence was rendered to fill the PTS gap, that the silent frames + // do not cause framePosition to advance. + final long ptsGapTimeoutMs = 1000; + long startTimeMs = System.currentTimeMillis(); + AudioTimestamp currentTimestamp = mMediaCodecPlayer.getTimestamp(); + AudioTimestamp ptsGapTimestamp; + do { + assertTrue(String.format("No audio PTS gap after %d milliseconds", ptsGapTimeoutMs), + System.currentTimeMillis() - startTimeMs < ptsGapTimeoutMs); + ptsGapTimestamp = currentTimestamp; + Thread.sleep(50); + currentTimestamp = mMediaCodecPlayer.getTimestamp(); + } while (currentTimestamp.framePosition != ptsGapTimestamp.framePosition); + + // Allow the playback to advance past the PTS gap and back to normal operation Thread.sleep(500); + // Simulate the end of playback mMediaCodecPlayer.stopWritingToAudioTrack(true); // Sleep till framePosition stabilizes, i.e. playback is complete or till max 3 seconds. - long framePosCurrent = 0; - int totalSleepMs = 0; - while (totalSleepMs < 3000 - && framePosCurrent != mMediaCodecPlayer.getTimestamp().framePosition) { - framePosCurrent = mMediaCodecPlayer.getTimestamp().framePosition; - Thread.sleep(500); - totalSleepMs += 500; - } + final long endOfPlayackTimeoutMs = 3000; + startTimeMs = System.currentTimeMillis(); + AudioTimestamp endOfPlaybackTimestamp; + do { + assertTrue(String.format("No end of playback after %d milliseconds", + endOfPlayackTimeoutMs), + System.currentTimeMillis() - startTimeMs < endOfPlayackTimeoutMs); + endOfPlaybackTimestamp = currentTimestamp; + Thread.sleep(50); + currentTimestamp = mMediaCodecPlayer.getTimestamp(); + } while (currentTimestamp.framePosition != endOfPlaybackTimestamp.framePosition); - // Verify if number of frames written and played are same even if PTS Gaps were present + // Verify if number of frames written and played are same even if PTS gaps were present // in the playback. assertEquals("Number of frames written != Number of frames played", mMediaCodecPlayer.getAudioFramesWritten(), - mMediaCodecPlayer.getTimestamp().framePosition); + endOfPlaybackTimestamp.framePosition); } /** @@ -4292,8 +4322,7 @@ public class DecoderTest extends MediaTestBase { private void testTunneledAudioTimestampProgressWithUnderrun( String mimeType, String fileName) throws Exception { - if (!MediaUtils.check(isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback), + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4305,11 +4334,22 @@ 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()); + // starts video playback mMediaCodecPlayer.startThread(); + sleepUntil(() -> + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, + Duration.ofSeconds(1)); + assertNotEquals("onFrameRendered was not called", + mMediaCodecPlayer.getVideoTimeUs(), CodecState.UNINITIALIZED_TIMESTAMP); + assertNotEquals("Audio timestamp is null", mMediaCodecPlayer.getTimestamp(), null); + assertNotEquals("Audio timestamp has a zero frame position", + mMediaCodecPlayer.getTimestamp().framePosition, 0); // Stop writing to the AudioTrack after 200 ms. Thread.sleep(200); @@ -4354,9 +4394,8 @@ public class DecoderTest extends MediaTestBase { return; } - if (!MediaUtils.check(isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback), - "No tunneled video playback codec found for MIME " + mimeType)){ + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4382,12 +4421,19 @@ public class DecoderTest extends MediaTestBase { // does. mMediaCodecPlayer.setVideoPeek(false); - // Start playback + // starts video playback mMediaCodecPlayer.startThread(); - Thread.sleep(maxAllowedTimeToFirstFrameMs); - assertNotEquals(String.format("No frame displayed after %d ms", - maxAllowedTimeToFirstFrameMs), CodecState.UNINITIALIZED_TIMESTAMP, - mMediaCodecPlayer.getCurrentPosition()); + sleepUntil(() -> + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, + Duration.ofSeconds(1)); + assertNotEquals("onFrameRendered was not called", + mMediaCodecPlayer.getVideoTimeUs(), CodecState.UNINITIALIZED_TIMESTAMP); + assertNotEquals("Audio timestamp is null", mMediaCodecPlayer.getTimestamp(), null); + assertNotEquals("Audio timestamp has a zero frame position", + mMediaCodecPlayer.getTimestamp().framePosition, 0); + // Pause playback mMediaCodecPlayer.pause(); // Ensure audio and video are in sync. We give some time to the codec to finish displaying @@ -4492,9 +4538,8 @@ public class DecoderTest extends MediaTestBase { private void testTunneledAudioTimestampProgress(String mimeType, String videoName) throws Exception { - if (!isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback)) { - MediaUtils.skipTest(TAG,"No tunneled video playback codec found for MIME " + mimeType); + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4510,15 +4555,18 @@ public class DecoderTest extends MediaTestBase { // starts video playback mMediaCodecPlayer.startThread(); - sleepUntil(() -> - mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP, + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, Duration.ofSeconds(1)); - final int firstPosition = mMediaCodecPlayer.getCurrentPosition(); - assertNotEquals("On frame rendered not called after playback start!", - CodecState.UNINITIALIZED_TIMESTAMP, firstPosition); - AudioTimestamp firstTimestamp = mMediaCodecPlayer.getTimestamp(); - assertTrue("Timestamp is null!", firstTimestamp != null); + long firstVideoPosition = mMediaCodecPlayer.getVideoTimeUs(); + assertNotEquals("onFrameRendered was not called", + firstVideoPosition, CodecState.UNINITIALIZED_TIMESTAMP); + AudioTimestamp firstAudioTimestamp = mMediaCodecPlayer.getTimestamp(); + assertNotEquals("Audio timestamp is null", firstAudioTimestamp, null); + assertNotEquals("Audio timestamp has a zero frame position", + firstAudioTimestamp.framePosition, 0); // Expected stabilization wait is 60ms. We triple to 180ms to prevent flakiness // and still test basic functionality. @@ -4527,15 +4575,15 @@ public class DecoderTest extends MediaTestBase { mMediaCodecPlayer.pause(); // pause might take some time to ramp volume down. Thread.sleep(sleepTimeMs); - AudioTimestamp timeStampAfterPause = mMediaCodecPlayer.getTimestamp(); + AudioTimestamp audioTimestampAfterPause = mMediaCodecPlayer.getTimestamp(); // Verify the video has advanced beyond the first position. - assertTrue(mMediaCodecPlayer.getCurrentPosition() > firstPosition); + assertTrue(mMediaCodecPlayer.getVideoTimeUs() > firstVideoPosition); // Verify that the timestamp has advanced beyond the first timestamp. - assertTrue(timeStampAfterPause.nanoTime > firstTimestamp.nanoTime); + assertTrue(audioTimestampAfterPause.nanoTime > firstAudioTimestamp.nanoTime); Thread.sleep(sleepTimeMs); // Verify that the timestamp does not advance after pause. - assertEquals(timeStampAfterPause.nanoTime, mMediaCodecPlayer.getTimestamp().nanoTime); + assertEquals(audioTimestampAfterPause.nanoTime, mMediaCodecPlayer.getTimestamp().nanoTime); } /** @@ -4547,11 +4595,8 @@ public class DecoderTest extends MediaTestBase { */ private void tunneledAudioUnderrun(String mimeType, String videoName, int frameRate) throws Exception { - if (!isVideoFeatureSupported(mimeType, - CodecCapabilities.FEATURE_TunneledPlayback)) { - MediaUtils.skipTest( - TAG, - "No tunneled video playback codec found for MIME " + mimeType); + if (!MediaUtils.check(isVideoFeatureSupported(mimeType, FEATURE_TunneledPlayback), + "No tunneled video playback codec found for MIME " + mimeType)) { return; } @@ -4565,90 +4610,112 @@ public class DecoderTest extends MediaTestBase { assertTrue("MediaCodecPlayer.start() failed!", mMediaCodecPlayer.start()); assertTrue("MediaCodecPlayer.prepare() failed!", mMediaCodecPlayer.prepare()); - // Start media playback + // Starts video playback mMediaCodecPlayer.startThread(); - final int waitStartMs = 50; - Thread.sleep(waitStartMs); - assertTrue(String.format("Playback has not started after %d milliseconds", waitStartMs), - mMediaCodecPlayer.getVideoTimeUs() != 0); + sleepUntil(() -> + mMediaCodecPlayer.getCurrentPosition() > CodecState.UNINITIALIZED_TIMESTAMP + && mMediaCodecPlayer.getTimestamp() != null + && mMediaCodecPlayer.getTimestamp().framePosition > 0, + Duration.ofSeconds(1)); + assertNotEquals("onFrameRendered was not called", + mMediaCodecPlayer.getVideoTimeUs(), CodecState.UNINITIALIZED_TIMESTAMP); + assertNotEquals("Audio timestamp is null", mMediaCodecPlayer.getTimestamp(), null); + assertNotEquals("Audio timestamp has a zero frame position", + mMediaCodecPlayer.getTimestamp().framePosition, 0); + // Keep buffering video content but stop buffering audio content -> audio underrun mMediaCodecPlayer.simulateAudioUnderrun(true); - // Loop to wait for audio underrun - // TODO(b/200280965): Find a more appropriate delay based on partner feedback + + // Wait for audio underrun final int audioUnderrunTimeoutMs = 1000; // Arbitrary upper time limit on loop time duration long startTimeMs = System.currentTimeMillis(); - AudioTimestamp previousTimestamp; - while ((previousTimestamp = mMediaCodecPlayer.getTimestamp()) == null) { - assertTrue(String.format("No audio timestamp after %d milliseconds", - System.currentTimeMillis() - startTimeMs), - System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs); - Thread.sleep(50); - } + AudioTimestamp currentAudioTimestamp = mMediaCodecPlayer.getTimestamp(); AudioTimestamp underrunAudioTimestamp; - while ((underrunAudioTimestamp = mMediaCodecPlayer.getTimestamp()) != previousTimestamp) { + do { assertTrue(String.format("No audio underrun after %d milliseconds", - audioUnderrunTimeoutMs), + System.currentTimeMillis() - startTimeMs), System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs); - previousTimestamp = underrunAudioTimestamp; + underrunAudioTimestamp = currentAudioTimestamp; Thread.sleep(50); - } - // Loop to wait until video playback stalls - long previousVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs(); - long underrunVideoTimeUs; - startTimeMs = System.currentTimeMillis(); - // TODO(b/200280965): Find a more appropriate delay based on partner feedback + currentAudioTimestamp = mMediaCodecPlayer.getTimestamp(); + } while (currentAudioTimestamp.framePosition != underrunAudioTimestamp.framePosition); + + + // Wait until video playback stalls final int videoUnderrunTimeoutMs = 1000; - while ((underrunVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs()) != previousVideoTimeUs) { + 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); - previousVideoTimeUs = underrunVideoTimeUs; + underrunVideoTimeUs = currentVideoTimeUs; Thread.sleep(50); - } + currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs(); + } while (currentVideoTimeUs != underrunVideoTimeUs); - final int underrunVideoRenderedTimestampIndex = + // Retrieve index for the video rendered frame at the time of underrun + int underrunVideoRenderedTimestampIndex = mMediaCodecPlayer.getRenderedVideoFrameTimestampList().size() - 1; + // Resume audio buffering with a negative offset, in order to simulate a desynchronisation. // TODO(b/202710709): Use timestamp relative to last played video frame before pause mMediaCodecPlayer.setAudioTrackOffsetMs(-100); mMediaCodecPlayer.simulateAudioUnderrun(false); - // Loop to wait until audio playback resumes + // Wait until audio playback resumes + final int audioResumeTimeoutMs = 1000; startTimeMs = System.currentTimeMillis(); - AudioTimestamp postResumeTimestamp; - while ((postResumeTimestamp = mMediaCodecPlayer.getTimestamp()) == underrunAudioTimestamp) { + currentAudioTimestamp = mMediaCodecPlayer.getTimestamp(); + AudioTimestamp postResumeAudioTimestamp; + do { assertTrue(String.format("Audio has not resumed after %d milliseconds", - audioUnderrunTimeoutMs), - System.currentTimeMillis() - startTimeMs < audioUnderrunTimeoutMs); + audioResumeTimeoutMs), + System.currentTimeMillis() - startTimeMs < audioResumeTimeoutMs); + postResumeAudioTimestamp = currentAudioTimestamp; Thread.sleep(50); - } - - long resumeAudioSystemTime = interpolateSystemTimeAt( - underrunAudioTimestamp.framePosition + 1, postResumeTimestamp, - mMediaCodecPlayer.getAudioTrack()); + currentAudioTimestamp = mMediaCodecPlayer.getTimestamp(); + } while(currentAudioTimestamp.framePosition == postResumeAudioTimestamp.framePosition); - // Now that audio playback has resumed, loop to wait until video playback resumes + // 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. - long resumeVideoTimeUs = 0; + final int videoResumeTimeoutMs = 1000; startTimeMs = System.currentTimeMillis(); - while ((resumeVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs()) == underrunVideoTimeUs) { + currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs(); + long resumeVideoTimeUs = -1; + do { assertTrue(String.format("Video has not resumed after %d milliseconds", - videoUnderrunTimeoutMs), - System.currentTimeMillis() - startTimeMs < videoUnderrunTimeoutMs); + videoResumeTimeoutMs), + System.currentTimeMillis() - startTimeMs < videoResumeTimeoutMs); + resumeVideoTimeUs = currentVideoTimeUs; Thread.sleep(50); - } - - final ImmutableList<Long> renderedSystemTimeList = - mMediaCodecPlayer.getRenderedVideoFrameSystemTimeList(); - final long resumeVideoFrameSystemTime = mMediaCodecPlayer - .getRenderedVideoFrameSystemTimeList().get(underrunVideoRenderedTimestampIndex + 1); - final long vsync = (long) (1000 / frameRate); - final long avSyncOffset = resumeAudioSystemTime + 100 - resumeVideoFrameSystemTime; - assertTrue(String.format("Audio and video tracks are more than %d milliseconds out of sync", - vsync), - Math.abs(avSyncOffset) <= vsync); + currentVideoTimeUs = mMediaCodecPlayer.getVideoTimeUs(); + } while (currentVideoTimeUs == resumeVideoTimeUs); + + // The system time when rendering the first audio frame after the resume + long playbackRateFps = mMediaCodecPlayer.getAudioTrack().getPlaybackRate(); + long playedFrames = postResumeAudioTimestamp.framePosition + - underrunAudioTimestamp.framePosition + 1; + double elapsedTimeNs = playedFrames * (1000.0 * 1000.0 * 1000.0 / playbackRateFps); + long resumeAudioSystemTimeNs = postResumeAudioTimestamp.nanoTime - (long) elapsedTimeNs; + long resumeAudioSystemTimeMs = resumeAudioSystemTimeNs / 1000 / 1000; + + // The system time when rendering the first video frame after the resume + long resumeVideoSystemTimeMs = mMediaCodecPlayer.getRenderedVideoFrameSystemTimeList() + .get(underrunVideoRenderedTimestampIndex + 1) / 1000 / 1000; + + // Verify that audio and video are in-sync after resume time + // Note: Because a -100ms PTS gap is introduced, the video should resume 100ms later + resumeAudioSystemTimeMs += 100; + long vsyncMs = 1000 / frameRate; + long avSyncOffsetMs = resumeAudioSystemTimeMs - resumeVideoSystemTimeMs; + assertTrue(String.format( + "Audio is %d milliseconds out of sync of video (audio:%d video:%d)", + avSyncOffsetMs, resumeAudioSystemTimeMs, resumeVideoSystemTimeMs), + Math.abs(avSyncOffsetMs) <= vsyncMs); } /** @@ -4692,18 +4759,6 @@ public class DecoderTest extends MediaTestBase { } /** - * Returns the system time of the frame {@code framePosition} from {@code timestamp}, for a - * specific {@code AudioTrack}. - */ - private static long interpolateSystemTimeAt(long framePosition, AudioTimestamp timestamp, - AudioTrack audioTrack) { - final long playbackRateFps = audioTrack.getPlaybackRate(); // Frames per second - final long playedFrames = timestamp.framePosition - framePosition; - final double elapsedTimeNs = playedFrames * (1000000000.0 / playbackRateFps); - return timestamp.nanoTime - (long) elapsedTimeNs; - } - - /** * Returns list of CodecCapabilities advertising support for the given MIME type. */ private static List<CodecCapabilities> getCodecCapabilitiesForMimeType(String mimeType) { diff --git a/tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java b/tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java index a28095f0842..eab6aebf495 100644 --- a/tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java +++ b/tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java @@ -449,6 +449,8 @@ public class CamcorderProfileTest { CamcorderProfile.getAll(String.valueOf(cameraId), quality); checkAllProfiles(allProfiles, profile, videoSizesToCheck); } + } else { + assertNull(CamcorderProfile.getAll(String.valueOf(cameraId), quality)); } } diff --git a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc index 8c17a72f38d..8533d7e47af 100644 --- a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc +++ b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc @@ -16,6 +16,7 @@ #include "jni.h" #include <cstring> +#include <cassert> #include <errno.h> #include <fcntl.h> @@ -118,9 +119,9 @@ JNIEXPORT bool JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_confirmKernelV int major, minor; struct utsname uts; - if (uname(&uts) != 0 || - strcmp(uts.sysname, "Linux") != 0 || - sscanf(uts.release, "%d.%d", &major, &minor) != 2 || + uname(&uts); + assert(strcmp(uts.sysname, "Linux") == 0); + if (sscanf(uts.release, "%d.%d", &major, &minor) != 2 || (major < kRequiredMajor || (major == kRequiredMajor && minor < kRequiredMinor))) { return false; } @@ -131,6 +132,22 @@ JNIEXPORT bool JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_confirmKernelV } extern "C" +JNIEXPORT bool JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_confirmKernelArch64bit(JNIEnv*) { +#if defined(__linux__) + struct utsname uts; + uname(&uts); + assert(strcmp(uts.sysname, "Linux") == 0); + if (strstr(uts.machine, "64") != nullptr || + strstr(uts.machine, "armv8") == uts.machine) { + return true; + } + return false; +#else + return false; +#endif +} + +extern "C" JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performKernelSpaceUffd(JNIEnv*) { int ret = 0, write_fd = 0; void* addr = nullptr; diff --git a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java index fc4df1397b9..2f092a62b36 100644 --- a/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java +++ b/tests/tests/os/UffdGc/src/android/os/cts/uffdgc/UserfaultfdTest.java @@ -71,6 +71,8 @@ public final class UserfaultfdTest { // Test if userfaultfd works for minor-faults on shmem. @Test public void minorUserfaultfd() { + // minor fault feature is not enabled on 32-bit kernel archs. + Assume.assumeTrue(confirmKernelArch64bit()); assertEquals(0, performMinorUffd()); } @@ -82,6 +84,7 @@ public final class UserfaultfdTest { assertEquals(13, checkGetattr()); } + private native boolean confirmKernelArch64bit(); private native boolean confirmKernelVersion(); private native int performKernelSpaceUffd(); private native int uffdWithoutUserModeOnly(); diff --git a/tests/tests/permission/Android.bp b/tests/tests/permission/Android.bp index b78b6c07d5d..eae727629f3 100644 --- a/tests/tests/permission/Android.bp +++ b/tests/tests/permission/Android.bp @@ -63,4 +63,54 @@ android_test { "android.test.runner", "android.test.base", ], + data: [ + ":AppThatDefinesUndefinedPermissionGroupElement", + ":AppThatDoesNotHaveBgLocationAccess", + ":CtsAdversarialPermissionDefinerApp", + ":CtsAdversarialPermissionUserApp", + ":CtsAppThatAccessesLocationOnCommand", + ":CtsAppThatAlsoDefinesPermissionA", + ":CtsAppThatAlsoDefinesPermissionADifferentCert", + ":CtsAppThatAlsoDefinesPermissionGroupADifferentCert", + ":CtsAppThatAlsoDefinesPermissionGroupADifferentCert30", + ":CtsAppThatDefinesPermissionA", + ":CtsAppThatDefinesPermissionInPlatformGroup", + ":CtsAppThatDefinesPermissionWithInvalidGroup", + ":CtsAppThatDefinesPermissionWithInvalidGroup30", + ":CtsAppThatRequestsBluetoothPermission30", + ":CtsAppThatRequestsCalendarContactsBodySensorCustomPermission", + ":CtsAppThatRequestsBluetoothPermission31", + ":CtsAppThatRequestsBluetoothPermissionNeverForLocation31", + ":CtsAppThatRequestsContactsAndCallLogPermission16", + ":CtsAppThatRequestsContactsPermission15", + ":CtsAppThatRequestsContactsPermission16", + ":CtsAppThatRequestsLocationAndBackgroundPermission28", + ":CtsAppThatRequestsLocationAndBackgroundPermission29", + ":CtsAppThatRequestsBluetoothPermissionNeverForLocationNoProvider", + ":CtsAppThatRequestsLocationPermission22", + ":CtsAppThatRequestsLocationPermission28", + ":CtsAppThatRequestsLocationPermission29", + ":CtsAppThatRequestsLocationPermission29v4", + ":CtsAppThatRequestsOneTimePermission", + ":CtsAppThatRequestsPermissionAandB", + ":CtsAppThatRequestsPermissionAandC", + ":CtsAppThatRequestsStoragePermission28", + ":CtsAppThatRequestsStoragePermission29", + ":CtsAppThatRunsRationaleTests", + ":CtsAppToTestRevokeSelfPermission", + ":CtsAppWithSharedUidThatRequestsLocationPermission28", + ":CtsAppWithSharedUidThatRequestsLocationPermission29", + ":CtsAppWithSharedUidThatRequestsNoPermissions", + ":CtsAppWithSharedUidThatRequestsPermissions", + ":CtsInstallPermissionDefinerApp", + ":CtsInstallPermissionEscalatorApp", + ":CtsInstallPermissionUserApp", + ":CtsRuntimePermissionDefinerApp", + ":CtsRuntimePermissionUserApp", + ":CtsStorageEscalationApp28", + ":CtsStorageEscalationApp29Full", + ":CtsStorageEscalationApp29Scoped", + ":CtsVictimPermissionDefinerApp", + ], + per_testcase_directory: true, } diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt index 57efe7410b7..31e544951b5 100644 --- a/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt +++ b/tests/tests/permission3/src/android/permission3/cts/PermissionAttributionTest.kt @@ -29,11 +29,9 @@ import com.android.compatibility.common.util.AppOpsUtils.setOpMode import com.android.compatibility.common.util.CtsDownstreamingTest import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity -import com.android.modules.utils.build.SdkLevel import org.junit.After import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue -import org.junit.Assume.assumeFalse import org.junit.Before import org.junit.Test import java.util.concurrent.TimeUnit @@ -41,19 +39,16 @@ import java.util.concurrent.TimeUnit /** * Tests permission attribution for location providers. */ -@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S) +// Tests converted to GTS since these are GMS requirements not CDD. +// These will be moved to GTS in U. +@CtsDownstreamingTest +@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU) class PermissionAttributionTest : BasePermissionHubTest() { private val micLabel = packageManager.getPermissionGroupInfo( android.Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString() val locationManager = context.getSystemService(LocationManager::class.java)!! private var wasEnabled = false - // Permission history is not available on Auto devices running S or below. - @Before - fun assumeNotAutoBelowT() { - assumeFalse(isAutomotive && !SdkLevel.isAtLeastT()) - } - @Before fun installAppLocationProviderAndAllowMockLocation() { installPackage(APP_APK_PATH, grantRuntimePermissions = true) @@ -79,7 +74,6 @@ class PermissionAttributionTest : BasePermissionHubTest() { } } - @CtsDownstreamingTest @Test fun testLocationProviderAttributionForMicrophone() { enableAppAsLocationProvider() diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt index f23faae7468..fe9037a571e 100644 --- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt +++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt @@ -295,7 +295,7 @@ class CameraMicIndicatorsPermissionTest { // indicator uiDevice.openQuickSettings() assertPrivacyChipAndIndicatorsPresent( - useMic || useHotword, + useMic, useCamera, chainUsage, safetyCenterEnabled @@ -390,11 +390,13 @@ class CameraMicIndicatorsPermissionTest { chainUsage: Boolean, safetyCenterEnabled: Boolean = false ) { - // Ensure the privacy chip is present - eventually { - val privacyChip = uiDevice.findObject(UiSelector().resourceId(PRIVACY_CHIP_ID)) - assertTrue("view with id $PRIVACY_CHIP_ID not found", privacyChip.exists()) - privacyChip.click() + // Ensure the privacy chip is present (or not) + val chipFound = isChipPresent() + if (useMic || useCamera) { + assertTrue("Did not find chip", chipFound) + } else { // hotword + assertFalse("Found chip, but did not expect to", chipFound) + return } eventually { @@ -455,6 +457,21 @@ class CameraMicIndicatorsPermissionTest { assertEquals("Expected only one shell view", 1, shellView.size) } + private fun isChipPresent(): Boolean { + var chipFound = false + try { + eventually { + val privacyChip = uiDevice.findObject(By.res(PRIVACY_CHIP_ID)) + assertNotNull("view with id $PRIVACY_CHIP_ID not found", privacyChip) + privacyChip.click() + chipFound = true + } + } catch (e: Exception) { + // Handle more gracefully after + } + return chipFound + } + private fun pressBack() { uiDevice.pressBack() waitForIdle() diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml index 5b53d0e4278..186c5e2ab7b 100644 --- a/tests/tests/security/AndroidManifest.xml +++ b/tests/tests/security/AndroidManifest.xml @@ -194,6 +194,13 @@ android:grantUriPermissions="true" android:process=":badprovider" /> + <activity android:name="android.security.cts.CVE_2022_20143.PocActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.app.action.AUTOMATIC_ZEN_RULE"/> + </intent-filter> + </activity> + </application> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20143/CVE_2022_20143.java b/tests/tests/security/src/android/security/cts/CVE_2022_20143/CVE_2022_20143.java new file mode 100644 index 00000000000..3c08cbb95b6 --- /dev/null +++ b/tests/tests/security/src/android/security/cts/CVE_2022_20143/CVE_2022_20143.java @@ -0,0 +1,117 @@ +/* + * 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_20143; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeNoException; +import static org.junit.Assume.assumeTrue; + +import android.app.AutomaticZenRule; +import android.app.Instrumentation; +import android.app.NotificationManager; +import android.app.UiAutomation; +import android.content.ComponentName; +import android.content.Context; +import android.net.Uri; +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.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; + +@RunWith(AndroidJUnit4.class) +public class CVE_2022_20143 extends StsExtraBusinessLogicTestCase { + + @AsbSecurityTest(cveBugId = 220735360) + @Test + public void testPocCVE_2022_20143() { + final int ruleLimitPerPackage = 200; + final int timeoutDuration = 5000; + final int waitDuration = 100; + Instrumentation instrumentation; + Context context; + NotificationManager notificationManager = null; + String packageName = null; + UiAutomation uiautomation = null; + boolean isVulnerable = true; + boolean notificationPolicyAccessGranted = false; + int automaticZenRules = 0; + ArrayList<String> ruleIds = new ArrayList<>(); + try { + instrumentation = InstrumentationRegistry.getInstrumentation(); + context = instrumentation.getContext(); + notificationManager = context.getSystemService(NotificationManager.class); + packageName = context.getPackageName(); + uiautomation = instrumentation.getUiAutomation(); + uiautomation.executeShellCommand("cmd notification allow_dnd " + packageName); + long startTime = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTime < timeoutDuration) { + // busy wait until notification policy access is granted + if (notificationManager.isNotificationPolicyAccessGranted()) { + notificationPolicyAccessGranted = true; + break; + } + Thread.sleep(waitDuration); + } + // storing the number of automaticZenRules present before test run + automaticZenRules = notificationManager.getAutomaticZenRules().size(); + ComponentName component = + new ComponentName(packageName, PocActivity.class.getCanonicalName()); + for (int i = 0; i < ruleLimitPerPackage; ++i) { + Uri conditionId = Uri.parse("condition://android/" + i); + AutomaticZenRule rule = new AutomaticZenRule("ZenRuleName" + i, null, component, + conditionId, null, NotificationManager.INTERRUPTION_FILTER_ALL, true); + String id = notificationManager.addAutomaticZenRule(rule); + ruleIds.add(id); + } + } catch (Exception e) { + if (e instanceof IllegalArgumentException) { + isVulnerable = false; // expected with fix + } else { + assumeNoException(e); + } + } finally { + try { + if (notificationPolicyAccessGranted) { + /* retrieving the total number of automaticZenRules added by test so that the */ + /* test fails only if all automaticZenRules were added successfully */ + automaticZenRules = + notificationManager.getAutomaticZenRules().size() - automaticZenRules; + for (String id : ruleIds) { + notificationManager.removeAutomaticZenRule(id); + } + uiautomation + .executeShellCommand("cmd notification disallow_dnd " + packageName); + } + boolean allZenRulesAdded = ruleLimitPerPackage == automaticZenRules; + assumeTrue("Notification policy access not granted", + notificationPolicyAccessGranted); + assertFalse( + "Vulnerable to b/220735360!! System can be corrupted by adding many" + + " AutomaticZenRules via NotificationManager#addAutomaticZenRule", + isVulnerable && allZenRulesAdded); + } catch (Exception e) { + assumeNoException(e); + } + } + } +} diff --git a/tests/tests/security/src/android/security/cts/CVE_2022_20143/PocActivity.java b/tests/tests/security/src/android/security/cts/CVE_2022_20143/PocActivity.java new file mode 100644 index 00000000000..4416990a804 --- /dev/null +++ b/tests/tests/security/src/android/security/cts/CVE_2022_20143/PocActivity.java @@ -0,0 +1,22 @@ +/* + * 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_20143; + +import android.app.Activity; + +public class PocActivity extends Activity { +} diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java index af5fb29dcb5..a06192036c8 100644 --- a/tests/tests/security/src/android/security/cts/StagefrightTest.java +++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java @@ -95,6 +95,8 @@ import org.junit.runner.RunWith; import static org.junit.Assume.*; import static org.junit.Assert.*; +import static org.hamcrest.Matchers.is; + /** * Verify that the device is not vulnerable to any known Stagefright * vulnerabilities. @@ -2361,6 +2363,16 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { try { MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime); if (caps != null) { + /* Add mainline skip to decoders in mainline module */ + if (isCodecInMainlineModule(info.getName())) { + Log.i(TAG, "Skipping codec " + info.getName() + + " as it is part of mainline"); + continue; + } + if (info.isAlias()) { + Log.i(TAG, "Skipping codec " + info.getName() + " as it is an alias"); + continue; + } matchingCodecs.add(info.getName()); Log.i(TAG, "Found matching codec " + info.getName() + " for track " + t); } @@ -2678,9 +2690,8 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { } catch (InterruptedException e) { fail("operation was interrupted"); } - if (t.isAlive()) { - fail("operation not completed within timeout of " + timeout + "ms"); - } + assumeThat("operation not completed within timeout of " + timeout + "ms", t.isAlive(), + is(false)); } private void releaseCodec(final MediaCodec codec) { @@ -2692,6 +2703,20 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { }, 5000); } + private boolean isCodecInMainlineModule(String codecName) { + boolean value = false; + if (codecName.startsWith("c2.android.")) { + try { + value = ModuleDetector.moduleIsPlayManaged( + getInstrumentation().getContext().getPackageManager(), + MainlineModule.MEDIA_SOFTWARE_CODEC); + } catch (Exception e) { + Log.e(TAG, "Exception caught " + e.toString()); + } + } + return value; + } + private void doStagefrightTestRawBlob( int rid, String mime, int initWidth, int initHeight) throws Exception { doStagefrightTestRawBlob(rid, mime, initWidth, initHeight, new CrashUtils.Config()); @@ -2755,6 +2780,16 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { try { MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime); if (caps != null) { + /* Add mainline skip to decoders in mainline module */ + if (isCodecInMainlineModule(info.getName())) { + Log.i(TAG, "Skipping codec " + info.getName() + + " as it is part of mainline"); + continue; + } + if (info.isAlias()) { + Log.i(TAG, "Skipping codec " + info.getName() + " as it is an alias"); + continue; + } matchingCodecs.add(info.getName()); } } catch (IllegalArgumentException e) { @@ -2886,6 +2921,16 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { try { MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime); if (caps != null) { + /* Add mainline skip to decoders in mainline module */ + if (isCodecInMainlineModule(info.getName())) { + Log.i(TAG, "Skipping codec " + info.getName() + + " as it is part of mainline"); + continue; + } + if (info.isAlias()) { + Log.i(TAG, "Skipping codec " + info.getName() + " as it is an alias"); + continue; + } matchingCodecs.add(info.getName()); } } catch (IllegalArgumentException e) { @@ -3031,6 +3076,16 @@ public class StagefrightTest extends StsExtraBusinessLogicTestCase { try { MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime); if (caps != null) { + /* Add mainline skip to decoders in mainline module */ + if (isCodecInMainlineModule(info.getName())) { + Log.i(TAG, "Skipping codec " + info.getName() + + " as it is part of mainline"); + continue; + } + if (info.isAlias()) { + Log.i(TAG, "Skipping codec " + info.getName() + " as it is an alias"); + continue; + } matchingCodecs.add(info.getName()); } } catch (IllegalArgumentException e) { diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java index e934b2aae5c..137a43b0ca2 100755 --- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java +++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java @@ -33,7 +33,6 @@ import static org.junit.Assert.fail; import static org.junit.Assume.assumeTrue; import android.annotation.Nullable; -import android.app.AppOpsManager; import android.app.UiAutomation; import android.content.BroadcastReceiver; import android.content.Context; @@ -50,7 +49,6 @@ import android.net.Uri; import android.os.Looper; import android.os.ParcelUuid; import android.os.PersistableBundle; -import android.os.Process; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; @@ -680,20 +678,10 @@ public class SubscriptionManagerTest { (sm) -> sm.createSubscriptionGroup(subGroup)); // Getting subscriptions in group. - List<SubscriptionInfo> infoList; - try { - mSm.getSubscriptionsInGroup(uuid); - fail("SecurityException should be thrown without USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"); - } catch (SecurityException ex) { - // Expected - } - - // has the READ_PRIVILEGED_PHONE_STATE permission - infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm, - (sm) -> sm.getSubscriptionsInGroup(uuid), READ_PRIVILEGED_PHONE_STATE); + List<SubscriptionInfo> infoList = mSm.getSubscriptionsInGroup(uuid); assertNotNull(infoList); assertEquals(1, infoList.size()); - assertEquals(uuid, infoList.get(0).getGroupUuid()); + assertNull(infoList.get(0).getGroupUuid()); infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm, (sm) -> sm.getSubscriptionsInGroup(uuid)); @@ -710,36 +698,30 @@ public class SubscriptionManagerTest { } availableInfoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm, (sm) -> sm.getAvailableSubscriptionInfoList()); - // has the USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER permission - try { - setIdentifierAccess(true); - if (availableInfoList.size() > 1) { - List<Integer> availableSubGroup = availableInfoList.stream() - .map(info -> info.getSubscriptionId()) - .filter(subId -> subId != mSubId) - .collect(Collectors.toList()); - - ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, - (sm) -> sm.addSubscriptionsIntoGroup(availableSubGroup, uuid)); - - infoList = mSm.getSubscriptionsInGroup(uuid); - assertNotNull(infoList); - assertEquals(availableInfoList.size(), infoList.size()); - - ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, - (sm) -> sm.removeSubscriptionsFromGroup(availableSubGroup, uuid)); - } + if (availableInfoList.size() > 1) { + List<Integer> availableSubGroup = availableInfoList.stream() + .map(info -> info.getSubscriptionId()) + .filter(subId -> subId != mSubId) + .collect(Collectors.toList()); - // Remove from subscription group with current sub Id. ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, - (sm) -> sm.removeSubscriptionsFromGroup(subGroup, uuid)); + (sm) -> sm.addSubscriptionsIntoGroup(availableSubGroup, uuid)); infoList = mSm.getSubscriptionsInGroup(uuid); assertNotNull(infoList); - assertTrue(infoList.isEmpty()); - } finally { - setIdentifierAccess(false); + assertEquals(availableInfoList.size(), infoList.size()); + + ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, + (sm) -> sm.removeSubscriptionsFromGroup(availableSubGroup, uuid)); } + + // Remove from subscription group with current sub Id. + ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, + (sm) -> sm.removeSubscriptionsFromGroup(subGroup, uuid)); + + infoList = mSm.getSubscriptionsInGroup(uuid); + assertNotNull(infoList); + assertTrue(infoList.isEmpty()); } @Test @@ -751,31 +733,23 @@ public class SubscriptionManagerTest { ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, (sm) -> sm.addSubscriptionsIntoGroup(subGroup, uuid)); - List<SubscriptionInfo> infoList; - try { - mSm.getSubscriptionsInGroup(uuid); - fail("SecurityException should be thrown without USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER"); - } catch (SecurityException ex) { - // Expected - } - // Getting subscriptions in group. - try { - setIdentifierAccess(true); - infoList = mSm.getSubscriptionsInGroup(uuid); - assertNotNull(infoList); - assertEquals(1, infoList.size()); - assertEquals(uuid, infoList.get(0).getGroupUuid()); - } finally { - setIdentifierAccess(false); - } + List<SubscriptionInfo> infoList = mSm.getSubscriptionsInGroup(uuid); + assertNotNull(infoList); + assertEquals(1, infoList.size()); + assertNull(infoList.get(0).getGroupUuid()); + + infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm, + (sm) -> sm.getSubscriptionsInGroup(uuid)); + assertNotNull(infoList); + assertEquals(1, infoList.size()); + assertEquals(uuid, infoList.get(0).getGroupUuid()); // Remove from subscription group with current sub Id. ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mSm, (sm) -> sm.removeSubscriptionsFromGroup(subGroup, uuid)); - infoList = ShellIdentityUtils.invokeMethodWithShellPermissions(mSm, - (sm) -> sm.getSubscriptionsInGroup(uuid)); + infoList = mSm.getSubscriptionsInGroup(uuid); assertNotNull(infoList); assertTrue(infoList.isEmpty()); } @@ -1485,13 +1459,4 @@ public class SubscriptionManagerTest { return validCarrier && validNetworkType && validCapabilities; } - - private void setIdentifierAccess(boolean allowed) { - String op = AppOpsManager.OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER; - AppOpsManager appOpsManager = InstrumentationRegistry.getContext().getSystemService( - AppOpsManager.class); - int mode = allowed ? AppOpsManager.MODE_ALLOWED : AppOpsManager.opToDefaultMode(op); - ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn( - appOpsManager, (appOps) -> appOps.setUidMode(op, Process.myUid(), mode)); - } } diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml index c8a450d1c49..22ec7d09a20 100644 --- a/tools/cts-tradefed/res/config/cts-known-failures.xml +++ b/tools/cts-tradefed/res/config/cts-known-failures.xml @@ -261,4 +261,10 @@ <!-- b/198021503 --> <option name="compatibility:exclude-filter" value="CtsAppSecurityHostTestCases android.appsecurity.cts.StorageHostTest#testFullDisk" /> + <!-- b/216546060 --> + <option name="compatibility:exclude-filter" value="CtsFragmentTestCases android.fragment.cts.FragmentAnimatorTest#saveWhileAnimatingAway" /> + + <!-- b/216553645 --> + <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.ECDSASignatureTest#testNONEwithECDSATruncatesInputToFieldSize" /> + </configuration> diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml index cbd7611c7c9..a6e59acd469 100644 --- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml +++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml @@ -112,4 +112,6 @@ <option name="compatibility:exclude-filter" value="CtsHdmiCecHostTestCases android.hdmicec.cts.tv.HdmiCecRoutingControlTest" /> <option name="compatibility:exclude-filter" value="CtsHdmiCecHostTestCases android.hdmicec.cts.tv.HdmiCecTvOneTouchPlayTest" /> + <!-- b/234409652 Stable API does not exist to enforce this requirement on variable geometry devices --> + <option name="compatibility:exclude-filter" value="CtsCameraTestCases android.hardware.camera2.cts.ExtendedCameraCharacteristicsTest#testCameraOrientationAlignedWithDevice"/> </configuration> |