diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-07-21 20:17:33 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-07-21 20:17:33 +0000 |
commit | 12fc82b7340f218be6746840d5aae029e24801dd (patch) | |
tree | 8778ae438000e70f3f730e7714b3ce265c8c209e | |
parent | 636c5b05629135109480b0e6abc035961065c212 (diff) | |
parent | 594dfb3dc7876ac581cd510d4292cff64e6bfe1c (diff) | |
download | cts-android13-mainline-go-mediaprovider-release.tar.gz |
Snap for 8857176 from 594dfb3dc7876ac581cd510d4292cff64e6bfe1c to mainline-go-mediaprovider-releaseaml_go_mpr_330912000android13-mainline-go-mediaprovider-release
Change-Id: Ib891c2c2703ae55baf5ebcd3f62e74c845b62534
85 files changed, 1927 insertions, 2217 deletions
diff --git a/apps/CameraITS/tests/scene2_a/test_auto_flash.py b/apps/CameraITS/tests/scene2_a/test_auto_flash.py index b20da2dbc54..c00cd5c358c 100644 --- a/apps/CameraITS/tests/scene2_a/test_auto_flash.py +++ b/apps/CameraITS/tests/scene2_a/test_auto_flash.py @@ -107,10 +107,10 @@ class AutoFlashTest(its_base_test.ItsBaseTest): test_name = os.path.join(self.log_path, _TEST_NAME) # check SKIP conditions - first_api_level = its_session_utils.get_first_api_level(self.dut.serial) + vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial) camera_properties_utils.skip_unless( camera_properties_utils.flash(props) and - first_api_level >= its_session_utils.ANDROID13_API_LEVEL) + vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL) # establish connection with lighting controller arduino_serial_port = lighting_control_utils.lighting_control( diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py index 1f5b7c0bad9..2781f18805e 100644 --- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py +++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py @@ -35,9 +35,9 @@ _MAX_STABILIZED_RADIUS_RATIO = 1.2 # radius of circle in stabilized preview _ROUNDESS_DELTA_THRESHOLD = 0.05 _MAX_CENTER_THRESHOLD_PERCENT = 0.075 -_MAX_DIMENSION_SIZE = (1920, 1440) # max mandatory preview stream resolution +_MAX_AREA = 1920 * 1440 # max mandatory preview stream resolution _MIN_CENTER_THRESHOLD_PERCENT = 0.02 -_MIN_DIMENSION_SIZE = (176, 144) # assume QCIF to be min preview size +_MIN_AREA = 176 * 144 # assume QCIF to be min preview size def _collect_data(cam, video_size, stabilize): @@ -93,23 +93,19 @@ def _calculate_center_offset_threshold(image_size): threshold value ratio between which the circle centers can differ """ - max_diagonal = _point_distance(0, 0, - _MAX_DIMENSION_SIZE[0], _MAX_DIMENSION_SIZE[1]) - min_diagonal = _point_distance(0, 0, - _MIN_DIMENSION_SIZE[0], _MIN_DIMENSION_SIZE[1]) + img_area = image_size[0] * image_size[1] - img_diagonal = _point_distance(0, 0, image_size[0], image_size[1]) + normalized_area = ((img_area - _MIN_AREA) / + (_MAX_AREA - _MIN_AREA)) - normalized_diagonal = ((img_diagonal - min_diagonal) / - (max_diagonal - min_diagonal)) - - if normalized_diagonal > 1 or normalized_diagonal < 0: - raise AssertionError(f'normalized diagonal > 1 or < 0!' - f' img_diag: {img_diagonal}, ' - f' normalized_diagonal: {normalized_diagonal}') + if normalized_area > 1 or normalized_area < 0: + raise AssertionError(f'normalized area > 1 or < 0! ' + f'image_size[0]: {image_size[0]}, ' + f'image_size[1]: {image_size[1]}, ' + f'normalized_area: {normalized_area}') # Threshold should be larger for images with smaller resolution - normalized_threshold_percent = ((1 - normalized_diagonal) * + normalized_threshold_percent = ((1 - normalized_area) * (_MAX_CENTER_THRESHOLD_PERCENT - _MIN_CENTER_THRESHOLD_PERCENT)) @@ -144,7 +140,7 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest): # Load scene. its_session_utils.load_scene(cam, props, self.scene, - self.tablet, chart_distance=0) + self.tablet, self.chart_distance) # Check skip condition first_api_level = its_session_utils.get_first_api_level(self.dut.serial) @@ -253,7 +249,8 @@ class PreviewStabilizationFoVTest(its_base_test.ItsBaseTest): f'{_ROUNDESS_DELTA_THRESHOLD}, ' f'actual ratio difference: {roundness_diff}. ') - # Distance between centers + # Distance between centers, x_offset and y_offset are relative to the + # radius of the circle, so they're normalized. Not pixel values. unstab_center = (ustab_circle['x_offset'], ustab_circle['y_offset']) logging.debug('unstabilized center: %s', unstab_center) stab_center = (stab_circle['x_offset'], stab_circle['y_offset']) diff --git a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py index 6eaca195c22..bb713672e00 100644 --- a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py +++ b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py @@ -137,13 +137,13 @@ class VideoAspectRatioAndCropTest(its_base_test.ItsBaseTest): logging.debug('physical available focal lengths: %s', str(fls_physical)) # Check SKIP conditions. - first_api_level = its_session_utils.get_first_api_level(self.dut.serial) + vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial) camera_properties_utils.skip_unless( - first_api_level >= its_session_utils.ANDROID13_API_LEVEL) + vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL) # Load scene. its_session_utils.load_scene(cam, props, self.scene, - self.tablet, chart_distance=0) + self.tablet, self.chart_distance) # Determine camera capabilities. supported_video_qualities = cam.get_supported_video_qualities( diff --git a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py index 0be38b56d11..195d5670eba 100644 --- a/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py +++ b/apps/CameraITS/tests/sensor_fusion/test_video_stabilization.py @@ -129,7 +129,7 @@ class VideoStabilizationTest(its_base_test.ItsBaseTest): in gyroscope movement. Test is a PASS if rotation is reduced in video. """ - def test_video_stability(self): + def test_video_stabilization(self): rot_rig = {} log_path = self.log_path @@ -139,12 +139,12 @@ class VideoStabilizationTest(its_base_test.ItsBaseTest): hidden_physical_id=self.hidden_physical_id) as cam: props = cam.get_camera_properties() props = cam.override_with_hidden_physical_camera_props(props) - first_api_level = its_session_utils.get_first_api_level(self.dut.serial) + vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial) supported_stabilization_modes = props[ 'android.control.availableVideoStabilizationModes'] camera_properties_utils.skip_unless( - first_api_level >= its_session_utils.ANDROID13_API_LEVEL and + vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL and _VIDEO_STABILIZATION_MODE in supported_stabilization_modes) # Raise error if not FRONT or REAR facing camera diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py index e91565e250f..c2065ba6ac4 100644 --- a/apps/CameraITS/utils/its_session_utils.py +++ b/apps/CameraITS/utils/its_session_utils.py @@ -1612,6 +1612,18 @@ def get_first_api_level(device_id): return first_api_level +def get_vendor_api_level(device_id): + """Return the int value for the vendor API level of the device.""" + cmd = 'adb -s %s shell getprop ro.vendor.api_level' % device_id + try: + vendor_api_level = int(subprocess.check_output(cmd.split()).rstrip()) + logging.debug('First vendor API level: %d', vendor_api_level) + except (subprocess.CalledProcessError, ValueError): + logging.error('No vendor_api_level. Setting to build version.') + vendor_api_level = get_build_sdk_version(device_id) + return vendor_api_level + + class ItsSessionUtilsTests(unittest.TestCase): """Run a suite of unit tests on this module.""" diff --git a/apps/CtsVerifier/Android.bp b/apps/CtsVerifier/Android.bp index b4485d19e99..024e0387c6f 100644 --- a/apps/CtsVerifier/Android.bp +++ b/apps/CtsVerifier/Android.bp @@ -91,6 +91,7 @@ android_library { "CtsForceStopHelper-constants", "ctsmediautil", "DpmWrapper", + "MediaPerformanceClassCommon", ], libs: ["telephony-common"] + ["android.test.runner.stubs"] + ["android.test.base.stubs"] + ["android.test.mock.stubs"] + ["android.car-test-stubs"] + ["voip-common"] + ["truth-prebuilt"], @@ -114,7 +115,7 @@ android_test { compile_multilib: "both", - manifest: "AndroidManifest-verifierConfig.xml", + additional_manifests: ["AndroidManifest-verifierConfig.xml"], jni_libs: [ "libctsverifier_jni", diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml index 5a257de64f1..db1ca21c978 100644 --- a/apps/CtsVerifier/AndroidManifest.xml +++ b/apps/CtsVerifier/AndroidManifest.xml @@ -248,6 +248,7 @@ <action android:name="android.intent.action.MAIN" /> <category android:name="android.cts.intent.category.MANUAL_TEST" /> </intent-filter> + <meta-data android:name="CddTest" android:value="3.8.17/C-1-1,C-2-1" /> <meta-data android:name="test_category" android:value="@string/test_category_features" /> <meta-data android:name="test_excluded_features" android:value="android.hardware.type.watch:android.software.leanback:android.hardware.type.automotive" /> @@ -3901,174 +3902,6 @@ android:value="single_display_mode" /> </activity> - <!-- CTS Verifier Presence Test Top Screen --> - <activity - android:name=".presence.PresenceTestActivity" - android:configChanges="keyboardHidden|orientation|screenSize" - android:exported="true" - android:label="@string/presence_test" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.cts.intent.category.MANUAL_TEST" /> - </intent-filter> - - <meta-data - android:name="test_category" - android:value="@string/test_category_networking" /> - <meta-data android:name="display_mode" - android:value="single_display_mode" /> - </activity> - - <!-- - CTS Verifier Uwb Precision Test Screen - test category : uwb - test parent : PresenceTestActivity - --> - <activity - android:name=".presence.UwbPrecisionActivity" - android:configChanges="keyboardHidden|orientation|screenSize" - android:exported="true" - android:label="@string/uwb_precision" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.cts.intent.category.MANUAL_TEST" /> - </intent-filter> - - <meta-data - android:name="test_category" - android:value="@string/uwb" /> - <meta-data - android:name="test_parent" - android:value="com.android.cts.verifier.presence.PresenceTestActivity" /> - <meta-data android:name="display_mode" - android:value="single_display_mode" /> - <meta-data android:name="CddTest" - android:value="7.4.9/C-1-1" /> - </activity> - - <!-- - CTS Verifier Uwb Short Range Test Screen - test category : uwb - test parent : PresenceTestActivity - --> - <activity - android:name=".presence.UwbShortRangeActivity" - android:configChanges="keyboardHidden|orientation|screenSize" - android:exported="true" - android:label="@string/uwb_short_range" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.cts.intent.category.MANUAL_TEST" /> - </intent-filter> - - <meta-data - android:name="test_category" - android:value="@string/uwb" /> - <meta-data - android:name="test_parent" - android:value="com.android.cts.verifier.presence.PresenceTestActivity" /> - <meta-data - android:name="display_mode" - android:value="single_display_mode" /> - <meta-data - android:name="CddTest" - android:value="7.4.9/C-1-2" /> - </activity> - - <!-- - CTS Verifier BLE RSSI Precision Test Screen - test category : BLE - test parent : PresenceTestActivity - --> - <activity - android:name=".presence.BleRssiPrecisionActivity" - android:exported="true" - android:label="@string/ble_rssi_precision_name"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.cts.intent.category.MANUAL_TEST" /> - </intent-filter> - - <meta-data - android:name="test_category" - android:value="@string/ble" /> - <meta-data - android:name="test_parent" - android:value="com.android.cts.verifier.presence.PresenceTestActivity" /> - <meta-data - android:name="test_required_features" - android:value="android.hardware.bluetooth_le" /> - <meta-data - android:name="display_mode" - android:value="single_display_mode" /> - <meta-data - android:name="CddText" - android:value="7.4.3/C-7-1" /> - </activity> - - <!-- - CTS Verifier BLE Rx/Tx Calibration Test Screen - test category : BLE - test parent : PresenceTestActivity - --> - <activity - android:name=".presence.BleRxTxCalibrationActivity" - android:exported="true" - android:label="@string/ble_rx_tx_calibration_name"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.cts.intent.category.MANUAL_TEST" /> - </intent-filter> - - <meta-data - android:name="test_category" - android:value="@string/ble" /> - <meta-data - android:name="test_parent" - android:value="com.android.cts.verifier.presence.PresenceTestActivity" /> - <meta-data - android:name="test_required_features" - android:value="android.hardware.bluetooth_le" /> - <meta-data - android:name="display_mode" - android:value="single_display_mode" /> - <meta-data - android:name="CddText" - android:value="7.4.3/C-7-2" /> - </activity> - - <!-- CTS Verifier Nan Precision and Bias Test Screen - test category : wifi_nan - test parent : PresenceTestActivity - --> - <activity - android:name=".presence.NanPrecisionTestActivity" - android:configChanges="keyboardHidden|orientation|screenSize" - android:exported="true" - android:label="@string/nan_precision" > - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - - <category android:name="android.cts.intent.category.MANUAL_TEST" /> - </intent-filter> - - <meta-data - android:name="test_category" - android:value="@string/wifi_nan" /> - <meta-data - android:name="test_parent" - android:value="com.android.cts.verifier.presence.PresenceTestActivity" /> - <meta-data android:name="display_mode" - android:value="single_display_mode" /> - <meta-data android:name="CddTest" - android:value="7.4.2.5/H-1-1|7.4.2.5/H-1-2" /> - </activity> - <activity-alias android:name=".CtsVerifierActivity" android:label="@string/app_name" @@ -6159,6 +5992,7 @@ <category android:name="android.cts.intent.category.MANUAL_TEST" /> </intent-filter> <meta-data android:name="test_category" android:value="@string/test_category_logcat" /> + <meta-data android:name="test_excluded_features" android:value="android.hardware.type.automotive" /> </activity> <activity android:name=".displaycutout.DisplayCutoutTestActivity" diff --git a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml b/apps/CtsVerifier/res/layout/ble_rssi_precision.xml deleted file mode 100644 index 5f01e1fc442..00000000000 --- a/apps/CtsVerifier/res/layout/ble_rssi_precision.xml +++ /dev/null @@ -1,60 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2022 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - style="@style/RootLayoutPadding" - tools:ignore="Autofill"> - - <ScrollView - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - - <LinearLayout - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <TextView - android:text="@string/ble_rssi_precision_test_instructions" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scrollbars="vertical" /> - - <EditText - android:id="@+id/report_rssi_range" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_ble_rssi_range" - android:inputType="number" /> - - <EditText - android:id="@+id/report_reference_device" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_reference_device" - android:inputType="text" /> - - <include - android:layout_width="match_parent" - android:layout_height="wrap_content" - layout="@layout/pass_fail_buttons" /> - </LinearLayout> - </ScrollView> -</RelativeLayout> diff --git a/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml b/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml deleted file mode 100644 index 3ca955b7e30..00000000000 --- a/apps/CtsVerifier/res/layout/ble_rx_tx_calibration.xml +++ /dev/null @@ -1,66 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?><!-- - ~ Copyright (C) 2022 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:tools="http://schemas.android.com/tools" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - style="@style/RootLayoutPadding" - tools:ignore="Autofill"> - - <ScrollView - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - - <LinearLayout - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - - <TextView - android:text="@string/ble_rx_tx_calibration_test_instructions" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scrollbars="vertical" /> - - <EditText - android:id="@+id/report_channels_rssi_range" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_channels_ble_rssi_range" - android:inputType="number" /> - - <EditText - android:id="@+id/report_cores_rssi_range" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_cores_ble_rssi_range" - android:inputType="number" /> - - <EditText - android:id="@+id/report_reference_device" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_reference_device" - android:inputType="text" /> - - <include - android:layout_width="match_parent" - android:layout_height="wrap_content" - layout="@layout/pass_fail_buttons" /> - </LinearLayout> - </ScrollView> -</RelativeLayout> diff --git a/apps/CtsVerifier/res/layout/clipboard_preview.xml b/apps/CtsVerifier/res/layout/clipboard_preview.xml index 85f38c8eef7..efec118cb4d 100644 --- a/apps/CtsVerifier/res/layout/clipboard_preview.xml +++ b/apps/CtsVerifier/res/layout/clipboard_preview.xml @@ -31,86 +31,6 @@ android:layout_marginBottom="100dp" android:layout_marginTop="30dp" android:text="@string/clipboard_preview_test_copy_button"/> - - <TableLayout - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TableRow - android:layout_width="match_parent" - android:layout_height="50dp"> - <View android:layout_weight="3" - android:layout_height="50dp"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b1" - android:layout_width="50dp" - android:layout_height="50dp" - android:text="1"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b2" - android:layout_width="50dp" - android:layout_height="50dp" - android:text="2"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b3" - android:layout_width="50dp" - android:layout_height="50dp" - android:text="3"/> - <View android:layout_weight="3" - android:layout_height="50dp"/> - </TableRow> - <TableRow - android:layout_width="match_parent" - android:layout_height="50dp"> - <View android:layout_weight="3" - android:layout_height="50dp"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b4" - android:layout_width="50dp" - android:layout_height="50dp" - android:text="4"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b5" - android:layout_width="50dp" - android:layout_height="50dp" - android:text="5"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b6" - android:layout_width="50dp" - android:layout_height="50dp" - android:text="6"/> - <View android:layout_weight="3" - android:layout_height="50dp"/> - </TableRow> - <TableRow - android:layout_width="match_parent" - android:layout_height="50dp"> - <View android:layout_weight="3" - android:layout_height="match_parent"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b7" - android:layout_width="50dp" - android:layout_height="match_parent" - android:text="7"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b8" - android:layout_width="50dp" - android:layout_height="match_parent" - android:text="8"/> - <Button android:layout_weight="1" - android:id="@+id/clipboard_preview_test_b9" - android:layout_width="50dp" - android:layout_height="match_parent" - android:text="9"/> - <View android:layout_weight="3" - android:layout_height="50dp"/> - </TableRow> - </TableLayout> - <Button - android:id="@+id/clipboard_preview_test_b0" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:text="0"/> <include android:id="@+id/clipboard_preview_test_pass_fail" android:layout_width="match_parent" diff --git a/apps/CtsVerifier/res/layout/nan_precision.xml b/apps/CtsVerifier/res/layout/nan_precision.xml deleted file mode 100644 index c81a9c4f120..00000000000 --- a/apps/CtsVerifier/res/layout/nan_precision.xml +++ /dev/null @@ -1,92 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - ~ Copyright (C) 2022 The Android Open Source Project - ~ - ~ Licensed under the Apache License, Version 2.0 (the "License"); - ~ you may not use this file except in compliance with the License. - ~ You may obtain a copy of the License at - ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 - ~ - ~ Unless required by applicable law or agreed to in writing, software - ~ distributed under the License is distributed on an "AS IS" BASIS, - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - ~ See the License for the specific language governing permissions and - ~ limitations under the License. - --> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - style="@style/RootLayoutPadding"> - <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - <LinearLayout android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TextView android:text="@string/nan_precision_instruction" - android:id="@+id/nan_precision_instruction" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scrollbars="vertical"/> - <LinearLayout android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <EditText android:id="@+id/nan_bandwidth" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="number" - android:hint="@string/report_nan_bandwidth_mhz"/> - <EditText android:id="@+id/distance_range_10cm_gt_68p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_10cm_gt_68p"/> - <EditText android:id="@+id/distance_range_1m_gt_68p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_1m_gt_68p"/> - <EditText android:id="@+id/distance_range_3m_gt_68p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_3m_gt_68p"/> - <EditText android:id="@+id/distance_range_5m_gt_68p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_5m_gt_68p"/> - <EditText android:id="@+id/distance_range_10cm_gt_90p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_10cm_gt_90p"/> - <EditText android:id="@+id/distance_range_1m_gt_90p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_1m_gt_90p"/> - <EditText android:id="@+id/distance_range_3m_gt_90p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_3m_gt_90p"/> - <EditText android:id="@+id/distance_range_5m_gt_90p" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_5m_gt_90p"/> - <EditText android:id="@+id/reference_device" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_reference_device"/> - </LinearLayout> - - <include android:layout_width="match_parent" - android:layout_height="wrap_content" - layout="@layout/pass_fail_buttons"/> - </LinearLayout> - </ScrollView> -</RelativeLayout> diff --git a/apps/CtsVerifier/res/layout/uwb_precision.xml b/apps/CtsVerifier/res/layout/uwb_precision.xml deleted file mode 100644 index 14e996d6f5f..00000000000 --- a/apps/CtsVerifier/res/layout/uwb_precision.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2022 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - style="@style/RootLayoutPadding"> - <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - <LinearLayout android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TextView android:text="@string/uwb_precision_instruction" - android:id="@+id/uwb_precision_instruction" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scrollbars="vertical"/> - <LinearLayout android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <EditText android:id="@+id/distance_range_cm" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:inputType="numberDecimal" - android:hint="@string/report_distance_range_cm"/> - <EditText android:id="@+id/reference_device" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_reference_device"/> - </LinearLayout> - - <include android:layout_width="match_parent" - android:layout_height="wrap_content" - layout="@layout/pass_fail_buttons"/> - </LinearLayout> - </ScrollView> -</RelativeLayout> diff --git a/apps/CtsVerifier/res/layout/uwb_short_range.xml b/apps/CtsVerifier/res/layout/uwb_short_range.xml deleted file mode 100644 index 9afc6e5a6b4..00000000000 --- a/apps/CtsVerifier/res/layout/uwb_short_range.xml +++ /dev/null @@ -1,51 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2022 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:orientation="vertical" - style="@style/RootLayoutPadding"> - <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content"> - <LinearLayout android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <TextView android:text="@string/uwb_short_range_instruction" - android:id="@+id/uwb_short_range_instruction" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:scrollbars="vertical"/> - <LinearLayout android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="wrap_content"> - <EditText android:id="@+id/distance_median_meters" - android:layout_width="wrap_content" - android:inputType="numberDecimal" - android:layout_height="wrap_content" - android:hint="@string/report_distance_median_meters"/> - <EditText android:id="@+id/reference_device" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:hint="@string/report_reference_device"/> - </LinearLayout> - - <include android:layout_width="match_parent" - android:layout_height="wrap_content" - layout="@layout/pass_fail_buttons"/> - </LinearLayout> - </ScrollView> -</RelativeLayout> diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml index 4862965ba9d..0f32b34e78e 100644 --- a/apps/CtsVerifier/res/values/strings.xml +++ b/apps/CtsVerifier/res/values/strings.xml @@ -32,6 +32,16 @@ <string name="finish_button_text">Finish</string> <string name="fail_and_next_button_text">Fail and Next</string> + <!-- Strings for CtsReportLog warning --> + <string name="reportlog_warning_title">CTS-Verifier Report Log</string> + <string name="reportlog_warning_body">Can\'t create folder for CTS-Verifier Report Logs. + \n\nPlease enable Report Log creation by exiting CTS Verifier and running the following commands: + \n\n<code>adb shell appops set com.android.cts.verifier android:read_device_identifiers allow</code> + \n\n<code>adb shell appops set com.android.cts.verifier MANAGE_EXTERNAL_STORAGE 0</code> + \n\nTest instructions are found in the \"Using CTS Verifier\" document found at + <a href="https://source.android.com/compatibility/cts/verifier">https://source.android.com/compatibility/cts/verifier</a> + </string> + <!-- Strings for TestListActivity --> <string name="test_category_audio">Audio</string> <string name="test_category_camera">Camera</string> @@ -301,9 +311,11 @@ </string> <string name="clipboard_preview_test_instructions"> Press the \'Copy\' button to copy the secret code to the clipboard. - \n\nUse the clipboard preview UI, or the clipboard editor component to view the secret code. - \n\nEnter the secret code using the buttons below. + \n\n If nothing happens, press Fail. + \n\n If you see the word "FAIL" appear on screen, press Fail. + \n\n If you see a confirmation that content has been copied to the clipboard, press Pass. </string> + <string name="clipboard_preview_test_secret">FAIL</string> <string name="clipboard_preview_test_copy_button">Copy</string> @@ -778,7 +790,7 @@ <!-- BLE Advertising Set test strings --> <string name="ble_advertising_set_test_name">Bluetooth LE Advertising Set Test</string> <string name="ble_advertising_set_test_info">Bluetooth LE Advertising Set tests AdvertisingSet and AdvertisingSetCallback APIs.</string> - <string name="ble_advertising_set_test_instruction">Press the \"Set Up\" button first, then start the test by pressing the \"Start Test\" button. UI thread may freeze for a few seconds while enabling/disabling bluetooth adapter.</string> + <string name="ble_advertising_set_test_instruction">Press the \"Start Test\" button. UI thread may freeze for a few seconds while enabling/disabling bluetooth adapter.</string> <string name="ble_advertising_set_start_test">Start Test</string> <string name="ble_advertising_set_running_test">Running Test...</string> <string name="ble_advertising_set_finished_test">Finished Test</string> @@ -5480,6 +5492,7 @@ You should be prompted to select credentials; choose the ones you just installed <string name="audio_general_test_not_run">Test Not Run</string> <string name="audio_general_testnotcompleted">Test not completed.</string> + <string name="audio_general_reportlogtest">[Can\'t Write ReportLog]</string> <!-- Audio Loopback Latency Test --> <string name="audio_loopback_latency_test">Audio Loopback Latency Test</string> diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java index b013bb7180e..a93e3b58c33 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/CtsVerifierReportLog.java @@ -74,6 +74,10 @@ public class CtsVerifierReportLog extends ReportLog { } } + public boolean isOpen() { + return mStore != null; + } + /** * Closes report file. Static functions that do not have access to instrumentation can * use this to close report logs. Summary, if present, is not reported to instrumentation, hence diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java index 0294ff78e7c..7b993eefc58 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java @@ -32,7 +32,6 @@ import android.database.Cursor; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; -import android.util.Log; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; @@ -146,6 +145,8 @@ public class PassFailButtons { private final CtsVerifierReportLog mReportLog; private final TestResultHistoryCollection mHistoryCollection; + protected boolean mRequireReportLogToPass; + public Activity() { this.mReportLog = new CtsVerifierReportLog(getReportFileName(), getReportSectionName()); this.mHistoryCollection = new TestResultHistoryCollection(); @@ -159,6 +160,10 @@ public class PassFailButtons { .newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "PassFailButtons"); mWakeLock.acquire(); } + + if (!this.mReportLog.isOpen()) { + showReportLogWarningDialog(this); + } } @Override @@ -212,6 +217,14 @@ public class PassFailButtons { } /** + * A mechanism to block tests from passing if no ReportLog data has been collected. + * @return true if the ReportLog is open OR if the test does not require that. + */ + public boolean isReportLogOkToPass() { + return !mRequireReportLogToPass || mReportLog.isOpen(); + } + + /** * @return The name of the file to store the (suite of) ReportLog information. */ @Override @@ -527,6 +540,12 @@ public class PassFailButtons { activity.showDialog(INFO_DIALOG_ID, args); } + protected static void showReportLogWarningDialog(final android.app.Activity activity) { + showInfoDialog(activity, + R.string.reportlog_warning_title, R.string.reportlog_warning_body, -1); + } + + protected static Dialog createDialog(final android.app.Activity activity, int id, Bundle args) { switch (id) { case INFO_DIALOG_ID: diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java index 528d9149588..83b32def714 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java @@ -182,12 +182,15 @@ public class AnalogHeadsetAudioActivity mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass_noheadset)); return true; } else { - boolean pass = mPlugIntentReceived && - mHeadsetDeviceInfo != null && - mPlaybackSuccess && - (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown; + boolean pass = isReportLogOkToPass() + && mPlugIntentReceived + && mHeadsetDeviceInfo != null + && mPlaybackSuccess + && (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown; if (pass) { mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass)); + } else if (!isReportLogOkToPass()) { + mResultsTxt.setText(getResources().getString(R.string.audio_general_reportlogtest)); } return pass; } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java index 48795efc142..3c1b8a1151e 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java @@ -542,8 +542,10 @@ public class AudioAEC extends AudioFrequencyActivity implements View.OnClickList Log.v(TAG, "Test EndedOk. " + testId + " str:"+str); showView(mProgress, false); mResultTest.setText("test completed. " + str); - if (mTestAECPassed) { - getPassButton().setEnabled(true);; + if (!isReportLogOkToPass()) { + mResultTest.setText(getResources().getString(R.string.audio_general_reportlogtest)); + } else if (mTestAECPassed) { + getPassButton().setEnabled(true); } } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java index a6bd4add994..79d3e3b2b0b 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioLoopbackLatencyActivity.java @@ -294,6 +294,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity { getPassButton().setEnabled(false); setInfoResources(R.string.audio_loopback_latency_test, R.string.audio_loopback_info, -1); + mRequireReportLogToPass = true; + mClaimsOutput = AudioSystemFlags.claimsOutput(this); mClaimsInput = AudioSystemFlags.claimsInput(this); mClaimsProAudio = AudioSystemFlags.claimsProAudio(this); @@ -683,7 +685,8 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity { mResultsText[mTestRoute].setText(testSpec.getResultString()); LoopbackLatencyRequirements requirements = new LoopbackLatencyRequirements(); - boolean pass = requirements.evaluate(mClaimsProAudio, + boolean pass = isReportLogOkToPass() + && requirements.evaluate(mClaimsProAudio, Build.VERSION.MEDIA_PERFORMANCE_CLASS, mTestSpecs[TESTROUTE_DEVICE].isMeasurementValid() ? mTestSpecs[TESTROUTE_DEVICE].mMeanLatencyMS : 0.0, @@ -694,8 +697,12 @@ public class AudioLoopbackLatencyActivity extends PassFailButtons.Activity { getPassButton().setEnabled(pass); - String resultText = requirements.getResultsString(); - mTestStatusText.setText(resultText); + StringBuilder sb = new StringBuilder(); + if (!isReportLogOkToPass()) { + sb.append(getResources().getString(R.string.audio_general_reportlogtest) + "\n"); + } + sb.append(requirements.getResultsString()); + mTestStatusText.setText(sb.toString()); showWait(false); enableStartButtons(true); diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java index 215d26fd65b..8ff23588889 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java @@ -154,6 +154,8 @@ public class AudioTap2ToneActivity String yesString = getResources().getString(R.string.audio_general_yes); String noString = getResources().getString(R.string.audio_general_no); + mRequireReportLogToPass = true; + boolean claimsProAudio = AudioSystemFlags.claimsProAudio(this); boolean claimsLowLatencyAudio = AudioSystemFlags.claimsLowLatencyAudio(this); @@ -311,11 +313,14 @@ public class AudioTap2ToneActivity } double averageLatency = mLatencyAve[mActiveTestAPI]; - boolean pass = averageLatency != 0 && averageLatency <= mMaxRequiredLatency; + boolean pass = isReportLogOkToPass() + && averageLatency != 0 && averageLatency <= mMaxRequiredLatency; if (pass) { mSpecView.setText("Average: " + averageLatency + " ms <= " + mMaxRequiredLatency + " ms -- PASS"); + } else if (!isReportLogOkToPass()) { + mSpecView.setText(getResources().getString(R.string.audio_general_reportlogtest)); } else { mSpecView.setText("Average: " + averageLatency + " ms > " + mMaxRequiredLatency + " ms -- FAIL"); diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java index 126d15fdacb..e93d2b319ff 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java @@ -158,11 +158,9 @@ public class ProAudioActivity boolean usbOK = mClaimsUSBHostMode && mClaimsUSBPeripheralMode; boolean hdmiOK = !mClaimsHDMI || isHDMIValid(); - boolean hasPassed = !mClaimsProAudio || - (mClaimsLowLatencyAudio && - mClaimsMIDI && - usbOK && - hdmiOK); + boolean hasPassed = isReportLogOkToPass() + && !mClaimsProAudio + || (mClaimsLowLatencyAudio && mClaimsMIDI && usbOK && hdmiOK); getPassButton().setEnabled(hasPassed); return hasPassed; @@ -172,7 +170,9 @@ public class ProAudioActivity boolean hasPassed = calculatePass(); Resources strings = getResources(); - if (hasPassed) { + if (!isReportLogOkToPass()) { + mTestStatusLbl.setText(getResources().getString(R.string.audio_general_reportlogtest)); + } else if (hasPassed) { mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_pass)); } else if (!mClaimsMIDI) { mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_midinotreported)); diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java index bc23048c28e..6270a5a8311 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralNotificationsTest.java @@ -20,23 +20,17 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; - import android.media.AudioDeviceCallback; import android.media.AudioDeviceInfo; import android.media.AudioManager; - import android.os.Bundle; import android.os.Handler; - import android.util.Log; - import android.widget.TextView; import com.android.compatibility.common.util.CddTest; -import com.android.compatibility.common.util.ReportLog; import com.android.compatibility.common.util.ResultType; import com.android.compatibility.common.util.ResultUnit; - import com.android.cts.verifier.PassFailButtons; import com.android.cts.verifier.R; // needed to access resource in CTSVerifier project namespace. @@ -173,9 +167,10 @@ public class USBAudioPeripheralNotificationsTest extends PassFailButtons.Activit // Test Status // private boolean calculatePass() { - return mUsbHeadsetInReceived && mUsbHeadsetOutReceived && - mUsbDeviceInReceived && mUsbDeviceOutReceived && - mPlugIntentReceived; + return isReportLogOkToPass() + && mUsbHeadsetInReceived && mUsbHeadsetOutReceived + && mUsbDeviceInReceived && mUsbDeviceOutReceived + && mPlugIntentReceived; } // diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java index 07a70c69cb4..164992b94a9 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BleAdvertisingSetTestActivity.java @@ -99,11 +99,6 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity { R.string.ble_advertising_set_test_info, -1); getPassButton().setEnabled(false); - mBluetoothManager = getSystemService(BluetoothManager.class); - mBluetoothAdapter = mBluetoothManager.getAdapter(); - mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); - mCallback = new TestAdvertisingSetCallback(); - mTestAdapter = new TestAdapter(this, setupTestList()); ListView listView = findViewById(R.id.ble_advertising_set_tests); listView.setAdapter(mTestAdapter); @@ -133,9 +128,7 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity { testEnableAndDisableAdvertising(); testSetAdvertisingData(); testSetAdvertisingParameters(); - if (mBluetoothAdapter.isLePeriodicAdvertisingSupported()) { - testPeriodicAdvertising(); - } + testPeriodicAdvertising(); testSetScanResponseData(); stopAdvertisingSet(); } catch (InterruptedException e) { @@ -167,6 +160,11 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity { }); mAllTestsPassed = 0; + + mBluetoothManager = getSystemService(BluetoothManager.class); + mBluetoothAdapter = mBluetoothManager.getAdapter(); + mAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser(); + mCallback = new TestAdvertisingSetCallback(); } private void startAdvertisingSet() throws InterruptedException { @@ -323,11 +321,9 @@ public class BleAdvertisingSetTestActivity extends PassFailButtons.Activity { testList.add(R.string.ble_advertising_set_enable_disable); testList.add(R.string.ble_advertising_set_advertising_data); testList.add(R.string.ble_advertising_set_advertising_params); - if (mBluetoothAdapter.isLePeriodicAdvertisingSupported()) { - testList.add(R.string.ble_advertising_set_periodic_advertising_data); - testList.add(R.string.ble_advertising_set_periodic_advertising_enabled_disabled); - testList.add(R.string.ble_advertising_set_periodic_advertising_params); - } + testList.add(R.string.ble_advertising_set_periodic_advertising_data); + testList.add(R.string.ble_advertising_set_periodic_advertising_enabled_disabled); + testList.add(R.string.ble_advertising_set_periodic_advertising_params); testList.add(R.string.ble_advertising_set_scan_response_data); testList.add(R.string.ble_advertising_set_stop); return testList; diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java index 861c6f68810..212f988d205 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java @@ -1847,6 +1847,8 @@ public class ItsService extends Service implements SensorEventListener { // s1440p which is the max supported stream size in a combination, when preview // stabilization is on. Size maxPreviewSize = new Size(1920, 1440); + // QCIF, we test only sizes >= this. + Size minPreviewSize = new Size(176, 144); Size[] outputSizes = configMap.getOutputSizes(ImageFormat.YUV_420_888); if (outputSizes == null) { mSocketRunnableObj.sendResponse("supportedPreviewSizes", ""); @@ -1857,6 +1859,8 @@ public class ItsService extends Service implements SensorEventListener { .distinct() .filter(s -> s.getWidth() * s.getHeight() <= maxPreviewSize.getWidth() * maxPreviewSize.getHeight()) + .filter(s -> s.getWidth() * s.getHeight() + >= minPreviewSize.getWidth() * minPreviewSize.getHeight()) .sorted(Comparator.comparingInt(s -> s.getWidth() * s.getHeight())) .map(Size::toString) .collect(Collectors.joining(";")); diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java index d83464bd549..692538a81c3 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java @@ -21,9 +21,8 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Configuration; -import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraManager; -import android.os.Build; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.os.Bundle; import android.text.method.ScrollingMovementMethod; import android.util.Log; @@ -31,6 +30,11 @@ import android.view.WindowManager; import android.widget.TextView; import android.widget.Toast; +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileNotFoundException; +import java.io.IOException; + import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; @@ -39,17 +43,11 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.io.BufferedReader; -import java.io.FileReader; -import java.io.FileNotFoundException; -import java.io.IOException; - import com.android.compatibility.common.util.ResultType; import com.android.compatibility.common.util.ResultUnit; import com.android.cts.verifier.ArrayTestListAdapter; @@ -59,6 +57,7 @@ import com.android.cts.verifier.TestResult; import org.json.JSONArray; import org.json.JSONObject; +import org.junit.rules.TestName; /** * Test for Camera features that require that the camera be aimed at a specific test scene. @@ -81,12 +80,6 @@ public class ItsTestActivity extends DialogTestListActivity { Arrays.asList(new String[] {RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED})); private static final int MAX_SUMMARY_LEN = 200; - private static final int MPC12_CAMERA_LAUNCH_THRESHOLD = 600; // ms - private static final int MPC12_JPEG_CAPTURE_THRESHOLD = 1000; // ms - - private static final String MPC_TESTS_REPORT_LOG_NAME = "MediaPerformanceClassLogs"; - private static final String MPC_TESTS_REPORT_LOG_SECTION = "CameraIts"; - private static final Pattern MPC12_CAMERA_LAUNCH_PATTERN = Pattern.compile("camera_launch_time_ms:(\\d+(\\.\\d+)?)"); private static final Pattern MPC12_JPEG_CAPTURE_PATTERN = @@ -95,8 +88,12 @@ public class ItsTestActivity extends DialogTestListActivity { private final ResultReceiver mResultsReceiver = new ResultReceiver(); private boolean mReceiverRegistered = false; + public final TestName mTestName = new TestName(); + // Initialized in onCreate List<String> mToBeTestedCameraIds = null; + String mPrimaryRearCameraId = null; + String mPrimaryFrontCameraId = null; // Scenes private static final ArrayList<String> mSceneIds = new ArrayList<String> () {{ @@ -132,8 +129,15 @@ public class ItsTestActivity extends DialogTestListActivity { private final HashMap<ResultKey, String> mSummaryMap = new HashMap<>(); // All primary cameras for which MPC level test has run private Set<ResultKey> mExecutedMpcTests = null; - // Map primary camera id to MPC level - private final HashMap<String, Integer> mMpcLevelMap = new HashMap<>(); + private static final String MPC_LAUNCH_REQ_NUM = "2.2.7.2/7.5/H-1-6"; + private static final String MPC_JPEG_CAPTURE_REQ_NUM = "2.2.7.2/7.5/H-1-5"; + // Performance class evaluator used for writing test result + PerformanceClassEvaluator mPce = new PerformanceClassEvaluator(mTestName); + PerformanceClassEvaluator.CameraLatencyRequirement mJpegLatencyReq = + mPce.addR7_5__H_1_5(); + PerformanceClassEvaluator.CameraLatencyRequirement mLaunchLatencyReq = + mPce.addR7_5__H_1_6(); + final class ResultKey { public final String cameraId; @@ -266,10 +270,7 @@ public class ItsTestActivity extends DialogTestListActivity { JSONArray metrics = sceneResult.getJSONArray("mpc_metrics"); for (int i = 0; i < metrics.length(); i++) { String mpcResult = metrics.getString(i); - if (!matchMpcResult(cameraId, mpcResult, MPC12_CAMERA_LAUNCH_PATTERN, - "2.2.7.2/7.5/H-1-6", MPC12_CAMERA_LAUNCH_THRESHOLD) && - !matchMpcResult(cameraId, mpcResult, MPC12_JPEG_CAPTURE_PATTERN, - "2.2.7.2/7.5/H-1-5", MPC12_JPEG_CAPTURE_THRESHOLD)) { + if (!matchMpcResult(cameraId, mpcResult)) { Log.e(TAG, "Error parsing MPC result string:" + mpcResult); return; } @@ -294,17 +295,6 @@ public class ItsTestActivity extends DialogTestListActivity { summary.toString(), 1.0, ResultType.NEUTRAL, ResultUnit.NONE); } - // Save MPC info once both front primary and rear primary data are collected. - if (mExecutedMpcTests.size() == 4) { - ItsTestActivity.this.getReportLog().addValue( - "Version", "0.0.1", ResultType.NEUTRAL, ResultUnit.NONE); - for (Map.Entry<String, Integer> entry : mMpcLevelMap.entrySet()) { - ItsTestActivity.this.getReportLog().addValue(entry.getKey(), - entry.getValue(), ResultType.NEUTRAL, ResultUnit.NONE); - } - ItsTestActivity.this.getReportLog().submit(); - } - // Display current progress StringBuilder progress = new StringBuilder(); for (ResultKey k : mAllScenes) { @@ -367,28 +357,44 @@ public class ItsTestActivity extends DialogTestListActivity { } } - private boolean matchMpcResult(String cameraId, String mpcResult, Pattern pattern, - String reqNum, float threshold) { - Matcher matcher = pattern.matcher(mpcResult); - boolean match = matcher.matches(); - final int LATEST_MPC_LEVEL = Build.VERSION_CODES.TIRAMISU; + private boolean matchMpcResult(String cameraId, String mpcResult) { + Matcher launchMatcher = MPC12_CAMERA_LAUNCH_PATTERN.matcher(mpcResult); + boolean launchMatches = launchMatcher.matches(); - if (match) { - // Store test result - ItsTestActivity.this.getReportLog().addValue("Cam" + cameraId, - mpcResult, ResultType.NEUTRAL, ResultUnit.NONE); + Matcher jpegMatcher = MPC12_JPEG_CAPTURE_PATTERN.matcher(mpcResult); + boolean jpegMatches = jpegMatcher.matches(); - float latency = Float.parseFloat(matcher.group(1)); - int mpcLevel = latency < threshold ? LATEST_MPC_LEVEL : 0; - mExecutedMpcTests.add(new ResultKey(cameraId, reqNum)); + if (!launchMatches && !jpegMatches) { + return false; + } + if (!cameraId.equals(mPrimaryRearCameraId) && + !cameraId.equals(mPrimaryFrontCameraId)) { + return false; + } - if (mMpcLevelMap.containsKey(reqNum)) { - mpcLevel = Math.min(mpcLevel, mMpcLevelMap.get(reqNum)); + if (launchMatches) { + float latency = Float.parseFloat(launchMatcher.group(1)); + if (cameraId.equals(mPrimaryRearCameraId)) { + mLaunchLatencyReq.setRearCameraLatency(latency); + } else { + mLaunchLatencyReq.setFrontCameraLatency(latency); + } + mExecutedMpcTests.add(new ResultKey(cameraId, MPC_LAUNCH_REQ_NUM)); + } else { + float latency = Float.parseFloat(jpegMatcher.group(1)); + if (cameraId.equals(mPrimaryRearCameraId)) { + mJpegLatencyReq.setRearCameraLatency(latency); + } else { + mJpegLatencyReq.setFrontCameraLatency(latency); } - mMpcLevelMap.put(reqNum, mpcLevel); + mExecutedMpcTests.add(new ResultKey(cameraId, MPC_JPEG_CAPTURE_REQ_NUM)); } - return match; + // Save MPC info once both front primary and rear primary data are collected. + if (mExecutedMpcTests.size() == 4) { + mPce.submit(); + } + return true; } } @@ -397,8 +403,11 @@ public class ItsTestActivity extends DialogTestListActivity { // Hide the test if all camera devices are legacy CameraManager manager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE); try { - ItsUtils.ItsCameraIdList cameraIdList = ItsUtils.getItsCompatibleCameraIds(manager); + ItsUtils.ItsCameraIdList cameraIdList = + ItsUtils.getItsCompatibleCameraIds(manager); mToBeTestedCameraIds = cameraIdList.mCameraIdCombos; + mPrimaryRearCameraId = cameraIdList.mPrimaryRearCameraId; + mPrimaryFrontCameraId = cameraIdList.mPrimaryFrontCameraId; } catch (ItsException e) { Toast.makeText(ItsTestActivity.this, "Received error from camera service while checking device capabilities: " @@ -499,14 +508,4 @@ public class ItsTestActivity extends DialogTestListActivity { setInfoResources(R.string.camera_its_test, R.string.camera_its_test_info, -1); setPassFailButtonClickListeners(); } - - @Override - public String getReportFileName() { - return MPC_TESTS_REPORT_LOG_NAME; - } - - @Override - public String getReportSectionName() { - return MPC_TESTS_REPORT_LOG_SECTION; - } } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java index c648e8e18d9..734b4a2a780 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsUtils.java @@ -16,28 +16,24 @@ package com.android.cts.verifier.camera.its; -import android.content.Context; import android.graphics.ImageFormat; import android.graphics.Rect; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CameraMetadata; import android.hardware.camera2.CaptureRequest; -import android.hardware.camera2.CaptureResult; import android.hardware.camera2.params.MeteringRectangle; import android.hardware.camera2.params.StreamConfigurationMap; import android.media.Image; import android.media.Image.Plane; -import android.net.Uri; -import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; import android.util.Log; import android.util.Size; import com.android.ex.camera2.blocking.BlockingCameraManager; -import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException; import com.android.ex.camera2.blocking.BlockingStateCallback; import org.json.JSONArray; @@ -322,6 +318,9 @@ public class ItsUtils { // Camera Id combos (ids from CameraIdList, and hidden physical camera Ids // in the form of [logical camera id]:[hidden physical camera id] public List<String> mCameraIdCombos; + // Primary rear and front camera Ids (as defined in MPC) + public String mPrimaryRearCameraId; + public String mPrimaryFrontCameraId; } public static ItsCameraIdList getItsCompatibleCameraIds(CameraManager manager) @@ -345,6 +344,18 @@ public class ItsUtils { CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE; final int LOGICAL_MULTI_CAMERA = CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA; + + final Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING); + if (facing != null) { + if (facing == CameraMetadata.LENS_FACING_BACK + && outList.mPrimaryRearCameraId == null) { + outList.mPrimaryRearCameraId = id; + } else if (facing == CameraMetadata.LENS_FACING_FRONT + && outList.mPrimaryFrontCameraId == null) { + outList.mPrimaryFrontCameraId = id; + } + } + for (int capability : actualCapabilities) { if (capability == BACKWARD_COMPAT) { haveBC = true; diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java index 3587e6f9b8c..63b8904fa03 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/ClipboardPreviewTestActivity.java @@ -18,49 +18,22 @@ package com.android.cts.verifier.clipboard; import android.content.ClipData; +import android.content.ClipDescription; import android.content.ClipboardManager; -import android.graphics.Color; import android.os.Bundle; +import android.os.PersistableBundle; import android.view.View; import android.widget.Button; import com.android.cts.verifier.PassFailButtons; import com.android.cts.verifier.R; -import java.util.concurrent.ThreadLocalRandom; - /** - * A CTS Verifier test case for validating the user-visible clipboard preview. - * - * This test assumes bluetooth is turned on and the device is already paired with a second device. - * Note: the second device need not be an Android device; it could be a laptop or desktop. + * A CTS Verifier test case for validating the user-visible clipboard confirmation. */ public class ClipboardPreviewTestActivity extends PassFailButtons.Activity { - /** - * The content of the test file being transferred. - */ - private static final String TEST_STRING = "Sample Test String"; - /** - * The name of the test file being transferred. - */ - private final int[] mSecretCode = new int[4]; - private final int[] mSecretGuess = new int[4]; - private final int[] mButtons = { - R.id.clipboard_preview_test_b0, - R.id.clipboard_preview_test_b1, - R.id.clipboard_preview_test_b2, - R.id.clipboard_preview_test_b3, - R.id.clipboard_preview_test_b4, - R.id.clipboard_preview_test_b5, - R.id.clipboard_preview_test_b6, - R.id.clipboard_preview_test_b7, - R.id.clipboard_preview_test_b8, - R.id.clipboard_preview_test_b9 - }; - private int mGuessIndex = 0; - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -74,87 +47,29 @@ public class ClipboardPreviewTestActivity extends PassFailButtons.Activity { copyButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - generateAndCopySecret(); + setClipboardData(); } }); - disableKeypad(); + disablePassFail(); } - private void generateAndCopySecret() { - String s = ""; - resetState(); - for (int i = 0; i < mSecretCode.length; ++i) { - mSecretCode[i] = ThreadLocalRandom.current().nextInt(0, 10); - s += mSecretCode[i]; - } + private void setClipboardData() { ClipboardManager cm = this.getSystemService(ClipboardManager.class); - cm.setPrimaryClip(ClipData.newPlainText("Secret", s)); - enableKeypad(); - } - private void enableKeypad() { - for (int i = 0; i < mButtons.length; ++i) { - Button numButton = findViewById(mButtons[i]); - numButton.setBackgroundColor(Color.GREEN); - int finalI = i; - numButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - buttonClicked(finalI); - } - }); - } + ClipData cd = ClipData.newPlainText("", + getString(R.string.clipboard_preview_test_secret)); + PersistableBundle pb = new PersistableBundle(1); + pb.putBoolean(ClipDescription.EXTRA_IS_SENSITIVE, true); + cd.getDescription().setExtras(pb); + cm.setPrimaryClip(cd); + enablePassFail(); } - private void disableKeypad() { - for (int i = 0; i < mButtons.length; ++i) { - Button numButton = findViewById(mButtons[i]); - numButton.setOnClickListener(null); - numButton.setBackgroundColor(Color.LTGRAY); - } - } - - private void resetState() { - for (int i = 0; i < mSecretGuess.length; ++i) { - mSecretGuess[i] = -1; - } - mGuessIndex = 0; - View v = findViewById(R.id.clipboard_preview_test_pass_fail); + private void disablePassFail() { findViewById(R.id.clipboard_preview_test_pass_fail).setVisibility(View.INVISIBLE); - findViewById(R.id.fail_button).setVisibility(View.VISIBLE); - findViewById(R.id.pass_button).setVisibility(View.VISIBLE); - } - - private void buttonClicked(int i) { - if (mGuessIndex < mSecretGuess.length) { - mSecretGuess[mGuessIndex] = i; - ++mGuessIndex; - } - checkSolution(); - } - - private void checkSolution() { - boolean testPassed = true; - if (mGuessIndex == mSecretGuess.length) { - for (int i = 0; i < mSecretGuess.length && i < mSecretCode.length; ++i) { - if (mSecretGuess[i] != mSecretCode[i]) { - testPassed = false; - } - } - markPassed(testPassed); - disableKeypad(); - } } - private void markPassed(boolean passed) { + private void enablePassFail() { findViewById(R.id.clipboard_preview_test_pass_fail).setVisibility(View.VISIBLE); - if (passed) { - findViewById(R.id.fail_button).setVisibility(View.INVISIBLE); - } else { - findViewById(R.id.pass_button).setVisibility(View.INVISIBLE); - } - } - - } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java index b8b96023cb7..97ec07acf78 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/CompanionDeviceServiceTestActivity.java @@ -118,7 +118,7 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity /** Stop observing to associated device and then disassociate. */ private void disassociate(AssociationInfo association) { - String deviceAddress = association.getDeviceMacAddressAsString(); + String deviceAddress = association.getDeviceMacAddress().toString(); mCompanionDeviceManager.stopObservingDevicePresence(deviceAddress); mCompanionDeviceManager.disassociate(association.getId()); Log.d(LOG_TAG, "Disassociated with device: " + deviceAddress); @@ -142,11 +142,14 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity AssociationInfo association = data.getParcelableExtra(CompanionDeviceManager.EXTRA_ASSOCIATION, AssociationInfo.class); - String deviceAddress = association.getDeviceMacAddressAsString(); // This test is for bluetooth devices, which should all have a MAC address. - if (deviceAddress == null) fail("The device was present but its address was null."); + if (association == null || association.getDeviceMacAddress() == null) { + fail("The device was present but its address was null."); + return; + } + String deviceAddress = association.getDeviceMacAddress().toString(); mCompanionDeviceManager.startObservingDevicePresence(deviceAddress); mCurrentAssociation = getAssociation(association.getId()); Log.d(LOG_TAG, "Associated with device: " + deviceAddress); @@ -285,7 +288,9 @@ public class CompanionDeviceServiceTestActivity extends PassFailButtons.Activity @Override boolean verify() { // Check that it is associated and being observed. - return mCurrentAssociation != null && mCurrentAssociation.isNotifyOnDeviceNearby(); + // Bypass inaccessible AssociationInfo#isNotifyOnDeviceNearby() with toString() + return mCurrentAssociation != null + && mCurrentAssociation.toString().contains("mNotifyOnDeviceNearby=true"); } } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java b/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java index 37760d54440..11829c3d4b7 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/companion/DevicePresenceListener.java @@ -45,7 +45,7 @@ public class DevicePresenceListener extends CompanionDeviceService { @Override public void onDeviceAppeared(AssociationInfo association) { NEARBY_DEVICES.add(association.getId()); - String message = "Device appeared: " + association.getDeviceMacAddressAsString(); + String message = "Device appeared: " + association.getDeviceMacAddress(); Log.d(LOG_TAG, message); Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } @@ -53,7 +53,7 @@ public class DevicePresenceListener extends CompanionDeviceService { @Override public void onDeviceDisappeared(AssociationInfo association) { NEARBY_DEVICES.remove(association.getId()); - String message = "Device disappeared: " + association.getDeviceMacAddressAsString(); + String message = "Device disappeared: " + association.getDeviceMacAddress(); Log.d(LOG_TAG, message); Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java deleted file mode 100644 index 1548910093a..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRssiPrecisionActivity.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.verifier.presence; - -import android.app.AlertDialog; -import android.bluetooth.BluetoothAdapter; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.Editable; -import android.util.Log; -import android.widget.EditText; - -import com.android.compatibility.common.util.ResultType; -import com.android.compatibility.common.util.ResultUnit; -import com.android.cts.verifier.PassFailButtons; -import com.android.cts.verifier.R; - -/** Tests the precision of the device's RSSI measurement wtfdelet */ -public class BleRssiPrecisionActivity extends PassFailButtons.Activity { - private static final String TAG = BleRssiPrecisionActivity.class.getName(); - - // Report log schema - private static final String KEY_RSSI_RANGE_DBM = "rssi_range_dbm"; - private static final String KEY_REFERENCE_DEVICE = "reference_device"; - - // Thresholds - private static final int MAX_RSSI_RANGE_DBM = 18; - - private EditText reportRssiRangeEditText; - private EditText reportReferenceDeviceEditText; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.ble_rssi_precision); - setPassFailButtonClickListeners(); - getPassButton().setEnabled(false); - - reportRssiRangeEditText = findViewById(R.id.report_rssi_range); - reportReferenceDeviceEditText = findViewById(R.id.report_reference_device); - - DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(), - PackageManager.FEATURE_BLUETOOTH_LE); - - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - - if (!adapter.isEnabled()) { - new AlertDialog.Builder(this) - .setTitle(R.string.ble_bluetooth_disable_title) - .setMessage(R.string.ble_bluetooth_disable_message) - .setOnCancelListener(dialog -> finish()) - .create().show(); - } - - reportRssiRangeEditText.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - reportReferenceDeviceEditText.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - } - - private void checkTestInputs() { - getPassButton().setEnabled(checkDistanceRangeInput() && checkReferenceDeviceInput()); - } - - private boolean checkDistanceRangeInput() { - String rssiRangeInput = reportRssiRangeEditText.getText().toString(); - - if (!rssiRangeInput.isEmpty()) { - int rssiRange = Integer.parseInt(rssiRangeInput); - // RSSI range must be inputted and within acceptable range before test can be passed - return rssiRange <= MAX_RSSI_RANGE_DBM; - } - return false; - } - - private boolean checkReferenceDeviceInput() { - // Reference device must be inputted before test can be passed - return !reportReferenceDeviceEditText.getText().toString().isEmpty(); - } - - @Override - public void recordTestResults() { - String rssiRange = reportRssiRangeEditText.getText().toString(); - String referenceDevice = reportReferenceDeviceEditText.getText().toString(); - - if (!rssiRange.isEmpty()) { - Log.i(TAG, "BLE RSSI Range (dBm): " + rssiRange); - getReportLog().addValue(KEY_RSSI_RANGE_DBM, Integer.parseInt(rssiRange), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!referenceDevice.isEmpty()) { - Log.i(TAG, "BLE Reference Device: " + referenceDevice); - getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice, - ResultType.NEUTRAL, ResultUnit.NONE); - } - getReportLog().submit(); - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java deleted file mode 100644 index 2de7edffe7c..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/BleRxTxCalibrationActivity.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.verifier.presence; - -import android.app.AlertDialog; -import android.bluetooth.BluetoothAdapter; -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.Editable; -import android.util.Log; -import android.widget.EditText; - -import com.android.compatibility.common.util.ResultType; -import com.android.compatibility.common.util.ResultUnit; -import com.android.cts.verifier.PassFailButtons; -import com.android.cts.verifier.R; - -/** - * Tests that the device's Rx/Tx calibration results in a median range (cm) within the specified - * bounds - */ -public class BleRxTxCalibrationActivity extends PassFailButtons.Activity { - private static final String TAG = BleRxTxCalibrationActivity.class.getName(); - - // Report log schema - private static final String KEY_CHANNEL_RSSI_RANGE = "channel_rssi_range"; - private static final String KEY_CORE_RSSI_RANGE = "core_rssi_range"; - private static final String KEY_REFERENCE_DEVICE = "reference_device"; - - // Thresholds - private static final int MAX_RSSI_RANGE = 6; - - private EditText reportChannelsRssiRangeEditText; - private EditText reportCoresRssiRangeEditText; - private EditText reportReferenceDeviceEditText; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.ble_rx_tx_calibration); - setPassFailButtonClickListeners(); - getPassButton().setEnabled(false); - - reportChannelsRssiRangeEditText = findViewById(R.id.report_channels_rssi_range); - reportCoresRssiRangeEditText = findViewById(R.id.report_cores_rssi_range); - reportReferenceDeviceEditText = findViewById(R.id.report_reference_device); - - DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(), - PackageManager.FEATURE_BLUETOOTH_LE); - - BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); - - if (!adapter.isEnabled()) { - new AlertDialog.Builder(this) - .setTitle(R.string.ble_bluetooth_disable_title) - .setMessage(R.string.ble_bluetooth_disable_message) - .setOnCancelListener(dialog -> finish()) - .create().show(); - } - - reportChannelsRssiRangeEditText.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - reportCoresRssiRangeEditText.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - reportReferenceDeviceEditText.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - } - - private void checkTestInputs() { - getPassButton().setEnabled( - checkChannelRssiInput() && checkCoreRssiInput() && checkReferenceDeviceInput()); - } - - private boolean checkChannelRssiInput() { - String channelsRssiRangeInput = reportChannelsRssiRangeEditText.getText().toString(); - if (!channelsRssiRangeInput.isEmpty()) { - int channelsRssiRange = Integer.parseInt(channelsRssiRangeInput); - // RSSI range must be inputted and within acceptable range before test can be passed - return channelsRssiRange <= MAX_RSSI_RANGE; - } - return false; - } - - private boolean checkCoreRssiInput() { - String coresRssiRangeInput = reportCoresRssiRangeEditText.getText().toString(); - if (!coresRssiRangeInput.isEmpty()) { - int coresRssiRange = Integer.parseInt(coresRssiRangeInput); - // RSSI range must be inputted and within acceptable range before test can be passed - return coresRssiRange <= MAX_RSSI_RANGE; - } - // This field is optional, so return true even if the user has not inputted anything - return true; - } - - private boolean checkReferenceDeviceInput() { - // Reference device must be inputted before test can be passed - return !reportReferenceDeviceEditText.getText().toString().isEmpty(); - } - - @Override - public void recordTestResults() { - String channelRssiRange = reportChannelsRssiRangeEditText.getText().toString(); - String coreRssiRange = reportCoresRssiRangeEditText.getText().toString(); - String referenceDevice = reportReferenceDeviceEditText.getText().toString(); - - if (!channelRssiRange.isEmpty()) { - Log.i(TAG, "BLE RSSI Range Across Channels (dBm): " + channelRssiRange); - getReportLog().addValue(KEY_CHANNEL_RSSI_RANGE, Integer.parseInt(channelRssiRange), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!coreRssiRange.isEmpty()) { - Log.i(TAG, "BLE RSSI Range Across Cores (dBm): " + coreRssiRange); - getReportLog().addValue(KEY_CORE_RSSI_RANGE, Integer.parseInt(coreRssiRange), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!referenceDevice.isEmpty()) { - Log.i(TAG, "BLE Reference Device: " + referenceDevice); - getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice, - ResultType.NEUTRAL, ResultUnit.NONE); - } - - getReportLog().submit(); - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java deleted file mode 100644 index 256fe3a078d..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/DeviceFeatureChecker.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.verifier.presence; -import android.app.Activity; -import android.content.Context; -import android.util.Log; -import android.view.View; -import android.widget.Toast; - -/** - * Checks if a device supports a hardware feature needed for a test, and passes the test - * automatically otherwise. - */ -public class DeviceFeatureChecker { - - /** Checks if a feature is supported. - * - * @param feature must be a string defined in PackageManager - */ - public static void checkFeatureSupported(Context context, View passButton, String feature) { - if (!context.getPackageManager().hasSystemFeature(feature)) { - String message = String.format("Device does not support %s, automatically passing test", - feature); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); - Log.e(context.getClass().getName(), message); - passButton.performClick(); - Activity activity = (Activity) (context); - activity.finish(); - } - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java deleted file mode 100644 index 2de68a5a78e..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/InputTextHandler.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.android.cts.verifier.presence; - -import android.text.Editable; -import android.text.TextWatcher; - -/** - * Handles editable text inputted into test activities. - */ -public class InputTextHandler { - - /** Callback that is executed when text is changed. Takes modified text as input. */ - public interface OnTextChanged { - void run(Editable s); - } - - /** - * Generic text changed handler that will execute the provided callback when text is modified. - * - * @param callback called when text is changed, and passed the modified text - */ - public static TextWatcher getOnTextChangedHandler(OnTextChanged callback) { - return new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) {} - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) {} - - @Override - public void afterTextChanged(Editable s) { - callback.run(s); - } - }; - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java deleted file mode 100644 index 458d1920eca..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/NanPrecisionTestActivity.java +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.verifier.presence; - -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.Editable; -import android.util.Log; -import android.widget.EditText; - -import com.android.compatibility.common.util.ResultType; -import com.android.compatibility.common.util.ResultUnit; -import com.android.cts.verifier.PassFailButtons; -import com.android.cts.verifier.R; - -import com.google.common.collect.ImmutableMap; - -import java.util.Arrays; -import java.util.List; - -/** - * Activity for testing that NAN measurements are within the acceptable ranges - */ -public class NanPrecisionTestActivity extends PassFailButtons.Activity { - private static final String TAG = NanPrecisionTestActivity.class.getName(); - - // Report log schema - private static final String KEY_BANDWIDTH = "nan_bandwidth"; - private static final String KEY_MEASUREMENT_RANGE_10CM_AT_68P = "measurement_range_10cm_68p"; - private static final String KEY_MEASUREMENT_RANGE_1M_AT_68P = "measurement_range_1m_68p"; - private static final String KEY_MEASUREMENT_RANGE_3M_AT_68p = "measurement_range_3m_68p"; - private static final String KEY_MEASUREMENT_RANGE_5M_AT_68p = "measurement_range_5m_68p"; - private static final String KEY_MEASUREMENT_RANGE_10CM_AT_90P = "measurement_range_10cm_90p"; - private static final String KEY_MEASUREMENT_RANGE_1M_AT_90P = "measurement_range_1m_90p"; - private static final String KEY_MEASUREMENT_RANGE_3M_AT_90p = "measurement_range_3m_90p"; - private static final String KEY_MEASUREMENT_RANGE_5M_AT_90p = "measurement_range_5m_90p"; - private static final String KEY_REFERENCE_DEVICE = "reference_device"; - - // Thresholds - private static final int MAX_DISTANCE_RANGE_METERS_160MHZ = 2; - private static final int MAX_DISTANCE_RANGE_METERS_80MHZ = 4; - private static final int MAX_DISTANCE_RANGE_METERS_40MHZ = 8; - private static final int MAX_DISTANCE_RANGE_METERS_20MHZ = 16; - - // Maps NAN bandwidths to acceptable range thresholds - private static final ImmutableMap<Integer, Integer> BANDWIDTH_TO_THRESHOLD_MAP = - ImmutableMap.of(160, MAX_DISTANCE_RANGE_METERS_160MHZ, 80, - MAX_DISTANCE_RANGE_METERS_80MHZ, 40, MAX_DISTANCE_RANGE_METERS_40MHZ, 20, - MAX_DISTANCE_RANGE_METERS_20MHZ); - - private EditText mBandwidthMhz; - private EditText mMeasurementRange10cmGt68p; - private EditText mMeasurementRange1mGt68p; - private EditText mMeasurementRange3mGt68p; - private EditText mMeasurementRange5mGt68p; - private EditText mMeasurementRange10cmGt90p; - private EditText mMeasurementRange1mGt90p; - private EditText mMeasurementRange3mGt90p; - private EditText mMeasurementRange5mGt90p; - private EditText mReferenceDeviceInput; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.nan_precision); - setPassFailButtonClickListeners(); - getPassButton().setEnabled(false); - - mBandwidthMhz = (EditText) findViewById(R.id.nan_bandwidth); - mMeasurementRange10cmGt68p = (EditText) findViewById(R.id.distance_range_10cm_gt_68p); - mMeasurementRange1mGt68p = (EditText) findViewById(R.id.distance_range_1m_gt_68p); - mMeasurementRange3mGt68p = (EditText) findViewById(R.id.distance_range_3m_gt_68p); - mMeasurementRange5mGt68p = (EditText) findViewById(R.id.distance_range_5m_gt_68p); - mMeasurementRange10cmGt90p = (EditText) findViewById(R.id.distance_range_10cm_gt_90p); - mMeasurementRange1mGt90p = (EditText) findViewById(R.id.distance_range_1m_gt_90p); - mMeasurementRange3mGt90p = (EditText) findViewById(R.id.distance_range_3m_gt_90p); - mMeasurementRange5mGt90p = (EditText) findViewById(R.id.distance_range_5m_gt_90p); - mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device); - - DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(), - PackageManager.FEATURE_WIFI_AWARE); - - mBandwidthMhz.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange10cmGt68p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange1mGt68p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange3mGt68p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange5mGt68p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange10cmGt90p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange1mGt90p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange3mGt90p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mMeasurementRange5mGt90p.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mReferenceDeviceInput.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - } - - private void checkTestInputs() { - getPassButton().setEnabled(checkMeasurementRange68thPercentileInput() - && checkMeasurementRange90thPercentileInput() - && checkReferenceDeviceInput()); - } - - private boolean checkMeasurementRange68thPercentileInput() { - return checkRequiredMeasurementRangeInput(mMeasurementRange10cmGt68p, - mMeasurementRange1mGt68p, mMeasurementRange3mGt68p, mMeasurementRange5mGt68p); - } - - private boolean checkMeasurementRange90thPercentileInput() { - String measurementRangeInput10cmGt90p = mMeasurementRange10cmGt90p.getText().toString(); - String measurementRangeInput1mGt90p = mMeasurementRange1mGt90p.getText().toString(); - String measurementRangeInput3mGt90p = mMeasurementRange3mGt90p.getText().toString(); - String measurementRangeInput5mGt90p = mMeasurementRange5mGt90p.getText().toString(); - List<String> optionalMeasurementRangeList = Arrays.asList(measurementRangeInput10cmGt90p, - measurementRangeInput1mGt90p, - measurementRangeInput3mGt90p, measurementRangeInput5mGt90p); - - boolean inputted = false; - for (String input : optionalMeasurementRangeList) { - if (!input.isEmpty()) { - inputted = true; - break; - } - } - // If one of the ranges is inputted for one of the distances, then it becomes required - // that the ranges are inputted for all the distances and for tests to pass, must be - // acceptable values - return !inputted || checkRequiredMeasurementRangeInput(mMeasurementRange10cmGt90p, - mMeasurementRange1mGt90p, mMeasurementRange3mGt90p, mMeasurementRange5mGt90p); - } - - private boolean checkRequiredMeasurementRangeInput(EditText rangeInput10cm, - EditText rangeInput1m, EditText rangeInput3m, EditText rangeInput5m) { - String bandwidthInputMhz = mBandwidthMhz.getText().toString(); - String measurementRangeInput10cmGt = rangeInput10cm.getText().toString(); - String measurementRangeInput1mGt = rangeInput1m.getText().toString(); - String measurementRangeInput3mGt = rangeInput3m.getText().toString(); - String measurementRangeInput5mGt = rangeInput5m.getText().toString(); - List<String> requiredMeasurementRangeList = Arrays.asList(measurementRangeInput10cmGt, - measurementRangeInput1mGt, - measurementRangeInput3mGt, measurementRangeInput5mGt); - - for (String input : requiredMeasurementRangeList) { - if (bandwidthInputMhz.isEmpty() || input.isEmpty()) { - // Distance range must be inputted for all fields so fail early otherwise - return false; - } - if (!BANDWIDTH_TO_THRESHOLD_MAP.containsKey(Integer.parseInt(bandwidthInputMhz))) { - // bandwidth must be one of the expected thresholds - return false; - } - double distanceRange = Double.parseDouble(input); - int bandwidth = Integer.parseInt(bandwidthInputMhz); - if (distanceRange > BANDWIDTH_TO_THRESHOLD_MAP.get(bandwidth)) { - // All inputs must be in acceptable range so fail early otherwise - return false; - } - } - return true; - } - - private boolean checkReferenceDeviceInput() { - // Reference device used must be inputted before test can be passed. - return !mReferenceDeviceInput.getText().toString().isEmpty(); - } - - @Override - public void recordTestResults() { - String nanBandwidthMhz = mBandwidthMhz.getText().toString(); - String measurementRange10cmGt68p = mMeasurementRange10cmGt68p.getText().toString(); - String measurementRange1mGt68p = mMeasurementRange1mGt68p.getText().toString(); - String measurementRange3mGt68p = mMeasurementRange3mGt68p.getText().toString(); - String measurementRange5mGt68p = mMeasurementRange5mGt68p.getText().toString(); - String measurementRange10cmGt90p = mMeasurementRange10cmGt90p.getText().toString(); - String measurementRange1mGt90p = mMeasurementRange1mGt90p.getText().toString(); - String measurementRange3mGt90p = mMeasurementRange3mGt90p.getText().toString(); - String measurementRange5mGt90p = mMeasurementRange5mGt90p.getText().toString(); - String referenceDevice = mReferenceDeviceInput.getText().toString(); - - if (!nanBandwidthMhz.isEmpty()) { - Log.i(TAG, "NAN Bandwidth at which data was collected: " + nanBandwidthMhz); - getReportLog().addValue(KEY_BANDWIDTH, - Integer.parseInt(nanBandwidthMhz), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange10cmGt68p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 10cm: " + measurementRange10cmGt68p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_10CM_AT_68P, - Double.parseDouble(measurementRange10cmGt68p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange1mGt68p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 1m: " + measurementRange1mGt68p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_1M_AT_68P, - Double.parseDouble(measurementRange1mGt68p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange3mGt68p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 3m: " + measurementRange3mGt68p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_3M_AT_68p, - Double.parseDouble(measurementRange3mGt68p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange5mGt68p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 5m: " + measurementRange5mGt68p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_5M_AT_68p, - Double.parseDouble(measurementRange5mGt68p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange10cmGt90p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 10cm: " + measurementRange10cmGt68p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_10CM_AT_90P, - Double.parseDouble(measurementRange10cmGt90p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange1mGt90p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 1m: " + measurementRange1mGt90p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_1M_AT_90P, - Double.parseDouble(measurementRange1mGt90p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange3mGt90p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 3m: " + measurementRange3mGt90p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_3M_AT_90p, - Double.parseDouble(measurementRange3mGt90p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!measurementRange5mGt90p.isEmpty()) { - Log.i(TAG, "NAN Measurement Range at 5m: " + measurementRange5mGt90p); - getReportLog().addValue(KEY_MEASUREMENT_RANGE_5M_AT_90p, - Double.parseDouble(measurementRange5mGt90p), - ResultType.NEUTRAL, ResultUnit.NONE); - } - - if (!referenceDevice.isEmpty()) { - Log.i(TAG, "NAN Reference Device: " + referenceDevice); - getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice, - ResultType.NEUTRAL, ResultUnit.NONE); - } - getReportLog().submit(); - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS deleted file mode 100644 index e8744995b6c..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/OWNERS +++ /dev/null @@ -1,4 +0,0 @@ -# Bug component: 1106357 -asalo@google.com -jbabs@google.com -christinatao@google.com
\ No newline at end of file diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java deleted file mode 100644 index 67766931591..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/PresenceTestActivity.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.cts.verifier.presence; - -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Bundle; -import android.os.SystemProperties; - -import com.android.cts.verifier.ManifestTestListAdapter; -import com.android.cts.verifier.PassFailButtons; -import com.android.cts.verifier.R; - -import java.util.ArrayList; -import java.util.List; - -public class PresenceTestActivity extends PassFailButtons.TestListActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.pass_fail_list); - setPassFailButtonClickListeners(); - - List<String> disabledTest = new ArrayList<String>(); - boolean isTv = getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); - if (isTv) { - setInfoResources(R.string.presence_test, R.string.presence_test_tv_info, -1); - int firstSdk = SystemProperties.getInt("ro.product.first_api_level", 0); - if (firstSdk < Build.VERSION_CODES.TIRAMISU) { - disabledTest.add("com.android.cts.verifier.presence.UwbPrecisionActivity"); - disabledTest.add("com.android.cts.verifier.presence.UwbShortRangeActivity"); - disabledTest.add("com.android.cts.verifier.presence.BleRssiPrecisionActivity"); - disabledTest.add("com.android.cts.verifier.presence.BleRxTxCalibrationActivity"); - disabledTest.add("com.android.cts.verifier.presence.BleRxOffsetActivity"); - disabledTest.add("com.android.cts.verifier.presence.BleTxOffsetActivity"); - disabledTest.add("com.android.cts.verifier.presence.NanPrecisionTestActivity"); - } - } else { - setInfoResources(R.string.presence_test, R.string.presence_test_info, -1); - } - - setTestListAdapter(new ManifestTestListAdapter(this, PresenceTestActivity.class.getName(), - disabledTest.toArray(new String[disabledTest.size()]))); - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java deleted file mode 100644 index 5d1ff8628dd..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbPrecisionActivity.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.verifier.presence; - -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.Editable; -import android.util.Log; -import android.widget.EditText; - -import com.android.compatibility.common.util.ResultType; -import com.android.compatibility.common.util.ResultUnit; -import com.android.cts.verifier.PassFailButtons; -import com.android.cts.verifier.R; - -/** - * Activity for testing that UWB distance and angle of arrival measurements are within the right - * range. - */ -public class UwbPrecisionActivity extends PassFailButtons.Activity { - private static final String TAG = UwbPrecisionActivity.class.getName(); - // Report log schema - private static final String KEY_DISTANCE_RANGE_CM = "distance_range_cm"; - private static final String KEY_REFERENCE_DEVICE = "reference_device"; - // Thresholds - private static final int MAX_DISTANCE_RANGE_CM = 30; - - private EditText mDistanceRangeInput; - private EditText mReferenceDeviceInput; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.uwb_precision); - setPassFailButtonClickListeners(); - getPassButton().setEnabled(false); - - mDistanceRangeInput = (EditText) findViewById(R.id.distance_range_cm); - mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device); - - DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(), - PackageManager.FEATURE_UWB); - - mDistanceRangeInput.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mReferenceDeviceInput.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - } - - private void checkTestInputs() { - getPassButton().setEnabled( - checkDistanceRangeInput() && checkReferenceDeviceInput()); - } - - private boolean checkDistanceRangeInput() { - String distanceRangeInput = mDistanceRangeInput.getText().toString(); - if (!distanceRangeInput.isEmpty()) { - double distanceRange = Double.parseDouble(distanceRangeInput); - // Distance range must be inputted and within acceptable range before test can be - // passed. - return distanceRange <= MAX_DISTANCE_RANGE_CM; - } - return false; - } - - private boolean checkReferenceDeviceInput() { - // Reference device must be inputted before test can be passed. - return !mReferenceDeviceInput.getText().toString().isEmpty(); - } - - @Override - public void recordTestResults() { - String distanceRange = mDistanceRangeInput.getText().toString(); - String referenceDevice = mReferenceDeviceInput.getText().toString(); - if (!distanceRange.isEmpty()) { - Log.i(TAG, "UWB Distance Range: " + distanceRange); - getReportLog().addValue(KEY_DISTANCE_RANGE_CM, Double.parseDouble(distanceRange), - ResultType.NEUTRAL, ResultUnit.NONE); - } - if (!referenceDevice.isEmpty()) { - Log.i(TAG, "UWB Reference Device: " + referenceDevice); - getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDevice, - ResultType.NEUTRAL, ResultUnit.NONE); - } - getReportLog().submit(); - } -} diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java deleted file mode 100644 index 7f14800b68c..00000000000 --- a/apps/CtsVerifier/src/com/android/cts/verifier/presence/UwbShortRangeActivity.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.cts.verifier.presence; - -import android.content.pm.PackageManager; -import android.os.Bundle; -import android.text.Editable; -import android.util.Log; -import android.widget.EditText; - -import com.android.compatibility.common.util.ResultType; -import com.android.compatibility.common.util.ResultUnit; -import com.android.cts.verifier.PassFailButtons; -import com.android.cts.verifier.R; - -/** - * Activity for testing that UWB distance measurements are within the acceptable median. - */ -public class UwbShortRangeActivity extends PassFailButtons.Activity { - private static final String TAG = UwbShortRangeActivity.class.getName(); - // Report log schema - private static final String KEY_DISTANCE_MEDIAN_CM = "distance_median_cm"; - private static final String KEY_REFERENCE_DEVICE = "reference_device"; - // Median Thresholds - private static final double MIN_MEDIAN = 0.75; - private static final double MAX_MEDIAN = 1.25; - private EditText mMedianInput; - private EditText mReferenceDeviceInput; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.uwb_short_range); - setPassFailButtonClickListeners(); - getPassButton().setEnabled(false); - - mMedianInput = (EditText) findViewById(R.id.distance_median_meters); - mReferenceDeviceInput = (EditText) findViewById(R.id.reference_device); - - DeviceFeatureChecker.checkFeatureSupported(this, getPassButton(), - PackageManager.FEATURE_UWB); - - mMedianInput.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - mReferenceDeviceInput.addTextChangedListener( - InputTextHandler.getOnTextChangedHandler((Editable s) -> checkTestInputs())); - } - - private void checkTestInputs() { - getPassButton().setEnabled(checkMedianInput() && checkReferenceDeviceInput()); - } - - private boolean checkMedianInput() { - String medianInput = mMedianInput.getText().toString(); - if (!medianInput.isEmpty()) { - double median = Double.parseDouble(medianInput); - return median >= MIN_MEDIAN && median <= MAX_MEDIAN; - } - return false; - } - - private boolean checkReferenceDeviceInput() { - return !mReferenceDeviceInput.getText().toString().isEmpty(); - } - - @Override - public void recordTestResults() { - String medianInput = mMedianInput.getText().toString(); - String referenceDeviceInput = mReferenceDeviceInput.getText().toString(); - if (!medianInput.isEmpty()) { - Log.i(TAG, "UWB Distance Median: " + medianInput); - getReportLog().addValue(KEY_DISTANCE_MEDIAN_CM, Double.parseDouble(medianInput), - ResultType.NEUTRAL, ResultUnit.NONE); - } - if (!referenceDeviceInput.isEmpty()) { - Log.i(TAG, "UWB Reference Device: " + referenceDeviceInput); - getReportLog().addValue(KEY_REFERENCE_DEVICE, referenceDeviceInput, ResultType.NEUTRAL, - ResultUnit.NONE); - } - getReportLog().submit(); - } -} diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java index 099a0ab7276..35cb549c529 100644 --- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java +++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java @@ -1772,6 +1772,37 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest { } /** + * Test that renaming file paths to an external directory such as Android/* and Android/* /* + * except Android/media/* /* is not allowed. + */ + @Test + public void testRenameFileToAppSpecificDir() throws Exception { + final File testFile = new File(getExternalMediaDir(), IMAGE_FILE_NAME); + final File testFileNew = new File(getExternalMediaDir(), NONMEDIA_FILE_NAME); + + try { + // Create a file in app's external media directory + if (!testFile.exists()) { + assertThat(testFile.createNewFile()).isTrue(); + } + + final String androidDirPath = getExternalStorageDir().getPath() + "/Android"; + + // Verify that we can't rename a file to Android/ or Android/data or + // Android/media directory + assertCantRenameFile(testFile, new File(androidDirPath, IMAGE_FILE_NAME)); + assertCantRenameFile(testFile, new File(androidDirPath + "/data", IMAGE_FILE_NAME)); + assertCantRenameFile(testFile, new File(androidDirPath + "/media", IMAGE_FILE_NAME)); + + // Verify that we can rename a file to app specific media directory. + assertCanRenameFile(testFile, testFileNew); + } finally { + testFile.delete(); + testFileNew.delete(); + } + } + + /** * Test that renaming directories is allowed and aligns to default directory restrictions. */ @Test diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java index 573035c2de3..13ade8b0585 100644 --- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java +++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java @@ -1367,7 +1367,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test { @CddTest(requirement="9.7") @Test public void testDrmServerDomain() throws DeviceNotAvailableException { - assertDomainN("u:r:drmserver:s0", "/system/bin/drmserver", "/system/bin/drmserver64"); + assertDomainHasExecutable("u:r:drmserver:s0", "/system/bin/drmserver", "/system/bin/drmserver64"); } /* Installd is always running */ diff --git a/hostsidetests/securitybulletin/Android.bp b/hostsidetests/securitybulletin/Android.bp index 30b61613f08..25242273f6b 100644 --- a/hostsidetests/securitybulletin/Android.bp +++ b/hostsidetests/securitybulletin/Android.bp @@ -43,6 +43,7 @@ java_test_host { cc_defaults { name: "cts_hostsidetests_securitybulletin_defaults", + auto_gen_config: false, compile_multilib: "both", multilib: { lib32: { diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java index 12287b0151d..95c90d4ec4b 100644 --- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0954.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,43 +16,39 @@ package android.security.cts; -import android.platform.test.annotations.AppModeFull; +import static org.junit.Assume.assumeNoException; + import android.platform.test.annotations.AsbSecurityTest; +import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase; import com.android.tradefed.device.ITestDevice; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; -import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase; -import org.junit.Assert; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(DeviceJUnit4ClassRunner.class) public class CVE_2021_0954 extends StsExtraBusinessLogicHostTestBase { - private static final String TEST_PKG = "android.security.cts.cve_2021_0954"; - private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest"; - private static final String TEST_APP = "CVE-2021-0954.apk"; - private ITestDevice device; - - @Before - public void setUp() throws Exception { - device = getDevice(); - uninstallPackage(device, TEST_PKG); - - /* Wake up the screen */ - AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device); - AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device); - AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device); - } + private static final String TEST_PKG = "android.security.cts.CVE_2021_0954"; - @AppModeFull @AsbSecurityTest(cveBugId = 143559931) @Test public void testPocCVE_2021_0954() throws Exception { - installPackage(TEST_APP); - AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW", - device); - runDeviceTests(TEST_PKG, TEST_CLASS, "testVulnerableActivityPresence"); + try { + ITestDevice device = getDevice(); + uninstallPackage(device, TEST_PKG); + + /* Wake up the screen */ + AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device); + + installPackage("CVE-2021-0954.apk"); + AdbUtils.runCommandLine( + "pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW", device); + runDeviceTests(TEST_PKG, TEST_PKG + "." + "DeviceTest", "testOverlayButtonPresence"); + } catch (Exception e) { + assumeNoException(e); + } } } diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java new file mode 100644 index 00000000000..e661b4ff4a1 --- /dev/null +++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2022_20353.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts; + +import static org.junit.Assume.assumeNoException; + +import android.platform.test.annotations.AsbSecurityTest; + +import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase; +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(DeviceJUnit4ClassRunner.class) +public class CVE_2022_20353 extends StsExtraBusinessLogicHostTestBase { + + @AsbSecurityTest(cveBugId = 221041256) + @Test + public void testPocCVE_2022_20353() { + try { + final String testPkg = "android.security.cts.CVE_2022_20353"; + ITestDevice device = getDevice(); + + AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device); + AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device); + + // to generate NOTICE.html if not already present + AdbUtils.runCommandLine("am start -a android.settings.LICENSE", device); + + installPackage("CVE-2022-20353.apk"); + + runDeviceTests(testPkg, testPkg + ".DeviceTest", "testDefaultRingtonePreference"); + } catch (Exception e) { + assumeNoException(e); + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp index aa9f71f574b..59350cf546f 100644 --- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/Android.bp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,10 @@ android_test_helper_app { name: "CVE-2021-0954", defaults: ["cts_support_defaults"], - srcs: ["src/**/*.java"], + srcs: [ + "src/**/*.java" + ], test_suites: [ - "cts", - "vts10", "sts", ], static_libs: [ diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml index a7e0218c422..75299c4ddfe 100644 --- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/AndroidManifest.xml @@ -1,5 +1,5 @@ <!-- - Copyright 2021 The Android Open Source Project + Copyright 2022 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,25 +13,19 @@ See the License for the specific language governing permissions and limitations under the License. --> + <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" - package="android.security.cts.cve_2021_0954" + package="android.security.cts.CVE_2021_0954" android:versionCode="1" android:versionName="1.0"> - <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> - - <application - android:allowBackup="true" - android:label="CVE_2021_0954" - android:supportsRtl="true"> - <uses-library android:name="android.test.runner" /> + <application> <service android:name=".PocService" android:enabled="true" - android:exported="false" /> + android:exported="true" /> </application> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.security.cts.cve_2021_0954" /> + android:targetPackage="android.security.cts.CVE_2021_0954" /> </manifest> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml new file mode 100644 index 00000000000..363df0001d7 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/integers.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<resources> + <integer name="assumptionFailure">-1</integer> + <integer name="noAssumptionFailure">0</integer> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml new file mode 100644 index 00000000000..7c4d959b70f --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/res/values/strings.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<resources> + <string name="canNotDrawOverlaysMsg">The application cannot draw overlays</string> + <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string> + <string name="cmdDumpsysActivity">dumpsys activity %1$s</string> + <string name="empty"></string> + <string name="overlayErrorMessage">Device is vulnerable to b/143559931 hence any app with + "SYSTEM_ALERT_WINDOW can overlay the %1$s screen</string> + <string name="mResumedTrue">mResumed=true</string> + <string name="messageKey">message</string> + <string name="overlayButtonText">OverlayButton</string> + <string name="overlayUiScreenError">Overlay UI did not appear on the screen</string> + <string name="resultKey">result</string> + <string name="sharedPreferences">CVE_2021_0954_prefs</string> + <string name="timedOutPocActivity">Timed out waiting on a result from PocActivity</string> + <string name="vulClass">com.android.internal.app.ResolverActivity</string> + <string name="vulClassAuto">com.android.car.activityresolver.CarResolverActivity</string> + <string name="vulPkg">android</string> + <string name="vulPkgAuto">com.android.car.activityresolver</string> + <string name="vulActivityNotRunningError">The %1$s is not currently running on the device + </string> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java index f98690625e9..9a94ef953c1 100644 --- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/DeviceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,20 @@ * limitations under the License. */ -package android.security.cts.cve_2021_0954; +package android.security.cts.CVE_2021_0954; import static androidx.test.core.app.ApplicationProvider.getApplicationContext; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; + +import static org.junit.Assert.assertTrue; import static org.junit.Assume.assumeNoException; +import static org.junit.Assume.assumeTrue; -import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.pm.PackageManager; import android.provider.Settings; import androidx.test.runner.AndroidJUnit4; @@ -32,90 +35,107 @@ import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.Until; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.io.IOException; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; @RunWith(AndroidJUnit4.class) public class DeviceTest { - private static final String TEST_PKG = "android.security.cts.cve_2021_0954"; - private static final String TEST_VULNERABLE_PKG = "android"; - private static final String TEST_VULNERABLE_ACTIVITY = - "com.android.internal.app.ResolverActivity"; - private static final int LAUNCH_TIMEOUT_MS = 20000; - private static final String vulnerableActivityName = "ResolverActivity"; - private UiDevice mDevice; - String activityDump = ""; - - private void startOverlayService() { - Context context = getApplicationContext(); - assertNotNull(context); - Intent intent = new Intent(context, PocService.class); - assertNotNull(intent); - - if (Settings.canDrawOverlays(getApplicationContext())) { - context.startService(intent); - } else { - try { - context.startService(intent); - } catch (Exception e) { - throw new RuntimeException("Unable to start the overlay service", e); - } - } + private Context mContext = getApplicationContext(); + private static final int TIMEOUT_MS = 10000; + + private boolean hasFeature(String feature) { + return mContext.getPackageManager().hasSystemFeature(feature); } - public void startVulnerableActivity() { - Context context = getApplicationContext(); - Intent intent = new Intent(); - intent.setClassName(TEST_VULNERABLE_PKG, TEST_VULNERABLE_ACTIVITY); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - try { - context.startActivity(intent); - } catch (ActivityNotFoundException e) { - assumeNoException("Activity not found on device", e); - } + private boolean isAuto() { + return hasFeature(PackageManager.FEATURE_AUTOMOTIVE); } - @Before - public void setUp() throws Exception { - mDevice = UiDevice.getInstance(getInstrumentation()); + String getStringRes(int key) { + return mContext.getResources().getString(key); + } - /* Start the vulnerable activity */ - startVulnerableActivity(); - if (!mDevice.wait(Until.hasObject(By.res("android:id/contentPanel") - .clazz("android.widget.ScrollView").pkg("android")), LAUNCH_TIMEOUT_MS)) { - return; - } + String getStringResWithArg(int key, String arg) { + return mContext.getResources().getString(key, arg); + } - /* Start the overlay service */ - startOverlayService(); + int getIntegerRes(int key) { + return mContext.getResources().getInteger(key); } @Test - public void testVulnerableActivityPresence() { - Pattern overlayTextPattern = Pattern.compile("OverlayButton", Pattern.CASE_INSENSITIVE); - if (!mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS)) { - return; - } - - /* - * Check if the currently running activity is the vulnerable activity, if not abort the test - */ + public void testOverlayButtonPresence() { try { - activityDump = mDevice.executeShellCommand("dumpsys activity"); - } catch (IOException e) { - throw new RuntimeException("Could not execute dumpsys activity command"); - } - Pattern activityPattern = - Pattern.compile("mResumedActivity.*" + vulnerableActivityName + ".*\n"); - if (!activityPattern.matcher(activityDump).find()) { - return; + UiDevice device = UiDevice.getInstance(getInstrumentation()); + + /* Start the overlay service */ + assumeTrue(getStringRes(R.string.canNotDrawOverlaysMsg), + Settings.canDrawOverlays(mContext)); + Intent intent = new Intent(mContext, PocService.class); + mContext.startService(intent); + + /* Wait for a result from overlay service */ + SharedPreferences sharedPrefs = mContext.getSharedPreferences( + getStringRes(R.string.sharedPreferences), Context.MODE_PRIVATE); + final Semaphore preferenceChanged = new Semaphore(0); + OnSharedPreferenceChangeListener listener = new OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + if (key.equals(getStringRes(R.string.resultKey))) { + preferenceChanged.release(); + } + } + }; + sharedPrefs.registerOnSharedPreferenceChangeListener(listener); + assumeTrue(preferenceChanged.tryAcquire(TIMEOUT_MS, TimeUnit.MILLISECONDS)); + int result = sharedPrefs.getInt(getStringRes(R.string.resultKey), + getIntegerRes(R.integer.assumptionFailure)); + String message = sharedPrefs.getString(getStringRes(R.string.messageKey), + getStringRes(R.string.defaultSemaphoreMsg)); + assumeTrue(message, result != getIntegerRes(R.integer.assumptionFailure)); + + /* Wait for the UI of overlay window to appear */ + Pattern overlayTextPattern = Pattern.compile( + mContext.getString(R.string.overlayButtonText), Pattern.CASE_INSENSITIVE); + assumeTrue(mContext.getString(R.string.overlayUiScreenError), + device.wait(Until.hasObject(By.text(overlayTextPattern)), TIMEOUT_MS)); + + /* Start the vulnerable activity */ + intent = new Intent(); + String vulActivity = getStringRes(R.string.vulClass); + String vulPkg = getStringRes(R.string.vulPkg); + if (isAuto()) { + vulActivity = getStringRes(R.string.vulClassAuto); + vulPkg = getStringRes(R.string.vulPkgAuto); + } + intent.setClassName(vulPkg, vulActivity); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + + /* Wait until the object of overlay window is gone */ + boolean overlayDisallowed = + device.wait(Until.gone(By.pkg(mContext.getPackageName())), TIMEOUT_MS); + + /* + * Check if the currently running activity is the vulnerable activity, if not abort the + * test + */ + String activityDump = device.executeShellCommand( + getStringResWithArg(R.string.cmdDumpsysActivity, vulActivity)); + Pattern activityPattern = Pattern.compile(getStringRes(R.string.mResumedTrue)); + assumeTrue(getStringRes(R.string.vulActivityNotRunningError), + activityPattern.matcher(activityDump).find()); + + /* Failing the test as fix is not present */ + assertTrue(getStringResWithArg(R.string.overlayErrorMessage, vulActivity), + overlayDisallowed); + } catch (Exception e) { + assumeNoException(e); } - String message = "Device is vulnerable to b/143559931 hence any app with " - + "SYSTEM_ALERT_WINDOW can overlay the ResolverActivity screen"; - assertNull(message, mDevice.findObject(By.text(overlayTextPattern))); } } diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java index 82b78a2beba..79270baa65e 100644 --- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java +++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0954/src/android/security/cts/CVE_2021_0954/PocService.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 The Android Open Source Project + * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,47 +14,65 @@ * limitations under the License. */ -package android.security.cts.cve_2021_0954; +package android.security.cts.CVE_2021_0954; import android.app.Service; +import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.PixelFormat; -import android.os.Handler; import android.os.IBinder; -import android.provider.Settings; import android.view.Gravity; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.Button; public class PocService extends Service { - public static Button mButton; - private WindowManager mWindowManager; - private WindowManager.LayoutParams mLayoutParams; + Button mButton; + WindowManager mWindowManager; - private static int getScreenWidth() { + private int getScreenWidth() { return Resources.getSystem().getDisplayMetrics().widthPixels; } - private static int getScreenHeight() { + private int getScreenHeight() { return Resources.getSystem().getDisplayMetrics().heightPixels; } + String getStringRes(int key) { + return getResources().getString(key); + } + + int getIntegerRes(int key) { + return getResources().getInteger(key); + } + @Override public void onCreate() { - super.onCreate(); - mWindowManager = getSystemService(WindowManager.class); - mLayoutParams = new WindowManager.LayoutParams(); - mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; - mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; - mLayoutParams.format = PixelFormat.OPAQUE; - mLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; - mLayoutParams.width = getScreenWidth(); - mLayoutParams.height = getScreenHeight(); - mLayoutParams.x = getScreenWidth() / 2; - mLayoutParams.y = getScreenHeight() / 2; + try { + super.onCreate(); + mWindowManager = getSystemService(WindowManager.class); + LayoutParams layoutParams = new LayoutParams(); + layoutParams.type = LayoutParams.TYPE_APPLICATION_OVERLAY; + layoutParams.flags = + LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE; + layoutParams.format = PixelFormat.OPAQUE; + layoutParams.gravity = Gravity.LEFT | Gravity.TOP; + layoutParams.width = getScreenWidth(); + layoutParams.height = getScreenHeight(); + layoutParams.x = getScreenWidth() / 2; + layoutParams.y = getScreenHeight() / 2; + + /* Show the floating window */ + mButton = new Button(this); + mButton.setText(getString(R.string.overlayButtonText)); + mWindowManager.addView(mButton, layoutParams); + } catch (Exception e) { + sendTestResult(getIntegerRes(R.integer.assumptionFailure), e.getMessage()); + return; + } + sendTestResult(getIntegerRes(R.integer.noAssumptionFailure), getStringRes(R.string.empty)); } @Override @@ -63,31 +81,27 @@ public class PocService extends Service { } @Override - public int onStartCommand(Intent intent, int flags, int startId) { - showFloatingWindow(); - return super.onStartCommand(intent, flags, startId); - } - - @Override public void onDestroy() { - if (mWindowManager != null && mButton != null) { - mWindowManager.removeView(mButton); + try { + if (mWindowManager != null && mButton != null) { + mWindowManager.removeView(mButton); + } + super.onDestroy(); + } catch (Exception e) { + sendTestResult(getIntegerRes(R.integer.assumptionFailure), e.getMessage()); } - super.onDestroy(); } - private void showFloatingWindow() { - if (Settings.canDrawOverlays(this)) { - mButton = new Button(getApplicationContext()); - mButton.setText("OverlayButton"); - mWindowManager.addView(mButton, mLayoutParams); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - onDestroy(); - } - }, 60000); // one minute - mButton.setTag(mButton.getVisibility()); + private void sendTestResult(int result, String message) { + try { + SharedPreferences sh = getSharedPreferences(getStringRes(R.string.sharedPreferences), + Context.MODE_PRIVATE); + SharedPreferences.Editor edit = sh.edit(); + edit.putInt(getStringRes(R.string.resultKey), result); + edit.putString(getStringRes(R.string.messageKey), message); + edit.commit(); + } catch (Exception e) { + // ignore the exception } } } diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp new file mode 100644 index 00000000000..37d35eb74f2 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/Android.bp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +android_test_helper_app { + name: "CVE-2022-20353", + defaults: [ + "cts_support_defaults", + ], + srcs: [ + "src/**/*.java", + ], + test_suites: [ + "sts", + ], + static_libs: [ + "androidx.test.core", + "androidx.test.rules", + "androidx.test.uiautomator_uiautomator", + ], + sdk_version: "current", +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml new file mode 100644 index 00000000000..d4129ac8823 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/AndroidManifest.xml @@ -0,0 +1,35 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.security.cts.CVE_2022_20353"> + <application + android:label="@string/appName" + android:supportsRtl="true"> + <activity + android:name=".PocActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.RINGTONE_PICKER" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + </activity> + </application> + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.security.cts.CVE_2022_20353" /> +</manifest> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml new file mode 100644 index 00000000000..3207c29a0bd --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/integers.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<resources> + <integer name="assumptionFailure">-1</integer> + <integer name="success">0</integer> + <integer name="timeoutMs">20000</integer> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml new file mode 100644 index 00000000000..27e87f65446 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/res/values/strings.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2022 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<resources> + <string name="alwaysButtonId">android:id/button_always</string> + <string name="appName">CVE-2022-20353</string> + <string name="defaultSemaphoreMsg">Could not get message key in shared preferences</string> + <string name="failureMessage"> + Device is vulnerable to b/221041256!! Privilege escalation possible in + com.android.settings.DefaultRingtonePreference + </string> + <string name="fileName">NOTICE.html</string> + <string name="getRingtoneCmd">settings get system ringtone</string> + <string name="messageKey">message</string> + <string name="noticeUri"> + content://com.android.settings.files/my_cache/NOTICE.html + </string> + <string name="resType">string</string> + <string name="resultKey">result</string> + <string name="setRingtoneCmd">settings put system ringtone</string> + <string name="sharedPreferences">sharedPreferences</string> + <string name="textResId">ringtone_title</string> + <string name="uiObjectNotFoundMsg">Unable to find UiObject with %1$s text/id</string> +</resources> diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java new file mode 100644 index 00000000000..af1f9782ab0 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/DeviceTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts.CVE_2022_20353; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assume.assumeNoException; +import static org.junit.Assume.assumeTrue; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.res.Resources; +import android.provider.Settings; + +import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.BySelector; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiScrollable; +import androidx.test.uiautomator.UiSelector; +import androidx.test.uiautomator.Until; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +@RunWith(AndroidJUnit4.class) +public class DeviceTest { + Resources mResources; + UiDevice mDevice; + Context mContext; + + // Wait for UiObject to appear and click on the UiObject if it is visible + private boolean clickUiObject(BySelector selector) { + boolean objectFound = + mDevice.wait(Until.hasObject(selector), mResources.getInteger(R.integer.timeoutMs)); + if (objectFound) { + mDevice.findObject(selector).click(); + } + return objectFound; + } + + @Test + public void testDefaultRingtonePreference() { + String defaultRingtone = null; + try { + mDevice = UiDevice.getInstance(getInstrumentation()); + mContext = getInstrumentation().getContext(); + mResources = mContext.getResources(); + defaultRingtone = + mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd)); + + Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(intent); + + String settingsPackageName = + intent.resolveActivity(mContext.getPackageManager()).getPackageName(); + Context settingsContext = mContext.createPackageContext(settingsPackageName, + Context.CONTEXT_IGNORE_SECURITY); + Resources res = settingsContext.getPackageManager() + .getResourcesForApplication(settingsPackageName); + String text = settingsContext + .getString(res.getIdentifier(mContext.getString(R.string.textResId), + mContext.getString(R.string.resType), settingsPackageName)); + // scroll until text 'Phone ringtone' is visible + UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true)); + uiScrollable.scrollTextIntoView(text); + // click on 'Phone ringtone' + BySelector selector = By.text(text); + assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text), + clickUiObject(selector)); + // select CTS PoC app + text = mContext.getString(R.string.appName); + selector = By.text(text); + assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, text), + clickUiObject(selector)); + // select 'Always' + String resId = mContext.getString(R.string.alwaysButtonId); + selector = By.res(resId); + assumeTrue(mContext.getString(R.string.uiObjectNotFoundMsg, resId), + clickUiObject(selector)); + + SharedPreferences sharedPrefs = mContext.getSharedPreferences( + mContext.getString(R.string.sharedPreferences), Context.MODE_APPEND); + Semaphore preferenceChanged = new Semaphore(0); + OnSharedPreferenceChangeListener sharedPrefListener = + new OnSharedPreferenceChangeListener() { + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, + String key) { + if (key.equals(mContext.getString(R.string.resultKey))) { + preferenceChanged.release(); + } + } + }; + sharedPrefs.registerOnSharedPreferenceChangeListener(sharedPrefListener); + // wait for PocActivity to complete + assumeTrue(preferenceChanged.tryAcquire(mResources.getInteger(R.integer.timeoutMs), + TimeUnit.MILLISECONDS)); + int result = sharedPrefs.getInt(mContext.getString(R.string.resultKey), + mResources.getInteger(R.integer.assumptionFailure)); + String message = sharedPrefs.getString(mContext.getString(R.string.messageKey), + mContext.getString(R.string.defaultSemaphoreMsg)); + assumeTrue(message, result != mResources.getInteger(R.integer.assumptionFailure)); + + String ringtoneUri = ""; + boolean isVulnerable = false; + long startTime = System.currentTimeMillis(); + while ((System.currentTimeMillis() - startTime) < mResources + .getInteger(R.integer.timeoutMs)) { + ringtoneUri = + mDevice.executeShellCommand(mContext.getString(R.string.getRingtoneCmd)); + if (ringtoneUri.contains(mContext.getString(R.string.fileName))) { + isVulnerable = true; + break; + } + } + assertFalse(mContext.getString(R.string.failureMessage), isVulnerable); + } catch (Exception e) { + assumeNoException(e); + } finally { + try { + // reset ringtone to default (other than 'null') present before test + mDevice.executeShellCommand( + mContext.getString(R.string.setRingtoneCmd) + " " + defaultRingtone); + mDevice.pressHome(); + } catch (Exception e) { + // ignore exception here + } + } + } +} diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java new file mode 100644 index 00000000000..977e647d2e2 --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2022-20353/src/android/security/cts/CVE_2022_20353/PocActivity.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts.CVE_2022_20353; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Bundle; + +/* PocActivity is required in this test since it is required that CTS PoC app is selected when */ +/* choosing an app for setting default ringtone. RingtonePicker appears due to actions done in */ +/* DeviceTest. */ +public class PocActivity extends Activity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + try { + super.onCreate(savedInstanceState); + Intent intent = new Intent(); + /* set NOTICE.html file uri as EXTRA_RINGTONE_PICKED_URI which sets NOTICE.html as */ + /* default ringtone if vulnerability is present */ + intent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, + Uri.parse(getString(R.string.noticeUri))); + setResult(Activity.RESULT_OK, intent); + finish(); + sendTestResult(getResources().getInteger(R.integer.success), ""); + } catch (Exception e) { + sendTestResult(getResources().getInteger(R.integer.assumptionFailure), e.getMessage()); + } + } + + void sendTestResult(int result, String message) { + try { + SharedPreferences sh = getSharedPreferences(getString(R.string.sharedPreferences), + Context.MODE_PRIVATE); + SharedPreferences.Editor edit = sh.edit(); + edit.putInt(getString(R.string.resultKey), result); + edit.putString(getString(R.string.messageKey), message); + edit.commit(); + } catch (Exception e) { + // ignore exception here + } + } + +} diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java index be665ba4013..7f29d44673c 100644 --- a/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java +++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/lib/ConfigUtils.java @@ -69,10 +69,6 @@ public final class ConfigUtils { .addAllowedLogSource("AID_SYSTEM") .addAllowedLogSource("AID_BLUETOOTH") .addAllowedLogSource("com.android.bluetooth") - // TODO(b/236681553): Remove this. - .addAllowedLogSource("com.android.bluetooth.services") - // TODO(b/236681553): Remove this. - .addAllowedLogSource("com.google.android.bluetooth.services") .addAllowedLogSource("AID_LMKD") .addAllowedLogSource("AID_MEDIA") .addAllowedLogSource("AID_RADIO") diff --git a/tests/camera/Android.bp b/tests/camera/Android.bp index aae58c689b7..c2334fc3b4c 100644 --- a/tests/camera/Android.bp +++ b/tests/camera/Android.bp @@ -65,6 +65,7 @@ android_test { "truth-prebuilt", "androidx.heifwriter_heifwriter", "androidx.test.rules", + "MediaPerformanceClassCommon", ], jni_libs: [ "libctscamera2_jni", diff --git a/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java b/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java index feb5567963f..772e7a599cb 100644 --- a/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java +++ b/tests/camera/api31test/src/android/camera/cts/api31test/SPerfClassTest.java @@ -36,6 +36,7 @@ import android.hardware.camera2.params.SessionConfiguration; import android.hardware.camera2.TotalCaptureResult; import android.media.Image; import android.media.ImageReader; +import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.test.AndroidTestCase; @@ -210,8 +211,9 @@ public class SPerfClassTest extends AndroidTestCase { * Version.MEDIA_PERFORMANCE_CLASS */ public void testSPerfClassJpegSizes() throws Exception { - boolean isSPerfClass = CameraTestUtils.isSPerfClass(); - if (!isSPerfClass) { + final boolean isAtLeastSPerfClass = + (Build.VERSION.MEDIA_PERFORMANCE_CLASS >= Build.VERSION_CODES.S); + if (!isAtLeastSPerfClass) { return; } diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java index 6af7758c533..d7dd63d1ff2 100644 --- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java +++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java @@ -55,6 +55,10 @@ import android.hardware.camera2.params.DynamicRangeProfiles; import android.hardware.camera2.params.RecommendedStreamConfigurationMap; import android.hardware.camera2.params.StreamConfigurationMap; import android.hardware.cts.helpers.CameraUtils; +import android.mediapc.cts.common.Requirement; +import android.mediapc.cts.common.RequiredMeasurement; +import android.mediapc.cts.common.RequirementConstants; +import android.mediapc.cts.common.PerformanceClassEvaluator; import android.media.CamcorderProfile; import android.media.ImageReader; import android.os.Build; @@ -74,15 +78,11 @@ import android.view.WindowMetrics; import androidx.test.rule.ActivityTestRule; -import androidx.test.InstrumentationRegistry; - import com.android.compatibility.common.util.CddTest; -import com.android.compatibility.common.util.DeviceReportLog; -import com.android.compatibility.common.util.ResultType; -import com.android.compatibility.common.util.ResultUnit; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestName; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; @@ -92,12 +92,10 @@ import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.function.BiPredicate; import java.util.regex.Matcher; import java.util.regex.Pattern; -import static android.hardware.camera2.cts.CameraTestUtils.MPC_REPORT_LOG_NAME; -import static android.hardware.camera2.cts.CameraTestUtils.MPC_STREAM_NAME; - /** * Extended tests for static camera characteristics. */ @@ -113,6 +111,9 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { */ private static final int MIN_ALLOWABLE_WHITELEVEL = 32; // must have sensor bit depth > 5 + @Rule + public final TestName mTestName = new TestName(); + private List<CameraCharacteristics> mCharacteristics; private static final Size FULLHD = new Size(1920, 1080); @@ -131,10 +132,6 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { private static final long PREVIEW_RUN_MS = 500; private static final long FRAME_DURATION_30FPS_NSEC = (long) 1e9 / 30; - private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000; - private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000; - private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000; - private static final long MIN_UHR_SENSOR_RESOLUTION = 24000000; /* * HW Levels short hand @@ -2857,28 +2854,70 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { } /** - * Update performance class level based on condition - * - * @param condition whether the condition is met for passLevel - * @param passLevel the highest performance class level when condition is true - * @param failLevel the performance class when condition is false + * Camera hardware level requirement for Media Performance Class */ - private int updatePerfClassLevel(boolean condition, int passLevel, int failLevel) { - return condition ? passLevel : failLevel; - } + public static class PrimaryCameraHwLevelReq extends Requirement { + private static final String TAG = PrimaryCameraHwLevelReq.class.getSimpleName(); + + /** + * Creates a >= predicate for camera hardware level + */ + private static BiPredicate<Integer, Integer> camHwLevelGte() { + return new BiPredicate<Integer, Integer>() { + @Override + public boolean test(Integer actual, Integer expected) { + return StaticMetadata.hardwareLevelPredicate(actual, expected); + } - /** - * Update perf class level based on meetSPerfClass and meetRPerfClass. - */ - private int updatePerfClassLevelRS(boolean meetSPerfClass, boolean meetRPerfClass, - int perfClassLevel) { - if (!meetRPerfClass) { - return CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } else if (!meetSPerfClass && - perfClassLevel > CameraTestUtils.PERFORMANCE_CLASS_R) { - return Math.min(CameraTestUtils.PERFORMANCE_CLASS_R, perfClassLevel); - } - return perfClassLevel; + @Override + public String toString() { + return "Camera Hardware Level Greater than or equal to"; + } + }; + } + private static final BiPredicate<Integer, Integer> CAM_HW_LEVEL_GTE = camHwLevelGte(); + private PrimaryCameraHwLevelReq(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setPrimaryRearCameraHwlLevel(Integer hwLevel) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_HWL_LEVEL, hwLevel); + } + + public void setPrimaryFrontCameraHwlLevel(Integer hwLevel) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_HWL_LEVEL, hwLevel); + } + + /** + * [2.2.7.2/7.5/H-1-3] MUST support android.info.supportedHardwareLevel property as FULL or + * better for back primary and LIMITED or better for front primary camera. + */ + public static PrimaryCameraHwLevelReq createPrimaryCameraHwLevelReq() { + RequiredMeasurement<Integer> rearCameraHwlLevel = RequiredMeasurement + .<Integer>builder() + .setId(RequirementConstants.REAR_CAMERA_HWL_LEVEL) + .setPredicate(CAM_HW_LEVEL_GTE) + .addRequiredValue(Build.VERSION_CODES.R, + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) + .addRequiredValue(Build.VERSION_CODES.S, + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) + .build(); + RequiredMeasurement<Integer> frontCameraHwlLevel = RequiredMeasurement + .<Integer>builder() + .setId(RequirementConstants.FRONT_CAMERA_HWL_LEVEL) + .setPredicate(CAM_HW_LEVEL_GTE) + .addRequiredValue(Build.VERSION_CODES.R, + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED) + .addRequiredValue(Build.VERSION_CODES.S, + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, + CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL) + .build(); + return new PrimaryCameraHwLevelReq(RequirementConstants.R7_5__H_1_3, + rearCameraHwlLevel, frontCameraHwlLevel); + } } /** @@ -2893,30 +2932,31 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { // ids. return; } - boolean assertRPerfClass = CameraTestUtils.isRPerfClass(); - boolean assertSPerfClass = CameraTestUtils.isSPerfClass(); - boolean assertTPerfClass = CameraTestUtils.isTPerfClass(); - boolean assertPerfClass = (assertRPerfClass || assertSPerfClass || assertTPerfClass); - - // R & S Performance Class - int perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH13 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH14 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH18 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - - // T Performance Class - int perfClassLevelH19 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH110 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH111 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH112 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH113 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - int perfClassLevelH114 = CameraTestUtils.PERFORMANCE_CLASS_CURRENT; - - DeviceReportLog reportLog = new DeviceReportLog(MPC_REPORT_LOG_NAME, MPC_STREAM_NAME); - - String primaryRearId = null; - String primaryFrontId = null; + PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); + PerformanceClassEvaluator.PrimaryCameraRequirement primaryRearReq = + pce.addPrimaryRearCameraReq(); + PerformanceClassEvaluator.PrimaryCameraRequirement primaryFrontReq = + pce.addPrimaryFrontCameraReq(); + PrimaryCameraHwLevelReq hwLevelReq = pce.addRequirement( + PrimaryCameraHwLevelReq.createPrimaryCameraHwLevelReq()); + PerformanceClassEvaluator.CameraTimestampSourceRequirement timestampSourceReq = + pce.addR7_5__H_1_4(); + PerformanceClassEvaluator.CameraRawRequirement rearRawReq = + pce.addR7_5__H_1_8(); + PerformanceClassEvaluator.Camera240FpsRequirement hfrReq = + pce.addR7_5__H_1_9(); + PerformanceClassEvaluator.UltraWideZoomRatioRequirement ultrawideZoomRatioReq = + pce.addR7_5__H_1_10(); + PerformanceClassEvaluator.ConcurrentRearFrontRequirement concurrentRearFrontReq = + pce.addR7_5__H_1_11(); + PerformanceClassEvaluator.PreviewStabilizationRequirement previewStabilizationReq = + pce.addR7_5__H_1_12(); + PerformanceClassEvaluator.LogicalMultiCameraRequirement logicalMultiCameraReq = + pce.addR7_5__H_1_13(); + PerformanceClassEvaluator.StreamUseCaseRequirement streamUseCaseReq = + pce.addR7_5__H_1_14(); + + HashSet<String> primaryCameras = new HashSet<String>(); for (int i = 0; i < mCameraIdsUnderTest.length; i++) { String cameraId = mCameraIdsUnderTest[i]; boolean isPrimaryRear = CameraTestUtils.isPrimaryRearFacingCamera( @@ -2940,42 +2980,27 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { List<Size> videoSizes = CameraTestUtils.getSupportedVideoSizes(cameraId, mCameraManager, null /*bound*/); + Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE); if (isPrimaryRear) { - primaryRearId = cameraId; - if (sensorResolution < MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION) { - mCollector.expectTrue("Primary rear camera resolution should be at least " + - MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION + " pixels, is "+ - sensorResolution, !assertPerfClass); - perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } - reportLog.addValue("rear camera resolution", sensorResolution, - ResultType.NEUTRAL, ResultUnit.NONE); + primaryCameras.add(cameraId); + primaryRearReq.setPrimaryCameraSupported(true); + primaryRearReq.setResolution(sensorResolution); + hwLevelReq.setPrimaryRearCameraHwlLevel(staticInfo.getHardwareLevelChecked()); + timestampSourceReq.setRearCameraTimestampSource(timestampSource); // 4K @ 30fps boolean supportUHD = videoSizes.contains(UHD); boolean supportDC4K = videoSizes.contains(DC4K); - reportLog.addValue("rear camera 4k support", supportUHD | supportDC4K, - ResultType.NEUTRAL, ResultUnit.NONE); - if (!supportUHD && !supportDC4K) { - mCollector.expectTrue("Primary rear camera should support 4k video recording", - !assertPerfClass); - perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } else { + boolean support4K = (supportUHD || supportDC4K); + primaryRearReq.setVideoSizeReqSatisfied(support4K); + if (support4K) { long minFrameDuration = config.getOutputMinFrameDuration( android.media.MediaRecorder.class, supportDC4K ? DC4K : UHD); - reportLog.addValue("rear camera 4k frame duration", minFrameDuration, - ResultType.NEUTRAL, ResultUnit.NONE); - if (minFrameDuration >= (1e9 / 29.9)) { - mCollector.expectTrue("Primary rear camera should support 4k video @ 30fps", - !assertPerfClass); - perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } + primaryRearReq.setVideoFps(1e9 / minFrameDuration); } // H-1-9 boolean supportHighSpeed = staticInfo.isCapabilitySupported(CONSTRAINED_HIGH_SPEED); - mCollector.expectTrue("Primary rear camera should support high speed recording", - !assertTPerfClass || supportHighSpeed); boolean support240Fps = false; if (supportHighSpeed) { Size[] availableHighSpeedSizes = config.getHighSpeedVideoSizes(); @@ -2995,101 +3020,29 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { break; } } - mCollector.expectTrue("Primary rear camera should support HD or FULLHD @ 240", - !assertTPerfClass || support240Fps); } - perfClassLevelH19 = updatePerfClassLevel(support240Fps, - perfClassLevelH19, CameraTestUtils.PERFORMANCE_CLASS_S); - reportLog.addValue("rear camera 720p/1080p @ 240fps support", support240Fps, - ResultType.NEUTRAL, ResultUnit.NONE); + hfrReq.setRear240FpsSupported(support240Fps); } else { - primaryFrontId = cameraId; - if (sensorResolution < MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION) { - mCollector.expectTrue("Primary front camera resolution should be at least " - + MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is " - + sensorResolution, !(assertSPerfClass || assertTPerfClass)); - perfClassLevelH12 = Math.min( - perfClassLevelH12, CameraTestUtils.PERFORMANCE_CLASS_R); - } - if (sensorResolution < MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION) { - mCollector.expectTrue("Primary front camera resolution should be at least " + - MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION + " pixels, is "+ - sensorResolution, !assertRPerfClass); - perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } - reportLog.addValue("front camera resolution", sensorResolution, - ResultType.NEUTRAL, ResultUnit.NONE); + primaryCameras.add(cameraId); + primaryFrontReq.setPrimaryCameraSupported(true); + primaryFrontReq.setResolution(sensorResolution); + hwLevelReq.setPrimaryFrontCameraHwlLevel(staticInfo.getHardwareLevelChecked()); + timestampSourceReq.setFrontCameraTimestampSource(timestampSource); // 1080P @ 30fps boolean supportFULLHD = videoSizes.contains(FULLHD); - reportLog.addValue("front camera 1080p support", supportFULLHD, - ResultType.NEUTRAL, ResultUnit.NONE); - if (!supportFULLHD) { - mCollector.expectTrue( - "Primary front camera should support 1080P video recording", - !assertPerfClass); - perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } else { + primaryFrontReq.setVideoSizeReqSatisfied(supportFULLHD); + if (supportFULLHD) { long minFrameDuration = config.getOutputMinFrameDuration( android.media.MediaRecorder.class, FULLHD); - if (minFrameDuration >= (1e9 / 29.9)) { - mCollector.expectTrue( - "Primary front camera should support 1080P video @ 30fps", - !assertPerfClass); - perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } - reportLog.addValue("front camera 1080p frame duration", minFrameDuration, - ResultType.NEUTRAL, ResultUnit.NONE); + primaryFrontReq.setVideoFps(1e9 / minFrameDuration); } } - String facingString = isPrimaryRear ? "rear" : "front"; - // H-1-3 - if (assertTPerfClass || assertSPerfClass || (assertRPerfClass && isPrimaryRear)) { - mCollector.expectTrue("Primary " + facingString + - " camera should be at least FULL, but is " + - toStringHardwareLevel(staticInfo.getHardwareLevelChecked()), - staticInfo.isHardwareLevelAtLeastFull()); - } else if (assertRPerfClass) { - mCollector.expectTrue("Primary " + facingString + - " camera should be at least LIMITED, but is " + - toStringHardwareLevel(staticInfo.getHardwareLevelChecked()), - staticInfo.isHardwareLevelAtLeastLimited()); - } - - reportLog.addValue(facingString + " camera hardware level", - staticInfo.getHardwareLevelChecked(), ResultType.NEUTRAL, ResultUnit.NONE); - if (isPrimaryRear) { - perfClassLevelH13 = updatePerfClassLevel(staticInfo.isHardwareLevelAtLeastFull(), - perfClassLevelH13, CameraTestUtils.PERFORMANCE_CLASS_NOT_MET); - } else { - perfClassLevelH13 = updatePerfClassLevelRS(staticInfo.isHardwareLevelAtLeastFull(), - staticInfo.isHardwareLevelAtLeastLimited(), perfClassLevelH13); - } - - // H-1-4 - Integer timestampSource = c.get(CameraCharacteristics.SENSOR_INFO_TIMESTAMP_SOURCE); - reportLog.addValue(facingString + " timestampSource", - timestampSource, ResultType.NEUTRAL, ResultUnit.NONE); - boolean realtimeTimestamp = (timestampSource != null && - timestampSource.equals(CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME)); - mCollector.expectTrue( - "Primary " + facingString + " camera should support real-time timestamp source", - !assertPerfClass || realtimeTimestamp); - perfClassLevelH14 = updatePerfClassLevel(realtimeTimestamp, perfClassLevelH14, - CameraTestUtils.PERFORMANCE_CLASS_NOT_MET); - // H-1-8 if (isPrimaryRear) { boolean supportRaw = staticInfo.isCapabilitySupported(RAW); - reportLog.addValue(facingString + " camera raw support", - supportRaw, ResultType.NEUTRAL, ResultUnit.NONE); - if (assertSPerfClass || assertTPerfClass) { - mCollector.expectTrue("Primary rear camera should support RAW capability", - supportRaw); - } - perfClassLevelH18 = updatePerfClassLevel(supportRaw, perfClassLevelH18, - CameraTestUtils.PERFORMANCE_CLASS_R); + rearRawReq.setRearRawSupported(supportRaw); } // H-1-10 @@ -3098,96 +3051,45 @@ public class ExtendedCameraCharacteristicsTest extends Camera2AndroidTestCase { Range<Float> zoomRatioRange = staticInfo.getZoomRatioRangeChecked(); boolean meetH110 = (primaryToMaxFovRatio >= 1.0f - FOV_THRESHOLD) || (zoomRatioRange.getLower() < 1.0f - FOV_THRESHOLD); - mCollector.expectTrue("Primary " + facingString + " camera must support zoomRatio < " - + "1.0f if there is an ultrawide lens with the same facing", - !assertTPerfClass || meetH110); - perfClassLevelH110 = updatePerfClassLevel(meetH110, perfClassLevelH110, - CameraTestUtils.PERFORMANCE_CLASS_S); - reportLog.addValue(facingString + " camera supports maximum FOV using zoom ratio", - meetH110, ResultType.NEUTRAL, ResultUnit.NONE); + if (isPrimaryRear) { + ultrawideZoomRatioReq.setRearUltraWideZoomRatioReqMet(meetH110); + } else { + ultrawideZoomRatioReq.setFrontUltraWideZoomRatioReqMet(meetH110); + } // H-1-12 - boolean meetH112 = staticInfo.isPreviewStabilizationSupported(); - mCollector.expectTrue("Primary " + facingString + " camera must support preview " - + "stabilization", !assertTPerfClass || meetH112); - perfClassLevelH112 = updatePerfClassLevel(meetH112, perfClassLevelH112, - CameraTestUtils.PERFORMANCE_CLASS_S); - reportLog.addValue(facingString + " camera preview stabilization", meetH112, - ResultType.NEUTRAL, ResultUnit.NONE); + boolean previewStab = staticInfo.isPreviewStabilizationSupported(); + if (isPrimaryRear) { + previewStabilizationReq.setRearPreviewStabilizationSupported(previewStab); + } else { + previewStabilizationReq.setFrontPreviewStabilizationSupported(previewStab); + } // H-1-13 int facing = staticInfo.getLensFacingChecked(); int numOfPhysicalRgbCameras = getNumberOfRgbPhysicalCameras(facing); - boolean meetH113 = (numOfPhysicalRgbCameras <= 1) || staticInfo.isLogicalMultiCamera(); - mCollector.expectTrue("Primary " + facingString + " camera must be LOGICAL_MULTI_CAMERA" - + " in case of multiple RGB cameras with same facing", - !assertTPerfClass || meetH113); - perfClassLevelH113 = updatePerfClassLevel(meetH113, perfClassLevelH113, - CameraTestUtils.PERFORMANCE_CLASS_S); - reportLog.addValue(facingString + " camera is LOGICAL_MULTI_CAMERA in case of multiple " - + "RGB cameras with same facing", meetH113, ResultType.NEUTRAL, - ResultUnit.NONE); + boolean logicalMultiCameraReqMet = + (numOfPhysicalRgbCameras <= 1) || staticInfo.isLogicalMultiCamera(); + if (isPrimaryRear) { + logicalMultiCameraReq.setRearLogicalMultiCameraReqMet(logicalMultiCameraReqMet); + } else { + logicalMultiCameraReq.setFrontLogicalMultiCameraReqMet(logicalMultiCameraReqMet); + } // H-1-14 - boolean meetH114 = staticInfo.isStreamUseCaseSupported(); - mCollector.expectTrue("Primary " + facingString + " camera must support stream " - + "use case", !assertTPerfClass || meetH114); - perfClassLevelH114 = updatePerfClassLevel(meetH114, perfClassLevelH114, - CameraTestUtils.PERFORMANCE_CLASS_S); - reportLog.addValue(facingString + " camera stream use case", meetH114, - ResultType.NEUTRAL, ResultUnit.NONE); - } - HashSet<String> primaryCameras = new HashSet<String>(); - if (primaryRearId == null) { - mCollector.expectTrue("There must be a primary rear camera for performance class.", - !assertPerfClass); - perfClassLevelH11 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } else { - primaryCameras.add(primaryRearId); - } - if (primaryFrontId == null) { - mCollector.expectTrue("There must be a primary front camera for performance class.", - !assertPerfClass); - perfClassLevelH12 = CameraTestUtils.PERFORMANCE_CLASS_NOT_MET; - } else { - primaryCameras.add(primaryFrontId); + boolean streamUseCaseSupported = staticInfo.isStreamUseCaseSupported(); + if (isPrimaryRear) { + streamUseCaseReq.setRearStreamUseCaseSupported(streamUseCaseSupported); + } else { + streamUseCaseReq.setFrontStreamUseCaseSupported(streamUseCaseSupported); + } } - // H-1-11 Set<Set<String>> concurrentCameraIds = mCameraManager.getConcurrentCameraIds(); boolean supportPrimaryFrontBack = concurrentCameraIds.contains(primaryCameras); - mCollector.expectTrue("Concurrent primary front and primary back streaming must be " - + "supported", !assertTPerfClass || supportPrimaryFrontBack); - perfClassLevelH111 = updatePerfClassLevel(supportPrimaryFrontBack, - perfClassLevelH111, CameraTestUtils.PERFORMANCE_CLASS_S); - reportLog.addValue("concurrent front back support", supportPrimaryFrontBack, - ResultType.NEUTRAL, ResultUnit.NONE); - - reportLog.addValue("Version", "0.0.1", ResultType.NEUTRAL, ResultUnit.NONE); - final String PERF_CLASS_REQ_NUM_PREFIX = "2.2.7.2/7.5/"; - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-1", - perfClassLevelH11, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-2", - perfClassLevelH12, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-3", - perfClassLevelH13, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-4", - perfClassLevelH14, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-8", - perfClassLevelH18, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-9", - perfClassLevelH19, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-10", - perfClassLevelH110, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-11", - perfClassLevelH111, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-12", - perfClassLevelH112, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-13", - perfClassLevelH113, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.addValue(PERF_CLASS_REQ_NUM_PREFIX + "H-1-14", - perfClassLevelH114, ResultType.NEUTRAL, ResultUnit.NONE); - reportLog.submit(InstrumentationRegistry.getInstrumentation()); + concurrentRearFrontReq.setConcurrentRearFrontSupported(supportPrimaryFrontBack); + + pce.submitAndCheck(); } /** diff --git a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java index 3c88a3a445c..c9c28eac4bf 100644 --- a/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java +++ b/tests/camera/src/android/hardware/camera2/cts/RecordingTest.java @@ -1234,8 +1234,13 @@ public class RecordingTest extends Camera2SurfaceViewTestCase { mOutMediaFileName = mDebugFileNameBase + "/test_cslowMo_video_" + captureRate + "fps_" + id + "_" + size.toString() + ".mp4"; - Log.v(TAG, "previewFrameRate:" + previewFrameRate); - prepareRecording(size, previewFrameRate, captureRate); + + // b/239101664 It appears that video frame rates higher than 30 fps may not + // trigger slow motion recording consistently. + int videoFrameRate = previewFrameRate > VIDEO_FRAME_RATE ? + VIDEO_FRAME_RATE : previewFrameRate; + Log.v(TAG, "videoFrameRate:" + videoFrameRate); + prepareRecording(size, videoFrameRate, captureRate); SystemClock.sleep(PREVIEW_DURATION_MS); @@ -1243,7 +1248,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase { SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); // Start recording - startSlowMotionRecording(/*useMediaRecorder*/true, previewFrameRate, + startSlowMotionRecording(/*useMediaRecorder*/true, videoFrameRate, captureRate, fpsRange, resultListener, /*useHighSpeedSession*/true); @@ -1256,7 +1261,7 @@ public class RecordingTest extends Camera2SurfaceViewTestCase { startConstrainedPreview(fpsRange, previewResultListener); // Convert number of frames camera produced into the duration in unit of ms. - float frameDurationMs = 1000.0f / previewFrameRate; + float frameDurationMs = 1000.0f / videoFrameRate; float durationMs = resultListener.getTotalNumFrames() * frameDurationMs; // Validation. diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java index e8d616880e7..4a86b49e51a 100644 --- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java +++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java @@ -142,8 +142,6 @@ public class CameraTestUtils extends Assert { public static final String OFFLINE_CAMERA_ID = "offline_camera_id"; public static final String REPORT_LOG_NAME = "CtsCameraTestCases"; - public static final String MPC_REPORT_LOG_NAME = "MediaPerformanceClassLogs"; - public static final String MPC_STREAM_NAME = "CameraCts"; private static final int EXIF_DATETIME_LENGTH = 19; private static final int EXIF_DATETIME_ERROR_MARGIN_SEC = 60; @@ -3815,33 +3813,6 @@ public class CameraTestUtils extends Assert { return zoomRatios; } - public static final int PERFORMANCE_CLASS_NOT_MET = 0; - public static final int PERFORMANCE_CLASS_R = Build.VERSION_CODES.R; - public static final int PERFORMANCE_CLASS_S = Build.VERSION_CODES.R + 1; - public static final int PERFORMANCE_CLASS_T = Build.VERSION_CODES.S + 2; - public static final int PERFORMANCE_CLASS_CURRENT = PERFORMANCE_CLASS_T; - - /** - * Check whether this mobile device is R performance class as defined in CDD - */ - public static boolean isRPerfClass() { - return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_R; - } - - /** - * Check whether this mobile device is S performance class as defined in CDD - */ - public static boolean isSPerfClass() { - return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_S; - } - - /** - * Check whether this mobile device is T performance class as defined in CDD - */ - public static boolean isTPerfClass() { - return Build.VERSION.MEDIA_PERFORMANCE_CLASS == PERFORMANCE_CLASS_T; - } - /** * Check whether a camera Id is a primary rear facing camera */ diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java index fc8c4db5164..f1886859d67 100644 --- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java +++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java @@ -229,6 +229,13 @@ public class StaticMetadata { * at least the desired one (but could be higher) */ public boolean isHardwareLevelAtLeast(int level) { + int deviceLevel = getHardwareLevelChecked(); + + return hardwareLevelPredicate(deviceLevel, level); + } + + // Return true if level1 is at least level2 + public static boolean hardwareLevelPredicate(int level1, int level2) { final int[] sortedHwLevels = { CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL, @@ -236,19 +243,19 @@ public class StaticMetadata { CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL, CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_3 }; - int deviceLevel = getHardwareLevelChecked(); - if (level == deviceLevel) { + + if (level1 == level2) { return true; } for (int sortedlevel : sortedHwLevels) { - if (sortedlevel == level) { + if (sortedlevel == level2) { return true; - } else if (sortedlevel == deviceLevel) { + } else if (sortedlevel == level1) { return false; } } - Assert.fail("Unknown hardwareLevel " + level + " and device hardware level " + deviceLevel); + Assert.fail("Unknown hardwareLevel " + level1 + " and device hardware level " + level2); return false; } diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java index 286ccae00a8..eee4b10d821 100644 --- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java +++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagementRoleHolderTest.java @@ -65,6 +65,7 @@ import com.android.bedstead.nene.utils.Poll; import com.android.bedstead.remotedpc.RemoteDpc; import com.android.bedstead.testapp.TestApp; import com.android.bedstead.testapp.TestAppInstance; +import com.android.compatibility.common.util.CddTest; import com.android.eventlib.truth.EventLogsSubject; import com.android.queryable.queries.ActivityQuery; @@ -140,6 +141,7 @@ public class DevicePolicyManagementRoleHolderTest { @EnsureHasNoDpc @EnsureHasNoSecondaryUser @Test + @CddTest(requirements = {"3.9.4/C-3-1"}) public void createAndProvisionManagedProfile_roleHolderIsInWorkProfile() throws ProvisioningException, InterruptedException { UserHandle profile = null; @@ -173,6 +175,7 @@ public class DevicePolicyManagementRoleHolderTest { @RequireRunOnPrimaryUser @EnsureHasNoSecondaryUser @Test + @CddTest(requirements = {"3.9.4/C-3-1"}) public void createAndManageUser_roleHolderIsInManagedUser() throws InterruptedException { UserHandle managedUser = null; String roleHolderPackageName = null; diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java index fcf71d0a19c..dfe77fb4121 100644 --- a/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java +++ b/tests/devicepolicy/src/android/devicepolicy/cts/UserControlDisabledPackagesTest.java @@ -45,6 +45,7 @@ import com.android.bedstead.harrier.policies.UserControlDisabledPackages; import com.android.bedstead.metricsrecorder.EnterpriseMetricsRecorder; import com.android.bedstead.nene.TestApis; import com.android.bedstead.nene.packages.Package; +import com.android.bedstead.nene.utils.Poll; import com.android.bedstead.testapp.TestApp; import com.android.bedstead.testapp.TestAppInstance; import com.android.queryable.queries.StringQuery; @@ -235,6 +236,11 @@ public final class UserControlDisabledPackagesTest { private void assertPackageStopped(String packageName) throws Exception { + Poll.forValue("Package " + packageName + " stopped", () -> isPackageStopped(packageName)) + .toBeEqualTo(true) + .errorOnFail() + .await(); + assertWithMessage("Package %s not stopped", packageName) .that(isPackageStopped(packageName)).isTrue(); } diff --git a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java index c13c4eec7f8..9fd1a41a416 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/TaskFragmentTrustedModeTest.java @@ -21,6 +21,7 @@ import static android.server.wm.jetpack.second.Components.SECOND_UNTRUSTED_EMBED import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.assumeActivityEmbeddingSupportedDevice; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -33,6 +34,7 @@ import android.content.Intent; import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; +import android.platform.test.annotations.Presubmit; import android.server.wm.WindowManagerState.Task; import android.window.TaskFragmentCreationParams; import android.window.TaskFragmentInfo; @@ -49,6 +51,7 @@ import org.junit.Test; * Build/Install/Run: * atest CtsWindowManagerDeviceTestCases:TaskFragmentTrustedModeTest */ +@Presubmit public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase { private final ComponentName mTranslucentActivity = new ComponentName(mContext, @@ -248,7 +251,7 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase { */ @Test public void testUntrustedModeTaskFragment_startActivityInTaskFragmentOutsideOfParentBounds() { - final Task parentTask = mWmState.getRootTask(mOwnerTaskId); + Task parentTask = mWmState.getRootTask(mOwnerTaskId); final Rect parentBounds = new Rect(parentTask.getBounds()); final IBinder errorCallbackToken = new Binder(); final WindowContainerTransaction wct = new WindowContainerTransaction() @@ -263,8 +266,11 @@ public class TaskFragmentTrustedModeTest extends TaskFragmentOrganizerTestBase { // It is disallowed to start activity to TaskFragment with bounds outside of its parent // in untrusted mode. assertTaskFragmentError(errorCallbackToken, SecurityException.class); - mWmState.waitForAppTransitionIdleOnDisplay(mOwnerActivity.getDisplayId()); - mWmState.assertNotExist(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY); + + parentTask = mWmState.getRootTask(mOwnerTaskId); + assertWithMessage("Activity must be started in parent Task because it's not" + + " allowed to be embedded").that(parentTask.mActivities).contains( + mWmState.getActivity(SECOND_UNTRUSTED_EMBEDDING_ACTIVITY)); } /** diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java index 65465b27895..8dc33b1f745 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java @@ -59,6 +59,7 @@ import android.app.AlertDialog; import android.app.Instrumentation; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.os.Bundle; import android.os.SystemClock; import android.platform.test.annotations.Presubmit; @@ -226,6 +227,11 @@ public class WindowInsetsControllerTests extends WindowManagerTestBase { final Instrumentation instrumentation = getInstrumentation(); assumeThat(MockImeSession.getUnavailabilityReason(instrumentation.getContext()), nullValue()); + final Resources resources = instrumentation.getContext().getResources(); + final boolean isHideNavBarForKeyboardEnabled = resources.getBoolean( + resources.getIdentifier("config_hideNavBarForKeyboard", "bool", "android")); + assumeFalse("Device is configured to not show navigation bar for keyboard", + isHideNavBarForKeyboardEnabled); final MockImeSession imeSession = MockImeHelper.createManagedMockImeSession(this); final ImeEventStream stream = imeSession.openEventStream(); final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class); diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java index ccd8659e3de..8855dee537b 100644 --- a/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java +++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/Watermark.java @@ -32,7 +32,7 @@ public final class Watermark { * * <p>See Bug 174534092 about why we ended up having this.</p> */ - private static final int TOLERANCE = 4; + private static final int TOLERANCE = 6; /** * A utility class that represents A8R8G8B bitmap as an integer array. diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java index 5f9aa09c891..39b90fff698 100644 --- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java +++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java @@ -158,10 +158,10 @@ public class CodecInfoTest { .noneMatch(x -> x == COLOR_FormatSurface)); } - // For devices launching with Android T, if a codec supports an HDR profile, it must - // advertise P010 support + // For devices launching with Android T, if a codec supports an HDR profile and device + // supports HDR display, it must advertise P010 support int[] HdrProfileArray = mProfileHdrMap.get(mMediaType); - if (FIRST_SDK_IS_AT_LEAST_T && HdrProfileArray != null) { + if (FIRST_SDK_IS_AT_LEAST_T && HdrProfileArray != null && DISPLAY_HDR_TYPES.length > 0) { for (CodecProfileLevel pl : caps.profileLevels) { if (IntStream.of(HdrProfileArray).anyMatch(x -> x == pl.profile)) { assertFalse(mCodecInfo.getName() + " supports HDR profile " + pl.profile + "," + diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java index 327fb9cf6c9..d3fd2921d5a 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.junit.Assume.assumeTrue; +import android.hardware.camera2.CameraMetadata; import android.media.MediaFormat; import android.os.Build; @@ -849,7 +850,493 @@ public class PerformanceClassEvaluator { } } - private <R extends Requirement> R addRequirement(R req) { + public static class PrimaryCameraRequirement extends Requirement { + private static final long MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION = 12000000; + private static final long MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION = 5000000; + private static final long MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION = 4000000; + private static final String TAG = PrimaryCameraRequirement.class.getSimpleName(); + + private PrimaryCameraRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setPrimaryCameraSupported(boolean hasPrimaryCamera) { + this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_AVAILABLE, + hasPrimaryCamera); + } + + public void setResolution(long resolution) { + this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_RESOLUTION, + resolution); + } + + public void setVideoSizeReqSatisfied(boolean videoSizeReqSatisfied) { + this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED, + videoSizeReqSatisfied); + } + + public void setVideoFps(double videoFps) { + this.setMeasuredValue(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS, videoFps); + } + + /** + * [2.2.7.2/7.5/H-1-1] MUST have a primary rear facing camera with a resolution of at + * least 12 megapixels supporting video capture at 4k@30fps + */ + public static PrimaryCameraRequirement createRearPrimaryCamera() { + RequiredMeasurement<Boolean> hasPrimaryCamera = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_AVAILABLE) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.R, true) + .addRequiredValue(Build.VERSION_CODES.S, true) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + RequiredMeasurement<Long> cameraResolution = RequiredMeasurement + .<Long>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_RESOLUTION) + .setPredicate(RequirementConstants.LONG_GTE) + .addRequiredValue(Build.VERSION_CODES.R, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION) + .addRequiredValue(Build.VERSION_CODES.S, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, MIN_BACK_SENSOR_PERF_CLASS_RESOLUTION) + .build(); + + RequiredMeasurement<Boolean> videoSizeReqSatisfied = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.R, true) + .addRequiredValue(Build.VERSION_CODES.S, true) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + RequiredMeasurement<Double> videoFps = RequiredMeasurement + .<Double>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + .addRequiredValue(Build.VERSION_CODES.R, 29.9) + .addRequiredValue(Build.VERSION_CODES.S, 29.9) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 29.9) + .build(); + + return new PrimaryCameraRequirement(RequirementConstants.R7_5__H_1_1, + hasPrimaryCamera, cameraResolution, videoSizeReqSatisfied, + videoFps); + } + + /** + * [2.2.7.2/7.5/H-1-2] MUST have a primary front facing camera with a resolution of + * at least 4 megapixels supporting video capture at 1080p@30fps. + */ + public static PrimaryCameraRequirement createFrontPrimaryCamera() { + RequiredMeasurement<Boolean> hasPrimaryCamera = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_AVAILABLE) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.R, true) + .addRequiredValue(Build.VERSION_CODES.S, true) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + RequiredMeasurement<Long> cameraResolution = RequiredMeasurement + .<Long>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_RESOLUTION) + .setPredicate(RequirementConstants.LONG_GTE) + .addRequiredValue(Build.VERSION_CODES.R, MIN_FRONT_SENSOR_R_PERF_CLASS_RESOLUTION) + .addRequiredValue(Build.VERSION_CODES.S, MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, + MIN_FRONT_SENSOR_S_PERF_CLASS_RESOLUTION) + .build(); + + RequiredMeasurement<Boolean> videoSizeReqSatisfied = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.R, true) + .addRequiredValue(Build.VERSION_CODES.S, true) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + RequiredMeasurement<Double> videoFps = RequiredMeasurement + .<Double>builder() + .setId(RequirementConstants.PRIMARY_CAMERA_VIDEO_FPS) + .setPredicate(RequirementConstants.DOUBLE_GTE) + .addRequiredValue(Build.VERSION_CODES.R, 29.9) + .addRequiredValue(Build.VERSION_CODES.S, 29.9) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 29.9) + .build(); + + return new PrimaryCameraRequirement(RequirementConstants.R7_5__H_1_2, + hasPrimaryCamera, cameraResolution, videoSizeReqSatisfied, + videoFps); + } + } + + public static class CameraTimestampSourceRequirement extends Requirement { + private static final String TAG = CameraTimestampSourceRequirement.class.getSimpleName(); + private static final int TIMESTAMP_REALTIME = + CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME; + + private CameraTimestampSourceRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearCameraTimestampSource(Integer timestampSource) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_TIMESTAMP_SOURCE, + timestampSource); + } + + public void setFrontCameraTimestampSource(Integer timestampSource) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_TIMESTAMP_SOURCE, + timestampSource); + } + /** + * [2.2.7.2/7.5/H-1-4] MUST support CameraMetadata.SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME + * for both primary cameras. + */ + public static CameraTimestampSourceRequirement createTimestampSourceReq() { + RequiredMeasurement<Integer> rearTimestampSource = RequiredMeasurement + .<Integer>builder() + .setId(RequirementConstants.REAR_CAMERA_TIMESTAMP_SOURCE) + .setPredicate(RequirementConstants.INTEGER_EQ) + .addRequiredValue(Build.VERSION_CODES.R, TIMESTAMP_REALTIME) + .addRequiredValue(Build.VERSION_CODES.S, TIMESTAMP_REALTIME) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TIMESTAMP_REALTIME) + .build(); + RequiredMeasurement<Integer> frontTimestampSource = RequiredMeasurement + .<Integer>builder() + .setId(RequirementConstants.FRONT_CAMERA_TIMESTAMP_SOURCE) + .setPredicate(RequirementConstants.INTEGER_EQ) + .addRequiredValue(Build.VERSION_CODES.R, TIMESTAMP_REALTIME) + .addRequiredValue(Build.VERSION_CODES.S, TIMESTAMP_REALTIME) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, TIMESTAMP_REALTIME) + .build(); + + return new CameraTimestampSourceRequirement(RequirementConstants.R7_5__H_1_4, + rearTimestampSource, frontTimestampSource); + } + } + + public static class CameraLatencyRequirement extends Requirement { + private static final String TAG = CameraTimestampSourceRequirement.class.getSimpleName(); + + private CameraLatencyRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearCameraLatency(float latency) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_LATENCY, latency); + } + + public void setFrontCameraLatency(float latency) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_LATENCY, latency); + } + + /** + * [2.2.7.2/7.5/H-1-5] MUST have camera2 JPEG capture latency < 1000ms for 1080p resolution + * as measured by the CTS camera PerformanceTest under ITS lighting conditions + * (3000K) for both primary cameras. + */ + public static CameraLatencyRequirement createJpegLatencyReq() { + RequiredMeasurement<Float> rearJpegLatency = RequiredMeasurement + .<Float>builder() + .setId(RequirementConstants.REAR_CAMERA_LATENCY) + .setPredicate(RequirementConstants.FLOAT_LTE) + .addRequiredValue(Build.VERSION_CODES.R, 1000.0f) + .addRequiredValue(Build.VERSION_CODES.S, 1000.0f) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1000.0f) + .build(); + RequiredMeasurement<Float> frontJpegLatency = RequiredMeasurement + .<Float>builder() + .setId(RequirementConstants.FRONT_CAMERA_LATENCY) + .setPredicate(RequirementConstants.FLOAT_LTE) + .addRequiredValue(Build.VERSION_CODES.R, 1000.0f) + .addRequiredValue(Build.VERSION_CODES.S, 1000.0f) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 1000.0f) + .build(); + + return new CameraLatencyRequirement(RequirementConstants.R7_5__H_1_5, + rearJpegLatency, frontJpegLatency); + } + + /** + * [2.2.7.2/7.5/H-1-6] MUST have camera2 startup latency (open camera to first + * preview frame) < 600ms as measured by the CTS camera PerformanceTest under ITS lighting + * conditions (3000K) for both primary cameras. + */ + public static CameraLatencyRequirement createLaunchLatencyReq() { + RequiredMeasurement<Float> rearLaunchLatency = RequiredMeasurement + .<Float>builder() + .setId(RequirementConstants.REAR_CAMERA_LATENCY) + .setPredicate(RequirementConstants.FLOAT_LTE) + .addRequiredValue(Build.VERSION_CODES.R, 600.0f) + .addRequiredValue(Build.VERSION_CODES.S, 600.0f) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 600.0f) + .build(); + RequiredMeasurement<Float> frontLaunchLatency = RequiredMeasurement + .<Float>builder() + .setId(RequirementConstants.FRONT_CAMERA_LATENCY) + .setPredicate(RequirementConstants.FLOAT_LTE) + .addRequiredValue(Build.VERSION_CODES.R, 600.0f) + .addRequiredValue(Build.VERSION_CODES.S, 600.0f) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 600.0f) + .build(); + + return new CameraLatencyRequirement(RequirementConstants.R7_5__H_1_6, + rearLaunchLatency, frontLaunchLatency); + } + } + + public static class CameraRawRequirement extends Requirement { + private static final String TAG = CameraRawRequirement.class.getSimpleName(); + + private CameraRawRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearRawSupported(boolean rearRawSupported) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_RAW_SUPPORTED, + rearRawSupported); + } + + /** + * [2.2.7.2/7.5/H-1-8] MUST support CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_RAW and + * android.graphics.ImageFormat.RAW_SENSOR for the primary back camera. + */ + public static CameraRawRequirement createRawReq() { + RequiredMeasurement<Boolean> requirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.REAR_CAMERA_RAW_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.S, true) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new CameraRawRequirement(RequirementConstants.R7_5__H_1_8, requirement); + } + } + + public static class Camera240FpsRequirement extends Requirement { + private static final String TAG = Camera240FpsRequirement.class.getSimpleName(); + + private Camera240FpsRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRear240FpsSupported(boolean rear240FpsSupported) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_240FPS_SUPPORTED, + rear240FpsSupported); + } + + /** + * [2.2.7.2/7.5/H-1-9] MUST have a rear-facing primary camera supporting 720p or 1080p @ 240fps. + */ + public static Camera240FpsRequirement create240FpsReq() { + RequiredMeasurement<Boolean> requirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.REAR_CAMERA_240FPS_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new Camera240FpsRequirement(RequirementConstants.R7_5__H_1_9, requirement); + } + } + + public static class UltraWideZoomRatioRequirement extends Requirement { + private static final String TAG = + UltraWideZoomRatioRequirement.class.getSimpleName(); + + private UltraWideZoomRatioRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearUltraWideZoomRatioReqMet(boolean ultrawideZoomRatioReqMet) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET, + ultrawideZoomRatioReqMet); + } + + public void setFrontUltraWideZoomRatioReqMet(boolean ultrawideZoomRatioReqMet) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET, + ultrawideZoomRatioReqMet); + } + + /** + * [2.2.7.2/7.5/H-1-10] MUST have min ZOOM_RATIO < 1.0 for the primary cameras if + * there is an ultrawide RGB camera facing the same direction. + */ + public static UltraWideZoomRatioRequirement createUltrawideZoomRatioReq() { + RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new UltraWideZoomRatioRequirement(RequirementConstants.R7_5__H_1_10, + rearRequirement, frontRequirement); + } + } + + public static class ConcurrentRearFrontRequirement extends Requirement { + private static final String TAG = ConcurrentRearFrontRequirement.class.getSimpleName(); + + private ConcurrentRearFrontRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setConcurrentRearFrontSupported(boolean concurrentRearFrontSupported) { + this.setMeasuredValue(RequirementConstants.CONCURRENT_REAR_FRONT_SUPPORTED, + concurrentRearFrontSupported); + } + + /** + * [2.2.7.2/7.5/H-1-11] MUST implement concurrent front-back streaming on primary cameras. + */ + public static ConcurrentRearFrontRequirement createConcurrentRearFrontReq() { + RequiredMeasurement<Boolean> requirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.CONCURRENT_REAR_FRONT_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new ConcurrentRearFrontRequirement(RequirementConstants.R7_5__H_1_11, + requirement); + } + } + + public static class PreviewStabilizationRequirement extends Requirement { + private static final String TAG = + PreviewStabilizationRequirement.class.getSimpleName(); + + private PreviewStabilizationRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearPreviewStabilizationSupported(boolean supported) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED, + supported); + } + + public void setFrontPreviewStabilizationSupported(boolean supported) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED, + supported); + } + + /** + * [2.2.7.2/7.5/H-1-12] MUST support CONTROL_VIDEO_STABILIZATION_MODE_PREVIEW_STABILIZATION + * for both primary front and primary back camera. + */ + public static PreviewStabilizationRequirement createPreviewStabilizationReq() { + RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new PreviewStabilizationRequirement(RequirementConstants.R7_5__H_1_12, + rearRequirement, frontRequirement); + } + } + + public static class LogicalMultiCameraRequirement extends Requirement { + private static final String TAG = + LogicalMultiCameraRequirement.class.getSimpleName(); + + private LogicalMultiCameraRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearLogicalMultiCameraReqMet(boolean reqMet) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET, + reqMet); + } + + public void setFrontLogicalMultiCameraReqMet(boolean reqMet) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET, + reqMet); + } + + /** + * [2.2.7.2/7.5/H-1-13] MUST support LOGICAL_MULTI_CAMERA capability for the primary + * cameras if there are greater than 1 RGB cameras facing the same direction. + */ + public static LogicalMultiCameraRequirement createLogicalMultiCameraReq() { + RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new LogicalMultiCameraRequirement(RequirementConstants.R7_5__H_1_13, + rearRequirement, frontRequirement); + } + } + + public static class StreamUseCaseRequirement extends Requirement { + private static final String TAG = + StreamUseCaseRequirement.class.getSimpleName(); + + private StreamUseCaseRequirement(String id, RequiredMeasurement<?> ... reqs) { + super(id, reqs); + } + + public void setRearStreamUseCaseSupported(boolean supported) { + this.setMeasuredValue(RequirementConstants.REAR_CAMERA_STREAM_USECASE_SUPPORTED, + supported); + } + + public void setFrontStreamUseCaseSupported(boolean supported) { + this.setMeasuredValue(RequirementConstants.FRONT_CAMERA_STREAM_USECASE_SUPPORTED, + supported); + } + + /** + * [2.2.7.2/7.5/H-1-14] MUST support STREAM_USE_CASE capability for both primary + * front and primary back camera. + */ + public static StreamUseCaseRequirement createStreamUseCaseReq() { + RequiredMeasurement<Boolean> rearRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.REAR_CAMERA_STREAM_USECASE_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + RequiredMeasurement<Boolean> frontRequirement = RequiredMeasurement + .<Boolean>builder() + .setId(RequirementConstants.FRONT_CAMERA_STREAM_USECASE_SUPPORTED) + .setPredicate(RequirementConstants.BOOLEAN_EQ) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, true) + .build(); + + return new StreamUseCaseRequirement(RequirementConstants.R7_5__H_1_14, + rearRequirement, frontRequirement); + } + } + + public <R extends Requirement> R addRequirement(R req) { if (!this.mRequirements.add(req)) { throw new IllegalStateException("Requirement " + req.id() + " already added"); } @@ -1000,16 +1487,69 @@ public class PerformanceClassEvaluator { return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_10()); } + public PrimaryCameraRequirement addPrimaryRearCameraReq() { + return this.addRequirement(PrimaryCameraRequirement.createRearPrimaryCamera()); + } + + public PrimaryCameraRequirement addPrimaryFrontCameraReq() { + return this.addRequirement(PrimaryCameraRequirement.createFrontPrimaryCamera()); + } + + public CameraTimestampSourceRequirement addR7_5__H_1_4() { + return this.addRequirement(CameraTimestampSourceRequirement.createTimestampSourceReq()); + } + + public CameraLatencyRequirement addR7_5__H_1_5() { + return this.addRequirement(CameraLatencyRequirement.createJpegLatencyReq()); + } + + public CameraLatencyRequirement addR7_5__H_1_6() { + return this.addRequirement(CameraLatencyRequirement.createLaunchLatencyReq()); + } + + public CameraRawRequirement addR7_5__H_1_8() { + return this.addRequirement(CameraRawRequirement.createRawReq()); + } + + public Camera240FpsRequirement addR7_5__H_1_9() { + return this.addRequirement(Camera240FpsRequirement.create240FpsReq()); + } + + public UltraWideZoomRatioRequirement addR7_5__H_1_10() { + return this.addRequirement(UltraWideZoomRatioRequirement.createUltrawideZoomRatioReq()); + } + + public ConcurrentRearFrontRequirement addR7_5__H_1_11() { + return this.addRequirement(ConcurrentRearFrontRequirement.createConcurrentRearFrontReq()); + } + + public PreviewStabilizationRequirement addR7_5__H_1_12() { + return this.addRequirement(PreviewStabilizationRequirement.createPreviewStabilizationReq()); + } + + public LogicalMultiCameraRequirement addR7_5__H_1_13() { + return this.addRequirement(LogicalMultiCameraRequirement.createLogicalMultiCameraReq()); + } + + public StreamUseCaseRequirement addR7_5__H_1_14() { + return this.addRequirement(StreamUseCaseRequirement.createStreamUseCaseReq()); + } + public void submitAndCheck() { - boolean perfClassMet = true; - for (Requirement req: this.mRequirements) { - perfClassMet &= req.writeLogAndCheck(this.mTestName); - } + boolean perfClassMet = submit(); // check performance class assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass()); assertThat(perfClassMet).isTrue(); + } + public boolean submit() { + boolean perfClassMet = true; + for (Requirement req: this.mRequirements) { + perfClassMet &= req.writeLogAndCheck(this.mTestName); + } this.mRequirements.clear(); // makes sure report isn't submitted twice + return perfClassMet; } + } diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java index d93cb2e0a00..ad0d0d5694f 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java @@ -16,8 +16,6 @@ package android.mediapc.cts.common; -import android.os.Build; - import java.util.function.BiPredicate; public class RequirementConstants { @@ -54,8 +52,13 @@ public class RequirementConstants { public static final String R7_5__H_1_4 = "r7_5__h_1_4"; // 7.5/H-1-4 public static final String R7_5__H_1_5 = "r7_5__h_1_5"; // 7.5/H-1-5 public static final String R7_5__H_1_6 = "r7_5__h_1_6"; // 7.5/H-1-6 - public static final String R7_5__H_1_7 = "r7_5__h_1_7"; // 7.5/H-1-7 public static final String R7_5__H_1_8 = "r7_5__h_1_8"; // 7.5/H-1-8 + public static final String R7_5__H_1_9 = "r7_5__h_1_9"; // 7.5/H-1-9 + public static final String R7_5__H_1_10 = "r7_5__h_1_10"; // 7.5/H-1-10 + public static final String R7_5__H_1_11 = "r7_5__h_1_11"; // 7.5/H-1-11 + public static final String R7_5__H_1_12 = "r7_5__h_1_12"; // 7.5/H-1-12 + public static final String R7_5__H_1_13 = "r7_5__h_1_13"; // 7.5/H-1-13 + public static final String R7_5__H_1_14 = "r7_5__h_1_14"; // 7.5/H-1-14 public static final String R7_1_1_1__H_1_1 = "r7_1_1_1__h_1_1"; // 7.1.1.1/H-1-1 public static final String R7_1_1_3__H_1_1 = "r7_1_1_3__h_1_1"; // 7.1.1.3/H-1-1 public static final String R7_6_1__H_1_1 = "r7_6_1__h_1_1"; // 7.6.1/H-1-1 @@ -90,14 +93,50 @@ public class RequirementConstants { public static final String NUM_CRYPTO_HW_SECURE_ALL_SUPPORT = "number_crypto_hw_secure_all_support"; + public static final String PRIMARY_CAMERA_AVAILABLE = "primary_camera_available"; + public static final String PRIMARY_CAMERA_RESOLUTION = "primary_camera_resolution"; + public static final String PRIMARY_CAMERA_VIDEO_SIZE_REQ_SATISFIED = + "primary_camera_video_size_req_satisfied"; + public static final String PRIMARY_CAMERA_VIDEO_FPS = + "primary_camera_video_fps"; + public static final String REAR_CAMERA_HWL_LEVEL = "rear_primary_camera_hwl_level"; + public static final String FRONT_CAMERA_HWL_LEVEL = "front_primary_camera_hwl_level"; + public static final String REAR_CAMERA_TIMESTAMP_SOURCE = + "rear_primary_camera_timestamp_source"; + public static final String FRONT_CAMERA_TIMESTAMP_SOURCE = + "front_primary_camera_timestamp_source"; + public static final String REAR_CAMERA_LATENCY = "rear_camera_latency"; + public static final String FRONT_CAMERA_LATENCY = "front_camera_latency"; + public static final String REAR_CAMERA_RAW_SUPPORTED = "rear_camera_raw_supported"; + public static final String REAR_CAMERA_240FPS_SUPPORTED = "rear_camera_240fps_supported"; + public static final String REAR_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET = + "rear_camera_ultrawide_zoom_req_met"; + public static final String FRONT_CAMERA_ULTRAWIDE_ZOOMRATIO_REQ_MET = + "front_camera_ultrawide_zoom_req_met"; + public static final String CONCURRENT_REAR_FRONT_SUPPORTED = "rear_front_concurrent_camera"; + public static final String REAR_CAMERA_PREVIEW_STABILIZATION_SUPPORTED = + "rear_camera_preview_stabilization_supported"; + public static final String FRONT_CAMERA_PREVIEW_STABILIZATION_SUPPORTED = + "front_camera_preview_stabilization_supported"; + public static final String REAR_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET = + "rear_camera_logical_multi_camera_req_met"; + public static final String FRONT_CAMERA_LOGICAL_MULTI_CAMERA_REQ_MET = + "front_camera_logical_multi_camera_req_met"; + public static final String REAR_CAMERA_STREAM_USECASE_SUPPORTED = + "rear_camera_stream_usecase_supported"; + public static final String FRONT_CAMERA_STREAM_USECASE_SUPPORTED = + "front_camera_stream_usecase_supported"; + public enum Result { NA, MET, UNMET } public static final BiPredicate<Long, Long> LONG_GTE = RequirementConstants.gte(); public static final BiPredicate<Long, Long> LONG_LTE = RequirementConstants.lte(); + public static final BiPredicate<Float, Float> FLOAT_LTE = RequirementConstants.lte(); public static final BiPredicate<Integer, Integer> INTEGER_GTE = RequirementConstants.gte(); public static final BiPredicate<Integer, Integer> INTEGER_LTE = RequirementConstants.lte(); + public static final BiPredicate<Integer, Integer> INTEGER_EQ = RequirementConstants.eq(); public static final BiPredicate<Double, Double> DOUBLE_EQ = RequirementConstants.eq(); public static final BiPredicate<Boolean, Boolean> BOOLEAN_EQ = RequirementConstants.eq(); public static final BiPredicate<Double, Double> DOUBLE_GTE = RequirementConstants.gte(); diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java index ac03705a1a2..28a122b4521 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java @@ -73,16 +73,24 @@ public class Utils { Context context = InstrumentationRegistry.getInstrumentation().getContext(); DisplayMetrics metrics = new DisplayMetrics(); - WindowManager windowManager = context.getSystemService(WindowManager.class); - windowManager.getDefaultDisplay().getMetrics(metrics); - DISPLAY_DPI = metrics.densityDpi; - DISPLAY_LONG_PIXELS = Math.max(metrics.widthPixels, metrics.heightPixels); - DISPLAY_SHORT_PIXELS = Math.min(metrics.widthPixels, metrics.heightPixels); - - ActivityManager activityManager = context.getSystemService(ActivityManager.class); - ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); - activityManager.getMemoryInfo(memoryInfo); - TOTAL_MEMORY_MB = memoryInfo.totalMem / 1024 / 1024; + // When used from ItsService, context will be null + if (context != null) { + WindowManager windowManager = context.getSystemService(WindowManager.class); + windowManager.getDefaultDisplay().getMetrics(metrics); + DISPLAY_DPI = metrics.densityDpi; + DISPLAY_LONG_PIXELS = Math.max(metrics.widthPixels, metrics.heightPixels); + DISPLAY_SHORT_PIXELS = Math.min(metrics.widthPixels, metrics.heightPixels); + + ActivityManager activityManager = context.getSystemService(ActivityManager.class); + ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); + activityManager.getMemoryInfo(memoryInfo); + TOTAL_MEMORY_MB = memoryInfo.totalMem / 1024 / 1024; + } else { + DISPLAY_DPI = 0; + DISPLAY_LONG_PIXELS = 0; + DISPLAY_SHORT_PIXELS = 0; + TOTAL_MEMORY_MB = 0; + } } /** diff --git a/tests/tests/assist/common/src/android/assist/common/Utils.java b/tests/tests/assist/common/src/android/assist/common/Utils.java index 0ffcb271093..98e857689cf 100755 --- a/tests/tests/assist/common/src/android/assist/common/Utils.java +++ b/tests/tests/assist/common/src/android/assist/common/Utils.java @@ -56,6 +56,7 @@ public class Utils { public static final String COMPARE_SCREENSHOT_KEY = "compare_screenshot"; public static final String DISPLAY_WIDTH_KEY = "display_width"; public static final String DISPLAY_HEIGHT_KEY = "dislay_height"; + public static final String DISPLAY_AREA_BOUNDS_KEY = "display_area_bounds"; public static final String SCROLL_X_POSITION = "scroll_x_position"; public static final String SCROLL_Y_POSITION = "scroll_y_position"; public static final String SHOW_SESSION_FLAGS_TO_SET = "show_session_flags_to_set"; diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java index 7f35367333a..25c080b9c0c 100644 --- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java +++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java @@ -56,6 +56,7 @@ public class MainInteractionSession extends VoiceInteractionSession { private int mCurColor; private int mDisplayHeight; private int mDisplayWidth; + private Rect mDisplayAreaBounds; private BroadcastReceiver mReceiver; private String mTestName; private View mContentView; @@ -106,7 +107,7 @@ public class MainInteractionSession extends VoiceInteractionSession { public void onPrepareShow(Bundle args, int showFlags) { if (Utils.LIFECYCLE_NOUI.equals(args.getString(Utils.TESTCASE_TYPE, ""))) { setUiEnabled(false); - } else { + } else { setUiEnabled(true); } } @@ -122,6 +123,7 @@ public class MainInteractionSession extends VoiceInteractionSession { mCurColor = args.getInt(Utils.SCREENSHOT_COLOR_KEY); mDisplayHeight = args.getInt(Utils.DISPLAY_HEIGHT_KEY); mDisplayWidth = args.getInt(Utils.DISPLAY_WIDTH_KEY); + mDisplayAreaBounds = args.getParcelable(Utils.DISPLAY_AREA_BOUNDS_KEY); mRemoteCallback = args.getParcelable(Utils.EXTRA_REMOTE_CALLBACK); super.onShow(args, showFlags); if (mContentView == null) return; // Happens when ui is not enabled. @@ -256,6 +258,11 @@ public class MainInteractionSession extends VoiceInteractionSession { int[] pixels = new int[size.x * size.y]; screenshot.getPixels(pixels, 0, size.x, 0, 0, size.x, size.y); + // screenshot bitmap contains the screenshot for the entire physical display. A single + // physical display could have multiple display area with different applications. + // Let's grab the region of the display area from the original screenshot. + Bitmap displayAreaScreenshot = Bitmap.createBitmap(screenshot, mDisplayAreaBounds.left, + mDisplayAreaBounds.top, mDisplayAreaBounds.width(), mDisplayAreaBounds.height()); int expectedColor = 0; for (int pixel : pixels) { // Check for roughly the same because there are rounding errors converting from the @@ -267,7 +274,7 @@ public class MainInteractionSession extends VoiceInteractionSession { } } - int pixelCount = screenshot.getWidth() * screenshot.getHeight(); + int pixelCount = displayAreaScreenshot.getWidth() * displayAreaScreenshot.getHeight(); double colorRatio = (double) expectedColor / pixelCount; Log.i(TAG, "the ratio is " + colorRatio); return colorRatio >= 0.6; diff --git a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java index 44a3109a740..c89119bdea1 100644 --- a/tests/tests/assist/src/android/assist/cts/AssistTestBase.java +++ b/tests/tests/assist/src/android/assist/cts/AssistTestBase.java @@ -35,9 +35,9 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Point; +import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; -import android.os.HandlerThread; import android.os.LocaleList; import android.os.RemoteCallback; import android.provider.Settings; @@ -341,6 +341,8 @@ abstract class AssistTestBase { Display.Mode dMode = mTestActivity.getWindowManager().getDefaultDisplay().getMode(); mDisplaySize = new Point(dMode.getPhysicalWidth(), dMode.getPhysicalHeight()); } + Rect bounds = mTestActivity.getWindowManager().getMaximumWindowMetrics().getBounds(); + intent.putExtra(Utils.DISPLAY_AREA_BOUNDS_KEY, bounds); intent.putExtra(Utils.DISPLAY_WIDTH_KEY, mDisplaySize.x); intent.putExtra(Utils.DISPLAY_HEIGHT_KEY, mDisplaySize.y); } diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml index 9a3075beee6..98189620bab 100644 --- a/tests/tests/bluetooth/AndroidTest.xml +++ b/tests/tests/bluetooth/AndroidTest.xml @@ -33,6 +33,6 @@ <!-- Only run Cts Tests in MTS if the Bluetooth Mainline module is installed. --> <object type="module_controller" class="com.android.tradefed.testtype.suite.module.MainlineTestModuleController"> - <option name="mainline-module-package-name" value="com.google.android.bluetooth" /> + <option name="mainline-module-package-name" value="com.android.btservices" /> </object> </configuration> diff --git a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java index 49b72549b7e..8bd1bb8fb33 100644 --- a/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java +++ b/tests/tests/content/CtsSyncAccountAccessOtherCertTests/src/com/android/cts/content/CtsSyncAccountAccessOtherCertTestCases.java @@ -43,6 +43,9 @@ import android.content.res.Configuration; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiDevice; import android.support.test.uiautomator.UiObject2; +import android.support.test.uiautomator.UiObjectNotFoundException; +import android.support.test.uiautomator.UiScrollable; +import android.support.test.uiautomator.UiSelector; import android.support.test.uiautomator.Until; import android.util.Log; @@ -140,7 +143,7 @@ public class CtsSyncAccountAccessOtherCertTestCases { } catch (Throwable t) { if (scrollUps < 10) { // The notification we search for is below the fold, scroll to find it - swipeUp(uiDevice); + scrollNotifications(); scrollUps++; continue; } @@ -200,6 +203,18 @@ public class CtsSyncAccountAccessOtherCertTestCases { 50 /* numberOfSteps */); } + private boolean scrollNotifications() { + UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true)); + if (!scrollable.exists()) { + return false; + } + try { + return scrollable.scrollForward(50); + } catch (UiObjectNotFoundException e) { + return false; + } + } + private boolean isRunningInVR() { final Context context = InstrumentationRegistry.getTargetContext(); return ((context.getResources().getConfiguration().uiMode & diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTest.java index a424edbd8c5..0b8c50598b1 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 @@ -124,10 +124,10 @@ public class DecoderTest extends MediaTestBase { private static final int CONFIG_MODE_NONE = 0; private static final int CONFIG_MODE_QUEUE = 1; - private static final int CODEC_ALL = 0; // All codecs must support - private static final int CODEC_ANY = 1; // At least one codec must support - private static final int CODEC_DEFAULT = 2; // Default codec must support - private static final int CODEC_OPTIONAL = 3; // Codec support is optional + public static final int CODEC_ALL = 0; // All codecs must support + public static final int CODEC_ANY = 1; // At least one codec must support + public static final int CODEC_DEFAULT = 2; // Default codec must support + public static final int CODEC_OPTIONAL = 3; // Codec support is optional short[] mMasterBuffer; static final String mInpPrefix = WorkDir.getMediaDirString(); diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java index f34f9e23146..0857809211e 100644 --- a/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java +++ b/tests/tests/media/decoder/src/android/media/decoder/cts/DecoderTestAacFormat.java @@ -81,9 +81,9 @@ public class DecoderTestAacFormat { AudioFormat.CHANNEL_OUT_QUAD | AudioFormat.CHANNEL_OUT_FRONT_CENTER}, {"noise_6ch_44khz_aot5_dr_sbr_sig2_mp4.m4a", 6, AudioFormat.CHANNEL_OUT_5POINT1}, }; - - for (Object [] sample: samples) { - for (String codecName : DecoderTest.codecsFor((String)sample[0] /* resource */)) { + for (Object[] sample: samples) { + for (String codecName : DecoderTest.codecsFor((String)sample[0] /* resource */, + DecoderTest.CODEC_DEFAULT)) { // verify correct number of channels is observed without downmixing AudioParameter chanParams = new AudioParameter(); decodeUpdateFormat(codecName, (String) sample[0] /*resource*/, chanParams, diff --git a/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt b/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt index f057b21a849..931ecd1bc6b 100644 --- a/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt +++ b/tests/tests/permission/src/android/permission/cts/SafetyCenterUtils.kt @@ -67,7 +67,7 @@ object SafetyCenterUtils { @JvmStatic fun assertSafetyCenterStarted() { // CollapsingToolbar title can't be found by text, so using description instead. - waitFindObject(By.desc("Security & Privacy")) + waitFindObject(By.desc("Security & privacy")) } @JvmStatic diff --git a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt index 598a59a1727..872a243ce2e 100644 --- a/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt +++ b/tests/tests/permission4/src/android/permission4/cts/CameraMicIndicatorsPermissionTest.kt @@ -78,6 +78,8 @@ private const val IDLE_TIMEOUT_MILLIS: Long = 1000 private const val UNEXPECTED_TIMEOUT_MILLIS = 1000 private const val TIMEOUT_MILLIS: Long = 20000 private const val TV_MIC_INDICATOR_WINDOW_TITLE = "MicrophoneCaptureIndicator" +private const val MIC_LABEL_NAME = "microphone_toggle_label_qs" +private const val CAMERA_LABEL_NAME = "camera_toggle_label_qs" class CameraMicIndicatorsPermissionTest { private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation() @@ -90,11 +92,9 @@ class CameraMicIndicatorsPermissionTest { private val isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK) private val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) + private val micLabel = getPermissionControllerString(MIC_LABEL_NAME) + private val cameraLabel = getPermissionControllerString(CAMERA_LABEL_NAME) private var wasEnabled = false - private val micLabel = packageManager.getPermissionGroupInfo( - Manifest.permission_group.MICROPHONE, 0).loadLabel(packageManager).toString() - private val cameraLabel = packageManager.getPermissionGroupInfo( - Manifest.permission_group.CAMERA, 0).loadLabel(packageManager).toString() private var isScreenOn = false private var screenTimeoutBeforeTest: Long = 0L @@ -520,4 +520,18 @@ class CameraMicIndicatorsPermissionTest { automatorMethod(remainingTime) } } + + private fun getPermissionControllerString(resourceName: String): String { + val permissionControllerPkg = context.packageManager.permissionControllerPackageName + try { + val permissionControllerContext = + context.createPackageContext(permissionControllerPkg, 0) + val resourceId = + permissionControllerContext.resources.getIdentifier( + resourceName, "string", "com.android.permissioncontroller") + return permissionControllerContext.getString(resourceId) + } catch (e: PackageManager.NameNotFoundException) { + throw RuntimeException(e) + } + } }
\ No newline at end of file diff --git a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt index 8cff38a67a9..67fa1bc3207 100644 --- a/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt +++ b/tests/tests/permission5/src/android/permission5/cts/RuntimePermissionsAppOpTrackingTest.kt @@ -25,6 +25,7 @@ import android.content.Context import android.content.ContextParams import android.content.Intent import android.content.pm.PackageManager.FEATURE_LEANBACK +import android.content.pm.PackageManager.FEATURE_TELEPHONY import android.net.Uri import android.os.Bundle import android.os.Process @@ -44,6 +45,7 @@ import com.android.compatibility.common.util.SystemUtil import com.google.common.truth.Truth.assertThat import org.junit.After import org.junit.Assume.assumeFalse +import org.junit.Assume.assumeTrue import org.junit.Before import org.junit.Test import org.mockito.ArgumentMatcher @@ -105,6 +107,7 @@ class RuntimePermissionsAppOpTrackingTest { @Throws(Exception::class) fun testSelfSmsAccess() { assumeNotTv() + assumeHasTelephony() testSelfAccess(Telephony.Sms.CONTENT_URI, Manifest.permission.READ_SMS) } @@ -178,6 +181,7 @@ class RuntimePermissionsAppOpTrackingTest { @Throws(Exception::class) fun testUntrustedSmsAccessAttributeToAnother() { assumeNotTv() + assumeHasTelephony() testUntrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI, Manifest.permission.READ_SMS) } @@ -225,6 +229,7 @@ class RuntimePermissionsAppOpTrackingTest { @Throws(Exception::class) fun testUntrustedSmsAccessAttributeToAnotherThroughIntermediary() { assumeNotTv() + assumeHasTelephony() testUntrustedAccessAttributeToAnotherThroughIntermediary( Telephony.Sms.CONTENT_URI, Manifest.permission.READ_SMS) @@ -323,6 +328,7 @@ class RuntimePermissionsAppOpTrackingTest { @Throws(Exception::class) fun testTrustedAccessSmsAttributeToAnother() { assumeNotTv() + assumeHasTelephony() testTrustedAccessAttributeToAnother(Telephony.Sms.CONTENT_URI, Manifest.permission.READ_SMS) } @@ -666,6 +672,7 @@ class RuntimePermissionsAppOpTrackingTest { get() = InstrumentationRegistry.getInstrumentation() private val isTv = context.packageManager.hasSystemFeature(FEATURE_LEANBACK) + private val isTel = context.packageManager.hasSystemFeature(FEATURE_TELEPHONY) fun ensureAuxiliaryAppsNotRunningAndNoResidualProcessState() { SystemUtil.runShellCommand("am force-stop $RECEIVER_PACKAGE_NAME") @@ -1178,5 +1185,6 @@ class RuntimePermissionsAppOpTrackingTest { } private fun assumeNotTv() = assumeFalse(isTv) + private fun assumeHasTelephony() = assumeTrue(isTel) } } diff --git a/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java b/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java index 29cf672a829..782f30c6508 100644 --- a/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java +++ b/tests/tests/preference/src/android/preference/cts/PreferenceActivityLegacyFlowTest.java @@ -103,7 +103,8 @@ public class PreferenceActivityLegacyFlowTest { } private void assertScreenshotsAreEqual(Bitmap before, Bitmap after) { - assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after)); + // TODO(b/227553681): remove the precision=0.99 arg so it does a pixel-by-pixel check + assertTrue("Screenshots do not match!", BitmapUtils.compareBitmaps(before, after, 0.99)); } private void assertTextShown(String text) { diff --git a/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java b/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java new file mode 100644 index 00000000000..c6b7e35b4ef --- /dev/null +++ b/tests/tests/security/src/android/security/cts/LocationDisabledAppOpsTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts; + +import static android.app.AppOpsManager.MODE_ALLOWED; +import static android.app.AppOpsManager.OPSTR_FINE_LOCATION; + +import static com.android.compatibility.common.util.SystemUtil.eventually; +import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; + +import android.app.ActivityManager; +import android.app.AppOpsManager; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.location.LocationManager; +import android.os.PackageTagsList; +import android.os.Process; +import android.os.UserHandle; +import android.platform.test.annotations.AsbSecurityTest; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import com.android.sts.common.util.StsExtraBusinessLogicTestCase; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(AndroidJUnit4.class) +public class LocationDisabledAppOpsTest extends StsExtraBusinessLogicTestCase { + + private final Context mContext = InstrumentationRegistry.getContext(); + private LocationManager mLm; + private AppOpsManager mAom; + + @Before + public void setUp() { + mLm = mContext.getSystemService(LocationManager.class); + mAom = mContext.getSystemService(AppOpsManager.class); + } + + @Test + @AsbSecurityTest(cveBugId = 231496105) + public void testLocationAppOpIsIgnoredForAppsWhenLocationIsDisabled() { + PackageTagsList ignoreList = mLm.getIgnoreSettingsAllowlist(); + + UserHandle[] userArr = {UserHandle.SYSTEM}; + runWithShellPermissionIdentity(() -> { + userArr[0] = UserHandle.of(ActivityManager.getCurrentUser()); + }); + + UserHandle user = userArr[0]; + + boolean wasEnabled = mLm.isLocationEnabledForUser(user); + + try { + runWithShellPermissionIdentity(() -> { + mLm.setLocationEnabledForUser(false, user); + }); + List<PackageInfo> pkgs = + mContext.getPackageManager().getInstalledPackagesAsUser( + 0, user.getIdentifier()); + + eventually(() -> { + List<String> bypassedNoteOps = new ArrayList<>(); + List<String> bypassedCheckOps = new ArrayList<>(); + for (PackageInfo pi : pkgs) { + ApplicationInfo ai = pi.applicationInfo; + if (ai.uid != Process.SYSTEM_UID) { + final int[] mode = {MODE_ALLOWED}; + runWithShellPermissionIdentity(() -> { + mode[0] = mAom.noteOpNoThrow( + OPSTR_FINE_LOCATION, ai.uid, ai.packageName); + }); + if (mode[0] == MODE_ALLOWED && !ignoreList.containsAll(pi.packageName)) { + bypassedNoteOps.add(pi.packageName); + } + + + mode[0] = MODE_ALLOWED; + runWithShellPermissionIdentity(() -> { + mode[0] = mAom + .checkOpNoThrow(OPSTR_FINE_LOCATION, ai.uid, ai.packageName); + }); + if (mode[0] == MODE_ALLOWED && !ignoreList.includes(pi.packageName)) { + bypassedCheckOps.add(pi.packageName); + } + + } + } + + String msg = ""; + if (!bypassedNoteOps.isEmpty()) { + msg += "Apps which still have access from noteOp " + bypassedNoteOps; + } + if (!bypassedCheckOps.isEmpty()) { + msg += (msg.isEmpty() ? "" : "\n\n") + + "Apps which still have access from checkOp " + bypassedCheckOps; + } + if (!msg.isEmpty()) { + Assert.fail(msg); + } + }); + } finally { + runWithShellPermissionIdentity(() -> { + mLm.setLocationEnabledForUser(wasEnabled, user); + }); + } + } + +} + diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java index 7d73da9dad1..f00f0b13b5c 100644 --- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java +++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/ExactCanvasTests.java @@ -125,6 +125,8 @@ public class ExactCanvasTests extends ActivityTestBase { canvas.drawColor(Color.WHITE); p.setColor(Color.BLACK); p.setAntiAlias(false); + // ensure the lines do not hit pixel edges + canvas.translate(0.05f, 0.05f); float[] pts = { 0, 0, 80, 80, 80, 0, 0, 80, 40, 50, 60, 50 }; diff --git a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java index f7322dde5e1..464fb4c40b8 100644 --- a/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java +++ b/tests/tests/wifi/src/android/net/wifi/cts/ConcurrencyTest.java @@ -274,6 +274,29 @@ public class ConcurrencyTest extends WifiJUnit3TestBase { new LinkedList<Integer>(Arrays.asList(waitSingleSync))); } + private NetworkInfo.DetailedState waitForNextNetworkState() { + assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); + assertNotNull(mMySync.expectedNetworkInfo); + return mMySync.expectedNetworkInfo.getDetailedState(); + } + + private boolean waitForConnectedNetworkState() { + // The possible orders of network states are: + // * IDLE > CONNECTING > CONNECTED for lazy initialization + // * DISCONNECTED > CONNECTING > CONNECTED for previous group removal + // * CONNECTING > CONNECTED + NetworkInfo.DetailedState state = waitForNextNetworkState(); + if (state == NetworkInfo.DetailedState.IDLE + || state == NetworkInfo.DetailedState.DISCONNECTED) { + state = waitForNextNetworkState(); + } + if (state != NetworkInfo.DetailedState.CONNECTING) { + return false; + } + state = waitForNextNetworkState(); + return state == NetworkInfo.DetailedState.CONNECTED; + } + private boolean waitForServiceResponse(MyResponse waitResponse) { synchronized (waitResponse) { long timeout = System.currentTimeMillis() + TIMEOUT_MSEC; @@ -508,21 +531,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase { mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener); assertTrue(waitForServiceResponse(mMyResponse)); assertTrue(mMyResponse.success); - - // The first network state might be IDLE due to - // lazy initialization, but not CONNECTED. - for (int i = 0; i < 2; i++) { - assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); - assertNotNull(mMySync.expectedNetworkInfo); - if (NetworkInfo.DetailedState.CONNECTED == - mMySync.expectedNetworkInfo.getDetailedState()) { - break; - } - assertEquals(NetworkInfo.DetailedState.IDLE, - mMySync.expectedNetworkInfo.getDetailedState()); - } - assertEquals(NetworkInfo.DetailedState.CONNECTED, - mMySync.expectedNetworkInfo.getDetailedState()); + assertTrue(waitForConnectedNetworkState()); resetResponse(mMyResponse); mWifiP2pManager.requestNetworkInfo(mWifiP2pChannel, @@ -660,21 +669,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase { mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener); assertTrue(waitForServiceResponse(mMyResponse)); assertTrue(mMyResponse.success); - - // The first network state might be IDLE due to - // lazy initialization, but not CONNECTED. - for (int i = 0; i < 2; i++) { - assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); - assertNotNull(mMySync.expectedNetworkInfo); - if (NetworkInfo.DetailedState.CONNECTED == - mMySync.expectedNetworkInfo.getDetailedState()) { - break; - } - assertEquals(NetworkInfo.DetailedState.IDLE, - mMySync.expectedNetworkInfo.getDetailedState()); - } - assertEquals(NetworkInfo.DetailedState.CONNECTED, - mMySync.expectedNetworkInfo.getDetailedState()); + assertTrue(waitForConnectedNetworkState()); resetResponse(mMyResponse); mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener); @@ -707,10 +702,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase { mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener); assertTrue(waitForServiceResponse(mMyResponse)); assertTrue(mMyResponse.success); - assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); - assertNotNull(mMySync.expectedNetworkInfo); - assertEquals(NetworkInfo.DetailedState.CONNECTED, - mMySync.expectedNetworkInfo.getDetailedState()); + assertTrue(waitForConnectedNetworkState()); resetResponse(mMyResponse); mWifiP2pManager.removeGroup(mWifiP2pChannel, mActionListener); @@ -812,21 +804,7 @@ public class ConcurrencyTest extends WifiJUnit3TestBase { mWifiP2pManager.createGroup(mWifiP2pChannel, mActionListener); assertTrue(waitForServiceResponse(mMyResponse)); assertTrue(mMyResponse.success); - - // The first network state might be IDLE due to - // lazy initialization, but not CONNECTED. - for (int i = 0; i < 2; i++) { - assertTrue(waitForBroadcasts(MySync.NETWORK_INFO)); - assertNotNull(mMySync.expectedNetworkInfo); - if (NetworkInfo.DetailedState.CONNECTED - == mMySync.expectedNetworkInfo.getDetailedState()) { - break; - } - assertEquals(NetworkInfo.DetailedState.IDLE, - mMySync.expectedNetworkInfo.getDetailedState()); - } - assertEquals(NetworkInfo.DetailedState.CONNECTED, - mMySync.expectedNetworkInfo.getDetailedState()); + assertTrue(waitForConnectedNetworkState()); resetResponse(mMyResponse); MacAddress peerMacAddress = MacAddress.fromString(mTestWifiP2pPeerConfig.deviceAddress); |