Merge "cts: Add default animation for UiAutomation test"
diff --git a/apps/CameraITS/tests/scene1_1/test_black_white.py b/apps/CameraITS/tests/scene1_1/test_black_white.py
index 2421cc9..6cf9de0 100644
--- a/apps/CameraITS/tests/scene1_1/test_black_white.py
+++ b/apps/CameraITS/tests/scene1_1/test_black_white.py
@@ -29,6 +29,7 @@
import image_processing_utils
import its_session_utils
+_ANDROID10_API_LEVEL = 29
CH_FULL_SCALE = 255
CH_THRESH_BLACK = 6
CH_THRESH_WHITE = CH_FULL_SCALE - 6
@@ -148,10 +149,12 @@
assert mean > CH_THRESH_WHITE, e_msg
# Assert channels saturate evenly (was test_channel_saturation)
- e_msg = 'ch saturation not equal! RGB: %s, ATOL: %.f' % (
- str(white_means), CH_TOL_WHITE)
- assert np.isclose(
- np.amin(white_means), np.amax(white_means), atol=CH_TOL_WHITE), e_msg
+ first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
+ if first_api_level > _ANDROID10_API_LEVEL:
+ e_msg = 'ch saturation not equal! RGB: %s, ATOL: %.f' % (
+ str(white_means), CH_TOL_WHITE)
+ assert np.isclose(
+ np.amin(white_means), np.amax(white_means), atol=CH_TOL_WHITE), e_msg
if __name__ == '__main__':
test_runner.main()
diff --git a/apps/CameraITS/tests/scene3/test_flip_mirror.py b/apps/CameraITS/tests/scene3/test_flip_mirror.py
index 2dff574..679b740 100644
--- a/apps/CameraITS/tests/scene3/test_flip_mirror.py
+++ b/apps/CameraITS/tests/scene3/test_flip_mirror.py
@@ -53,10 +53,6 @@
Returns:
boolean: True if flipped, False if not
"""
-
- # determine if monochrome camera
- mono_camera = camera_properties_utils.mono_camera(props)
-
# get a local copy of the chart template
template = cv2.imread(opencv_processing_utils.CHART_FILE, cv2.IMREAD_ANYDEPTH)
@@ -139,6 +135,10 @@
debug = self.debug_mode
chart_loc_arg = self.chart_loc_arg
+ # check SKIP conditions
+ camera_properties_utils.skip_unless(
+ not camera_properties_utils.mono_camera(props))
+
# load chart for scene
its_session_utils.load_scene(
cam, props, self.scene, self.tablet, self.chart_distance)
diff --git a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
index 73d1276..af55ebc 100644
--- a/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
+++ b/apps/CameraITS/tests/scene4/test_multi_camera_alignment.py
@@ -29,7 +29,7 @@
import opencv_processing_utils
ALIGN_TOL_MM = 4.0 # mm
-ALIGN_TOL = 0.01 # multiplied by sensor diagonal to convert to pixels
+ALIGN_TOL = 0.0075 # multiplied by sensor diagonal to convert to pixels
CIRCLE_COLOR = 0 # [0: black, 255: white]
CIRCLE_MIN_AREA = 0.01 # multiplied by image size
CIRCLE_RTOL = 0.1 # 10%
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index d5d3b06..410b277 100644
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -604,8 +604,9 @@
logging.info('Test execution completed.')
# Power down tablet
- cmd = f'adb -s {tablet_id} shell input keyevent KEYCODE_POWER'
- subprocess.Popen(cmd.split())
+ if tablet_id:
+ cmd = f'adb -s {tablet_id} shell input keyevent KEYCODE_POWER'
+ subprocess.Popen(cmd.split())
if __name__ == '__main__':
main()
diff --git a/apps/CtsVerifier/res/layout/audio_aec_activity.xml b/apps/CtsVerifier/res/layout/audio_aec_activity.xml
index 83aa9cd..d6d4bb0 100644
--- a/apps/CtsVerifier/res/layout/audio_aec_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_aec_activity.xml
@@ -48,12 +48,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/audio_aec_mandatory_no"
- android:text="@string/af_no" />
+ android:text="@string/audio_general_no" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/audio_aec_mandatory_yes"
- android:text="@string/af_yes" />
+ android:text="@string/audio_general_yes" />
</LinearLayout>
<LinearLayout
@@ -79,7 +79,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_test"
+ android:text="@string/audio_general_test"
android:id="@+id/audio_aec_button_test" />
<ProgressBar
android:layout_width="wrap_content"
@@ -90,7 +90,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/af_test_results"
+ android:text="@string/audio_general_results"
android:id="@+id/audio_aec_test_result" />
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
index 3ae6d43..fd5f619 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_line_activity.xml
@@ -70,7 +70,7 @@
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/audio_frequency_line_test_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/audio_frequency_line_test_btn"
android:nextFocusForward="@+id/pass_button"
android:nextFocusUp="@+id/audio_frequency_line_plug_ready_btn"
@@ -87,7 +87,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/audio_frequency_line_results_text"
+ android:text="@string/audio_general_results"
android:id="@+id/audio_frequency_line_results_text" />
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
index a991a15..fb2dd32 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_mic_activity.xml
@@ -67,7 +67,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/frequency_mic_test_noise_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/frequency_mic_test_noise_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -91,14 +91,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/frequency_mic_play"
+ android:text="@string/audio_general_play"
android:id="@+id/frequency_mic_play_noise_btn" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/frequency_mic_test_noise_result"
+ android:text="@string/audio_general_results"
android:id="@+id/frequency_mic_test_noise_result" />
</LinearLayout>
@@ -137,7 +137,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/frequency_mic_test_usb_background_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/frequency_mic_test_usb_background_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -149,7 +149,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/frequency_mic_test_usb_background_result"
+ android:text="@string/audio_general_results"
android:id="@+id/frequency_mic_test_usb_background_result" />
</LinearLayout>
@@ -188,7 +188,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/frequency_mic_test_usb_noise_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/frequency_mic_test_usb_noise_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -212,14 +212,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/frequency_mic_play"
+ android:text="@string/audio_general_play"
android:id="@+id/frequency_mic_play_usb_noise_btn" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/frequency_mic_test_usb_noise_result"
+ android:text="@string/audio_general_results"
android:id="@+id/frequency_mic_test_usb_noise_result" />
</LinearLayout>
<View
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
index a9aeafa..7c051cc 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_speaker_activity.xml
@@ -72,7 +72,7 @@
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/audio_frequency_speaker_test_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/audio_frequency_speaker_test_btn"
android:nextFocusForward="@+id/pass_button"
android:nextFocusUp="@+id/audio_frequency_speaker_mic_ready_btn"
@@ -89,7 +89,7 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/audio_frequency_speaker_results_text"
+ android:text="@string/audio_general_results"
android:id="@+id/audio_frequency_speaker_results_text"/>
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
index 8032f93..bbd576d 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_unprocessed_activity.xml
@@ -67,7 +67,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_test_tone_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/unprocessed_test_tone_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -91,14 +91,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_play"
+ android:text="@string/audio_general_play"
android:id="@+id/unprocessed_play_tone_btn" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/unprocessed_test_tone_result"
+ android:text="@string/audio_general_results"
android:id="@+id/unprocessed_test_tone_result" />
</LinearLayout>
@@ -136,7 +136,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_test_noise_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/unprocessed_test_noise_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -159,14 +159,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_play"
+ android:text="@string/audio_general_play"
android:id="@+id/unprocessed_play_noise_btn" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/unprocessed_test_noise_result"
+ android:text="@string/audio_general_results"
android:id="@+id/unprocessed_test_noise_result" />
</LinearLayout>
@@ -204,7 +204,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_test_usb_background_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/unprocessed_test_usb_background_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -216,7 +216,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/unprocessed_test_usb_background_result"
+ android:text="@string/audio_general_results"
android:id="@+id/unprocessed_test_usb_background_result" />
</LinearLayout>
@@ -254,7 +254,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_test_usb_noise_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/unprocessed_test_usb_noise_btn" />
<ProgressBar
android:layout_width="wrap_content"
@@ -277,14 +277,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/unprocessed_play"
+ android:text="@string/audio_general_play"
android:id="@+id/unprocessed_play_usb_noise_btn" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/unprocessed_test_usb_noise_result"
+ android:text="@string/audio_general_results"
android:id="@+id/unprocessed_test_usb_noise_result" />
</LinearLayout>
<View
@@ -295,7 +295,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/unprocessed_test_global_result"
+ android:text="@string/audio_general_results"
android:id="@+id/unprocessed_test_global_result" />
<include layout="@layout/pass_fail_buttons" />
diff --git a/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml b/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml
index 1ccd947..f283388 100644
--- a/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_frequency_voice_recognition_activity.xml
@@ -67,7 +67,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_test"
+ android:text="@string/audio_general_test"
android:id="@+id/vr_button_test_tone" />
<ProgressBar
android:layout_width="wrap_content"
@@ -91,14 +91,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_play"
+ android:text="@string/audio_general_play"
android:id="@+id/vr_button_play_tone" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/af_test_results"
+ android:text="@string/audio_general_results"
android:id="@+id/vr_test_tone_result" />
</LinearLayout>
@@ -136,7 +136,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_test"
+ android:text="@string/audio_general_test"
android:id="@+id/vr_button_test_noise" />
<ProgressBar
android:layout_width="wrap_content"
@@ -159,14 +159,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_play"
+ android:text="@string/audio_general_play"
android:id="@+id/vr_button_play_noise" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/af_test_results"
+ android:text="@string/audio_general_results"
android:id="@+id/vr_test_noise_result" />
</LinearLayout>
@@ -204,7 +204,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_test"
+ android:text="@string/audio_general_test"
android:id="@+id/vr_button_test_usb_background" />
<ProgressBar
android:layout_width="wrap_content"
@@ -216,7 +216,7 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/af_test_results"
+ android:text="@string/audio_general_results"
android:id="@+id/vr_test_usb_background_result" />
</LinearLayout>
@@ -254,7 +254,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_test"
+ android:text="@string/audio_general_test"
android:id="@+id/vr_button_test_usb_noise" />
<ProgressBar
android:layout_width="wrap_content"
@@ -277,14 +277,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/af_button_play"
+ android:text="@string/audio_general_play"
android:id="@+id/vr_button_play_usb_noise" />
</LinearLayout>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/af_test_results"
+ android:text="@string/audio_general_results"
android:id="@+id/vr_test_usb_noise_result" />
</LinearLayout>
<View
diff --git a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
index 24767d2..964985c 100644
--- a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
@@ -70,12 +70,12 @@
android:orientation="horizontal"
android:layout_marginLeft="10dp">
<Button
- android:text="@string/analog_headset_play"
+ android:text="@string/audio_general_play"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/headset_analog_play"/>
<Button
- android:text="@string/analog_headset_stop"
+ android:text="@string/audio_general_stop"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:id="@+id/headset_analog_stop"/>
diff --git a/apps/CtsVerifier/res/layout/audio_loopback_footer_layout.xml b/apps/CtsVerifier/res/layout/audio_loopback_footer_layout.xml
index f59afeb..624602c 100644
--- a/apps/CtsVerifier/res/layout/audio_loopback_footer_layout.xml
+++ b/apps/CtsVerifier/res/layout/audio_loopback_footer_layout.xml
@@ -13,6 +13,6 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/audio_loopback_results_text"
+ android:text="@string/audio_general_results"
android:id="@+id/audio_loopback_results_text" />
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
index 9d9631a..894e1d3 100644
--- a/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_loopback_latency_activity.xml
@@ -65,12 +65,11 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text="Pro Audio:"/>
+ android:text="@string/audio_loopback_lbl_proaudio"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text=""
android:id="@+id/audio_loopback_pro_audio"/>
</LinearLayout>
@@ -82,12 +81,11 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text="MMAP Supported:"/>
+ android:text="@string/audio_loopback_lbl_mmap"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text=""
android:id="@+id/audio_loopback_mmap"/>
</LinearLayout>
@@ -99,12 +97,11 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text="MMAP Exclusive Supported:"/>
+ android:text="@string/audio_loopback_lbl_mmexclusive"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text=""
android:id="@+id/audio_loopback_mmap_exclusive"/>
</LinearLayout>
@@ -116,12 +113,11 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text="Low Latency Support:"/>
+ android:text="@string/audio_loopback_lbl_lowlatency"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text=""
android:id="@+id/audio_loopback_low_latency"/>
</LinearLayout>
@@ -138,7 +134,6 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text=""
android:id="@+id/audio_loopback_must_latency"/>
</LinearLayout>
@@ -150,12 +145,11 @@
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text="Recommended Max Latency (ms):"/>
+ android:text="@string/audio_loopback_lbl_recommededlatency"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:text=""
android:id="@+id/audio_loopback_recommended_latency"/>
</LinearLayout>
@@ -168,7 +162,7 @@
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/audio_loopback_test_btn"
+ android:text="@string/audio_general_test"
android:id="@+id/audio_loopback_test_btn"
android:nextFocusForward="@+id/pass_button"
android:nextFocusUp="@+id/audio_loopback_level_seekbar"
diff --git a/apps/CtsVerifier/res/layout/audio_refmic_layout.xml b/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
index bd806a1..74ee203 100644
--- a/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
+++ b/apps/CtsVerifier/res/layout/audio_refmic_layout.xml
@@ -18,21 +18,21 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/refmic_test_yes"
+ android:text="@string/audio_general_yes"
android:id="@+id/refmic_tests_yes_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/refmic_test_no"
+ android:text="@string/audio_general_no"
android:id="@+id/refmic_tests_no_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/refmic_test_info"
+ android:text="@string/audio_general_info"
android:id="@+id/refmic_test_info_btn" />
</LinearLayout>
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/audio_wired_query_layout.xml b/apps/CtsVerifier/res/layout/audio_wired_query_layout.xml
index bc8038b..bd67643 100644
--- a/apps/CtsVerifier/res/layout/audio_wired_query_layout.xml
+++ b/apps/CtsVerifier/res/layout/audio_wired_query_layout.xml
@@ -21,12 +21,12 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/audio_wired_no"
- android:text="@string/audio_wired_no" />
+ android:text="@string/audio_general_no" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/audio_wired_yes"
- android:text="@string/audio_wired_yes" />
+ android:text="@string/audio_general_yes" />
</LinearLayout>
</LinearLayout>
diff --git a/apps/CtsVerifier/res/layout/uap_attribs_panel.xml b/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
index b9c5d3e..45cfcd0 100644
--- a/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_attribs_panel.xml
@@ -24,7 +24,7 @@
android:layout_height="wrap_content"/>
<TextView
- android:text="status"
+ android:text="@string/audio_general_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/uap_attribsStatusTx"
diff --git a/apps/CtsVerifier/res/layout/uap_play_panel.xml b/apps/CtsVerifier/res/layout/uap_play_panel.xml
index 30ef884..a263d45 100644
--- a/apps/CtsVerifier/res/layout/uap_play_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_play_panel.xml
@@ -32,7 +32,7 @@
android:layout_height="5dp"/>
<Button
- android:text="@string/audio_uap_play_playBtn"
+ android:text="@string/audio_general_play"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/uap_playPlayBtn"
diff --git a/apps/CtsVerifier/res/layout/uap_record_panel.xml b/apps/CtsVerifier/res/layout/uap_record_panel.xml
index a5bfcfc..ff993a3 100644
--- a/apps/CtsVerifier/res/layout/uap_record_panel.xml
+++ b/apps/CtsVerifier/res/layout/uap_record_panel.xml
@@ -32,7 +32,7 @@
android:layout_height="5dp"/>
<Button
- android:text="@string/audio_uap_record_recordBtn"
+ android:text="@string/audio_general_record"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/uap_recordRecordBtn"
@@ -40,7 +40,7 @@
android:nextFocusDown="@+id/uap_recordRecordLoopBtn"/>
<Button
- android:text="@string/audio_uap_record_recordLoopbackBtn"
+ android:text="@string/audio_general_recordLoopback"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/uap_recordRecordLoopBtn"
diff --git a/apps/CtsVerifier/res/layout/uap_usb_confirm.xml b/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
index ea73b88..e89ce84e 100644
--- a/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
+++ b/apps/CtsVerifier/res/layout/uap_usb_confirm.xml
@@ -18,21 +18,21 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/uap_test_yes"
+ android:text="@string/audio_general_yes"
android:id="@+id/uap_tests_yes_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/uap_test_no"
+ android:text="@string/audio_general_no"
android:id="@+id/uap_tests_no_btn" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:soundEffectsEnabled="false"
- android:text="@string/uap_test_info"
+ android:text="@string/audio_general_info"
android:id="@+id/uap_test_info_btn" />
</LinearLayout>
</LinearLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 3df2bc4..aaac43c 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -4960,15 +4960,10 @@
<string name="audio_uap_play_test">USB Audio Peripheral Play Test</string>
<string name="uapPlayTestInstructions">Connect the USB Audio Interface Peripheral and press the
PLAY button below. Verify that a tone is correctly played.</string>
- <string name="audio_uap_play_playBtn">Play</string>
- <string name="audio_uap_play_stopBtn">Stop</string>
<string name="audio_uap_record_test">USB Audio Peripheral Record Test</string>
<string name="uapRecordTestInstructions">Connect the USB Audio Peripheral and press the RECORD or
RECORD LOOPBACK button below. Verify that a tone is correctly played.</string>
- <string name="audio_uap_record_recordBtn">Record</string>
- <string name="audio_uap_record_recordLoopbackBtn">Record Loopback</string>
- <string name="audio_uap_record_stopBtn">Stop</string>
<string name="audio_uap_buttons_test">USB Audio Peripheral Buttons Test</string>
<string name="uapButtonTestInstructions">Connect the USB Audio headset with buttons
@@ -5049,7 +5044,6 @@
flag and therefore does not need to run this test.</string>
<!-- Various test status strings -->
- <string name="audio_proaudio_pass">Pass</string>
<string name="audio_proaudio_latencytoohigh">Latency is too high</string>
<string name="audio_proaudio_confidencetoolow">"Insufficient Confidence value"</string>
<string name="audio_proaudio_midinotreported">"No MIDI support reported"</string>
@@ -5100,8 +5094,6 @@
<!-- Audio general text -->
<string name="audio_wired_exists">Does this device support wired USB or Analog audio peripherals?</string>
- <string name="audio_wired_no">No</string>
- <string name="audio_wired_yes">Yes</string>
<string name="audio_general_deficiency_found">WARNING: Some results show potential deficiencies on the system.
Please consider addressing them for a future release.</string>
<string name="audio_general_test_passed">Test Result: Successful</string>
@@ -5118,6 +5110,13 @@
<string name="audio_general_ok">Ok</string>
<string name="audio_general_start">Start</string>
<string name="audio_general_stop">Stop</string>
+ <string name="audio_general_play">Play</string>
+ <string name="audio_general_test">Test</string>
+ <string name="audio_general_status">Status</string>
+ <string name="audio_general_record">Record</string>
+ <string name="audio_general_recordLoopback">Record Loopback</string>
+ <string name="audio_general_results">Results...</string>
+ <string name="audio_general_pass">Pass</string>
<string name="audio_general_JavaApi">Java API</string>
<string name="audio_general_NativeApi">Native API</string>
@@ -5148,9 +5147,15 @@
It might require multiple tries until a confidence >= 0.6 is achieved.
</string>
<string name="audio_loopback_level_text">Audio Level</string>
- <string name="audio_loopback_test_btn">Test</string>
- <string name="audio_loopback_results_text">Results...</string>
+ <!-- UI Labels -->
+ <string name="audio_loopback_lbl_proaudio">Pro Audio:</string>
+ <string name="audio_loopback_lbl_mmap">MMAP Supported:</string>
+ <string name="audio_loopback_lbl_mmexclusive">MMAP Exclusive Supported:</string>
+ <string name="audio_loopback_lbl_lowlatency">Low Latency Support:</string>
+ <string name="audio_loopback_lbl_testpath">Test Path:</string>
+ <string name="audio_loopback_lbl_mustlatency">Required Max Latency (ms):</string>
+ <string name="audio_loopback_lbl_recommededlatency">Recommended Max Latency (ms):</string>
<string name="audio_loopback_failure">FAILURE - Could not allocate analyzer thread.</string>
<!-- Audio Cold-Start Latency Test -->
@@ -5206,9 +5211,6 @@
</string>
<string name="audio_frequency_line_plug_ready_btn">Loopback Plug Ready</string>
- <string name="audio_frequency_line_test_btn">Test</string>
- <string name="audio_frequency_line_results_text">Results...</string>
-
<!-- Audio Frequency Speaker Test -->
<string name="audio_frequency_speaker_test">Audio Frequency Speaker Test</string>
<string name="audio_frequency_speaker_info">
@@ -5223,8 +5225,6 @@
<string name="audio_frequency_speaker_mic_ready_text">USB Audio device detected\n\nPlease set up Device Under test
in quiet room, and Microphone 20 cms perpendicular to center of screen, then press TEST</string>
<string name="audio_frequency_speaker_mic_not_ready_text">"No USB Audio device detected. Please reconnect."</string>
- <string name="audio_frequency_speaker_test_btn">Test</string>
- <string name="audio_frequency_speaker_results_text">Results...</string>
<!-- Audio Frequency Microphone Test -->
<string name="audio_frequency_mic_test">Audio Frequency Microphone Test</string>
@@ -5234,23 +5234,15 @@
Follow the instructions on the screen to measure the frequency response for the built in microphone.
</string>
- <string name="frequency_mic_play">Play</string>
- <string name="frequency_mic_stop">Stop</string>
<string name="frequency_mic_noise_instructions">TEST NOISE: Position speakers 40 cms from device under test.
Press [PLAY] to play broadband white noise. Press [TEST]
</string>
- <string name="frequency_mic_test_noise_btn">Test</string>
- <string name="frequency_mic_test_noise_result">Results...</string>
<string name="frequency_mic_test_usb_background_instructions">TEST USB BACKGROUND: Connect USB microphone and position it right next to microphone under test.
No source of noise should be active during this test. Press [TEST]</string>
- <string name="frequency_mic_test_usb_background_btn">Test</string>
- <string name="frequency_mic_test_usb_background_result">Results...</string>
<string name="frequency_mic_test_usb_noise_instructions">TEST USB NOISE: Connect USB microphone and position it right next to microphone under test.
Position speakers 40 cms from device under test. Press [PLAY] to play broadband white noise. Press [TEST]</string>
- <string name="frequency_mic_test_usb_noise_btn">Test</string>
- <string name="frequency_mic_test_usb_noise_result">Results...</string>
<string name="frequency_mic_test_global_result">Global Results...</string>
@@ -5267,30 +5259,17 @@
<string name="audio_frequency_unprocessed_defined">Audio Frequency Unprocessed feature is defined. Success in all tests is mandatory to pass</string>
<string name="audio_frequency_unprocessed_not_defined">Audio Frequency Unprocessed feature is NOT defined. Success in all test is NOT mandatory to pass</string>
- <string name="unprocessed_play">Play</string>
- <string name="unprocessed_stop">Stop</string>
-
<string name="unprocessed_test_tone_instructions">TEST TONE: Press [PLAY] to play tone at 1 Khz. Measure sound SPL to be 94 dB
right next to microphone under test. Press [TEST]</string>
- <string name="unprocessed_test_tone_btn">Test</string>
- <string name="unprocessed_test_tone_result">Results...</string>
<string name="unprocessed_test_noise_instructions">TEST NOISE: Position speakers 40 cms from device under test.
Press [PLAY] to play broadband white noise. Press [TEST]</string>
- <string name="unprocessed_test_noise_btn">Test</string>
- <string name="unprocessed_test_noise_result">Results...</string>
<string name="unprocessed_test_usb_background_instructions">TEST USB BACKGROUND: Connect USB microphone and position it right next to microphone under test.
No source of noise should be active during this test. Press [TEST]</string>
- <string name="unprocessed_test_usb_background_btn">Test</string>
- <string name="unprocessed_test_usb_background_result">Results...</string>
<string name="unprocessed_test_usb_noise_instructions">TEST USB NOISE: Connect USB microphone and position it right next to microphone under test.
Position speakers 40 cms from device under test. Press [PLAY] to play broadband white noise. Press [TEST]</string>
- <string name="unprocessed_test_usb_noise_btn">Test</string>
- <string name="unprocessed_test_usb_noise_result">Results...</string>
-
- <string name="unprocessed_test_global_result">Global Results...</string>
<!-- Audio Frequency Voice_Recognition Test -->
<string name="audio_frequency_voice_recognition_test">Audio Frequency Voice Recognition Test</string>
@@ -5311,8 +5290,6 @@
<!-- Analog Headset Test -->
<string name="audio_headset_audio_test">Analog Headset Audio Test</string>
<string name="analog_headset_query">Does this Android device have an analog headset jack?</string>
- <string name="analog_headset_play">Play</string>
- <string name="analog_headset_stop">Stop</string>
<string name="analog_headset_playback_prompt">Play a test tone and verify correct playback</string>
<string name="analog_headset_playback_query">Was the audio correctly played through the headset?</string>
<string name="analog_headset_keycodes_label">Headset key codes</string>
@@ -5342,27 +5319,26 @@
\n(see <a href="https://source.android.com/devices/accessories/headset/plug-headset-spec">3.5 mm Headset: Accessory Specification</a> and
<a href="https://source.android.com/compatibility/android-cdd#7_8_2_1_analog_audio_ports">Android CDD § 7.8.2.1. Analog Audio Ports</a>)
</string>
+
<!-- Audio AEC Test -->
<string name="audio_aec_test">Audio Acoustic Echo Cancellation (AEC) Test</string>
- <string name="audio_aec_info">
- The recording source VOICE_COMMUNICATION will be tested with/without the Acoustic Echo Canceller effect engaged.
- The Acoustic Coupling Factor (ACF) will be computed for each case. A successful test expects ACF less than 0.4 for AEC ON,
- and ACF greater than 0.6 for AEC OFF.
- This test requires a quiet environment, and no headphones or similar connected.
- This test must pass in devices where AEC functionality is mandatory or any device which implements AEC.
+ <string name="audio_aec_info">Tests Acoustic Echo Canceler (AEC) functionality.
+ \n\nTest Setup:
+ \n\"Microphone\" permission is required.
+ \nPerform the test in a quiet room, placing the DUT on a flat surface. Do not connect any headphones or other audio peripherals.
+ \n\nTest Process:
+ \n1. Verify that AEC is mandatory for the DUT. If the answer is NO, the test passes at this point.
+ \n2. Press the \"Test\" button. The test will playback/record a short audio clip with both AEC enabled and disabled
+ to verify that the DUT meets the requirements for Acoustic Coupling Factor (ACF) in both modes.
+ \n\nTest Criteria:
+ \nRequires an ACF of less that 0.4 with AEC engaged and greater that 0.6 with AEC disengaged.
+ \n\nCDD Section: <a href="https://source.android.com/compatibility/android-cdd#544_acoustic_echo_canceler">5.4.4. Acoustic Echo Canceler</a>
</string>
<string name="audio_aec_instructions">Press [TEST] to play a voice recording twice with different parameters.</string>
<string name="audio_aec_mandatory_test">Is AEC mandatory in this device?</string>
<!--Audio Frequency Global strings -->
- <string name="af_button_play">Play</string>
- <string name="af_button_stop">Stop</string>
-
- <string name="af_button_test">Test</string>
- <string name="af_test_results">Results...</string>
<string name="af_global_test_results">Global Results...</string>
- <string name="af_no">No</string>
- <string name="af_yes">Yes</string>
<!-- AudioTap2Tone test -->
<string name="audio_tap2tone">Audio Tap To Tone Test</string>
@@ -6076,9 +6052,6 @@
7. Click Pass button if checks in step 5 and 6 passed, otherwise click Fail button.
</string>
- <string name="uap_test_no">No</string>
- <string name="uap_test_yes">Yes</string>
- <string name="uap_test_info">Info</string>
<string name="uap_test_question">Does this device allow for the connection of a USB audio peripheral?\nNote: phones and tablets generally do, watches and automobiles generally do not.</string>
<string name="uap_refmic_question">Does this device allow for the connection of a USB reference microphone?</string>
<string name="uap_mic_dlg_caption">USB Host Mode Audio Required</string>
@@ -6090,9 +6063,6 @@
Note: Devices declaring feature android.hardware.audio.pro MUST implement USB host mode (CDD 5.10 C-1-3) and if they omit a 4 conductor 3.5mm audio jack MUST support USB audio class (CDD 5.10 C-3-1)
</string>
- <string name="refmic_test_no">No</string>
- <string name="refmic_test_yes">Yes</string>
- <string name="refmic_test_info">Info</string>
<string name="refmic_test_question">Does this device allow for the connection of a USB reference microphone?</string>
<string name="ref_mic_dlg_caption">Reference Mic Required</string>
<string name="ref_mic_dlg_text">This test requires a USB Reference Mic to be connected to the device.
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
index 72f5ae1..0f2ce9a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyMicActivity.java
@@ -266,8 +266,8 @@
}
private void setButtonPlayStatus(int playResId) {
- String play = getResources().getText(R.string.frequency_mic_play).toString();
- String stop = getResources().getText(R.string.frequency_mic_stop).toString();
+ String play = getResources().getText(R.string.audio_general_play).toString();
+ String stop = getResources().getText(R.string.audio_general_stop).toString();
mButtonPlayNoise.setText(playResId == R.id.frequency_mic_play_noise_btn ? stop : play);
mButtonPlayUsbNoise.setText(playResId ==
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
index 5509501..f8a0aca 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyUnprocessedActivity.java
@@ -333,8 +333,8 @@
}
private void setButtonPlayStatus(int playResId) {
- String play = getResources().getText(R.string.unprocessed_play).toString();
- String stop = getResources().getText(R.string.unprocessed_stop).toString();
+ String play = getResources().getText(R.string.audio_general_play).toString();
+ String stop = getResources().getText(R.string.audio_general_stop).toString();
mButtonPlayTone.setText(playResId == R.id.unprocessed_play_tone_btn ? stop : play);
mButtonPlayNoise.setText(playResId == R.id.unprocessed_play_noise_btn ? stop : play);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
index 5ed51e3..b93ac62 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioFrequencyVoiceRecognitionActivity.java
@@ -376,8 +376,8 @@
}
private void setButtonPlayStatus(int playResId) {
- String play = getResources().getText(R.string.af_button_play).toString();
- String stop = getResources().getText(R.string.af_button_stop).toString();
+ String play = getResources().getText(R.string.audio_general_play).toString();
+ String stop = getResources().getText(R.string.audio_general_stop).toString();
mButtonPlayTone.setText(playResId == R.id.vr_button_play_tone ? stop : play);
mButtonPlayNoise.setText(playResId == R.id.vr_button_play_noise ? stop : play);
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 9804cd3..9da33de 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/ProAudioActivity.java
@@ -166,7 +166,7 @@
Resources strings = getResources();
if (hasPassed) {
- mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_pass));
+ mTestStatusLbl.setText(strings.getString(R.string.audio_general_pass));
} else if (!mClaimsMIDI) {
mTestStatusLbl.setText(strings.getString(R.string.audio_proaudio_midinotreported));
} else if (!mClaimsUSBHostMode) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
index 4ae5ec3..5ce3da3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
@@ -74,10 +74,10 @@
Log.i(TAG, "Play Button Pressed");
if (!isPlaying()) {
startPlay();
- mPlayBtn.setText(getString(R.string.audio_uap_play_stopBtn));
+ mPlayBtn.setText(getString(R.string.audio_general_stop));
} else {
stopPlay();
- mPlayBtn.setText(getString(R.string.audio_uap_play_playBtn));
+ mPlayBtn.setText(getString(R.string.audio_general_play));
}
break;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
index 880013f..5cd9884 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
@@ -167,12 +167,12 @@
case R.id.uap_recordRecordBtn:
if (!isRecording()) {
if (startRecording(false)) {
- mRecordBtn.setText(getString(R.string.audio_uap_record_stopBtn));
+ mRecordBtn.setText(getString(R.string.audio_general_stop));
mRecordLoopbackBtn.setEnabled(false);
}
} else {
stopRecording();
- mRecordBtn.setText(getString(R.string.audio_uap_record_recordBtn));
+ mRecordBtn.setText(getString(R.string.audio_general_record));
mRecordLoopbackBtn.setEnabled(true);
}
break;
@@ -180,13 +180,13 @@
case R.id.uap_recordRecordLoopBtn:
if (!isRecording()) {
if (startRecording(true)) {
- mRecordLoopbackBtn.setText(getString(R.string.audio_uap_record_stopBtn));
+ mRecordLoopbackBtn.setText(getString(R.string.audio_general_stop));
mRecordBtn.setEnabled(false);
}
} else {
stopRecording();
mRecordLoopbackBtn.setText(
- getString(R.string.audio_uap_record_recordLoopbackBtn));
+ getString(R.string.audio_general_recordLoopback));
mRecordBtn.setEnabled(true);
}
break;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BackgroundRfcommTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BackgroundRfcommTestActivity.java
index feb8ce5..bf1a12c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BackgroundRfcommTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/bluetooth/BackgroundRfcommTestActivity.java
@@ -79,7 +79,7 @@
PendingIntent pendingIntent =
PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);
- mBluetoothAdapter.closeRfcommServer(mUuid);
+ mBluetoothAdapter.stopRfcommServer(mUuid);
if (mBluetoothAdapter.startRfcommServer("TestBackgroundRfcomm", mUuid, pendingIntent)
!= BluetoothStatusCodes.SUCCESS) {
@@ -90,7 +90,7 @@
@Override
protected void onDestroy() {
- mBluetoothAdapter.closeRfcommServer(mUuid);
+ mBluetoothAdapter.stopRfcommServer(mUuid);
if (mReceiver != null) {
unregisterReceiver(mReceiver);
mReceiver = null;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/OWNERS
new file mode 100644
index 0000000..2718191
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/clipboard/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1151772
+mrcasey@google.com
+mkephart@google.com
+moellerj@google.com
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/logcat/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/logcat/OWNERS
new file mode 100644
index 0000000..37638f4
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/logcat/OWNERS
@@ -0,0 +1,7 @@
+# Bug Component: 36824
+
+cbrubaker@google.com
+eunjeongshin@google.com
+jsharkey@google.com
+vishwath@google.com
+wenhaowang@google.com
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java
index 4b682c1..263d43f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/BaseEmulatorActivity.java
@@ -110,9 +110,8 @@
changeDefault.putExtra(CardEmulation.EXTRA_CATEGORY,
CardEmulation.CATEGORY_PAYMENT);
changeDefault.putExtra(CardEmulation.EXTRA_SERVICE_COMPONENT, defaultComponent);
- changeDefault.putExtra(CardEmulation.EXTRA_USERID,
- UserHandle.getUserHandleForUid(getApplicationInfo().uid)
- .getIdentifier());
+ changeDefault.putExtra(Intent.EXTRA_USER,
+ UserHandle.getUserHandleForUid(getApplicationInfo().uid));
startActivityForResult(changeDefault, 0);
}
});
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
index ab66339..bd4a262 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceEmulatorTestActivity.java
@@ -27,6 +27,7 @@
import android.nfc.cardemulation.CardEmulation;
import android.os.Build;
import android.os.Bundle;
+import android.os.SystemProperties;
/** Activity that lists all the NFC HCE emulator tests. */
public class HceEmulatorTestActivity extends PassFailButtons.TestListActivity {
@@ -131,13 +132,17 @@
}
}
- adapter.add(TestListItem.newTest(this, R.string.nfc_screen_on_only_offhost_emulator,
- ScreenOnOnlyOffHostEmulatorActivity.class.getName(),
- new Intent(this, ScreenOnOnlyOffHostEmulatorActivity.class), null));
+ int firstSdk =
+ SystemProperties.getInt("ro.product.first_api_level", Build.VERSION_CODES.S);
+ if (firstSdk >= Build.VERSION_CODES.S) {
+ adapter.add(TestListItem.newTest(this, R.string.nfc_screen_on_only_offhost_emulator,
+ ScreenOnOnlyOffHostEmulatorActivity.class.getName(),
+ new Intent(this, ScreenOnOnlyOffHostEmulatorActivity.class), null));
- adapter.add(TestListItem.newTest(this, R.string.nfc_screen_off_hce_payment_emulator,
- ScreenOffPaymentEmulatorActivity.class.getName(),
- new Intent(this, ScreenOffPaymentEmulatorActivity.class), null));
+ adapter.add(TestListItem.newTest(this, R.string.nfc_screen_off_hce_payment_emulator,
+ ScreenOffPaymentEmulatorActivity.class.getName(),
+ new Intent(this, ScreenOffPaymentEmulatorActivity.class), null));
+ }
}
setTestListAdapter(adapter);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java
index 4998d5c..fa5da2b 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/hce/HceReaderTestActivity.java
@@ -25,7 +25,9 @@
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Bundle;
+import android.os.SystemProperties;
/** Activity that lists all the NFC HCE reader tests. */
public class HceReaderTestActivity extends PassFailButtons.TestListActivity {
@@ -121,14 +123,17 @@
ConflictingNonPaymentPrefixEmulatorActivity.buildReaderIntent(this), null));
}
- adapter.add(TestListItem.newTest(this, R.string.nfc_screen_on_only_offhost_reader,
- getString(R.string.nfc_screen_on_only_offhost_reader),
- ScreenOnOnlyOffHostEmulatorActivity.buildReaderIntent(this), null));
+ int firstSdk =
+ SystemProperties.getInt("ro.product.first_api_level", Build.VERSION_CODES.S);
+ if (firstSdk >= Build.VERSION_CODES.S) {
+ adapter.add(TestListItem.newTest(this, R.string.nfc_screen_on_only_offhost_reader,
+ getString(R.string.nfc_screen_on_only_offhost_reader),
+ ScreenOnOnlyOffHostEmulatorActivity.buildReaderIntent(this), null));
- adapter.add(TestListItem.newTest(this, R.string.nfc_screen_off_hce_payment_reader,
- getString(R.string.nfc_screen_off_hce_payment_reader),
- ScreenOffPaymentEmulatorActivity.buildReaderIntent(this), null));
-
+ adapter.add(TestListItem.newTest(this, R.string.nfc_screen_off_hce_payment_reader,
+ getString(R.string.nfc_screen_off_hce_payment_reader),
+ ScreenOffPaymentEmulatorActivity.buildReaderIntent(this), null));
+ }
}
setTestListAdapter(adapter);
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/ApiLevelUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/ApiLevelUtil.java
index 943ebc7..bb4c46e 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/ApiLevelUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/ApiLevelUtil.java
@@ -17,6 +17,7 @@
package com.android.compatibility.common.util;
import android.os.Build;
+import android.os.SystemProperties;
import java.lang.reflect.Field;
@@ -61,6 +62,10 @@
return Build.VERSION.SDK_INT;
}
+ public static boolean isFirstApiAtLeast(int version) {
+ return SystemProperties.getInt("ro.product.first_api_level", 0) >= version;
+ }
+
public static boolean codenameEquals(String name) {
return Build.VERSION.CODENAME.equalsIgnoreCase(name.trim());
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/util/CarrierPrivilegeUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java
similarity index 63%
rename from tests/tests/telephony/current/src/android/telephony/cts/util/CarrierPrivilegeUtils.java
rename to common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java
index ea46c9b..2b174a7 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/util/CarrierPrivilegeUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/CarrierPrivilegeUtils.java
@@ -14,16 +14,14 @@
* limitations under the License.
*/
-package android.telephony.cts.util;
+package com.android.compatibility.common.util;
+
+import static android.telephony.TelephonyManager.CarrierPrivilegesListener;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
-import static com.android.internal.util.FunctionalUtils.ThrowingRunnable;
-import static com.android.internal.util.FunctionalUtils.ThrowingSupplier;
-import android.content.BroadcastReceiver;
+import android.Manifest;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.PersistableBundle;
@@ -32,9 +30,8 @@
import android.telephony.TelephonyManager;
import android.util.Log;
-import com.android.internal.telephony.uicc.IccUtils;
-
import java.security.MessageDigest;
+import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -45,73 +42,79 @@
* task is completed.
*
* <p>Example:
- *
* <pre>
* CarrierPrivilegeUtils.withCarrierPrivileges(c, subId, () -> telephonyManager.setFoo(bar));
* </pre>
+ *
+ * @see {@link TelephonyManager#hasCarrierPrivileges()}
*/
-public class CarrierPrivilegeUtils {
+public final class CarrierPrivilegeUtils {
private static final String TAG = CarrierPrivilegeUtils.class.getSimpleName();
- private static class CarrierPrivilegeReceiver extends BroadcastReceiver
- implements AutoCloseable {
-
+ private static class CarrierPrivilegeChangeMonitor implements AutoCloseable {
private final CountDownLatch mLatch = new CountDownLatch(1);
private final Context mContext;
private final int mSubId;
private final boolean mGain;
+ private final boolean mIsShell;
+ private final TelephonyManager mTelephonyManager;
+ private final CarrierPrivilegesListener mCarrierPrivilegesListener;
/**
- * Construct a listener that will wait for adding or removing carrier privileges.
- *
- * @param subId the subId to wait for.
- * @param hash the package hash that indicate carrier privileges.
- * @param gain if true, wait for the package to be added; if false, wait for the package to
- * be removed.
+ * Construct a {@link CarrierPrivilegesListener} to monitor carrier privileges change.
+ * @param c context
+ * @param subId subscriptionId to listen to
+ * @param gain true if wait to grant carrier privileges, false if wait to revoke
+ * @param isShell true if the caller is Shell
*/
- CarrierPrivilegeReceiver(Context c, int subId, String hash, boolean gain) {
+ CarrierPrivilegeChangeMonitor(Context c, int subId, boolean gain, boolean isShell) {
mContext = c;
mSubId = subId;
mGain = gain;
+ mIsShell = isShell;
+ mTelephonyManager = mContext.getSystemService(
+ TelephonyManager.class).createForSubscriptionId(subId);
+ Objects.requireNonNull(mTelephonyManager);
- mContext.registerReceiver(
- this, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
+ mCarrierPrivilegesListener =
+ (privilegedPackageNames, privilegedUids) -> {
+ if (mTelephonyManager.hasCarrierPrivileges() == mGain) {
+ mLatch.countDown();
+ }
+ };
+
+ // Run with shell identify only when caller is not Shell to avoid overriding current
+ // SHELL permissions
+ if (mIsShell) {
+ mTelephonyManager.addCarrierPrivilegesListener(
+ SubscriptionManager.getSlotIndex(subId),
+ mContext.getMainExecutor(),
+ mCarrierPrivilegesListener);
+ } else {
+ runWithShellPermissionIdentity(() -> {
+ mTelephonyManager.addCarrierPrivilegesListener(
+ SubscriptionManager.getSlotIndex(subId),
+ mContext.getMainExecutor(),
+ mCarrierPrivilegesListener);
+ }, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ }
}
@Override
public void close() {
- mContext.unregisterReceiver(this);
- }
+ if (mTelephonyManager == null) return;
- @Override
- public void onReceive(Context c, Intent intent) {
- if (!CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(intent.getAction())) {
- return;
- }
-
- final int subId = intent.getIntExtra(
- CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- if (mSubId != subId) {
- return;
- }
-
- final PersistableBundle carrierConfigs =
- c.getSystemService(CarrierConfigManager.class).getConfigForSubId(mSubId);
- if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfigs)) {
- return;
- }
-
- try {
- if (hasCarrierPrivileges(c, mSubId) == mGain) {
- mLatch.countDown();
- }
- } catch (Exception e) {
+ if (mIsShell) {
+ mTelephonyManager.removeCarrierPrivilegesListener(mCarrierPrivilegesListener);
+ } else {
+ runWithShellPermissionIdentity(() -> {
+ mTelephonyManager.removeCarrierPrivilegesListener(mCarrierPrivilegesListener);
+ }, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
}
}
public void waitForCarrierPrivilegeChanged() throws Exception {
- if (!mLatch.await(5000 /* millis */, TimeUnit.MILLISECONDS)) {
+ if (!mLatch.await(5, TimeUnit.SECONDS)) {
throw new IllegalStateException("Failed to update carrier privileges");
}
}
@@ -130,7 +133,7 @@
.getPackageInfo(c.getOpPackageName(), PackageManager.GET_SIGNATURES);
final MessageDigest md = MessageDigest.getInstance("SHA-256");
final byte[] certHash = md.digest(pkgInfo.signatures[0].toByteArray());
- return IccUtils.bytesToHexString(certHash);
+ return UiccUtil.bytesToHexString(certHash);
}
private static void changeCarrierPrivileges(Context c, int subId, boolean gain, boolean isShell)
@@ -154,8 +157,8 @@
final CarrierConfigManager configManager = c.getSystemService(CarrierConfigManager.class);
- try (CarrierPrivilegeReceiver receiver =
- new CarrierPrivilegeReceiver(c, subId, certHash, gain)) {
+ try (CarrierPrivilegeChangeMonitor monitor =
+ new CarrierPrivilegeChangeMonitor(c, subId, gain, isShell)) {
// If the caller is the shell, it's dangerous to adopt shell permission identity for
// the CarrierConfig override (as it will override the existing shell permissions).
if (isShell) {
@@ -166,7 +169,7 @@
}, android.Manifest.permission.MODIFY_PHONE_STATE);
}
- receiver.waitForCarrierPrivilegeChanged();
+ monitor.waitForCarrierPrivilegeChanged();
}
}
@@ -174,7 +177,7 @@
throws Exception {
try {
changeCarrierPrivileges(c, subId, true /* gain */, false /* isShell */);
- action.runOrThrow();
+ action.run();
} finally {
changeCarrierPrivileges(c, subId, false /* lose */, false /* isShell */);
}
@@ -185,7 +188,7 @@
throws Exception {
try {
changeCarrierPrivileges(c, subId, true /* gain */, true /* isShell */);
- action.runOrThrow();
+ action.run();
} finally {
changeCarrierPrivileges(c, subId, false /* lose */, true /* isShell */);
}
@@ -195,7 +198,7 @@
throws Exception {
try {
changeCarrierPrivileges(c, subId, true /* gain */, false /* isShell */);
- return action.getOrThrow();
+ return action.get();
} finally {
changeCarrierPrivileges(c, subId, false /* lose */, false /* isShell */);
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
index 8318201..6f0c6ed 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaUtils.java
@@ -16,6 +16,9 @@
package com.android.compatibility.common.util;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.res.AssetFileDescriptor;
import android.drm.DrmConvertedStatus;
import android.drm.DrmManagerClient;
@@ -32,10 +35,16 @@
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.net.Uri;
+import android.os.BatteryManager;
import android.os.Build;
+import android.os.SystemProperties;
import android.os.ParcelFileDescriptor;
+import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Range;
+import android.view.WindowManager;
+
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
@@ -61,6 +70,11 @@
public class MediaUtils {
private static final String TAG = "MediaUtils";
+ private static final Context mContext =
+ InstrumentationRegistry.getInstrumentation().getTargetContext();
+ private static final PackageManager pm = mContext.getPackageManager();
+ private static final boolean FIRST_SDK_IS_AT_LEAST_R =
+ ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.R);
/*
* ----------------------- HELPER METHODS FOR SKIPPING TESTS -----------------------
@@ -1409,6 +1423,70 @@
return result.toString();
}
+
+ /*
+ * ------------------- HELPER METHODS FOR DETECTING DEVICE TYPES -------------------
+ */
+
+ public static boolean hasDeviceGotBattery() {
+ final Intent batteryInfo = mContext.registerReceiver(null,
+ new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ return batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
+ }
+
+ public static double getScreenSizeInInches() {
+ DisplayMetrics dm = mContext.getResources().getDisplayMetrics();
+ double widthInInchesSquared = Math.pow(dm.widthPixels/dm.xdpi,2);
+ double heightInInchesSquared = Math.pow(dm.heightPixels/dm.ydpi,2);
+ double diagonalInInches = Math.sqrt(widthInInchesSquared + heightInInchesSquared);
+ return diagonalInInches;
+ }
+
+ public static boolean isTv() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK) ||
+ pm.hasSystemFeature(PackageManager.FEATURE_TELEVISION);
+ }
+
+ public static boolean hasMicrophone() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE);
+ }
+
+ public static boolean hasCamera() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
+ }
+
+ public static boolean isWatch() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
+
+ public static boolean isAutomotive() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ public static boolean isPc() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_PC);
+ }
+
+ public static boolean hasAudioOutput() {
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
+ }
+
+ public static boolean isHandheld() {
+ double screenSize = getScreenSizeInInches();
+ if (screenSize < (FIRST_SDK_IS_AT_LEAST_R ? 3.3 : 2.5)) return false;
+ if (screenSize > 8.0) return false;
+ if (!hasDeviceGotBattery()) return false;
+ return true;
+ }
+
+ public static boolean isTablet() {
+ double screenSize = getScreenSizeInInches();
+ if (screenSize < 7.0) return false;
+ if (screenSize > 18.0) return false;
+ if (!hasDeviceGotBattery()) return false;
+ return true;
+ }
+
/*
* ------------------- HELPER METHODS FOR DETECTING NON-PRODUCTION DEVICES -------------------
*/
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
index b8562ab..4125ede 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -44,7 +44,6 @@
private static final String CAMERAX_EXTENSIONS_ENABLED = "ro.camerax.extensions.enabled";
private static final String MANUFACTURER_PROPERTY = "ro.product.manufacturer";
private static final String TAG_DEV_KEYS = "dev-keys";
- private static final String VENDOR_BUILD_VERSION_SDK = "ro.vendor.build.version.sdk";
private static final String VNDK_VERSION = "ro.vndk.version";
public static final String GOOGLE_SETTINGS_QUERY =
@@ -91,12 +90,12 @@
/**
* Return the API level that the VSR requirement must be fulfilled. It reads
- * ro.product.first_api_level, ro.board.first_api_level, and ro.board.api_level
- * to find the minimum required VSR api_level for the DUT.
+ * ro.product.first_api_level and ro.board.first_api_level to find the minimum required VSR
+ * api_level for the DUT.
*/
public static int getVsrApiLevel() {
// Api level properties of the board. The order of the properties must be kept.
- String[] boardApiLevelProps = { BOARD_API_LEVEL, BOARD_FIRST_API_LEVEL, VENDOR_BUILD_VERSION_SDK };
+ String[] boardApiLevelProps = {BOARD_API_LEVEL, BOARD_FIRST_API_LEVEL};
for (String apiLevelProp : boardApiLevelProps) {
int apiLevel = getPropertyInt(apiLevelProp);
if (apiLevel != INT_VALUE_IF_UNSET) {
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiccUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiccUtil.java
index 69b59e8..610ce88 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiccUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiccUtil.java
@@ -19,6 +19,7 @@
import android.Manifest;
import android.telephony.TelephonyManager;
+import androidx.annotation.Nullable;
import androidx.annotation.StringDef;
import androidx.test.InstrumentationRegistry;
@@ -26,6 +27,11 @@
/** Utility class for common UICC- and SIM-related operations. */
public final class UiccUtil {
+ // A table mapping from a number to a hex character for fast encoding hex strings.
+ private static final char[] HEX_CHARS = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
/** The hashes of all supported CTS UICC test keys and their corresponding specification. */
@StringDef({UiccCertificate.CTS_UICC_LEGACY, UiccCertificate.CTS_UICC_2021})
public @interface UiccCertificate {
@@ -72,4 +78,28 @@
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
return uiccCerts == null ? false : uiccCerts.contains(requiredCert);
}
+
+ /**
+ * Converts a byte array into a String of hexadecimal characters.
+ *
+ * @param bytes an array of bytes
+ *
+ * @return hex string representation of bytes array
+ */
+ @Nullable
+ public static String bytesToHexString(@Nullable byte[] bytes) {
+ if (bytes == null) return null;
+
+ StringBuilder ret = new StringBuilder(2*bytes.length);
+
+ for (int i = 0 ; i < bytes.length ; i++) {
+ int b;
+ b = 0x0f & (bytes[i] >> 4);
+ ret.append(HEX_CHARS[b]);
+ b = 0x0f & bytes[i];
+ ret.append(HEX_CHARS[b]);
+ }
+
+ return ret.toString();
+ }
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
index db6124a..be7ab00 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
@@ -86,6 +86,7 @@
removeTestPackages();
deviceDisableDeviceConfigSync();
+ deviceSetupServerBasedParameter();
}
@After
@@ -95,46 +96,8 @@
}
@Test
- public void resumeOnReboot_SingleUser_Success() throws Exception {
- if (!isSupportedDevice()) {
- CLog.v(TAG, "Device not supported; skipping test");
- return;
- }
-
- int[] users = Utils.prepareSingleUser(getDevice());
- int initialUser = users[0];
-
- // Clean up the server based parameters for HAL based test.
- deviceCleanupServerBasedParameter();
-
- try {
- installTestPackages();
-
- deviceSetup(initialUser);
- deviceRequestLskf();
- deviceLock(initialUser);
- deviceEnterLskf(initialUser);
- deviceRebootAndApply();
-
- runDeviceTestsAsUser("testVerifyUnlockedAndDismiss", initialUser);
- } finally {
- try {
- // Remove secure lock screens and tear down test app
- runDeviceTestsAsUser("testTearDown", initialUser);
-
- deviceClearLskf();
- } finally {
- removeTestPackages();
- }
- }
- }
-
- @Test
public void resumeOnReboot_ManagedProfile_Success() throws Exception {
- if (!isSupportedDevice()) {
- CLog.v(TAG, "Device not supported; skipping test");
- return;
- }
+ assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
if (!getDevice().hasFeature("android.software.managed_users")) {
CLog.v(TAG, "Device doesn't support managed users; skipping test");
@@ -146,8 +109,6 @@
int managedUserId = createManagedProfile(initialUser);
- deviceCleanupServerBasedParameter();
-
try {
// Set up test app and secure lock screens
installTestPackages();
@@ -177,10 +138,7 @@
@Test
public void resumeOnReboot_TwoUsers_SingleUserUnlock_Success() throws Exception {
- if (!isSupportedDevice()) {
- CLog.v(TAG, "Device not supported; skipping test");
- return;
- }
+ assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
if (!mSupportsMultiUser) {
CLog.v(TAG, "Device doesn't support multi-user; skipping test");
@@ -191,8 +149,6 @@
int initialUser = users[0];
int secondaryUser = users[1];
- deviceCleanupServerBasedParameter();
-
try {
// Set up test app and secure lock screens
installTestPackages();
@@ -234,10 +190,7 @@
@Test
public void resumeOnReboot_TwoUsers_BothUserUnlock_Success() throws Exception {
- if (!isSupportedDevice()) {
- CLog.v(TAG, "Device not supported; skipping test");
- return;
- }
+ assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
if (!mSupportsMultiUser) {
CLog.v(TAG, "Device doesn't support multi-user; skipping test");
@@ -248,8 +201,6 @@
int initialUser = users[0];
int secondaryUser = users[1];
- deviceCleanupServerBasedParameter();
-
try {
installTestPackages();
@@ -291,23 +242,13 @@
}
}
- private boolean isSupportedSDevice() throws Exception {
- // The following tests targets API level >= S.
- boolean isAtleastS = ApiLevelUtil.isAfter(getDevice(), 30 /* BUILD.VERSION_CODES.R */)
- || ApiLevelUtil.codenameEquals(getDevice(), "S");
-
- return isAtleastS && getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN);
- }
-
@Test
public void resumeOnReboot_SingleUser_ServerBased_Success() throws Exception {
- assumeTrue("Device isn't at least S or have no lock screen", isSupportedSDevice());
+ assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
int[] users = Utils.prepareSingleUser(getDevice());
int initialUser = users[0];
- deviceSetupServerBasedParameter();
-
try {
installTestPackages();
@@ -327,7 +268,6 @@
deviceClearLskf();
} finally {
removeTestPackages();
- deviceCleanupServerBasedParameter();
getDevice().rebootUntilOnline();
getDevice().waitForDeviceAvailable();
@@ -337,13 +277,11 @@
@Test
public void resumeOnReboot_SingleUser_MultiClient_ClientASuccess() throws Exception {
- assumeTrue("Device isn't at least S or have no lock screen", isSupportedSDevice());
+ assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
int[] users = Utils.prepareSingleUser(getDevice());
int initialUser = users[0];
- deviceSetupServerBasedParameter();
-
final String clientA = "ClientA";
final String clientB = "ClientB";
try {
@@ -370,7 +308,6 @@
deviceClearLskf();
} finally {
removeTestPackages();
- deviceCleanupServerBasedParameter();
getDevice().rebootUntilOnline();
getDevice().waitForDeviceAvailable();
@@ -380,13 +317,11 @@
@Test
public void resumeOnReboot_SingleUser_MultiClient_ClientBSuccess() throws Exception {
- assumeTrue("Device isn't at least S or have no lock screen", isSupportedSDevice());
+ assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
int[] users = Utils.prepareSingleUser(getDevice());
int initialUser = users[0];
- deviceSetupServerBasedParameter();
-
final String clientA = "ClientA";
final String clientB = "ClientB";
try {
@@ -412,7 +347,6 @@
deviceClearLskf();
} finally {
removeTestPackages();
- deviceCleanupServerBasedParameter();
getDevice().rebootUntilOnline();
getDevice().waitForDeviceAvailable();
@@ -631,9 +565,12 @@
Utils.runDeviceTestsAsCurrentUser(getDevice(), PKG, CLASS, testMethodName);
}
- private boolean isSupportedDevice() throws Exception {
- return getDevice().hasFeature(FEATURE_DEVICE_ADMIN)
- && getDevice().hasFeature(FEATURE_REBOOT_ESCROW);
+ private boolean isSupportedSDevice() throws Exception {
+ // The following tests targets API level >= S.
+ boolean isAtleastS = ApiLevelUtil.isAfter(getDevice(), 30 /* BUILD.VERSION_CODES.R */)
+ || ApiLevelUtil.codenameEquals(getDevice(), "S");
+
+ return isAtleastS && getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN);
}
private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
diff --git a/hostsidetests/blobstore/src/com/android/cts/host/blob/DataPersistenceTest.java b/hostsidetests/blobstore/src/com/android/cts/host/blob/DataPersistenceTest.java
index 973ca8b..076819b 100644
--- a/hostsidetests/blobstore/src/com/android/cts/host/blob/DataPersistenceTest.java
+++ b/hostsidetests/blobstore/src/com/android/cts/host/blob/DataPersistenceTest.java
@@ -31,7 +31,7 @@
rebootAndWaitUntilReady();
runDeviceTest(TARGET_PKG, TEST_CLASS, "testOpenSessionAndWrite");
rebootAndWaitUntilReady();
- runDeviceTest(TARGET_PKG, TEST_CLASS, "testCommitSession");
+ runDeviceTest(TARGET_PKG, TEST_CLASS, "testCommitSessionAndAcquireLease");
rebootAndWaitUntilReady();
runDeviceTest(TARGET_PKG, TEST_CLASS, "testOpenBlob");
}
diff --git a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java
index 2efc523..90a406c 100644
--- a/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java
+++ b/hostsidetests/blobstore/test-apps/BlobStoreHostTestHelper/src/com/android/cts/device/blob/DataPersistenceTest.java
@@ -75,7 +75,7 @@
}
@Test
- public void testCommitSession() throws Exception {
+ public void testCommitSessionAndAcquireLease() throws Exception {
final long sessionId = readSessionIdFromDisk();
try (BlobStoreManager.Session session = mBlobStoreManager.openSession(sessionId)) {
final CompletableFuture<Integer> callback = new CompletableFuture<>();
@@ -83,6 +83,8 @@
assertThat(callback.get(TIMEOUT_COMMIT_CALLBACK_MS, TimeUnit.MILLISECONDS))
.isEqualTo(0);
}
+ final BlobHandle blobHandle = readBlobHandleFromDisk();
+ mBlobStoreManager.acquireLease(blobHandle, "test desc");
}
@Test
diff --git a/hostsidetests/content/OWNERS b/hostsidetests/content/OWNERS
index 84911ce..6f4eaa8 100644
--- a/hostsidetests/content/OWNERS
+++ b/hostsidetests/content/OWNERS
@@ -1,2 +1,3 @@
# Bug component: 197138
-svetoslavganov@google.com
+omakoto@google.com
+varunshah@google.com
diff --git a/hostsidetests/hdmicec/app/Android.bp b/hostsidetests/hdmicec/app/Android.bp
index 09f4fbf..965746b 100644
--- a/hostsidetests/hdmicec/app/Android.bp
+++ b/hostsidetests/hdmicec/app/Android.bp
@@ -20,7 +20,6 @@
name: "HdmiCecHelperApp",
defaults: ["cts_defaults"],
platform_apis: true,
- certificate: "platform",
srcs: ["src/**/*.java"],
static_libs: [
"androidx.test.runner",
diff --git a/hostsidetests/hdmicec/app/AndroidManifest.xml b/hostsidetests/hdmicec/app/AndroidManifest.xml
index dde8441..4eb046e3 100644
--- a/hostsidetests/hdmicec/app/AndroidManifest.xml
+++ b/hostsidetests/hdmicec/app/AndroidManifest.xml
@@ -19,7 +19,6 @@
package="android.hdmicec.app">
<uses-feature android:name="android.software.leanback"
android:required="false"/>
- <uses-permission android:name="android.permission.HDMI_CEC" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<activity android:name=".HdmiCecKeyEventCapture"
@@ -49,21 +48,6 @@
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
</intent-filter>
</activity>
- <activity android:name=".HdmiControlManagerHelper" >
- <intent-filter>
- <action android:name="android.hdmicec.app.OTP" />
- <action android:name="android.hdmicec.app.DEVICE_SELECT" />
- </intent-filter>
- </activity>
- <activity android:name=".HdmiCecVendorCommandListener"
- android:exported="true">
- <intent-filter>
- <action android:name="android.hdmicec.app.VENDOR_LISTENER_WITH_ID"/>
- <action android:name="android.hdmicec.app.VENDOR_LISTENER_WITHOUT_ID"/>
- <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
- </intent-filter>
- </activity>
-
<uses-library android:name="android.test.runner" />
</application>
diff --git a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiControlManagerHelper.java b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiControlManagerHelper.java
index 5ff7aaa..7a05c13 100755
--- a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiControlManagerHelper.java
+++ b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiControlManagerHelper.java
@@ -16,67 +16,60 @@
package android.hdmicec.app;
+import static android.Manifest.permission.HDMI_CEC;
+
import android.app.Activity;
+import android.content.Context;
+import android.hardware.hdmi.HdmiClient;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiPlaybackClient;
import android.hardware.hdmi.HdmiTvClient;
-import android.os.Bundle;
import android.util.Log;
+import android.view.KeyEvent;
+
+
+import java.util.concurrent.TimeUnit;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
- * A simple activity that can be used to trigger actions using the HdmiControlManager. The actions
- * supported are:
- *
- * <p>
- *
- * <p>1. android.hdmicec.app.OTP: Triggers the OTP
- *
- * <p>Usage: <code>START_COMMAND -a android.hdmicec.app.OTP</code>
- *
- * <p>
- *
- * <p>2. android.hdmicec.app.SELECT_DEVICE: Selects a device to be the active source. The logical
- * address of the device that has to be made the active source has to passed as a parameter.
- *
- * <p>Usage: <code>START_COMMAND -a android.hdmicec.app.DEVICE_SELECT --ei "la" [LOGICAL_ADDRESS]
- * </code>
- *
- * <p>
- *
- * <p>where START_COMMAND is
- *
- * <p><code>
- * adb shell am start -n "android.hdmicec.app/android.hdmicec.app.HdmiControlManagerHelper"
- * </code>
+ * A simple class that can be used to trigger actions using the HdmiControlManager.
*/
-public class HdmiControlManagerHelper extends Activity {
-
+@RunWith(AndroidJUnit4.class)
+public final class HdmiControlManagerHelper {
+ private static final String LOGICAL_ADDR = "ARG_LOGICAL_ADDR";
private static final String TAG = HdmiControlManagerHelper.class.getSimpleName();
HdmiControlManager mHdmiControlManager;
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
+ @Before
+ public void setUp() throws Exception {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
+ HDMI_CEC);
- mHdmiControlManager = getSystemService(HdmiControlManager.class);
+ mHdmiControlManager = context.getSystemService(HdmiControlManager.class);
if (mHdmiControlManager == null) {
Log.i(TAG, "Failed to get HdmiControlManager");
return;
}
-
- switch (getIntent().getAction()) {
- case "android.hdmicec.app.OTP":
- initiateOtp();
- break;
- case "android.hdmicec.app.DEVICE_SELECT":
- int logicalAddress = getIntent().getIntExtra("la", 50);
- deviceSelect(logicalAddress);
- default:
- Log.w(TAG, "Unknown intent!");
- }
}
- private void deviceSelect(int logicalAddress) {
+ @After
+ public void tearDown() {
+ InstrumentationRegistry.getInstrumentation()
+ .getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ @Test
+ public void deviceSelect() throws InterruptedException {
+ final String param = InstrumentationRegistry.getArguments().getString(LOGICAL_ADDR);
+ int logicalAddress = Integer.parseInt(param);
HdmiTvClient client = mHdmiControlManager.getTvClient();
if (client == null) {
Log.e(TAG, "Failed to get the TV client");
@@ -93,25 +86,32 @@
TAG,
"Could not select device with logical address " + logicalAddress);
}
- finishAndRemoveTask();
});
}
- private void initiateOtp() {
- HdmiPlaybackClient client = mHdmiControlManager.getPlaybackClient();
+ @Test
+ public void interruptedLongPress() throws InterruptedException {
+ HdmiClient client = mHdmiControlManager.getPlaybackClient();
if (client == null) {
- Log.i(TAG, "Failed to get HdmiPlaybackClient");
+ client = mHdmiControlManager.getTvClient();
+ }
+
+ if (client == null) {
+ Log.i(TAG, "Could not get a TV/Playback client, cannot send key event");
return;
}
- client.oneTouchPlay(
- (result) -> {
- if (result == HdmiControlManager.RESULT_SUCCESS) {
- Log.i(TAG, "OTP successful");
- } else {
- Log.i(TAG, "OTP failed");
- }
- finishAndRemoveTask();
- });
+ try {
+ for (int i = 0; i < 5; i++) {
+ client.sendKeyEvent(KeyEvent.KEYCODE_DPAD_UP, true);
+ TimeUnit.MILLISECONDS.sleep(450);
+ }
+ client.sendKeyEvent(KeyEvent.KEYCODE_DPAD_UP, false);
+ // Sleep for 500ms more
+ TimeUnit.MILLISECONDS.sleep(500);
+ client.sendKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, true);
+ } catch (InterruptedException ie) {
+ Log.w(TAG, "Interrupted between keyevents, could not send all keyevents!");
+ }
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
index 58e767e..f5a6454 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/BaseHdmiCecCtsTest.java
@@ -16,7 +16,7 @@
package android.hdmicec.cts;
-import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assume.assumeTrue;
@@ -47,6 +47,8 @@
public static final String PROPERTY_LOCALE = "persist.sys.locale";
private static final String POWER_CONTROL_MODE = "power_control_mode";
+ private static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST =
+ "power_state_change_on_active_source_lost";
/** Enum contains the list of possible address types. */
private enum AddressType {
@@ -190,6 +192,36 @@
"Could not parse logicalAddress from dumpsys.");
}
+ /**
+ * Gets the system audio mode status of the device by parsing the dumpsys hdmi_control. Returns
+ * true when system audio mode is on and false when system audio mode is off
+ */
+ public boolean isSystemAudioModeOn(ITestDevice device) throws DumpsysParseException {
+ List<LogicalAddress> logicalAddressList = new ArrayList<>();
+ String line;
+ String pattern =
+ "(.*?)"
+ + "(mSystemAudioActivated: )"
+ + "(?<"
+ + "systemAudioModeStatus"
+ + ">[true|false])"
+ + "(.*?)";
+ Pattern p = Pattern.compile(pattern);
+ try {
+ String dumpsys = device.executeShellCommand("dumpsys hdmi_control");
+ BufferedReader reader = new BufferedReader(new StringReader(dumpsys));
+ while ((line = reader.readLine()) != null) {
+ Matcher m = p.matcher(line);
+ if (m.matches()) {
+ return m.group("systemAudioModeStatus").equals("true");
+ }
+ }
+ } catch (IOException | DeviceNotAvailableException e) {
+ throw new DumpsysParseException("Could not parse system audio mode from dumpsys.", e);
+ }
+ throw new DumpsysParseException("Could not parse system audio mode from dumpsys.");
+ }
+
/** Gets the DUT's logical address to which messages should be sent */
public LogicalAddress getTargetLogicalAddress() throws DumpsysParseException {
return getTargetLogicalAddress(getDevice(), mTestDeviceType);
@@ -366,16 +398,9 @@
"dumpsys hdmi_control | sed -n '/mDeviceInfos/,/mCecController/{//!p;}'");
}
- public void checkDeviceAsleep() throws Exception {
- ITestDevice device = getDevice();
- TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
- String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertThat(wakeState.trim()).isEqualTo("mWakefulness=Asleep");
- }
-
public void sendDeviceToSleepAndValidate() throws Exception {
sendDeviceToSleep();
- checkDeviceAsleep();
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
}
public void waitForTransitionTo(int finalState) throws Exception {
@@ -417,6 +442,7 @@
public void sendDeviceToSleep() throws Exception {
sendDeviceToSleepWithoutWait();
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
waitForTransitionTo(HdmiCecConstants.CEC_POWER_STATUS_STANDBY);
}
@@ -436,15 +462,45 @@
public void wakeUpDevice() throws Exception {
ITestDevice device = getDevice();
device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
waitForTransitionTo(HdmiCecConstants.CEC_POWER_STATUS_ON);
WakeLockHelper.releasePartialWakeLock(device);
}
+ public void wakeUpDeviceWithoutWait() throws Exception {
+ ITestDevice device = getDevice();
+ device.executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
+ WakeLockHelper.releasePartialWakeLock(device);
+ }
+
public void checkStandbyAndWakeUp() throws Exception {
- checkDeviceAsleep();
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
wakeUpDevice();
}
+ public void assertDeviceWakefulness(String wakefulness) throws Exception {
+ ITestDevice device = getDevice();
+ String actualWakefulness;
+ int waitTimeSeconds = 0;
+
+ do {
+ TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
+ waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
+ actualWakefulness =
+ device.executeShellCommand("dumpsys power | grep mWakefulness=")
+ .trim().replace("mWakefulness=", "");
+ } while (!actualWakefulness.equals(wakefulness)
+ && waitTimeSeconds <= HdmiCecConstants.MAX_SLEEP_TIME_SECONDS);
+ assertWithMessage(
+ "Device wakefulness is "
+ + actualWakefulness
+ + " but expected to be "
+ + wakefulness)
+ .that(actualWakefulness)
+ .isEqualTo(wakefulness);
+ }
+
public void sendOtp() throws Exception {
ITestDevice device = getDevice();
device.executeShellCommand("cmd hdmi_control onetouchplay");
@@ -456,6 +512,13 @@
return val;
}
+ public String setPowerStateChangeOnActiveSourceLost(String valToSet) throws Exception {
+ String previousPowerStateChange =
+ getSettingsValue(POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST);
+ setSettingsValue(POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST, valToSet);
+ return previousPowerStateChange;
+ }
+
public boolean isDeviceActiveSource(ITestDevice device) throws DumpsysParseException {
final String activeSource = "activeSource";
final String pattern =
@@ -481,4 +544,39 @@
}
throw new DumpsysParseException("Could not parse isActiveSource() from dumpsys.");
}
+
+ /**
+ * For source devices, simulate that a sink is connected by responding to the
+ * {@code Give Power Status} message that is sent when re-enabling CEC.
+ * Validate that HdmiControlService#mIsCecAvailable is set to true as a result.
+ */
+ public void simulateCecSinkConnected(ITestDevice device, LogicalAddress source)
+ throws Exception {
+ hdmiCecClient.clearClientOutput();
+ device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 0");
+ device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 1");
+ // When a CEC device has just become available, the CEC adapter isn't able to send it
+ // messages right away. Therefore we let the first <Give Power Status> message time-out, and
+ // only respond to the retry.
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
+ hdmiCecClient.clearClientOutput();
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
+ hdmiCecClient.sendCecMessage(LogicalAddress.TV, source, CecOperand.REPORT_POWER_STATUS,
+ CecMessage.formatParams(HdmiCecConstants.CEC_POWER_STATUS_STANDBY));
+ checkIsCecAvailable(device);
+ }
+
+ private void checkIsCecAvailable(ITestDevice device) throws Exception {
+ boolean isCecAvailable;
+ int waitTimeSeconds = 0;
+ do {
+ TimeUnit.SECONDS.sleep(HdmiCecConstants.SLEEP_TIMESTEP_SECONDS);
+ waitTimeSeconds += HdmiCecConstants.SLEEP_TIMESTEP_SECONDS;
+ isCecAvailable =
+ device.executeShellCommand("dumpsys hdmi_control | grep mIsCecAvailable:")
+ .replace("mIsCecAvailable:", "").trim().equals("true");
+ } while (!isCecAvailable && waitTimeSeconds <= HdmiCecConstants.MAX_SLEEP_TIME_SECONDS);
+ assertWithMessage("Simulating that a sink is connected, failed.")
+ .that(isCecAvailable).isTrue();
+ }
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
index c313680..083cf2e 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecConstants.java
@@ -130,6 +130,10 @@
public static final int CEC_POWER_STATUS_IN_TRANSITION_TO_ON = 0x2;
public static final int CEC_POWER_STATUS_IN_TRANSITION_TO_STANDBY = 0x3;
+ /** PowerManager wakefulness states */
+ public static final String WAKEFULNESS_AWAKE = "Awake";
+ public static final String WAKEFULNESS_ASLEEP = "Asleep";
+
/** Poll Message Success */
public static final String POLL_SUCCESS = "POLL message sent";
@@ -153,6 +157,10 @@
public static final String POWER_CONTROL_MODE_NONE = "none";
public static final String POWER_CONTROL_MODE_TV = "to_tv";
+ // Power State Change on Active Source Lost Settings values
+ public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE = "none";
+ public static final String POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_STANDBY_NOW = "standby_now";
+
// CEC 2.0 Report Feature Bits
public static final int FEATURES_SINK_SUPPORTS_ARC_TX_BIT = 0x4;
public static final int FEATURES_SINK_SUPPORTS_ARC_RX_BIT = 0x2;
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiControlManagerUtility.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiControlManagerUtility.java
index cb92093..8e81ab3 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiControlManagerUtility.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiControlManagerUtility.java
@@ -18,37 +18,51 @@
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-/** Helper class to call intents in the HdmiCecControlManagerHelper app */
+import java.util.HashMap;
+import java.util.Map;
+
+/** Helper class to call tests in the HdmiCecControlManagerHelper app */
public class HdmiControlManagerUtility {
/** The package name of the APK. */
- private static final String PACKAGE = "android.hdmicec.app";
+ private static final String TEST_PKG = "android.hdmicec.app";
/** The class name of the main activity in the APK. */
- private static final String CLASS = "HdmiControlManagerHelper";
+ private static final String TEST_CLS = "android.hdmicec.app.HdmiControlManagerHelper";
- /** The command to launch the main activity. */
- private static final String START_COMMAND =
- String.format("am start -n %s/%s.%s -a ", PACKAGE, PACKAGE, CLASS);
+ /** The method name of the set active source case. */
+ private static final String SELECT_DEVICE = "deviceSelect";
- /** The command to clear the main activity. */
- private static final String CLEAR_COMMAND = String.format("pm clear %s", PACKAGE);
+ /** The method name of the set active source case. */
+ private static final String SEND_INTERRUPTED_LONG_PRESS = "interruptedLongPress";
+
+ /** The key of the set active source case arguments. */
+ private static final String LOGICAL_ADDR = "ARG_LOGICAL_ADDR";
+
+ /** The timeout of the test. */
+ private static final long TEST_TIMEOUT_MS = 10 * 60 * 1000L;
/**
* Method to make a device the active source. Will only work if the DUT is TV.
*
+ * @param host Reference to the JUnit4 host test class
* @param device Reference to the DUT
* @param logicalAddress The logical address of the device that should be made the active source
*/
- public static void setActiveSource(ITestDevice device, int logicalAddress)
- throws DeviceNotAvailableException {
- // Clear activity
- device.executeShellCommand(CLEAR_COMMAND);
- // Start the APK and wait for it to complete.
- device.executeShellCommand(
- START_COMMAND
- + "android.hdmicec.app.DEVICE_SELECT --ei "
- + "\"la\" "
- + logicalAddress);
+ public static void selectDevice(BaseHostJUnit4Test host, ITestDevice device,
+ String logicalAddress) throws DeviceNotAvailableException {
+ Map<String, String> args = new HashMap<>();
+ args.put(LOGICAL_ADDR, logicalAddress);
+ host.runDeviceTests(device, null, TEST_PKG, TEST_CLS, SELECT_DEVICE, null,
+ TEST_TIMEOUT_MS, TEST_TIMEOUT_MS, 0L, true, false, args);
+ }
+
+ /**
+ * Sends a long press keyevent (KEYCODE_UP) followed by a short press of another keyevent
+ * (KEYCODE_DOWN).
+ */
+ public static void sendLongPressKeyevent(BaseHostJUnit4Test host) throws DeviceNotAvailableException {
+ host.runDeviceTests(TEST_PKG, TEST_CLS, SEND_INTERRUPTED_LONG_PRESS);
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java
index f95a98c..55606e4 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecPowerStatusTest.java
@@ -17,7 +17,6 @@
package android.hdmicec.cts.common;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
import android.hdmicec.cts.BaseHdmiCecCtsTest;
import android.hdmicec.cts.CecMessage;
@@ -315,17 +314,9 @@
for (Integer operand : powerControlOperands) {
try {
sendDeviceToSleep();
- String wakeStateBefore = device.executeShellCommand(
- "dumpsys power | grep mWakefulness=");
- assertThat(wakeStateBefore.trim()).isEqualTo("mWakefulness=Asleep");
-
hdmiCecClient.sendUserControlPressAndRelease(source, operand, false);
-
TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
- String wakeStateAfter = device.executeShellCommand(
- "dumpsys power | grep mWakefulness=");
- assertWithMessage("Device should wake up on <User Control Pressed> %s", operand)
- .that(wakeStateAfter.trim()).isEqualTo("mWakefulness=Awake");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
} finally {
wakeUpDevice();
}
@@ -352,19 +343,10 @@
for (Integer operand : powerControlOperands) {
try {
wakeUpDevice();
- String wakeStateBefore = device.executeShellCommand(
- "dumpsys power | grep mWakefulness=");
- assertThat(wakeStateBefore.trim()).isEqualTo("mWakefulness=Awake");
-
WakeLockHelper.acquirePartialWakeLock(device);
hdmiCecClient.sendUserControlPressAndRelease(source, operand, false);
-
TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
- String wakeStateAfter = device.executeShellCommand(
- "dumpsys power | grep mWakefulness=");
- assertWithMessage("Device should go to standby on <User Control Pressed> %s",
- operand)
- .that(wakeStateAfter.trim()).isEqualTo("mWakefulness=Asleep");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
} finally {
wakeUpDevice();
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemAudioControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemAudioControlTest.java
index 0eebc18..132c19f 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemAudioControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecSystemAudioControlTest.java
@@ -153,10 +153,8 @@
@Test
public void cect_GiveSystemAudioModeStatus() throws Exception {
ITestDevice device = getDevice();
- /* Home Key to prevent device from going to deep suspend state */
- device.executeShellCommand("input keyevent KEYCODE_HOME");
sendDeviceToSleep();
- wakeUpDevice();
+ wakeUpDeviceWithoutWait();
hdmiCecClient.checkExpectedOutput(
hdmiCecClient.getSelfDevice(), CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceSelectForPlaybackTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceSelectForPlaybackTest.java
index d46150b..279bc2b 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceSelectForPlaybackTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecDeviceSelectForPlaybackTest.java
@@ -52,15 +52,6 @@
this, HdmiCecConstants.CEC_DEVICE_TYPE_PLAYBACK_DEVICE))
.around(hdmiCecClient);
- private String setPowerStateChangeOnActiveSourceLost(String valToSet) throws Exception {
- ITestDevice device = getDevice();
- String previousPowerStateChange = device.executeShellCommand("cmd hdmi_control cec_setting "
- + "get power_state_change_on_active_source_lost").split(" = ")[1].trim();
- device.executeShellCommand("cmd hdmi_control cec_setting "
- + "set power_state_change_on_active_source_lost " + valToSet);
- return previousPowerStateChange;
- }
-
private int getUnusedPhysicalAddress(int initialValue, int usedValue) {
if (initialValue == usedValue)
return 0x2000;
@@ -89,7 +80,8 @@
// Store previous power state change on active source lost.
// Set the power state change to none, such that the device won't go to sleep when the
// active source is changed.
- String previousPowerStateChange = setPowerStateChangeOnActiveSourceLost("none");
+ String previousPowerStateChange = setPowerStateChangeOnActiveSourceLost(
+ HdmiCecConstants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE);
try {
int dumpsysPhysicalAddress = getDumpsysPhysicalAddress();
// Add Playback 2 in the network.
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java
index 408d719..5b361be 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecPowerStatusTest.java
@@ -16,9 +16,6 @@
package android.hdmicec.cts.playback;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-
import android.hdmicec.cts.BaseHdmiCecCtsTest;
import android.hdmicec.cts.CecMessage;
import android.hdmicec.cts.CecOperand;
@@ -28,16 +25,16 @@
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
/**
* HDMI CEC tests verifying power status related messages of the device (CEC 2.0 CTS Section 7.6)
*/
@@ -113,29 +110,15 @@
*/
@Test
public void cect_hf4_6_7_setStreamPath_powerOn() throws Exception {
- ITestDevice device = getDevice();
-
try {
sendDeviceToSleep();
-
- TimeUnit.SECONDS.sleep(HdmiCecConstants.MAX_SLEEP_TIME_SECONDS);
-
- String wakeStateBefore = device.executeShellCommand(
- "dumpsys power | grep mWakefulness=");
- assertThat(wakeStateBefore.trim()).isEqualTo("mWakefulness=Asleep");
-
hdmiCecClient.sendCecMessage(
LogicalAddress.TV,
LogicalAddress.BROADCAST,
CecOperand.SET_STREAM_PATH,
CecMessage.formatParams(getDumpsysPhysicalAddress(),
HdmiCecConstants.PHYSICAL_ADDRESS_LENGTH));
-
- TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
- String wakeStateAfter = device.executeShellCommand(
- "dumpsys power | grep mWakefulness=");
- assertWithMessage("Device should wake up on <Set Stream Path>")
- .that(wakeStateAfter.trim()).isEqualTo("mWakefulness=Awake");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
} finally {
wakeUpDevice();
}
@@ -150,7 +133,6 @@
*/
@Test
public void cect_hf4_6_16_standby_tvBeforeUcp_20() throws Exception {
- ITestDevice device = getDevice();
setCec20();
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_TV);
@@ -176,7 +158,6 @@
*/
@Test
public void cect_hf4_6_19_standby_broadcastBeforeUcp_20() throws Exception {
- ITestDevice device = getDevice();
setCec20();
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_BROADCAST);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
index cc7d5fd..18fe41f 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
@@ -16,15 +16,21 @@
package android.hdmicec.cts.playback;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import android.hdmicec.cts.BaseHdmiCecCtsTest;
import android.hdmicec.cts.CecMessage;
import android.hdmicec.cts.CecOperand;
import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.HdmiControlManagerUtility;
import android.hdmicec.cts.LogicalAddress;
import android.hdmicec.cts.RemoteControlPassthrough;
+import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
@@ -141,4 +147,102 @@
cecKeycode,
androidKeycode);
}
+
+ /**
+ * Test HF4-8-9 (CEC 2.0)
+ *
+ * <p>Tests that the DUT sends multiple {@code <USER_CONTROL_PRESSED>[KEYCODE]} when there is a
+ * long press keyevent.
+ */
+ @Test
+ public void cect_hf4_8_9_SendLongPress() throws Exception {
+ setCec20();
+ String message;
+ int i;
+
+ HdmiControlManagerUtility.sendLongPressKeyevent(this);
+ // The above command should send 5 <UCP>[KEYCODE_UP] messages followed by 1 <UCR> message
+ // and finally, a <UCP>[KEYCODE_DOWN].
+ for (i = 0; i < 5; i++) {
+ message =
+ hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(message)).isEqualTo(HdmiCecConstants.CEC_KEYCODE_UP);
+ }
+ message =
+ hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.USER_CONTROL_RELEASED);
+ message =
+ hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(message)).isEqualTo(HdmiCecConstants.CEC_KEYCODE_DOWN);
+ }
+
+ /**
+ * Test HF4-8-13 (CEC 2.0)
+ *
+ * <p>Tests that the device responds with a {@code <FEATURE_ABORT>[Not in correct mode]} when it
+ * is not in a mode to action the message.
+ */
+ @Test
+ public void cect_hf4_8_13_AbortIncorrectMode() throws Exception {
+ setCec20();
+ try {
+ sendDeviceToSleep();
+ hdmiCecClient.sendUserControlPressAndRelease(
+ LogicalAddress.TV, HdmiCecConstants.CEC_KEYCODE_ROOT_MENU, false);
+ String message =
+ hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.FEATURE_ABORT);
+ int reason = CecMessage.getParams(message) & 0xFF;
+ assertThat(reason).isEqualTo(HdmiCecConstants.ABORT_NOT_IN_CORRECT_MODE);
+ } finally {
+ wakeUpDevice();
+ }
+ }
+
+ /*
+ * Test to check that the DUT sends volume key press events to the TV when system audio mode is
+ * not turned on.
+ */
+ @Test
+ @Ignore("b/218266432")
+ public void cect_sendVolumeKeyPressToTv() throws Exception {
+ ITestDevice device = getDevice();
+ String ucpMessage;
+ String command = "cmd hdmi_control setsam ";
+
+ simulateCecSinkConnected(device, getTargetLogicalAddress());
+
+ boolean wasSystemAudioModeOn = isSystemAudioModeOn(device);
+ if (wasSystemAudioModeOn) {
+ device.executeShellCommand(command + "off");
+ assertWithMessage("System audio mode is not off")
+ .that(isSystemAudioModeOn(device))
+ .isFalse();
+ }
+ try {
+ device.executeShellCommand("input keyevent KEYCODE_VOLUME_UP");
+ ucpMessage =
+ hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(ucpMessage))
+ .isEqualTo(HdmiCecConstants.CEC_KEYCODE_VOLUME_UP);
+ device.executeShellCommand("input keyevent KEYCODE_VOLUME_DOWN");
+ ucpMessage =
+ hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(ucpMessage))
+ .isEqualTo(HdmiCecConstants.CEC_KEYCODE_VOLUME_DOWN);
+ device.executeShellCommand("input keyevent KEYCODE_VOLUME_MUTE");
+ ucpMessage =
+ hdmiCecClient.checkExpectedOutput(
+ LogicalAddress.TV, CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(ucpMessage))
+ .isEqualTo(HdmiCecConstants.CEC_KEYCODE_MUTE);
+ } finally {
+ if (wasSystemAudioModeOn) {
+ device.executeShellCommand(command + "on");
+ }
+ }
+ }
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
index e715f91..65da394 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRoutingControlTest.java
@@ -132,7 +132,6 @@
*/
@Test
public void cect_11_2_2_4_InactiveSourceOnStandby() throws Exception {
- ITestDevice device = getDevice();
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_NONE);
try {
@@ -143,7 +142,7 @@
CecOperand.SET_STREAM_PATH,
CecMessage.formatParams(dumpsysPhysicalAddress));
TimeUnit.SECONDS.sleep(5);
- sendDeviceToSleep();
+ sendDeviceToSleepWithoutWait();
String message = hdmiCecClient.checkExpectedOutput(LogicalAddress.TV,
CecOperand.INACTIVE_SOURCE);
CecMessage.assertPhysicalAddressValid(message, dumpsysPhysicalAddress);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
new file mode 100644
index 0000000..718ae56
--- /dev/null
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecSystemAudioControlTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hdmicec.cts.playback;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hdmicec.cts.BaseHdmiCecCtsTest;
+import android.hdmicec.cts.CecMessage;
+import android.hdmicec.cts.CecOperand;
+import android.hdmicec.cts.HdmiCecConstants;
+import android.hdmicec.cts.LogicalAddress;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.Rule;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+/** HDMI CEC test verifying system audio control commands (CEC 2.0 CTS Section 7.6) */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public final class HdmiCecSystemAudioControlTest extends BaseHdmiCecCtsTest {
+
+ public HdmiCecSystemAudioControlTest() {
+ super("-t", "a", "-t", "x");
+ }
+
+ @Rule
+ public RuleChain ruleChain =
+ RuleChain.outerRule(CecRules.requiresCec(this))
+ .around(CecRules.requiresLeanback(this))
+ .around(
+ CecRules.requiresDeviceType(
+ this, HdmiCecConstants.CEC_DEVICE_TYPE_PLAYBACK_DEVICE))
+ .around(hdmiCecClient);
+
+ /**
+ * Test HF4-10-5
+ *
+ * <p>Tests that a device forwards all remote control commands to the device that is providing
+ * the audio rendering.
+ */
+ @Test
+ @Ignore("b/218266432")
+ public void cect_hf4_10_5_RemoteControlCommandsWithSystemAudioControlProperty()
+ throws Exception {
+ setCec20();
+
+ ITestDevice device = getDevice();
+ // Broadcast <Set System Audio Mode> ["off"].
+ broadcastSystemAudioModeMessage(false);
+ // All remote control commands should forward to the TV.
+ sendVolumeUpCommandAndCheckForUcp(LogicalAddress.TV);
+
+ // Broadcast <Set System Audio Mode> ["on"].
+ broadcastSystemAudioModeMessage(true);
+ // All remote control commands should forward to the audio rendering device.
+ sendVolumeUpCommandAndCheckForUcp(LogicalAddress.AUDIO_SYSTEM);
+ }
+
+ private void broadcastSystemAudioModeMessage(boolean val) throws Exception {
+ hdmiCecClient.sendCecMessage(
+ hdmiCecClient.getSelfDevice(),
+ LogicalAddress.BROADCAST,
+ CecOperand.SET_SYSTEM_AUDIO_MODE,
+ CecMessage.formatParams(val ? 1 : 0));
+ }
+
+ private void sendVolumeUpCommandAndCheckForUcp(LogicalAddress toDevice) throws Exception {
+ getDevice().executeShellCommand("input keyevent KEYCODE_VOLUME_UP");
+ String message =
+ hdmiCecClient.checkExpectedOutput(toDevice, CecOperand.USER_CONTROL_PRESSED);
+ assertThat(CecMessage.getParams(message)).isEqualTo(HdmiCecConstants.CEC_KEYCODE_VOLUME_UP);
+ hdmiCecClient.checkExpectedOutput(toDevice, CecOperand.USER_CONTROL_RELEASED);
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecTvPowerToggleTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecTvPowerToggleTest.java
index 7f666e4..125b1e3 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecTvPowerToggleTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecTvPowerToggleTest.java
@@ -16,8 +16,6 @@
package android.hdmicec.cts.playback;
-import static com.google.common.truth.Truth.assertThat;
-
import android.hdmicec.cts.BaseHdmiCecCtsTest;
import android.hdmicec.cts.CecMessage;
import android.hdmicec.cts.CecOperand;
@@ -71,13 +69,10 @@
device.waitForBootComplete(HdmiCecConstants.REBOOT_TIMEOUT);
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_TV);
+ String previousPowerStateChange = setPowerStateChangeOnActiveSourceLost(
+ HdmiCecConstants.POWER_STATE_CHANGE_ON_ACTIVE_SOURCE_LOST_NONE);
try {
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 0");
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 1");
- hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
- hdmiCecClient.sendCecMessage(LogicalAddress.TV, PLAYBACK_DEVICE,
- CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(OFF));
- TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
+ simulateCecSinkConnected(device, PLAYBACK_DEVICE);
hdmiCecClient.sendCecMessage(LogicalAddress.TV, LogicalAddress.BROADCAST,
CecOperand.ACTIVE_SOURCE, CecMessage.formatParams("0000"));
TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
@@ -89,10 +84,10 @@
CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(ON));
// Verify that device is asleep and <Standby> was sent to TV.
hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.STANDBY);
- String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertThat(wakeState.trim()).isEqualTo("mWakefulness=Asleep");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
} finally {
setPowerControlMode(previousPowerControlMode);
+ setPowerStateChangeOnActiveSourceLost(previousPowerStateChange);
wakeUpDevice();
}
}
@@ -109,12 +104,7 @@
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_TV);
try {
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 0");
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 1");
- hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
- hdmiCecClient.sendCecMessage(LogicalAddress.TV, PLAYBACK_DEVICE,
- CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(OFF));
- TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
+ simulateCecSinkConnected(device, PLAYBACK_DEVICE);
device.executeShellCommand("input keyevent KEYCODE_HOME");
TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
hdmiCecClient.clearClientOutput();
@@ -125,8 +115,7 @@
CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(ON));
// Verify that device is asleep and <Standby> was sent to TV.
hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.STANDBY);
- String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertThat(wakeState.trim()).isEqualTo("mWakefulness=Asleep");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
} finally {
setPowerControlMode(previousPowerControlMode);
wakeUpDevice();
@@ -145,13 +134,9 @@
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_TV);
try {
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 0");
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 1");
- hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
- hdmiCecClient.sendCecMessage(LogicalAddress.TV, PLAYBACK_DEVICE,
- CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(OFF));
- TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
+ simulateCecSinkConnected(device, PLAYBACK_DEVICE);
sendDeviceToSleep();
+ TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
hdmiCecClient.clearClientOutput();
device.executeShellCommand("input keyevent KEYCODE_TV_POWER");
hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
@@ -159,8 +144,7 @@
CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(ON));
// Verify that device is asleep and <Standby> was sent to TV.
hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.STANDBY);
- String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertThat(wakeState.trim()).isEqualTo("mWakefulness=Asleep");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_ASLEEP);
} finally {
setPowerControlMode(previousPowerControlMode);
wakeUpDevice();
@@ -179,13 +163,9 @@
String previousPowerControlMode =
setPowerControlMode(HdmiCecConstants.POWER_CONTROL_MODE_TV);
try {
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 0");
- device.executeShellCommand("cmd hdmi_control cec_setting set hdmi_cec_enabled 1");
- hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
- hdmiCecClient.sendCecMessage(LogicalAddress.TV, PLAYBACK_DEVICE,
- CecOperand.REPORT_POWER_STATUS, CecMessage.formatParams(OFF));
- TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
+ simulateCecSinkConnected(device, PLAYBACK_DEVICE);
sendDeviceToSleep();
+ TimeUnit.SECONDS.sleep(HdmiCecConstants.DEVICE_WAIT_TIME_SECONDS);
hdmiCecClient.clearClientOutput();
device.executeShellCommand("input keyevent KEYCODE_TV_POWER");
hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.GIVE_POWER_STATUS);
@@ -194,8 +174,7 @@
// Verify that device is awake and <Text View On> and <Active Source> were sent.
hdmiCecClient.checkExpectedOutput(LogicalAddress.TV, CecOperand.TEXT_VIEW_ON);
hdmiCecClient.checkExpectedOutput(LogicalAddress.BROADCAST, CecOperand.ACTIVE_SOURCE);
- String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertThat(wakeState.trim()).isEqualTo("mWakefulness=Awake");
+ assertDeviceWakefulness(HdmiCecConstants.WAKEFULNESS_AWAKE);
} finally {
setPowerControlMode(previousPowerControlMode);
wakeUpDevice();
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRemoteControlPassThroughTest.java
index ff2ff00..605ecee 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRemoteControlPassThroughTest.java
@@ -46,7 +46,7 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecRemoteControlPassThroughTest extends BaseHdmiCecCtsTest {
- private static final int WAIT_TIME_MS = 300;
+ private static final int WAIT_TIME_MS = 1000;
private HashMap<String, Integer> remoteControlKeys = new HashMap<String, Integer>();
private HashMap<String, Integer> remoteControlAudioKeys = new HashMap<String, Integer>();
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRoutingControlTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRoutingControlTest.java
index 1775f5e..75d006a 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRoutingControlTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecRoutingControlTest.java
@@ -41,7 +41,7 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecRoutingControlTest extends BaseHdmiCecCtsTest {
- private static final int WAIT_TIME_MS = 300;
+ private static final int WAIT_TIME_MS = 1000;
@Rule
public RuleChain ruleChain =
@@ -98,8 +98,8 @@
hdmiCecClient.broadcastReportPhysicalAddress(LogicalAddress.PLAYBACK_1, 0x2200);
TimeUnit.SECONDS.sleep(2);
// Make the device with LA 4 as the active source.
- HdmiControlManagerUtility.setActiveSource(
- getDevice(), LogicalAddress.PLAYBACK_1.getLogicalAddressAsInt());
+ HdmiControlManagerUtility.selectDevice(
+ this, getDevice(), LogicalAddress.PLAYBACK_1.toString());
String message = hdmiCecClient.checkExpectedOutput(CecOperand.SET_STREAM_PATH);
assertWithMessage("Device has not sent a Set Stream Path message to the selected device")
.that(CecMessage.getParams(message))
@@ -115,8 +115,7 @@
@Test
public void cect_11_1_2_2_DutDoesNotRespondToRequestActiveSourceMessage() throws Exception {
// Ensure that DUT is the active source.
- HdmiControlManagerUtility.setActiveSource(
- getDevice(), LogicalAddress.TV.getLogicalAddressAsInt());
+ HdmiControlManagerUtility.selectDevice(this, getDevice(), LogicalAddress.TV.toString());
hdmiCecClient.checkExpectedOutput(CecOperand.ACTIVE_SOURCE);
// Broadcast an active source from the client device.
hdmiCecClient.broadcastActiveSource(hdmiCecClient.getSelfDevice());
@@ -137,8 +136,7 @@
@Test
public void cect_11_1_2_3_DutDoesRespondToRequestActiveSourceMessage() throws Exception {
// Make the TV device the active source.
- HdmiControlManagerUtility.setActiveSource(
- getDevice(), LogicalAddress.TV.getLogicalAddressAsInt());
+ HdmiControlManagerUtility.selectDevice(this, getDevice(), LogicalAddress.TV.toString());
hdmiCecClient.sendCecMessage(
hdmiCecClient.getSelfDevice(),
LogicalAddress.BROADCAST,
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvOneTouchPlayTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvOneTouchPlayTest.java
index 4aba289..7ee413a 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvOneTouchPlayTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvOneTouchPlayTest.java
@@ -40,7 +40,7 @@
@RunWith(DeviceJUnit4ClassRunner.class)
public class HdmiCecTvOneTouchPlayTest extends BaseHdmiCecCtsTest {
- private static final int WAIT_TIME_MS = 300;
+ private static final int WAIT_TIME_MS = 1000;
private static final int SLEEP_TIMESTEP_SECONDS = 1;
private static final int POWER_TRANSITION_WAIT_TIME = 10;
@@ -131,8 +131,7 @@
TimeUnit.MILLISECONDS.sleep(WAIT_TIME_MS);
}
// Make the TV device the active source.
- HdmiControlManagerUtility.setActiveSource(
- getDevice(), LogicalAddress.TV.getLogicalAddressAsInt());
+ HdmiControlManagerUtility.selectDevice(this, getDevice(), LogicalAddress.TV.toString());
hdmiCecClient.checkExpectedOutput(LogicalAddress.BROADCAST, CecOperand.ACTIVE_SOURCE);
}
@@ -209,4 +208,3 @@
.isEqualTo(powerStatus);
}
}
-
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvStandbyTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvStandbyTest.java
index 4efab29..d3b6d1d 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvStandbyTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/tv/HdmiCecTvStandbyTest.java
@@ -64,10 +64,6 @@
try {
sendDeviceToSleep();
hdmiCecClient.checkExpectedOutput(LogicalAddress.BROADCAST, CecOperand.STANDBY);
- String wakeState = device.executeShellCommand("dumpsys power | grep mWakefulness=");
- assertWithMessage("Device is not in standby.")
- .that(wakeState.trim())
- .isEqualTo("mWakefulness=Asleep");
} finally {
wakeUpDevice();
setHdmiControlDeviceAutoOff(wasOn);
diff --git a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
index afaa9c8..6423aff 100644
--- a/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
+++ b/hostsidetests/inputmethodservice/common/src/android/inputmethodservice/cts/common/test/ShellCommandUtils.java
@@ -29,6 +29,8 @@
// Copied from android.content.pm.PackageManager#FEATURE_INPUT_METHODS.
public static final String FEATURE_INPUT_METHODS = "android.software.input_methods";
+ public static final String FEATURE_TV_OPERATOR_TIER = "com.google.android.tv.operator_tier";
+
private static final String SETTING_DEFAULT_IME = "secure default_input_method";
/** Command to get ID of current IME. */
diff --git a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
index 4064ff5..bd6e4e3 100644
--- a/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
+++ b/hostsidetests/inputmethodservice/hostside/src/android/inputmethodservice/cts/hostside/InputMethodServiceLifecycleTest.java
@@ -24,6 +24,7 @@
import static android.inputmethodservice.cts.common.DeviceEventConstants.RECEIVER_COMPONENT;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.inputmethodservice.cts.common.ComponentNameUtils;
@@ -460,6 +461,8 @@
private void testImeSwitchingWithoutWindowFocusAfterDisplayOffOn(boolean instant)
throws Exception {
+ // Skip whole tests when DUT has com.google.android.tv.operator_tier feature.
+ assumeFalse(hasDeviceFeature(ShellCommandUtils.FEATURE_TV_OPERATOR_TIER));
sendTestStartEvent(
DeviceTestConstants.TEST_IME_SWITCHING_WITHOUT_WINDOW_FOCUS_AFTER_DISPLAY_OFF_ON);
installPossibleInstantPackage(
diff --git a/hostsidetests/jvmti/redefining/app/src/android/jvmti/cts/JvmtiRedefineClassesTest.java b/hostsidetests/jvmti/redefining/app/src/android/jvmti/cts/JvmtiRedefineClassesTest.java
index d68d1ddc..0e101d9 100644
--- a/hostsidetests/jvmti/redefining/app/src/android/jvmti/cts/JvmtiRedefineClassesTest.java
+++ b/hostsidetests/jvmti/redefining/app/src/android/jvmti/cts/JvmtiRedefineClassesTest.java
@@ -742,7 +742,7 @@
@Test
public void testCannotRetransformOnLoadTest() throws Exception {
- // Just a sanity check along with below.
+ // Just a confidence check along with below.
Class<?> target_class = new InMemoryDexClassLoader(
ByteBuffer.wrap(ONLOAD_INITIAL_CLASS),
getClass().getClassLoader()).loadClass(ONLOAD_TEST_CLASS_NAME);
diff --git a/hostsidetests/multiuser/OWNERS b/hostsidetests/multiuser/OWNERS
index 2b344eb..cbd8eb1 100644
--- a/hostsidetests/multiuser/OWNERS
+++ b/hostsidetests/multiuser/OWNERS
@@ -1,4 +1,3 @@
# Bug component: 71510
include /tests/app/OWNERS
-
-bookatz@google.com
+include platform/frameworks/base:/MULTIUSER_OWNERS
diff --git a/hostsidetests/sample/AndroidTest.xml b/hostsidetests/sample/AndroidTest.xml
index 80189da..2878a31 100644
--- a/hostsidetests/sample/AndroidTest.xml
+++ b/hostsidetests/sample/AndroidTest.xml
@@ -15,6 +15,8 @@
-->
<configuration description="Config for CTS Sample host test cases">
<option name="test-suite-tag" value="cts" />
+ <!-- Change the value field of `component` into an appropriate one.
+ See README for the full list. -->
<option name="config-descriptor:metadata" key="component" value="misc" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/hostsidetests/sample/README b/hostsidetests/sample/README
new file mode 100644
index 0000000..71dbbce
--- /dev/null
+++ b/hostsidetests/sample/README
@@ -0,0 +1,4 @@
+This 'sample' folder is a sample which illustrates the basic structure and contents of a CTS
+hostside module.
+
+Please refer to 'cts/tests/sample/README' for more details on how to use this sample.
\ No newline at end of file
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
index 0ba69f5..17aab09 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
@@ -32,7 +32,7 @@
private void startOverlayService() {
if (Settings.canDrawOverlays(this)) {
- Intent intent = new Intent(PocActivity.this, PocService.class);
+ Intent intent = new Intent(PocActivity.this, PocService.class);
startService(intent);
} else {
try {
@@ -45,7 +45,7 @@
}
private void stopOverlayService() {
- Intent intent = new Intent(PocActivity.this, PocService.class);
+ Intent intent = new Intent(PocActivity.this, PocService.class);
stopService(intent);
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
index 11fd02c..b654e0c 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/PocActivity.java
@@ -25,7 +25,7 @@
private void startOverlayService() {
if (Settings.canDrawOverlays(this)) {
- Intent intent = new Intent(PocActivity.this, PocService.class);
+ Intent intent = new Intent(PocActivity.this, PocService.class);
startService(intent);
} else {
try {
@@ -38,7 +38,7 @@
}
private void stopOverlayService() {
- Intent intent = new Intent(PocActivity.this, PocService.class);
+ Intent intent = new Intent(PocActivity.this, PocService.class);
stopService(intent);
}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/perfetto/PerfettoTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/perfetto/PerfettoTests.java
index 22b2b49..6b2f95f 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/perfetto/PerfettoTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/perfetto/PerfettoTests.java
@@ -36,6 +36,7 @@
import com.android.os.AtomsProto.Atom;
import com.android.os.AtomsProto.PerfettoTrigger;
import com.android.os.AtomsProto.PerfettoUploaded;
+import com.android.os.AtomsProto.TracingServiceReportEvent;
import com.android.os.StatsLog.EventMetricData;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.testtype.DeviceTestCase;
@@ -45,17 +46,18 @@
import com.google.protobuf.ByteString;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+
import perfetto.protos.PerfettoConfig.DataSourceConfig;
import perfetto.protos.PerfettoConfig.FtraceConfig;
import perfetto.protos.PerfettoConfig.TraceConfig;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
public class PerfettoTests extends DeviceTestCase implements IBuildReceiver {
- private static final int WAIT_AFTER_START_PERFETTO_MS = 2000;
+ private static final int WAIT_AFTER_START_PERFETTO_MS = 3000;
// Config constants
// These were chosen to match the statsd <-> Perfetto CTS integration
@@ -84,11 +86,11 @@
public void setBuild(IBuildInfo buildInfo) {
}
- public void testPerfettoUploadedAtoms() throws Exception {
+ public void testPerfettoUploadedIncidentdAtoms() throws Exception {
if (DeviceUtils.hasFeature(getDevice(), DeviceUtils.FEATURE_WATCH)) return;
resetPerfettoGuardrails();
- StatsdConfig.Builder config = getStatsdConfig();
+ StatsdConfig.Builder config = getStatsdConfig(getPerfettoIncidentConfig());
ConfigUtils.addEventMetric(config, AtomsProto.Atom.PERFETTO_UPLOADED_FIELD_NUMBER);
ConfigUtils.uploadConfig(getDevice(), config);
@@ -106,6 +108,49 @@
PerfettoUploaded.Event.PERFETTO_TRACED_START_TRACING);
}
+ public void testSkipReportAtoms() throws Exception {
+ if (DeviceUtils.hasFeature(getDevice(), DeviceUtils.FEATURE_WATCH)) return;
+ resetPerfettoGuardrails();
+
+ StatsdConfig.Builder config = getStatsdConfig(getPerfettoReportConfig(true));
+ ConfigUtils.addEventMetric(config, AtomsProto.Atom.PERFETTO_UPLOADED_FIELD_NUMBER);
+ ConfigUtils.uploadConfig(getDevice(), config);
+
+ startPerfettoTrace();
+ Thread.sleep(WAIT_AFTER_START_PERFETTO_MS);
+
+ List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+ assertThat(extractPerfettoUploadedEvents(data))
+ .containsAtLeast(
+ PerfettoUploaded.Event.PERFETTO_TRACE_BEGIN,
+ PerfettoUploaded.Event.PERFETTO_ON_CONNECT,
+ PerfettoUploaded.Event.PERFETTO_TRACED_ENABLE_TRACING,
+ PerfettoUploaded.Event.PERFETTO_TRACED_START_TRACING);
+ }
+
+ public void testReportAtoms() throws Exception {
+ if (DeviceUtils.hasFeature(getDevice(), DeviceUtils.FEATURE_WATCH)) return;
+ resetPerfettoGuardrails();
+
+ StatsdConfig.Builder config = getStatsdConfig(getPerfettoReportConfig(false));
+ ConfigUtils.addEventMetric(config, AtomsProto.Atom.PERFETTO_UPLOADED_FIELD_NUMBER);
+ ConfigUtils.addEventMetric(config, Atom.TRACING_SERVICE_REPORT_EVENT_FIELD_NUMBER);
+ ConfigUtils.uploadConfig(getDevice(), config);
+
+ startPerfettoTrace();
+ Thread.sleep(WAIT_AFTER_START_PERFETTO_MS);
+
+ List<EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+ assertThat(extractPerfettoUploadedEvents(data))
+ .containsAtLeast(
+ PerfettoUploaded.Event.PERFETTO_CMD_FW_REPORT_BEGIN,
+ PerfettoUploaded.Event.PERFETTO_CMD_FW_REPORT_HANDOFF);
+ assertThat(extractReportEvents(data))
+ .containsExactly(
+ TracingServiceReportEvent.Event.TRACING_SERVICE_REPORT_BEGIN,
+ TracingServiceReportEvent.Event.TRACING_SERVICE_REPORT_BIND_PERM_INCORRECT);
+ }
+
public void testPerfettoTriggerAtoms() throws Exception {
if (DeviceUtils.hasFeature(getDevice(), DeviceUtils.FEATURE_WATCH)) return;
@@ -123,11 +168,31 @@
PerfettoTrigger.Event.PERFETTO_TRIGGER_PERFETTO_TRIGGER);
}
- /**
- * Returns a protobuf-encoded perfetto config that enables the kernel ftrace tracer with
- * sched_switch for 10 seconds.
- */
- private ByteString getPerfettoConfig() {
+ private ByteString getPerfettoIncidentConfig() {
+ TraceConfig.IncidentReportConfig incident =
+ TraceConfig.IncidentReportConfig.newBuilder()
+ .setSkipIncidentd(true)
+ .build();
+ return getBasePerfettoConfigBuilder()
+ .setIncidentReportConfig(incident)
+ .build()
+ .toByteString();
+ }
+
+ private ByteString getPerfettoReportConfig(boolean skipReport) {
+ TraceConfig.AndroidReportConfig config = TraceConfig.AndroidReportConfig.newBuilder()
+ .setSkipReport(skipReport)
+ .setReporterServicePackage("android.cts")
+ .setReporterServiceClass("android.cts.class")
+ .setUsePipeInFrameworkForTesting(true)
+ .build();
+ return getBasePerfettoConfigBuilder()
+ .setAndroidReportConfig(config)
+ .build()
+ .toByteString();
+ }
+
+ private TraceConfig.Builder getBasePerfettoConfigBuilder() {
TraceConfig.Builder builder = TraceConfig.newBuilder();
TraceConfig.BufferConfig buffer =
@@ -146,15 +211,9 @@
TraceConfig.DataSource.newBuilder().setConfig(dataSourceConfig).build();
builder.addDataSources(dataSource);
- builder.setDurationMs(3000);
+ builder.setDurationMs(500);
builder.setAllowUserBuildTracing(true);
- TraceConfig.IncidentReportConfig incident =
- TraceConfig.IncidentReportConfig.newBuilder()
- .setSkipIncidentd(true)
- .build();
- builder.setIncidentReportConfig(incident);
-
// To avoid being hit with guardrails firing in multiple test runs back
// to back, we set a unique session key for each config.
Random random = new Random();
@@ -162,14 +221,16 @@
sessionNameBuilder.append(random.nextInt() & Integer.MAX_VALUE);
builder.setUniqueSessionName(sessionNameBuilder.toString());
- return builder.build().toByteString();
+ return builder;
}
private List<PerfettoUploaded.Event> extractPerfettoUploadedEvents(
List<EventMetricData> input) {
List<PerfettoUploaded.Event> output = new ArrayList<>();
for (EventMetricData data : input) {
- output.add(data.getAtom().getPerfettoUploaded().getEvent());
+ if (data.getAtom().hasPerfettoUploaded()) {
+ output.add(data.getAtom().getPerfettoUploaded().getEvent());
+ }
}
return output;
}
@@ -178,7 +239,20 @@
List<EventMetricData> input) {
List<PerfettoTrigger.Event> output = new ArrayList<>();
for (EventMetricData data : input) {
- output.add(data.getAtom().getPerfettoTrigger().getEvent());
+ if (data.getAtom().hasPerfettoTrigger()) {
+ output.add(data.getAtom().getPerfettoTrigger().getEvent());
+ }
+ }
+ return output;
+ }
+
+ private List<TracingServiceReportEvent.Event> extractReportEvents(
+ List<EventMetricData> input) {
+ List<TracingServiceReportEvent.Event> output = new ArrayList<>();
+ for (EventMetricData data : input) {
+ if (data.getAtom().hasTracingServiceReportEvent()) {
+ output.add(data.getAtom().getTracingServiceReportEvent().getEvent());
+ }
}
return output;
}
@@ -190,11 +264,12 @@
private void runTriggerPerfetto() throws Exception {
final String cmd = "trigger_perfetto cts.test.trigger";
CommandResult cr = getDevice().executeShellV2Command(cmd);
- if (cr.getStatus() != CommandStatus.SUCCESS)
+ if (cr.getStatus() != CommandStatus.SUCCESS) {
throw new Exception(
String.format(
"Error while executing %s: %s %s",
cmd, cr.getStdout(), cr.getStderr()));
+ }
}
/**
@@ -204,11 +279,12 @@
private void resetPerfettoGuardrails() throws Exception {
final String cmd = "perfetto --reset-guardrails";
CommandResult cr = getDevice().executeShellV2Command(cmd);
- if (cr.getStatus() != CommandStatus.SUCCESS)
+ if (cr.getStatus() != CommandStatus.SUCCESS) {
throw new Exception(
String.format(
"Error while executing %s: %s %s",
cmd, cr.getStdout(), cr.getStderr()));
+ }
}
private void startPerfettoTrace() throws Exception {
@@ -219,7 +295,7 @@
1, AppBreadcrumbReported.State.START.ordinal()));
}
- private final StatsdConfig.Builder getStatsdConfig() throws Exception {
+ private final StatsdConfig.Builder getStatsdConfig(ByteString config) throws Exception {
return ConfigUtils.createConfigBuilder("AID_NOBODY")
.addSubscription(
Subscription.newBuilder()
@@ -228,7 +304,7 @@
.setRuleId(ALERT_ID)
.setPerfettoDetails(
PerfettoDetails.newBuilder()
- .setTraceConfig(getPerfettoConfig())))
+ .setTraceConfig(config)))
.addValueMetric(
ValueMetric.newBuilder()
.setId(METRIC_ID)
diff --git a/libs/json/fuzzers/Android.bp b/libs/json/fuzzers/Android.bp
index 6434e9a..d6f7f0d 100644
--- a/libs/json/fuzzers/Android.bp
+++ b/libs/json/fuzzers/Android.bp
@@ -12,6 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
java_fuzz_host {
name: "json-reader-fuzzer",
srcs: [
@@ -21,4 +25,4 @@
"jazzer",
"jsonlib",
],
-}
\ No newline at end of file
+}
diff --git a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
index 9b7951f..1c17037 100644
--- a/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
+++ b/tests/accessibility/src/android/view/accessibility/cts/AccessibilityEventTest.java
@@ -19,22 +19,28 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.accessibility.cts.common.AccessibilityDumpOnFailureRule;
import android.accessibility.cts.common.InstrumentedAccessibilityServiceTestRule;
import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.UiAutomation;
import android.content.Context;
import android.os.Message;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
+import android.text.SpannableString;
import android.text.TextUtils;
+import android.text.style.LocaleSpan;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityRecord;
import android.widget.LinearLayout;
+import android.widget.TextView;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -49,45 +55,59 @@
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
-/**
- * Class for testing {@link AccessibilityEvent}.
- */
+/** Class for testing {@link AccessibilityEvent}. */
@Presubmit
@RunWith(AndroidJUnit4.class)
public class AccessibilityEventTest {
+ private static final long IDLE_TIMEOUT_MS = 500;
+ private static final long DEFAULT_TIMEOUT_MS = 1000;
+
+ // From ViewConfiguration.SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS
+ private static final long SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS = 100;
private EventReportingLinearLayout mParentView;
private View mChildView;
- private AccessibilityManager mAccessibilityManager;
+ private TextView mTextView;
+ private String mPackageName;
+ private static Instrumentation sInstrumentation;
+ private static UiAutomation sUiAutomation;
private final ActivityTestRule<DummyActivity> mActivityRule =
new ActivityTestRule<>(DummyActivity.class, false, false);
private final AccessibilityDumpOnFailureRule mDumpOnFailureRule =
new AccessibilityDumpOnFailureRule();
private InstrumentedAccessibilityServiceTestRule<SpeakingAccessibilityService>
- mInstrumentedAccessibilityServiceRule = new InstrumentedAccessibilityServiceTestRule<>(
- SpeakingAccessibilityService.class, false);
+ mInstrumentedAccessibilityServiceRule =
+ new InstrumentedAccessibilityServiceTestRule<>(
+ SpeakingAccessibilityService.class, false);
@Rule
- public final RuleChain mRuleChain = RuleChain
- .outerRule(mActivityRule)
- .around(mInstrumentedAccessibilityServiceRule)
- .around(mDumpOnFailureRule);
+ public final RuleChain mRuleChain =
+ RuleChain.outerRule(mActivityRule)
+ .around(mInstrumentedAccessibilityServiceRule)
+ .around(mDumpOnFailureRule);
@Before
public void setUp() throws Throwable {
final Activity activity = mActivityRule.launchActivity(null);
- mAccessibilityManager = activity.getSystemService(AccessibilityManager.class);
+ mPackageName = activity.getApplicationContext().getPackageName();
+ sInstrumentation = InstrumentationRegistry.getInstrumentation();
+ sUiAutomation = sInstrumentation.getUiAutomation();
mInstrumentedAccessibilityServiceRule.enableService();
- mActivityRule.runOnUiThread(() -> {
- final LinearLayout grandparent = new LinearLayout(activity);
- activity.setContentView(grandparent);
- mParentView = new EventReportingLinearLayout(activity);
- mChildView = new View(activity);
- grandparent.addView(mParentView);
- mParentView.addView(mChildView);
- });
+ mActivityRule.runOnUiThread(
+ () -> {
+ final LinearLayout grandparent = new LinearLayout(activity);
+ activity.setContentView(grandparent);
+ mParentView = new EventReportingLinearLayout(activity);
+ mChildView = new View(activity);
+ mTextView = new TextView(activity);
+ grandparent.addView(mParentView);
+ mParentView.addView(mChildView);
+ mParentView.addView(mTextView);
+ });
+ sUiAutomation.waitForIdle(IDLE_TIMEOUT_MS, DEFAULT_TIMEOUT_MS);
}
private static class EventReportingLinearLayout extends LinearLayout {
@@ -106,52 +126,66 @@
@Test
public void testScrollEvent() throws Exception {
- mChildView.scrollTo(0, 100);
- Thread.sleep(1000);
- scrollEventFilter.assertReceivedEventCount(1);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> mChildView.scrollTo(0, 100), new ScrollEventFilter(1), DEFAULT_TIMEOUT_MS);
}
@Test
public void testScrollEventBurstCombined() throws Exception {
- mChildView.scrollTo(0, 100);
- mChildView.scrollTo(0, 125);
- mChildView.scrollTo(0, 150);
- mChildView.scrollTo(0, 175);
- Thread.sleep(1000);
- scrollEventFilter.assertReceivedEventCount(1);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ mChildView.scrollTo(0, 100);
+ mChildView.scrollTo(0, 125);
+ mChildView.scrollTo(0, 150);
+ mChildView.scrollTo(0, 175);
+ },
+ new ScrollEventFilter(1),
+ DEFAULT_TIMEOUT_MS);
}
@Test
public void testScrollEventsDeliveredInCorrectInterval() throws Exception {
- mChildView.scrollTo(0, 25);
- mChildView.scrollTo(0, 50);
- mChildView.scrollTo(0, 100);
- Thread.sleep(150);
- mChildView.scrollTo(0, 150);
- mChildView.scrollTo(0, 175);
- Thread.sleep(50);
- mChildView.scrollTo(0, 200);
- Thread.sleep(1000);
- scrollEventFilter.assertReceivedEventCount(2);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ try {
+ mChildView.scrollTo(0, 25);
+ mChildView.scrollTo(0, 50);
+ mChildView.scrollTo(0, 100);
+ Thread.sleep(SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS * 2);
+ mChildView.scrollTo(0, 150);
+ mChildView.scrollTo(0, 175);
+ Thread.sleep(SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS / 2);
+ mChildView.scrollTo(0, 200);
+ } catch (InterruptedException e) {
+ fail("Interrupted while dispatching event bursts.");
+ }
+ },
+ new ScrollEventFilter(2),
+ DEFAULT_TIMEOUT_MS);
}
- private AccessibilityEventFilter scrollEventFilter = new AccessibilityEventFilter() {
- public boolean pass(AccessibilityEvent event) {
- return event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED;
- }
- };
-
@Test
public void testScrollEventsClearedOnDetach() throws Throwable {
- mChildView.scrollTo(0, 25);
- mChildView.scrollTo(5, 50);
- mChildView.scrollTo(7, 100);
- mActivityRule.runOnUiThread(() -> {
- mParentView.removeView(mChildView);
- mParentView.addView(mChildView);
- });
- mChildView.scrollTo(0, 150);
- Thread.sleep(1000);
+ ScrollEventFilter scrollEventFilter = new ScrollEventFilter(1);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ mChildView.scrollTo(0, 25);
+ mChildView.scrollTo(5, 50);
+ mChildView.scrollTo(7, 100);
+ },
+ scrollEventFilter,
+ DEFAULT_TIMEOUT_MS);
+ mActivityRule.runOnUiThread(
+ () -> {
+ mParentView.removeView(mChildView);
+ mParentView.addView(mChildView);
+ });
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ mChildView.scrollTo(0, 150);
+ },
+ scrollEventFilter,
+ DEFAULT_TIMEOUT_MS);
AccessibilityEvent event = scrollEventFilter.getLastEvent();
assertEquals(-7, event.getScrollDeltaX());
assertEquals(50, event.getScrollDeltaY());
@@ -159,10 +193,15 @@
@Test
public void testScrollEventsCaptureTotalDelta() throws Throwable {
- mChildView.scrollTo(0, 25);
- mChildView.scrollTo(5, 50);
- mChildView.scrollTo(7, 100);
- Thread.sleep(1000);
+ ScrollEventFilter scrollEventFilter = new ScrollEventFilter(1);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ mChildView.scrollTo(0, 25);
+ mChildView.scrollTo(5, 50);
+ mChildView.scrollTo(7, 100);
+ },
+ scrollEventFilter,
+ DEFAULT_TIMEOUT_MS);
AccessibilityEvent event = scrollEventFilter.getLastEvent();
assertEquals(7, event.getScrollDeltaX());
assertEquals(100, event.getScrollDeltaY());
@@ -170,12 +209,24 @@
@Test
public void testScrollEventsClearDeltaAfterSending() throws Throwable {
- mChildView.scrollTo(0, 25);
- mChildView.scrollTo(5, 50);
- mChildView.scrollTo(7, 100);
- Thread.sleep(1000);
- mChildView.scrollTo(0, 150);
- Thread.sleep(1000);
+ ScrollEventFilter scrollEventFilter = new ScrollEventFilter(2);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ try {
+ mChildView.scrollTo(0, 25);
+ mChildView.scrollTo(5, 50);
+ mChildView.scrollTo(7, 100);
+ Thread.sleep(SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS * 2);
+ mChildView.scrollTo(0, 25);
+ mChildView.scrollTo(5, 50);
+ mChildView.scrollTo(7, 100);
+ mChildView.scrollTo(0, 150);
+ } catch (InterruptedException e) {
+ fail("Interrupted while dispatching event bursts.");
+ }
+ },
+ scrollEventFilter,
+ DEFAULT_TIMEOUT_MS);
AccessibilityEvent event = scrollEventFilter.getLastEvent();
assertEquals(-7, event.getScrollDeltaX());
assertEquals(50, event.getScrollDeltaY());
@@ -183,94 +234,132 @@
@Test
public void testStateEvent() throws Throwable {
- sendStateDescriptionChangedEvent(mChildView);
- Thread.sleep(1000);
- stateDescriptionEventFilter.assertReceivedEventCount(1);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ sendStateDescriptionChangedEvent(mChildView);
+ },
+ new StateDescriptionEventFilter(1),
+ DEFAULT_TIMEOUT_MS);
}
@Test
public void testStateEventBurstCombined() throws Throwable {
- sendStateDescriptionChangedEvent(mChildView);
- sendStateDescriptionChangedEvent(mChildView);
- sendStateDescriptionChangedEvent(mChildView);
- sendStateDescriptionChangedEvent(mChildView);
- Thread.sleep(1000);
- stateDescriptionEventFilter.assertReceivedEventCount(1);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ sendStateDescriptionChangedEvent(mChildView);
+ sendStateDescriptionChangedEvent(mChildView);
+ sendStateDescriptionChangedEvent(mChildView);
+ sendStateDescriptionChangedEvent(mChildView);
+ },
+ new StateDescriptionEventFilter(1),
+ DEFAULT_TIMEOUT_MS);
}
@Test
public void testStateEventsDeliveredInCorrectInterval() throws Throwable {
- sendStateDescriptionChangedEvent(mChildView);
- sendStateDescriptionChangedEvent(mChildView);
- sendStateDescriptionChangedEvent(mChildView);
- Thread.sleep(150);
- sendStateDescriptionChangedEvent(mChildView);
- sendStateDescriptionChangedEvent(mChildView);
- Thread.sleep(50);
- sendStateDescriptionChangedEvent(mChildView);
- Thread.sleep(1000);
- stateDescriptionEventFilter.assertReceivedEventCount(2);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ try {
+ sendStateDescriptionChangedEvent(mChildView);
+ sendStateDescriptionChangedEvent(mChildView);
+ sendStateDescriptionChangedEvent(mChildView);
+ Thread.sleep(SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS * 2);
+ sendStateDescriptionChangedEvent(mChildView);
+ sendStateDescriptionChangedEvent(mChildView);
+ Thread.sleep(SEND_RECURRING_ACCESSIBILITY_EVENTS_INTERVAL_MILLIS / 2);
+ sendStateDescriptionChangedEvent(mChildView);
+ } catch (InterruptedException e) {
+ fail("Interrupted while dispatching event bursts.");
+ }
+ },
+ new StateDescriptionEventFilter(2),
+ DEFAULT_TIMEOUT_MS);
}
@Test
public void testStateEventsHaveLastEventText() throws Throwable {
- sendStateDescriptionChangedEvent(mChildView, "First state");
+ StateDescriptionEventFilter stateDescriptionEventFilter =
+ new StateDescriptionEventFilter(1);
String expectedState = "Second state";
- sendStateDescriptionChangedEvent(mChildView, expectedState);
- Thread.sleep(1000);
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ sendStateDescriptionChangedEvent(mChildView, "First state");
+ sendStateDescriptionChangedEvent(mChildView, expectedState);
+ },
+ stateDescriptionEventFilter,
+ DEFAULT_TIMEOUT_MS);
AccessibilityEvent event = stateDescriptionEventFilter.getLastEvent();
assertEquals(expectedState, event.getText().get(0));
}
- private AccessibilityEventFilter stateDescriptionEventFilter = new AccessibilityEventFilter() {
- public boolean pass(AccessibilityEvent event) {
- return event.getContentChangeTypes()
- == AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION;
- }
- };
-
- private abstract class AccessibilityEventFilter {
- abstract boolean pass(AccessibilityEvent event);
-
- void assertReceivedEventCount(int count) {
- assertEquals(count, filteredEventsReceived().size());
- }
-
- AccessibilityEvent getLastEvent() {
- List<AccessibilityEvent> events = filteredEventsReceived();
- if (events.size() > 0) {
- return events.get(events.size() - 1);
- }
- return null;
- }
-
- private List<AccessibilityEvent> filteredEventsReceived() {
- List<AccessibilityEvent> filteredEvents = new ArrayList<AccessibilityEvent>();
- List<AccessibilityEvent> receivedEvents = mParentView.mReceivedEvents;
- for (int i = 0; i < receivedEvents.size(); i++) {
- if (pass(receivedEvents.get(i))) {
- filteredEvents.add(receivedEvents.get(i));
- }
- }
- return filteredEvents;
- }
- }
-
private void sendStateDescriptionChangedEvent(View view) {
sendStateDescriptionChangedEvent(view, null);
}
private void sendStateDescriptionChangedEvent(View view, CharSequence text) {
- AccessibilityEvent event = AccessibilityEvent.obtain(
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
+ AccessibilityEvent event =
+ AccessibilityEvent.obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION);
event.getText().add(text);
view.sendAccessibilityEventUnchecked(event);
}
+ @Test
+ public void setText_textChanged_receivesTextEvent() throws Throwable {
+ sUiAutomation.executeAndWaitForEvent(
+ () -> sInstrumentation.runOnMainSync(() -> mTextView.setText("a")),
+ event -> isExpectedChangeType(event, AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT),
+ DEFAULT_TIMEOUT_MS);
+
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ sInstrumentation.runOnMainSync(
+ () -> {
+ mTextView.setText("b");
+ });
+ },
+ event ->
+ isExpectedSource(event, mTextView)
+ && isExpectedChangeType(
+ event, AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT),
+ DEFAULT_TIMEOUT_MS);
+ }
+
+ @Test
+ public void setText_parcelableSpanChanged_receivesUndefinedEvent() throws Throwable {
+ String text = "a";
+ sUiAutomation.executeAndWaitForEvent(
+ () -> sInstrumentation.runOnMainSync(() -> mTextView.setText(text)),
+ event -> isExpectedChangeType(event, AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT),
+ DEFAULT_TIMEOUT_MS);
+
+ sUiAutomation.executeAndWaitForEvent(
+ () -> {
+ sInstrumentation.runOnMainSync(
+ () -> {
+ SpannableString spannableString = new SpannableString(text);
+ spannableString.setSpan(new LocaleSpan(Locale.ENGLISH), 0, 1, 0);
+ mTextView.setText(spannableString);
+ });
+ },
+ event ->
+ isExpectedSource(event, mTextView)
+ && isExpectedChangeType(
+ event, AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED),
+ DEFAULT_TIMEOUT_MS);
+ }
+
+ private static boolean isExpectedSource(AccessibilityEvent event, View view) {
+ return TextUtils.equals(view.getContext().getPackageName(), event.getPackageName())
+ && TextUtils.equals(view.getAccessibilityClassName(), event.getClassName());
+ }
+
+ private static boolean isExpectedChangeType(AccessibilityEvent event, int changeType) {
+ return (event.getContentChangeTypes() & changeType) == changeType;
+ }
+
/**
- * Tests whether accessibility events are correctly written and
- * read from a parcel (version 1).
+ * Tests whether accessibility events are correctly written and read from a parcel (version 1).
*/
@SmallTest
@Test
@@ -291,9 +380,7 @@
parcel.recycle();
}
- /**
- * Tests if {@link AccessibilityEvent} are properly reused.
- */
+ /** Tests if {@link AccessibilityEvent} are properly reused. */
@SmallTest
@Test
public void testReuse() {
@@ -303,9 +390,7 @@
assertSame("AccessibilityEvent not properly reused", firstEvent, secondEvent);
}
- /**
- * Tests if {@link AccessibilityEvent} are properly recycled.
- */
+ /** Tests if {@link AccessibilityEvent} are properly recycled. */
@SmallTest
@Test
public void testRecycle() {
@@ -321,61 +406,80 @@
assertAccessibilityEventCleared(recycledEvent);
}
- /**
- * Tests whether the event types are correctly converted to strings.
- */
+ /** Tests whether the event types are correctly converted to strings. */
@SmallTest
@Test
public void testEventTypeToString() {
- assertEquals("TYPE_NOTIFICATION_STATE_CHANGED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED));
- assertEquals("TYPE_TOUCH_EXPLORATION_GESTURE_END", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END));
- assertEquals("TYPE_TOUCH_EXPLORATION_GESTURE_START", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START));
- assertEquals("TYPE_VIEW_CLICKED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_CLICKED));
- assertEquals("TYPE_VIEW_FOCUSED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_FOCUSED));
- assertEquals("TYPE_VIEW_HOVER_ENTER",
+ assertEquals(
+ "TYPE_NOTIFICATION_STATE_CHANGED",
+ AccessibilityEvent.eventTypeToString(
+ AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED));
+ assertEquals(
+ "TYPE_TOUCH_EXPLORATION_GESTURE_END",
+ AccessibilityEvent.eventTypeToString(
+ AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END));
+ assertEquals(
+ "TYPE_TOUCH_EXPLORATION_GESTURE_START",
+ AccessibilityEvent.eventTypeToString(
+ AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START));
+ assertEquals(
+ "TYPE_VIEW_CLICKED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_CLICKED));
+ assertEquals(
+ "TYPE_VIEW_FOCUSED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_FOCUSED));
+ assertEquals(
+ "TYPE_VIEW_HOVER_ENTER",
AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER));
- assertEquals("TYPE_VIEW_HOVER_EXIT", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_HOVER_EXIT));
- assertEquals("TYPE_VIEW_LONG_CLICKED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_LONG_CLICKED));
- assertEquals("TYPE_VIEW_CONTEXT_CLICKED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED));
- assertEquals("TYPE_VIEW_SCROLLED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_SCROLLED));
- assertEquals("TYPE_VIEW_SELECTED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_SELECTED));
- assertEquals("TYPE_VIEW_TEXT_CHANGED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED));
- assertEquals("TYPE_VIEW_TEXT_SELECTION_CHANGED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED));
- assertEquals("TYPE_WINDOW_CONTENT_CHANGED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED));
- assertEquals("TYPE_WINDOW_STATE_CHANGED", AccessibilityEvent.eventTypeToString(
- AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED));
+ assertEquals(
+ "TYPE_VIEW_HOVER_EXIT",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT));
+ assertEquals(
+ "TYPE_VIEW_LONG_CLICKED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED));
+ assertEquals(
+ "TYPE_VIEW_CONTEXT_CLICKED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED));
+ assertEquals(
+ "TYPE_VIEW_SCROLLED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_SCROLLED));
+ assertEquals(
+ "TYPE_VIEW_SELECTED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_SELECTED));
+ assertEquals(
+ "TYPE_VIEW_TEXT_CHANGED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED));
+ assertEquals(
+ "TYPE_VIEW_TEXT_SELECTION_CHANGED",
+ AccessibilityEvent.eventTypeToString(
+ AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED));
+ assertEquals(
+ "TYPE_WINDOW_CONTENT_CHANGED",
+ AccessibilityEvent.eventTypeToString(
+ AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED));
+ assertEquals(
+ "TYPE_WINDOW_STATE_CHANGED",
+ AccessibilityEvent.eventTypeToString(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED));
}
- /**
- * Tests whether the event describes its contents consistently.
- */
+ /** Tests whether the event describes its contents consistently. */
@SmallTest
@Test
public void testDescribeContents() {
AccessibilityEvent event = AccessibilityEvent.obtain();
- assertSame("Accessibility events always return 0 for this method.", 0,
+ assertSame(
+ "Accessibility events always return 0 for this method.",
+ 0,
event.describeContents());
fullyPopulateAccessibilityEvent(event);
- assertSame("Accessibility events always return 0 for this method.", 0,
+ assertSame(
+ "Accessibility events always return 0 for this method.",
+ 0,
event.describeContents());
}
/**
- * Tests whether accessibility events are correctly written and
- * read from a parcel (version 2).
+ * Tests whether accessibility events are correctly written and read from a parcel (version 2).
*/
@SmallTest
@Test
@@ -429,8 +533,8 @@
final AccessibilityEvent firstEvent = new AccessibilityEvent();
firstEvent.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
- final AccessibilityEvent secondEvent = new AccessibilityEvent(
- AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ final AccessibilityEvent secondEvent =
+ new AccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
assertEqualsAccessibilityEvent(firstEvent, secondEvent);
}
@@ -475,59 +579,104 @@
}
/**
- * Compares all properties of the <code>expectedEvent</code> and the
- * <code>receivedEvent</code> to verify that the received event is the one
- * that is expected.
+ * Compares all properties of the <code>expectedEvent</code> and the <code>receivedEvent</code>
+ * to verify that the received event is the one that is expected.
*/
- private static void assertEqualsAccessibilityEvent(AccessibilityEvent expectedEvent,
- AccessibilityEvent receivedEvent) {
- assertEquals("addedCount has incorrect value", expectedEvent.getAddedCount(), receivedEvent
- .getAddedCount());
- assertEquals("beforeText has incorrect value", expectedEvent.getBeforeText(), receivedEvent
- .getBeforeText());
- assertEquals("checked has incorrect value", expectedEvent.isChecked(), receivedEvent
- .isChecked());
- assertEquals("className has incorrect value", expectedEvent.getClassName(), receivedEvent
- .getClassName());
- assertEquals("contentDescription has incorrect value", expectedEvent
- .getContentDescription(), receivedEvent.getContentDescription());
- assertEquals("currentItemIndex has incorrect value", expectedEvent.getCurrentItemIndex(),
+ private static void assertEqualsAccessibilityEvent(
+ AccessibilityEvent expectedEvent, AccessibilityEvent receivedEvent) {
+ assertEquals(
+ "addedCount has incorrect value",
+ expectedEvent.getAddedCount(),
+ receivedEvent.getAddedCount());
+ assertEquals(
+ "beforeText has incorrect value",
+ expectedEvent.getBeforeText(),
+ receivedEvent.getBeforeText());
+ assertEquals(
+ "checked has incorrect value",
+ expectedEvent.isChecked(),
+ receivedEvent.isChecked());
+ assertEquals(
+ "className has incorrect value",
+ expectedEvent.getClassName(),
+ receivedEvent.getClassName());
+ assertEquals(
+ "contentDescription has incorrect value",
+ expectedEvent.getContentDescription(),
+ receivedEvent.getContentDescription());
+ assertEquals(
+ "currentItemIndex has incorrect value",
+ expectedEvent.getCurrentItemIndex(),
receivedEvent.getCurrentItemIndex());
- assertEquals("enabled has incorrect value", expectedEvent.isEnabled(), receivedEvent
- .isEnabled());
- assertEquals("eventType has incorrect value", expectedEvent.getEventType(), receivedEvent
- .getEventType());
- assertEquals("fromIndex has incorrect value", expectedEvent.getFromIndex(), receivedEvent
- .getFromIndex());
- assertEquals("fullScreen has incorrect value", expectedEvent.isFullScreen(), receivedEvent
- .isFullScreen());
- assertEquals("itemCount has incorrect value", expectedEvent.getItemCount(), receivedEvent
- .getItemCount());
- assertEquals("password has incorrect value", expectedEvent.isPassword(), receivedEvent
- .isPassword());
- assertEquals("removedCount has incorrect value", expectedEvent.getRemovedCount(),
+ assertEquals(
+ "enabled has incorrect value",
+ expectedEvent.isEnabled(),
+ receivedEvent.isEnabled());
+ assertEquals(
+ "eventType has incorrect value",
+ expectedEvent.getEventType(),
+ receivedEvent.getEventType());
+ assertEquals(
+ "fromIndex has incorrect value",
+ expectedEvent.getFromIndex(),
+ receivedEvent.getFromIndex());
+ assertEquals(
+ "fullScreen has incorrect value",
+ expectedEvent.isFullScreen(),
+ receivedEvent.isFullScreen());
+ assertEquals(
+ "itemCount has incorrect value",
+ expectedEvent.getItemCount(),
+ receivedEvent.getItemCount());
+ assertEquals(
+ "password has incorrect value",
+ expectedEvent.isPassword(),
+ receivedEvent.isPassword());
+ assertEquals(
+ "removedCount has incorrect value",
+ expectedEvent.getRemovedCount(),
receivedEvent.getRemovedCount());
- assertSame("maxScrollX has incorrect value", expectedEvent.getMaxScrollX(),
+ assertSame(
+ "maxScrollX has incorrect value",
+ expectedEvent.getMaxScrollX(),
receivedEvent.getMaxScrollX());
- assertSame("maxScrollY has incorrect value", expectedEvent.getMaxScrollY(),
+ assertSame(
+ "maxScrollY has incorrect value",
+ expectedEvent.getMaxScrollY(),
receivedEvent.getMaxScrollY());
- assertSame("scrollX has incorrect value", expectedEvent.getScrollX(),
+ assertSame(
+ "scrollX has incorrect value",
+ expectedEvent.getScrollX(),
receivedEvent.getScrollX());
- assertSame("scrollY has incorrect value", expectedEvent.getScrollY(),
+ assertSame(
+ "scrollY has incorrect value",
+ expectedEvent.getScrollY(),
receivedEvent.getScrollY());
- assertSame("scrollDeltaX has incorrect value", expectedEvent.getScrollDeltaX(),
+ assertSame(
+ "scrollDeltaX has incorrect value",
+ expectedEvent.getScrollDeltaX(),
receivedEvent.getScrollDeltaX());
- assertSame("scrollDeltaY has incorrect value", expectedEvent.getScrollDeltaY(),
+ assertSame(
+ "scrollDeltaY has incorrect value",
+ expectedEvent.getScrollDeltaY(),
receivedEvent.getScrollDeltaY());
- assertSame("toIndex has incorrect value", expectedEvent.getToIndex(),
+ assertSame(
+ "toIndex has incorrect value",
+ expectedEvent.getToIndex(),
receivedEvent.getToIndex());
- assertSame("scrollable has incorrect value", expectedEvent.isScrollable(),
+ assertSame(
+ "scrollable has incorrect value",
+ expectedEvent.isScrollable(),
receivedEvent.isScrollable());
- assertSame("granularity has incorrect value", expectedEvent.getMovementGranularity(),
+ assertSame(
+ "granularity has incorrect value",
+ expectedEvent.getMovementGranularity(),
receivedEvent.getMovementGranularity());
- assertSame("action has incorrect value", expectedEvent.getAction(),
- receivedEvent.getAction());
- assertSame("windowChangeTypes has incorrect value", expectedEvent.getWindowChanges(),
+ assertSame(
+ "action has incorrect value", expectedEvent.getAction(), receivedEvent.getAction());
+ assertSame(
+ "windowChangeTypes has incorrect value",
+ expectedEvent.getWindowChanges(),
receivedEvent.getWindowChanges());
AccessibilityRecordTest.assertEqualsText(expectedEvent.getText(), receivedEvent.getText());
@@ -536,12 +685,14 @@
assertEqualAppendedRecord(expectedEvent, receivedEvent);
}
- private static void assertEqualAppendedRecord(AccessibilityEvent expectedEvent,
- AccessibilityEvent receivedEvent) {
- assertEquals("recordCount has incorrect value", expectedEvent.getRecordCount(),
+ private static void assertEqualAppendedRecord(
+ AccessibilityEvent expectedEvent, AccessibilityEvent receivedEvent) {
+ assertEquals(
+ "recordCount has incorrect value",
+ expectedEvent.getRecordCount(),
receivedEvent.getRecordCount());
if (expectedEvent.getRecordCount() != 0 && receivedEvent.getRecordCount() != 0) {
- AccessibilityRecord expectedRecord = expectedEvent.getRecord(0);
+ AccessibilityRecord expectedRecord = expectedEvent.getRecord(0);
AccessibilityRecord receivedRecord = receivedEvent.getRecord(0);
AccessibilityRecordTest.assertEqualAccessibilityRecord(expectedRecord, receivedRecord);
}
@@ -558,4 +709,60 @@
TestCase.assertEquals("eventType not properly recycled", 0, event.getEventType());
TestCase.assertNull("packageName not properly recycled", event.getPackageName());
}
+
+ class ScrollEventFilter extends AccessibilityEventFilter {
+ private int mCount = 0;
+ private int mTargetCount;
+
+ ScrollEventFilter(int count) {
+ mTargetCount = count;
+ }
+
+ public boolean accept(AccessibilityEvent event) {
+ if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
+ mCount += 1;
+ mEvents.add(event);
+ return mCount >= mTargetCount;
+ }
+ return false;
+ }
+ }
+
+ class StateDescriptionEventFilter extends AccessibilityEventFilter {
+ private int mCount;
+ private int mTargetCount;
+
+ StateDescriptionEventFilter(int count) {
+ mTargetCount = count;
+ }
+
+ public boolean accept(AccessibilityEvent event) {
+ if (event.getContentChangeTypes()
+ == AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) {
+ mCount += 1;
+ mEvents.add(event);
+ return mCount >= mTargetCount;
+ }
+ return false;
+ }
+ }
+ ;
+
+ private abstract class AccessibilityEventFilter
+ implements UiAutomation.AccessibilityEventFilter {
+ protected List<AccessibilityEvent> mEvents = new ArrayList<>();
+
+ public abstract boolean accept(AccessibilityEvent event);
+
+ void assertReceivedEventCount(int count) {
+ assertEquals(count, mEvents.size());
+ }
+
+ AccessibilityEvent getLastEvent() {
+ if (mEvents.size() > 0) {
+ return mEvents.get(mEvents.size() - 1);
+ }
+ return null;
+ }
+ }
}
diff --git a/tests/app/src/android/app/cts/OWNERS b/tests/app/src/android/app/cts/OWNERS
new file mode 100644
index 0000000..7a6f201
--- /dev/null
+++ b/tests/app/src/android/app/cts/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 803062
+per-file NearbyMediaDevicesProviderTest.kt=file:platform/frameworks/base:/packages/SystemUI/OWNERS
+# Bug component: 803062
+per-file UpdateMediaTapToTransfer*.kt=file:platform/frameworks/base:/packages/SystemUI/OWNERS
diff --git a/tests/autofillservice/OWNERS b/tests/autofillservice/OWNERS
index 7f4d695..5c14735 100644
--- a/tests/autofillservice/OWNERS
+++ b/tests/autofillservice/OWNERS
@@ -1,7 +1,3 @@
# Bug component: 351486
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+
+include platform/frameworks/base:/core/java/android/view/autofill/OWNERS
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 af15ff0..b466feb 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -186,7 +186,7 @@
/*gpsLocation*/ sTestLocation2,
/* orientation */270,
/* jpgQuality */(byte) 100,
- /* thumbQuality */(byte) 100)
+ /* thumbQuality */(byte) 80)
};
/**
diff --git a/tests/contentcaptureservice/OWNERS b/tests/contentcaptureservice/OWNERS
index 4135301..4bea4c8 100644
--- a/tests/contentcaptureservice/OWNERS
+++ b/tests/contentcaptureservice/OWNERS
@@ -1,7 +1,3 @@
# Bug component: 544200
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+
+include platform/frameworks/base:/core/java/android/view/contentcapture/OWNERS
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java
index ad79e02..6f6aac2 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/CustomViewActivityTest.java
@@ -16,9 +16,6 @@
package android.contentcaptureservice.cts;
import static android.contentcaptureservice.cts.Assertions.assertRightActivity;
-import static android.contentcaptureservice.cts.Assertions.assertViewTextChanged;
-import static android.contentcaptureservice.cts.Assertions.assertVirtualViewAppeared;
-import static android.contentcaptureservice.cts.Assertions.assertVirtualViewsDisappeared;
import static android.contentcaptureservice.cts.Helper.MY_PACKAGE;
import static android.contentcaptureservice.cts.Helper.NO_ACTIVITIES;
import static android.contentcaptureservice.cts.Helper.OTHER_PACKAGE;
@@ -278,14 +275,11 @@
final AutofillId customViewId = activity.mCustomView.getAutofillId();
final ContentCaptureSession mainSession = activity.mCustomView.getContentCaptureSession();
- final int i = CustomViewActivity.MIN_EVENTS;
-
- assertVirtualViewAppeared(events, i, mainSession, customViewId, 1, "child1");
- assertVirtualViewAppeared(events, i + 1, mainSession, customViewId, 2, "child2");
- assertViewTextChanged(events, i + 2, child2IdRef.get(), "The Times They Are a-Changin'");
- assertVirtualViewsDisappeared(events, i + 3, customViewId, mainSession, 2, 1);
-
- activity.assertInitialViewsDisappeared(events, additionalEvents);
+ new EventsAssertor(events)
+ .assertVirtualViewAppeared(mainSession, customViewId, 1, "child1")
+ .assertVirtualViewAppeared(mainSession, customViewId, 2, "child2")
+ .assertViewTextChanged(child2IdRef.get(), "The Times They Are a-Changin'")
+ .assertVirtualViewsDisappeared(customViewId, mainSession, 2, 1);
// TODO(b/122315042): assert views disappeared
}
@@ -392,18 +386,15 @@
final AutofillId customViewId = activity.mCustomView.getAutofillId();
final ContentCaptureSession mainSession = activity.mCustomView.getContentCaptureSession();
- final int i = CustomViewActivity.MIN_EVENTS;
-
- assertVirtualViewAppeared(events, i, mainSession, customViewId, 1, "c1");
- assertVirtualViewAppeared(events, i + 1, mainSession, customViewId, 11, "c1g1");
- assertVirtualViewAppeared(events, i + 2, mainSession, customViewId, 12, "c1g2");
- assertVirtualViewAppeared(events, i + 3, mainSession, customViewId, 2, "c2");
- assertVirtualViewAppeared(events, i + 4, mainSession, customViewId, 21, "c2g1");
- assertVirtualViewAppeared(events, i + 5, mainSession, customViewId, 211, "c2g1gg1");
- assertVirtualViewAppeared(events, i + 6, mainSession, customViewId, 3, "c3");
- assertVirtualViewsDisappeared(events, i + 7, customViewId, mainSession, 21, 2, 11, 1, 12);
-
- activity.assertInitialViewsDisappeared(events, additionalEvents);
+ new EventsAssertor(events)
+ .assertVirtualViewAppeared(mainSession, customViewId, 1, "c1")
+ .assertVirtualViewAppeared(mainSession, customViewId, 11, "c1g1")
+ .assertVirtualViewAppeared(mainSession, customViewId, 12, "c1g2")
+ .assertVirtualViewAppeared(mainSession, customViewId, 2, "c2")
+ .assertVirtualViewAppeared(mainSession, customViewId, 21, "c2g1")
+ .assertVirtualViewAppeared(mainSession, customViewId, 211, "c2g1gg1")
+ .assertVirtualViewAppeared(mainSession, customViewId, 3, "c3")
+ .assertVirtualViewsDisappeared(customViewId, mainSession, 21, 2, 11, 1, 12);
// TODO(b/122315042): assert other views disappeared
}
@@ -458,13 +449,10 @@
final AutofillId customViewId = activity.mCustomView.getAutofillId();
final ContentCaptureSession mainSession = activity.mCustomView.getContentCaptureSession();
- final int i = CustomViewActivity.MIN_EVENTS;
-
- assertVirtualViewAppeared(events, i, mainSession, customViewId, 1, "child1");
- assertVirtualViewAppeared(events, i + 1, mainSession, customViewId, 2, "child2");
- assertVirtualViewsDisappeared(events, i + 2, customViewId, mainSession, 2, 1);
-
- activity.assertInitialViewsDisappeared(events, additionalEvents);
+ new EventsAssertor(events)
+ .assertVirtualViewAppeared(mainSession, customViewId, 1, "child1")
+ .assertVirtualViewAppeared(mainSession, customViewId, 2, "child2")
+ .assertVirtualViewsDisappeared(customViewId, mainSession, 2, 1);
// TODO(b/122315042): assert other views disappeared
}
diff --git a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java
index d00b031..eaf07f9 100644
--- a/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java
+++ b/tests/contentcaptureservice/src/android/contentcaptureservice/cts/EventsAssertor.java
@@ -200,6 +200,18 @@
}
/**
+ * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_TEXT_CHANGED} event.
+ */
+ @NonNull
+ public EventsAssertor assertViewTextChanged(@NonNull AutofillId expectedId,
+ @NonNull String expectedText) {
+ assertNextEvent((event) -> assertTextChangedEvent(event, expectedId, expectedText),
+ ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED,
+ String.format("no VIEW_TEXT_CHANGED event for %s", expectedId));
+ return this;
+ }
+
+ /**
* Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_APPEARED}
* event for a virtual node.
*/
@@ -223,14 +235,30 @@
return assertViewDisappeared(session.newAutofillId(parentId, childId));
}
+ /**
+ * Asserts the contents of a {@link ContentCaptureEvent#TYPE_VIEW_DISAPPEARED}
+ * event for many virtual nodes.
+ */
+ @NonNull
+ public EventsAssertor assertVirtualViewsDisappeared(AutofillId parentId,
+ ContentCaptureSession session, int... childId) {
+ final AutofillId[] ids = new AutofillId[childId.length];
+ for (int i = 0; i < childId.length; i++) {
+ ids[i] = session.newAutofillId(parentId, childId[i]);
+ }
+ return assertViewDisappeared(ids);
+ }
+
@Nullable
private String assertVirtualViewEvent(@NonNull ContentCaptureEvent event,
@NonNull AutofillId expectedId, @Nullable String expectedText) {
final ViewNode node = event.getViewNode();
assertThat(node).isNotNull();
- assertWithMessage("wrong autofill id on %s", event)
- .that(node.getAutofillId()).isEqualTo(expectedId);
- if (expectedText != null) {
+ if (!node.getAutofillId().equals(expectedId)) {
+ return String.format("wrong autofill id (expected %s, actual is %s) at %s",
+ expectedId, node.getAutofillId(), event);
+ }
+ if (expectedText != null && node.getText() != null) {
assertWithMessage("wrong text on %s", event)
.that(node.getText().toString()).isEqualTo(expectedText);
} else {
@@ -266,6 +294,16 @@
return null;
}
+ @Nullable
+ private String assertTextChangedEvent(@NonNull ContentCaptureEvent event,
+ @NonNull AutofillId expectedId, @NonNull String expectedText) {
+ assertWithMessage("Wrong id on %s", event).that(event.getId())
+ .isEqualTo(expectedId);
+ assertWithMessage("Wrong text on %s", event).that(event.getText().toString())
+ .isEqualTo(expectedText);
+ return null;
+ }
+
private void assertCommonViewDisappearedProperties(@NonNull ContentCaptureEvent event) {
assertWithMessage("event %s should not have a ViewNode", event)
.that(event.getViewNode()).isNull();
diff --git a/tests/controls/src/android/controls/cts/CtsControlsPublisher.java b/tests/controls/src/android/controls/cts/CtsControlsPublisher.java
index 643d80e..c8c09c8 100644
--- a/tests/controls/src/android/controls/cts/CtsControlsPublisher.java
+++ b/tests/controls/src/android/controls/cts/CtsControlsPublisher.java
@@ -38,7 +38,7 @@
}
}
- public void subscribe(Subscriber<? super Control> subscriber) {
+ public void subscribe(Subscriber<? super Control> subscriber) {
mSubscriber = subscriber;
mSubscriber.onSubscribe(new Subscription() {
public void request(long n) {
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
index b7f0ec2..fa6dcde 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/DevicePolicyManagerTest.java
@@ -52,7 +52,10 @@
import com.android.bedstead.harrier.annotations.Postsubmit;
import com.android.bedstead.nene.TestApis;
import com.android.bedstead.nene.packages.Package;
+import com.android.bedstead.nene.packages.PackageReference;
import com.android.bedstead.nene.permissions.PermissionContext;
+import com.android.bedstead.nene.users.UnresolvedUser;
+import com.android.bedstead.nene.users.UserReference;
import com.android.compatibility.common.util.SystemUtil;
import org.junit.ClassRule;
@@ -62,7 +65,9 @@
import org.junit.runner.RunWith;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
@@ -383,8 +388,17 @@
}
private Set<String> getInstalledPackagesOnUser(Set<String> packages, UserHandle user) {
- return packages.stream().filter(p -> isPackageInstalledOnUser(p, user))
- .collect(Collectors.toSet());
+ Set<String> installedPackagesOnUser = new HashSet<>();
+
+ UserReference userRef = sTestApis.users().find(user);
+ Collection<PackageReference> packageInUser = sTestApis.packages().installedForUser(userRef);
+ for (PackageReference pkg : packageInUser) {
+ if (packages.contains(pkg.packageName())) {
+ installedPackagesOnUser.add(pkg.packageName());
+ }
+ }
+
+ return installedPackagesOnUser;
}
private boolean isPackageInstalledOnCurrentUser(String packageName) {
diff --git a/tests/framework/base/biometrics/Android.bp b/tests/framework/base/biometrics/Android.bp
index 369faa7..66c8134 100644
--- a/tests/framework/base/biometrics/Android.bp
+++ b/tests/framework/base/biometrics/Android.bp
@@ -43,6 +43,10 @@
"ub-uiautomator",
],
srcs: ["src/**/*.java"],
+ data: [
+ ":CtsBiometricServiceTestApp",
+ ":CtsFingerprintServiceTestApp",
+ ],
sdk_version: "test_current",
per_testcase_directory: true,
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java
index 28608d0..dfb4252 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayCutoutTests.java
@@ -25,6 +25,7 @@
import static android.server.wm.DisplayCutoutTests.TestActivity.EXTRA_ORIENTATION;
import static android.server.wm.DisplayCutoutTests.TestDef.Which.DISPATCHED;
import static android.server.wm.DisplayCutoutTests.TestDef.Which.ROOT;
+import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
@@ -527,14 +528,9 @@
new Intent().putExtra(EXTRA_CUTOUT_MODE, cutoutMode)
.putExtra(EXTRA_ORIENTATION, orientation));
PollingCheck.waitFor(activity::hasWindowFocus);
- PollingCheck.waitFor(() -> {
- final Rect appBounds = getAppBounds(activity);
- final Point displaySize = new Point();
- activity.getDisplay().getRealSize(displaySize);
- // During app launch into a different rotation, we have temporarily have the display
- // in a different rotation than the app itself. Wait for this to settle.
- return (appBounds.width() > appBounds.height()) == (displaySize.x > displaySize.y);
- });
+ final WindowManagerStateHelper wmState = new WindowManagerStateHelper();
+ wmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
+ wmState.waitForDisplayUnfrozen();
return activity;
}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt b/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
index 110f9d0..cac75be 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/SpellCheckerTest.kt
@@ -270,36 +270,39 @@
.addSuggestions("suggestion")
.setAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
).build()
- MockSpellCheckerClient.create(context, configuration).use {
- val tsm = context.getSystemService(TextServicesManager::class.java)
- assertThat(tsm).isNotNull()
- val fakeListener = FakeSpellCheckerSessionListener()
- val fakeExecutor = FakeExecutor()
- val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
- .setLocale(Locale.US)
- .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
- .build()
- val session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
- params, fakeExecutor, fakeListener)
- assertThat(session).isNotNull()
- session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
- waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
- fakeExecutor.runnables[0].run()
+ // Use MockIme, in case the default IME sets android:suppressesSpellChecker="true"
+ MockImeSession.create(context).use { session ->
+ MockSpellCheckerClient.create(context, configuration).use {
+ val tsm = context.getSystemService(TextServicesManager::class.java)
+ assertThat(tsm).isNotNull()
+ val fakeListener = FakeSpellCheckerSessionListener()
+ val fakeExecutor = FakeExecutor()
+ val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
+ .setLocale(Locale.US)
+ .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
+ .build()
+ val session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
+ params, fakeExecutor, fakeListener)
+ assertThat(session).isNotNull()
+ session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
+ waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
+ fakeExecutor.runnables[0].run()
- assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
- assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
- val sentenceSuggestionsInfo = fakeListener.getSentenceSuggestionsResults[0]!![0]
- assertThat(sentenceSuggestionsInfo.suggestionsCount).isEqualTo(1)
- assertThat(sentenceSuggestionsInfo.getOffsetAt(0)).isEqualTo(0)
- assertThat(sentenceSuggestionsInfo.getLengthAt(0)).isEqualTo("match".length)
- val suggestionsInfo = sentenceSuggestionsInfo.getSuggestionsInfoAt(0)
- assertThat(suggestionsInfo.suggestionsCount).isEqualTo(1)
- assertThat(suggestionsInfo.getSuggestionAt(0)).isEqualTo("suggestion")
+ assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
+ assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
+ val sentenceSuggestionsInfo = fakeListener.getSentenceSuggestionsResults[0]!![0]
+ assertThat(sentenceSuggestionsInfo.suggestionsCount).isEqualTo(1)
+ assertThat(sentenceSuggestionsInfo.getOffsetAt(0)).isEqualTo(0)
+ assertThat(sentenceSuggestionsInfo.getLengthAt(0)).isEqualTo("match".length)
+ val suggestionsInfo = sentenceSuggestionsInfo.getSuggestionsInfoAt(0)
+ assertThat(suggestionsInfo.suggestionsCount).isEqualTo(1)
+ assertThat(suggestionsInfo.getSuggestionAt(0)).isEqualTo("suggestion")
- assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
- assertThat(fakeListener.getSentenceSuggestionsCallingThreads).hasSize(1)
- assertThat(fakeListener.getSentenceSuggestionsCallingThreads[0])
- .isEqualTo(Thread.currentThread())
+ assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
+ assertThat(fakeListener.getSentenceSuggestionsCallingThreads).hasSize(1)
+ assertThat(fakeListener.getSentenceSuggestionsCallingThreads[0])
+ .isEqualTo(Thread.currentThread())
+ }
}
}
@@ -312,24 +315,27 @@
.addSuggestions("suggestion")
.setAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
).build()
- MockSpellCheckerClient.create(context, configuration).use {
- val tsm = context.getSystemService(TextServicesManager::class.java)
- assertThat(tsm).isNotNull()
- val fakeListener = FakeSpellCheckerSessionListener()
- var session: SpellCheckerSession? = null
- runOnMainSync {
- session = tsm?.newSpellCheckerSession(null /* bundle */, Locale.US,
- fakeListener, false /* referToSpellCheckerLanguageSettings */)
- }
- assertThat(session).isNotNull()
- session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
- waitOnMainUntil({
- fakeListener.getSentenceSuggestionsCallingThreads.size > 0
- }, TIMEOUT)
- runOnMainSync {
- assertThat(fakeListener.getSentenceSuggestionsCallingThreads).hasSize(1)
- assertThat(fakeListener.getSentenceSuggestionsCallingThreads[0])
- .isEqualTo(Looper.getMainLooper().thread)
+ // Use MockIme, in case the default IME sets android:suppressesSpellChecker="true"
+ MockImeSession.create(context).use { session ->
+ MockSpellCheckerClient.create(context, configuration).use {
+ val tsm = context.getSystemService(TextServicesManager::class.java)
+ assertThat(tsm).isNotNull()
+ val fakeListener = FakeSpellCheckerSessionListener()
+ var session: SpellCheckerSession? = null
+ runOnMainSync {
+ session = tsm?.newSpellCheckerSession(null /* bundle */, Locale.US,
+ fakeListener, false /* referToSpellCheckerLanguageSettings */)
+ }
+ assertThat(session).isNotNull()
+ session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
+ waitOnMainUntil({
+ fakeListener.getSentenceSuggestionsCallingThreads.size > 0
+ }, TIMEOUT)
+ runOnMainSync {
+ assertThat(fakeListener.getSentenceSuggestionsCallingThreads).hasSize(1)
+ assertThat(fakeListener.getSentenceSuggestionsCallingThreads[0])
+ .isEqualTo(Looper.getMainLooper().thread)
+ }
}
}
}
@@ -343,33 +349,36 @@
.addSuggestions("suggestion")
.setAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
).build()
- MockSpellCheckerClient.create(context, configuration).use {
- val tsm = context.getSystemService(TextServicesManager::class.java)
- assertThat(tsm).isNotNull()
- val fakeListener = FakeSpellCheckerSessionListener()
- val fakeExecutor = FakeExecutor()
- // Set a prefix. MockSpellChecker will add "test_" to the spell check result.
- val extras = Bundle()
- extras.putString(EXTRAS_KEY_PREFIX, "test_")
- val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
- .setLocale(Locale.US)
- .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
- .setExtras(extras)
- .build()
- val session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
- params, fakeExecutor, fakeListener)
- assertThat(session).isNotNull()
- session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
- waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
- fakeExecutor.runnables[0].run()
+ // Use MockIme, in case the default IME sets android:suppressesSpellChecker="true"
+ MockImeSession.create(context).use { session ->
+ MockSpellCheckerClient.create(context, configuration).use {
+ val tsm = context.getSystemService(TextServicesManager::class.java)
+ assertThat(tsm).isNotNull()
+ val fakeListener = FakeSpellCheckerSessionListener()
+ val fakeExecutor = FakeExecutor()
+ // Set a prefix. MockSpellChecker will add "test_" to the spell check result.
+ val extras = Bundle()
+ extras.putString(EXTRAS_KEY_PREFIX, "test_")
+ val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
+ .setLocale(Locale.US)
+ .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
+ .setExtras(extras)
+ .build()
+ val session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
+ params, fakeExecutor, fakeListener)
+ assertThat(session).isNotNull()
+ session?.getSentenceSuggestions(arrayOf(TextInfo("match")), 5)
+ waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
+ fakeExecutor.runnables[0].run()
- assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
- assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
- val sentenceSuggestionsInfo = fakeListener.getSentenceSuggestionsResults[0]!![0]
- assertThat(sentenceSuggestionsInfo.suggestionsCount).isEqualTo(1)
- val suggestionsInfo = sentenceSuggestionsInfo.getSuggestionsInfoAt(0)
- assertThat(suggestionsInfo.suggestionsCount).isEqualTo(1)
- assertThat(suggestionsInfo.getSuggestionAt(0)).isEqualTo("test_suggestion")
+ assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
+ assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
+ val sentenceSuggestionsInfo = fakeListener.getSentenceSuggestionsResults[0]!![0]
+ assertThat(sentenceSuggestionsInfo.suggestionsCount).isEqualTo(1)
+ val suggestionsInfo = sentenceSuggestionsInfo.getSuggestionsInfoAt(0)
+ assertThat(suggestionsInfo.suggestionsCount).isEqualTo(1)
+ assertThat(suggestionsInfo.getSuggestionAt(0)).isEqualTo("test_suggestion")
+ }
}
}
@@ -497,24 +506,27 @@
.addSuggestions("suggestion")
.setAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
).build()
- MockSpellCheckerClient.create(context, configuration).use {
- val tsm = context.getSystemService(TextServicesManager::class.java)
- assertThat(tsm).isNotNull()
- val fakeListener = FakeSpellCheckerSessionListener()
- val fakeExecutor = FakeExecutor()
- val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
- .setLocale(Locale.US)
- .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
- .build()
- var session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
- params, fakeExecutor, fakeListener)
- assertThat(session).isNotNull()
- session?.getSentenceSuggestions(arrayOf(TextInfo(". ")), 5)
- waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
- fakeExecutor.runnables[0].run()
- assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
- assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
- assertThat(fakeListener.getSentenceSuggestionsResults[0]!![0]).isNull()
+ // Use MockIme, in case the default IME sets android:suppressesSpellChecker="true"
+ MockImeSession.create(context).use { session ->
+ MockSpellCheckerClient.create(context, configuration).use {
+ val tsm = context.getSystemService(TextServicesManager::class.java)
+ assertThat(tsm).isNotNull()
+ val fakeListener = FakeSpellCheckerSessionListener()
+ val fakeExecutor = FakeExecutor()
+ val params = SpellCheckerSession.SpellCheckerSessionParams.Builder()
+ .setLocale(Locale.US)
+ .setSupportedAttributes(RESULT_ATTR_LOOKS_LIKE_TYPO)
+ .build()
+ var session: SpellCheckerSession? = tsm?.newSpellCheckerSession(
+ params, fakeExecutor, fakeListener)
+ assertThat(session).isNotNull()
+ session?.getSentenceSuggestions(arrayOf(TextInfo(". ")), 5)
+ waitOnMainUntil({ fakeExecutor.runnables.size == 1 }, TIMEOUT)
+ fakeExecutor.runnables[0].run()
+ assertThat(fakeListener.getSentenceSuggestionsResults).hasSize(1)
+ assertThat(fakeListener.getSentenceSuggestionsResults[0]).hasLength(1)
+ assertThat(fakeListener.getSentenceSuggestionsResults[0]!![0]).isNull()
+ }
}
}
diff --git a/tests/libcore/luni/Android.bp b/tests/libcore/luni/Android.bp
index 2fc1f56..78ea004 100644
--- a/tests/libcore/luni/Android.bp
+++ b/tests/libcore/luni/Android.bp
@@ -39,11 +39,6 @@
enabled: false,
},
dxflags: ["--multi-dex"],
- // Exclude apache harmony tests from coverage instrumentation, since it breaks
- // the tests of reflection APIs by adding fields and methods to the test classes.
- jacoco: {
- exclude_filter: ["org.apache.harmony.tests.**"],
- },
optimize: {
enabled: false,
},
diff --git a/tests/libcore/luni/AndroidTest.xml b/tests/libcore/luni/AndroidTest.xml
index 13fd8d4..58bb535 100644
--- a/tests/libcore/luni/AndroidTest.xml
+++ b/tests/libcore/luni/AndroidTest.xml
@@ -47,26 +47,6 @@
<option name="device-listeners" value="org.conscrypt.ConscryptInstrumentationListener" />
<option name="instrumentation-arg" key="conscrypt_sslsocket_implementation" value="engine" />
</test>
- <!-- Re-run a subset of tests using Conscrypt's file-descriptor based implementation to ensure
- there are no regressions in this implementation before it is fully deprecated.
-
- Expectations for these tests are the same as above, only timeout and SSLSocket
- implementation are different.
- -->
- <test class="com.android.compatibility.testtype.LibcoreTest" >
- <option name="package" value="android.libcore.cts" />
- <option name="include-filter" value="libcore.javax.net.ssl" />
- <option name="include-filter" value="com.android.org.conscrypt.javax.net.ssl" />
- <option name="include-filter" value="org.apache.harmony.tests.javax.net.ssl" />
- <option name="instrumentation-arg" key="filter"
- value="com.android.cts.core.runner.ExpectationBasedFilter" />
- <option name="core-expectation" value="/knownfailures.txt" />
- <option name="virtual-device-core-expectation" value="/virtualdeviceknownfailures.txt" />
- <option name="runtime-hint" value="5m"/>
- <option name="hidden-api-checks" value="false"/>
- <option name="device-listeners" value="org.conscrypt.ConscryptInstrumentationListener" />
- <option name="instrumentation-arg" key="conscrypt_sslsocket_implementation" value="fd" />
- </test>
<object type="module_controller" class="com.android.tradefed.testtype.suite.module.TestFailureModuleController">
<option name="screenshot-on-failure" value="false" />
diff --git a/tests/media/Android.bp b/tests/media/Android.bp
index b2a2db3..03ff17d 100644
--- a/tests/media/Android.bp
+++ b/tests/media/Android.bp
@@ -21,6 +21,7 @@
defaults: ["cts_defaults"],
compile_multilib: "both",
static_libs: [
+ "androidx.test.core",
"compatibility-device-util-axt",
"ctstestrunner-axt",
"ctstestserver",
diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml
index 820fd60..8290a9f 100644
--- a/tests/media/AndroidTest.xml
+++ b/tests/media/AndroidTest.xml
@@ -26,7 +26,7 @@
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaV2TestCases-2.0" />
+ <option name="media-folder-name" value="CtsMediaV2TestCases-2.1" />
<option name="dynamic-config-module" value="CtsMediaV2TestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/media/DynamicConfig.xml b/tests/media/DynamicConfig.xml
index 26cf0fc..195333b 100644
--- a/tests/media/DynamicConfig.xml
+++ b/tests/media/DynamicConfig.xml
@@ -1,5 +1,5 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.0.zip</value>
+ <value>https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.1.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/media/README.md b/tests/media/README.md
index 38fdafb..931f431 100644
--- a/tests/media/README.md
+++ b/tests/media/README.md
@@ -3,7 +3,10 @@
The aim of these tests is not solely to verify the CDD requirements but also to test components, their plugins and their interactions with media framework.
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.0.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/media/CtsMediaV2TestCases-2.1.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory.
+
+All Big Buck Bunny(bbb) test vectors are of 8-bit format. They are downloaded from [link](https://peach.blender.org/download/) and resampled according to the test requirements.
+All Driving POV(dpov) test vectors are of 10-bit format. They are downloaded from [link](https://media.xiph.org/video/derf/) and resampled according to the test requirements.
The test suite looks to cover sdk/ndk api in normal and error scenarios. Error scenarios are separated from regular usage and are placed under class *UnitTest (MuxerUnitTest, ExtractorUnitTest, ...).
diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh
index 4e5a086..de8d997 100755
--- a/tests/media/copy_media.sh
+++ b/tests/media/copy_media.sh
@@ -17,7 +17,7 @@
## script to install mediav2 test files manually
adbOptions=" "
-resLabel=CtsMediaV2TestCases-2.0
+resLabel=CtsMediaV2TestCases-2.1
srcDir="/tmp/$resLabel"
tgtDir="/sdcard/test"
usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
index ae9054f..911a29f 100644
--- a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
+++ b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
@@ -21,10 +21,12 @@
import android.media.MediaExtractor;
import android.media.MediaFormat;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
+import org.junit.After;
import org.junit.Assume;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -38,31 +40,43 @@
import java.util.Collection;
import java.util.List;
-import static org.junit.Assert.fail;
+import static android.mediav2.cts.CodecTestBase.SupportClass.*;
@RunWith(Parameterized.class)
public class AdaptivePlaybackTest extends CodecDecoderTestBase {
private final String[] mSrcFiles;
- private final int mSupport;
+ private final SupportClass mSupportRequirements;
private long mMaxPts = 0;
- public AdaptivePlaybackTest(String decoder, String mime, String[] srcFiles, int support) {
+ public AdaptivePlaybackTest(String decoder, String mime, String[] srcFiles,
+ SupportClass supportRequirements) {
super(decoder, mime, null);
mSrcFiles = srcFiles;
- mSupport = support;
+ mSupportRequirements = supportRequirements;
}
@Rule
- public ActivityTestRule<CodecTestActivity> mActivityRule =
- new ActivityTestRule<>(CodecTestActivity.class);
+ public ActivityScenarioRule<CodecTestActivity> mActivityRule =
+ new ActivityScenarioRule<>(CodecTestActivity.class);
+
+ @Before
+ public void setUp() throws IOException, InterruptedException {
+ mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
+ setUpSurface(mActivity);
+ }
+
+ @After
+ public void tearDown() {
+ tearDownSurface();
+ }
@Parameterized.Parameters(name = "{index}({0}_{1})")
public static Collection<Object[]> input() {
final boolean isEncoder = false;
final boolean needAudio = false;
final boolean needVideo = true;
- // mime, array list of test files we'll play, codec should support adaptive feature
+ // mediaType, array list of test files, SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
{MediaFormat.MIMETYPE_VIDEO_AVC, new String[]{
"bbb_800x640_768kbps_30fps_avc_2b.mp4",
@@ -177,21 +191,10 @@
formats.add(setUpSource(file));
mExtractor.release();
}
- if (!areFormatsSupported(mCodecName, mMime, formats)) {
- if (mSupport == CODEC_ALL) {
- fail("format(s) not supported by component: " + mCodecName + " for mime : " +
- mMime);
- }
- if (mSupport != CODEC_OPTIONAL && selectCodecs(mMime, formats,
- new String[]{MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback}, false)
- .isEmpty()) {
- fail("format(s) not supported by any component for mime : " + mMime);
- }
- return;
- }
+ checkFormatSupport(mCodecName, mMime, formats,
+ new String[]{MediaCodecInfo.CodecCapabilities.FEATURE_AdaptivePlayback},
+ mSupportRequirements);
formats.clear();
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
int totalSize = 0;
for (String srcFile : mSrcFiles) {
File file = new File(mInpPrefix + srcFile);
@@ -211,7 +214,7 @@
{
mCodec = MediaCodec.createByCodecName(mCodecName);
MediaFormat format = formats.get(0);
- activity.setScreenParams(getWidth(format), getHeight(format), true);
+ mActivity.setScreenParams(getWidth(format), getHeight(format), true);
mOutputBuff.reset();
configureCodec(format, true, false, false);
mCodec.start();
@@ -221,6 +224,5 @@
mCodec.reset();
mCodec.release();
}
- tearDownSurface();
}
}
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
index 59b469d..1caa96b 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderPauseTest.java
@@ -32,8 +32,8 @@
import java.util.Collection;
import java.util.List;
+import static android.mediav2.cts.CodecTestBase.SupportClass.*;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
/**
* The following test validates that the decode can be paused
@@ -43,11 +43,12 @@
private static final String LOG_TAG = CodecDecoderPauseTest.class.getSimpleName();
private final long PAUSE_TIME_MS = 10000;
private final int NUM_FRAMES = 8;
- private final int mSupport;
+ private final SupportClass mSupportRequirements;
- public CodecDecoderPauseTest(String decoder, String mime, String srcFile, int support) {
+ public CodecDecoderPauseTest(String decoder, String mime, String srcFile,
+ SupportClass supportRequirements) {
super(decoder, mime, srcFile);
- mSupport = support;
+ mSupportRequirements = supportRequirements;
}
@Parameterized.Parameters(name = "{index}({0}_{1})")
@@ -55,14 +56,16 @@
final boolean isEncoder = false;
final boolean needAudio = true;
final boolean needVideo = true;
- // mime, source file, codecs required to support
+ /// mediaType, test file, SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
{MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_2ch_48kHz_he_aac.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_cif_avc_delay16.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_H263, "bbb_176x144_128kbps_15fps_h263.3gp", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_cif_hevc_delay15.mp4", CODEC_ALL},
- {MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_640x360_512kbps_30fps_mpeg2_2b.mp4", CODEC_ALL},
- {MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_176x144_192kbps_15fps_mpeg4.mp4", CODEC_ALL},
+ {MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_640x360_512kbps_30fps_mpeg2_2b.mp4",
+ CODEC_ALL},
+ {MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_176x144_192kbps_15fps_mpeg4.mp4",
+ CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_640x360_512kbps_30fps_vp8.webm", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_cif_768kbps_30fps_vp9.mkv", CODEC_ALL},
});
@@ -78,16 +81,7 @@
ArrayList<MediaFormat> formats = new ArrayList<>();
formats.add(setUpSource(mTestFile));
mExtractor.release();
- if (!areFormatsSupported(mCodecName, mMime, formats)) {
- if (mSupport == CODEC_ALL) {
- fail("format(s) not supported by component: " + mCodecName + " for mime : " +
- mMime);
- }
- if (mSupport != CODEC_OPTIONAL && selectCodecs(mMime, formats, null, false).isEmpty()) {
- fail("format(s) not supported by any component for mime : " + mMime);
- }
- return;
- }
+ checkFormatSupport(mCodecName, mMime, formats, null, mSupportRequirements);
final boolean isAsync = true;
MediaFormat format = setUpSource(mTestFile);
{
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
index bea8487..0dc1e95 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderSurfaceTest.java
@@ -22,10 +22,12 @@
import android.util.Log;
import android.view.Surface;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
+import org.junit.After;
import org.junit.Assume;
+import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -33,10 +35,12 @@
import org.junit.runners.Parameterized;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import static android.mediav2.cts.CodecTestBase.SupportClass.*;
import static org.junit.Assert.assertTrue;
@RunWith(Parameterized.class)
@@ -44,11 +48,13 @@
private static final String LOG_TAG = CodecDecoderSurfaceTest.class.getSimpleName();
private final String mReconfigFile;
+ private final SupportClass mSupportRequirements;
public CodecDecoderSurfaceTest(String decoder, String mime, String testFile,
- String reconfigFile) {
+ String reconfigFile, SupportClass supportRequirements) {
super(decoder, mime, testFile);
mReconfigFile = reconfigFile;
+ mSupportRequirements = supportRequirements;
}
void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
@@ -86,49 +92,66 @@
}
@Rule
- public ActivityTestRule<CodecTestActivity> mActivityRule =
- new ActivityTestRule<>(CodecTestActivity.class);
+ public ActivityScenarioRule<CodecTestActivity> mActivityRule =
+ new ActivityScenarioRule<>(CodecTestActivity.class);
+
+ @Before
+ public void setUp() throws IOException, InterruptedException {
+ MediaFormat format = setUpSource(mTestFile);
+ mExtractor.release();
+ ArrayList<MediaFormat> formatList = new ArrayList<>();
+ formatList.add(format);
+ checkFormatSupport(mCodecName, mMime, formatList, null, mSupportRequirements);
+ mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
+ setUpSurface(mActivity);
+ }
+
+ @After
+ public void tearDown() {
+ tearDownSurface();
+ }
@Parameterized.Parameters(name = "{index}({0}_{1})")
public static Collection<Object[]> input() {
final boolean isEncoder = false;
final boolean needAudio = false;
final boolean needVideo = true;
+ // mediaType, test file, reconfig test file, SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
{MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_340x280_768kbps_30fps_mpeg2.mp4",
- "bbb_520x390_1mbps_30fps_mpeg2.mp4"},
+ "bbb_520x390_1mbps_30fps_mpeg2.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_MPEG2,
"bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_2fields.mp4",
- "bbb_520x390_1mbps_30fps_mpeg2.mp4"},
+ "bbb_520x390_1mbps_30fps_mpeg2.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_MPEG2,
"bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_1field.ts",
- "bbb_520x390_1mbps_30fps_mpeg2.mp4"},
+ "bbb_520x390_1mbps_30fps_mpeg2.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_340x280_768kbps_30fps_avc.mp4",
- "bbb_520x390_1mbps_30fps_avc.mp4"},
+ "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_360x640_768kbps_30fps_avc.mp4",
- "bbb_520x390_1mbps_30fps_avc.mp4"},
+ "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_160x1024_1500kbps_30fps_avc.mp4",
- "bbb_520x390_1mbps_30fps_avc.mp4"},
+ "bbb_520x390_1mbps_30fps_avc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_1280x120_1500kbps_30fps_avc.mp4",
- "bbb_340x280_768kbps_30fps_avc.mp4"},
+ "bbb_340x280_768kbps_30fps_avc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_520x390_1mbps_30fps_hevc.mp4",
- "bbb_340x280_768kbps_30fps_hevc.mp4"},
+ "bbb_340x280_768kbps_30fps_hevc.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_128x96_64kbps_12fps_mpeg4.mp4",
- "bbb_176x144_192kbps_15fps_mpeg4.mp4"},
+ "bbb_176x144_192kbps_15fps_mpeg4.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_H263, "bbb_176x144_128kbps_15fps_h263.3gp",
- "bbb_176x144_192kbps_10fps_h263.3gp"},
+ "bbb_176x144_192kbps_10fps_h263.3gp", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_340x280_768kbps_30fps_vp8.webm",
- "bbb_520x390_1mbps_30fps_vp8.webm"},
+ "bbb_520x390_1mbps_30fps_vp8.webm", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_340x280_768kbps_30fps_vp9.webm",
- "bbb_520x390_1mbps_30fps_vp9.webm"},
+ "bbb_520x390_1mbps_30fps_vp9.webm", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP9,
"bbb_340x280_768kbps_30fps_split_non_display_frame_vp9.webm",
- "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm"},
+ "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_340x280_768kbps_30fps_av1.mp4",
- "bbb_520x390_1mbps_30fps_av1.mp4"},
+ "bbb_520x390_1mbps_30fps_av1.mp4", CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AV1,
"bikes_qcif_color_bt2020_smpte2086Hlg_bt2020Ncl_fr_av1.mp4",
- "bbb_520x390_1mbps_30fps_av1.mp4"},
+ "bbb_520x390_1mbps_30fps_av1.mp4", CODEC_ALL},
});
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, true);
}
@@ -145,8 +168,6 @@
OutputManager test = new OutputManager();
final long pts = 0;
final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
{
decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
ref = mOutputBuff;
@@ -158,7 +179,7 @@
}
MediaFormat format = setUpSource(mTestFile);
mCodec = MediaCodec.createByCodecName(mCodecName);
- activity.setScreenParams(getWidth(format), getHeight(format), true);
+ mActivity.setScreenParams(getWidth(format), getHeight(format), true);
for (boolean isAsync : boolStates) {
String log = String.format("codec: %s, file: %s, mode: %s:: ", mCodecName,
mTestFile, (isAsync ? "async" : "sync"));
@@ -187,7 +208,6 @@
mCodec.release();
mExtractor.release();
}
- tearDownSurface();
}
/**
@@ -211,8 +231,6 @@
final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
boolean[] boolStates = {true, false};
OutputManager test = new OutputManager();
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
{
decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
OutputManager ref = mOutputBuff;
@@ -225,7 +243,7 @@
mOutputBuff = test;
setUpSource(mTestFile);
mCodec = MediaCodec.createByCodecName(mCodecName);
- activity.setScreenParams(getWidth(format), getHeight(format), false);
+ mActivity.setScreenParams(getWidth(format), getHeight(format), false);
for (boolean isAsync : boolStates) {
String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
mTestFile, (isAsync ? "async" : "sync"));
@@ -293,7 +311,6 @@
mCodec.release();
mExtractor.release();
}
- tearDownSurface();
}
/**
@@ -309,12 +326,13 @@
mExtractor.release();
MediaFormat newFormat = setUpSource(mReconfigFile);
mExtractor.release();
+ ArrayList<MediaFormat> formatList = new ArrayList<>();
+ formatList.add(newFormat);
+ checkFormatSupport(mCodecName, mMime, formatList, null, mSupportRequirements);
final long pts = 500000;
final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
boolean[] boolStates = {true, false};
OutputManager test = new OutputManager();
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
{
decodeAndSavePts(mTestFile, mCodecName, pts, mode, Integer.MAX_VALUE);
OutputManager ref = mOutputBuff;
@@ -332,7 +350,7 @@
}
mOutputBuff = test;
mCodec = MediaCodec.createByCodecName(mCodecName);
- activity.setScreenParams(getWidth(format), getHeight(format), false);
+ mActivity.setScreenParams(getWidth(format), getHeight(format), false);
for (boolean isAsync : boolStates) {
setUpSource(mTestFile);
String log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
@@ -397,7 +415,7 @@
setUpSource(mReconfigFile);
log = String.format("decoder: %s, input file: %s, mode: %s:: ", mCodecName,
mReconfigFile, (isAsync ? "async" : "sync"));
- activity.setScreenParams(getWidth(newFormat), getHeight(newFormat), true);
+ mActivity.setScreenParams(getWidth(newFormat), getHeight(newFormat), true);
reConfigureCodec(newFormat, isAsync, false, false);
mCodec.start();
test.reset();
@@ -422,7 +440,6 @@
}
mCodec.release();
}
- tearDownSurface();
}
private native boolean nativeTestSimpleDecode(String decoder, Surface surface, String mime,
@@ -430,17 +447,12 @@
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testSimpleDecodeToSurfaceNative() throws IOException, InterruptedException {
+ public void testSimpleDecodeToSurfaceNative() throws IOException {
MediaFormat format = setUpSource(mTestFile);
mExtractor.release();
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
- activity.setScreenParams(getWidth(format), getHeight(format), false);
- {
- assertTrue(nativeTestSimpleDecode(mCodecName, mSurface, mMime, mInpPrefix + mTestFile,
- mInpPrefix + mReconfigFile, -1.0f, 0L));
- }
- tearDownSurface();
+ mActivity.setScreenParams(getWidth(format), getHeight(format), false);
+ assertTrue(nativeTestSimpleDecode(mCodecName, mSurface, mMime, mInpPrefix + mTestFile,
+ mInpPrefix + mReconfigFile, -1.0f, 0L));
}
private native boolean nativeTestFlush(String decoder, Surface surface, String mime,
@@ -448,15 +460,10 @@
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testFlushNative() throws IOException, InterruptedException {
+ public void testFlushNative() throws IOException {
MediaFormat format = setUpSource(mTestFile);
mExtractor.release();
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
- activity.setScreenParams(getWidth(format), getHeight(format), true);
- {
- assertTrue(nativeTestFlush(mCodecName, mSurface, mMime, mInpPrefix + mTestFile));
- }
- tearDownSurface();
+ mActivity.setScreenParams(getWidth(format), getHeight(format), true);
+ assertTrue(nativeTestFlush(mCodecName, mSurface, mMime, mInpPrefix + mTestFile));
}
}
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index 16faa41..072222b 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -27,6 +27,7 @@
import androidx.test.filters.SmallTest;
import org.junit.Assume;
+import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,6 +44,7 @@
import java.util.Collection;
import java.util.List;
+import static android.mediav2.cts.CodecTestBase.SupportClass.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -64,14 +66,16 @@
private final String mReconfigFile;
private final float mRmsError;
private final long mRefCRC;
+ private final SupportClass mSupportRequirements;
public CodecDecoderTest(String decoder, String mime, String testFile, String refFile,
- String reconfigFile, float rmsError, long refCRC) {
+ String reconfigFile, float rmsError, long refCRC, SupportClass supportRequirements) {
super(decoder, mime, testFile);
mRefFile = refFile;
mReconfigFile = reconfigFile;
mRmsError = rmsError;
mRefCRC = refCRC;
+ mSupportRequirements = supportRequirements;
}
static short[] setUpAudioReference(String file) throws IOException {
@@ -129,53 +133,61 @@
final boolean isEncoder = false;
final boolean needAudio = true;
final boolean needVideo = true;
- // mime, testClip, referenceClip, reconfigureTestClip, refRmsError, refCRC32
+ // mediaType, testClip, referenceClip, reconfigureTestClip, refRmsError, refCRC32,
+ // SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
{MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_lame_vbr.mp3", 91.022f, -1L},
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_lame_vbr.mp3", 91.022f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_cbr.mp3",
- "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_lame_vbr.mp3", 103.60f, -1L},
+ "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_lame_vbr.mp3", 103.60f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_16kbps_amrwb.3gp",
"bbb_1ch_16kHz_s16le.raw", "bbb_1ch_16kHz_23kbps_amrwb.3gp", 2393.598f,
- -1L},
+ -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_10kbps_amrnb.3gp",
- "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_8kbps_amrnb.3gp", -1.0f, -1L},
+ "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_8kbps_amrnb.3gp", -1.0f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_1ch_16kHz_flac.mka",
- "bbb_1ch_16kHz_s16le.raw", "bbb_2ch_44kHz_flac.mka", 0.0f, -1L},
+ "bbb_1ch_16kHz_s16le.raw", "bbb_2ch_44kHz_flac.mka", 0.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_FLAC, "bbb_2ch_44kHz_flac.mka",
- "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_flac.mka", 0.0f, -1L},
+ "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_flac.mka", 0.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_1ch_16kHz.wav", "bbb_1ch_16kHz_s16le.raw",
- "bbb_2ch_44kHz.wav", 0.0f, -1L},
+ "bbb_2ch_44kHz.wav", 0.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_2ch_44kHz.wav", "bbb_2ch_44kHz_s16le.raw",
- "bbb_1ch_16kHz.wav", 0.0f, -1L},
+ "bbb_1ch_16kHz.wav", 0.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_1ch_8kHz_alaw.wav",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_alaw.wav", 23.08678f, -1L},
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_alaw.wav", 23.08678f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_1ch_8kHz_mulaw.wav",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_mulaw.wav", 24.4131f, -1L},
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_mulaw.wav", 24.4131f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav",
- "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_gsm.wav", 946.02698f, -1L},
+ "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_gsm.wav", 946.02698f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_1ch_16kHz_vorbis.mka",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_vorbis.mka", -1.0f, -1L},
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_vorbis.mka", -1.0f, -1L,
+ CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_OPUS, "bbb_2ch_48kHz_opus.mka",
- "bbb_2ch_48kHz_s16le.raw", "bbb_1ch_48kHz_opus.mka", -1.0f, -1L},
+ "bbb_2ch_48kHz_s16le.raw", "bbb_1ch_48kHz_opus.mka", -1.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_AAC, "bbb_1ch_16kHz_aac.mp4",
- "bbb_1ch_16kHz_s16le.raw", "bbb_2ch_44kHz_aac.mp4", -1.0f, -1L},
+ "bbb_1ch_16kHz_s16le.raw", "bbb_2ch_44kHz_aac.mp4", -1.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_340x280_768kbps_30fps_mpeg2.mp4", null,
- "bbb_520x390_1mbps_30fps_mpeg2.mp4", -1.0f, -1L},
+ "bbb_520x390_1mbps_30fps_mpeg2.mp4", -1.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AVC, "bbb_340x280_768kbps_30fps_avc.mp4", null,
- "bbb_520x390_1mbps_30fps_avc.mp4", -1.0f, 1746312400L},
+ "bbb_520x390_1mbps_30fps_avc.mp4", -1.0f, 1746312400L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_HEVC, "bbb_520x390_1mbps_30fps_hevc.mp4", null,
- "bbb_340x280_768kbps_30fps_hevc.mp4", -1.0f, 3061322606L},
+ "bbb_340x280_768kbps_30fps_hevc.mp4", -1.0f, 3061322606L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_MPEG4, "bbb_128x96_64kbps_12fps_mpeg4.mp4",
- null, "bbb_176x144_192kbps_15fps_mpeg4.mp4", -1.0f, -1L},
+ null, "bbb_176x144_192kbps_15fps_mpeg4.mp4", -1.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_H263, "bbb_176x144_128kbps_15fps_h263.3gp",
- null, "bbb_176x144_192kbps_10fps_h263.3gp", -1.0f, -1L},
+ null, "bbb_176x144_192kbps_10fps_h263.3gp", -1.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP8, "bbb_340x280_768kbps_30fps_vp8.webm", null,
- "bbb_520x390_1mbps_30fps_vp8.webm", -1.0f, 2030620796L},
+ "bbb_520x390_1mbps_30fps_vp8.webm", -1.0f, 2030620796L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_VP9, "bbb_340x280_768kbps_30fps_vp9.webm", null,
- "bbb_520x390_1mbps_30fps_vp9.webm", -1.0f, 4122701060L},
+ "bbb_520x390_1mbps_30fps_vp9.webm", -1.0f, 4122701060L, CODEC_ALL},
{MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_340x280_768kbps_30fps_av1.mp4", null,
- "bbb_520x390_1mbps_30fps_av1.mp4", -1.0f, 400672933L},
+ "bbb_520x390_1mbps_30fps_av1.mp4", -1.0f, 400672933L, CODEC_ALL},
});
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, true);
}
@@ -196,6 +208,15 @@
}
}
+ @Before
+ public void setUp() throws IOException {
+ MediaFormat format = setUpSource(mTestFile);
+ mExtractor.release();
+ ArrayList<MediaFormat> formatList = new ArrayList<>();
+ formatList.add(format);
+ checkFormatSupport(mCodecName, mMime, formatList, null, mSupportRequirements);
+ }
+
/**
* Tests decoder for combinations:
* 1. Codec Sync Mode, Signal Eos with Last frame
@@ -419,6 +440,9 @@
mExtractor.release();
MediaFormat newFormat = setUpSource(mReconfigFile);
mExtractor.release();
+ ArrayList<MediaFormat> formatList = new ArrayList<>();
+ formatList.add(newFormat);
+ checkFormatSupport(mCodecName, mMime, formatList, null, mSupportRequirements);
final long startTs = 0;
final long seekTs = 500000;
final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 5819bfb..4dd9923 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -31,8 +31,8 @@
import java.util.Collection;
import java.util.List;
+import static android.mediav2.cts.CodecTestBase.SupportClass.*;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
/**
* The following test validates decoder for the given input clip. For audio components, we check
@@ -50,16 +50,16 @@
private final String mRefFile;
private final float mRmsError;
private final long mRefCRC;
- private final int mSupport;
+ private final SupportClass mSupportRequirements;
public CodecDecoderValidationTest(String decoder, String mime, String[] srcFiles,
- String refFile, float rmsError, long refCRC, int support) {
+ String refFile, float rmsError, long refCRC, SupportClass supportRequirements) {
super(decoder, mime, null);
mSrcFiles = srcFiles;
mRefFile = refFile;
mRmsError = rmsError;
mRefCRC = refCRC;
- mSupport = support;
+ mSupportRequirements = supportRequirements;
}
@Parameterized.Parameters(name = "{index}({0}_{1})")
@@ -67,8 +67,8 @@
final boolean isEncoder = false;
final boolean needAudio = true;
final boolean needVideo = true;
- // mime, array list of test files (underlying elementary stream is same, except they
- // are placed in different containers), ref file, rms error, checksum
+ // mediaType, array list of test files (underlying elementary stream is same, except they
+ // are placed in different containers), ref file, rms error, checksum, SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
// vp9 test vectors with no-show frames signalled in alternate ways
{MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
@@ -471,19 +471,7 @@
formats.add(setUpSource(file));
mExtractor.release();
}
- if (!areFormatsSupported(mCodecName, mMime, formats)) {
- if (mSupport == CODEC_ALL) {
- fail("format(s) not supported by component: " + mCodecName + " for mime : " +
- mMime);
- } else if (mSupport == CODEC_ANY && selectCodecs(mMime, formats, null,
- false).isEmpty()) {
- fail("format(s) not supported by any component for mime : " + mMime);
- } else if (mSupport == CODEC_DEFAULT && isDefaultCodec(mCodecName, mMime, false)) {
- fail("format(s) not supported by " + mCodecName
- + " which is a default codec for mime : " + mMime);
- }
- return;
- }
+ checkFormatSupport(mCodecName, mMime, formats, null, mSupportRequirements);
final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
{
OutputManager ref = null;
diff --git a/tests/media/src/android/mediav2/cts/CodecListTest.java b/tests/media/src/android/mediav2/cts/CodecListTest.java
index 07bf4ac..04568f8 100644
--- a/tests/media/src/android/mediav2/cts/CodecListTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecListTest.java
@@ -21,6 +21,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.MediaUtils;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -52,8 +54,8 @@
CodecTestBase.hasDecoder(mime));
}
}
- if (CodecTestBase.hasCamera()) {
- assertTrue("device doesn't support either VP8 or AVC video encoders",
+ if (MediaUtils.hasCamera()) {
+ assertTrue("device has neither VP8 or AVC encoding",
CodecTestBase.hasEncoder(MediaFormat.MIMETYPE_VIDEO_AVC) ||
CodecTestBase.hasEncoder(MediaFormat.MIMETYPE_VIDEO_VP8));
}
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index c22b896..9cd7fe6 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -38,6 +38,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Before;
import java.io.File;
@@ -60,6 +61,7 @@
import java.util.zip.CRC32;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.MediaUtils;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
@@ -512,6 +514,12 @@
abstract class CodecTestBase {
public static final boolean IS_AT_LEAST_R = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.R);
private static final String LOG_TAG = CodecTestBase.class.getSimpleName();
+ enum SupportClass {
+ CODEC_ALL, // All codecs must support
+ CODEC_ANY, // At least one codec must support
+ CODEC_DEFAULT, // Default codec must support
+ CODEC_OPTIONAL // Codec support is optional
+ }
static final String CODEC_PREFIX_KEY = "codec-prefix";
static final String MIME_SEL_KEY = "mime-sel";
@@ -522,10 +530,6 @@
static final int PER_TEST_TIMEOUT_LARGE_TEST_MS = 300000;
static final int PER_TEST_TIMEOUT_SMALL_TEST_MS = 60000;
static final int UNSPECIFIED = 0;
- static final int CODEC_ALL = 0; // All codecs must support
- static final int CODEC_ANY = 1; // At least one codec must support
- static final int CODEC_DEFAULT = 2; // Default codec must support
- static final int CODEC_OPTIONAL = 3; // Codec support is optional
// Maintain Timeouts in sync with their counterpart in NativeMediaCommon.h
static final long Q_DEQ_TIMEOUT_US = 5000; // block at most 5ms while looking for io buffers
static final int RETRY_LIMIT = 100; // max poll counter before test aborts and returns error
@@ -584,41 +588,6 @@
codecPrefix = args.getString(CODEC_PREFIX_KEY);
}
- static boolean isTv() {
- return pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
- }
-
- static boolean hasMicrophone() {
- return pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE);
- }
-
- static boolean hasCamera() {
- return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
- }
-
- static boolean isWatch() {
- return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
- }
-
- static boolean isAutomotive() {
- return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
- }
-
- static boolean isPc() {
- return pm.hasSystemFeature(PackageManager.FEATURE_PC);
- }
-
- static boolean hasAudioOutput() {
- return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
- }
-
- static boolean isHandheld() {
- // handheld nature is not exposed to package manager, for now
- // we check for touchscreen and NOT watch and NOT tv and NOT pc
- return pm.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN) && !isWatch() && !isTv() &&
- !isAutomotive() && !isPc();
- }
-
static boolean hasDecoder(String mime) {
return CodecTestBase.selectCodecs(mime, null, null, false).size() != 0;
}
@@ -627,6 +596,31 @@
return CodecTestBase.selectCodecs(mime, null, null, true).size() != 0;
}
+ public static void checkFormatSupport(String codecName, String mime,
+ ArrayList<MediaFormat> formats, String[] features, SupportClass supportRequirements)
+ throws IOException {
+ if (!areFormatsSupported(codecName, mime, formats)) {
+ switch (supportRequirements) {
+ case CODEC_ALL:
+ fail("format(s) not supported by codec: " + codecName + " for mime : " + mime);
+ break;
+ case CODEC_ANY:
+ if (selectCodecs(mime, formats, features, false).isEmpty())
+ fail("format(s) not supported by any component for mime : " + mime);
+ break;
+ case CODEC_DEFAULT:
+ if (isDefaultCodec(codecName, mime, false))
+ fail("format(s) not supported by default codec : " + codecName +
+ "for mime : " + mime);
+ break;
+ case CODEC_OPTIONAL:
+ default:
+ Assume.assumeTrue("format(s) not supported by codec: " + codecName +
+ " for mime : " + mime, false);
+ }
+ }
+ }
+
static boolean isFeatureSupported(String name, String mime, String feature) throws IOException {
MediaCodec codec = MediaCodec.createByCodecName(name);
MediaCodecInfo.CodecCapabilities codecCapabilities =
@@ -637,38 +631,39 @@
}
static boolean doesAnyFormatHaveHDRProfile(String mime, ArrayList<MediaFormat> formats) {
- boolean isHDR = false;
for (MediaFormat format : formats) {
assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
- if (mime.equals(MediaFormat.MIMETYPE_VIDEO_AVC)) {
- int profile = format.getInteger(MediaFormat.KEY_PROFILE);
- if (profile == AVCProfileHigh10 || profile == AVCProfileHigh422 ||
- profile == AVCProfileHigh444) {
- isHDR = true;
- break;
+ switch (mime) {
+ case MediaFormat.MIMETYPE_VIDEO_AVC: {
+ int profile = format.getInteger(MediaFormat.KEY_PROFILE);
+ if (profile == AVCProfileHigh10 || profile == AVCProfileHigh422 ||
+ profile == AVCProfileHigh444) {
+ return true;
+ }
}
- } else if (mime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- int profile = format.getInteger(MediaFormat.KEY_PROFILE, VP9Profile0);
- if (profile == VP9Profile2HDR || profile == VP9Profile3HDR ||
- profile == VP9Profile2HDR10Plus || profile == VP9Profile3HDR10Plus) {
- isHDR = true;
- break;
+ case MediaFormat.MIMETYPE_VIDEO_VP9: {
+ int profile = format.getInteger(MediaFormat.KEY_PROFILE, VP9Profile0);
+ if (profile == VP9Profile2HDR || profile == VP9Profile3HDR ||
+ profile == VP9Profile2HDR10Plus || profile == VP9Profile3HDR10Plus) {
+ return true;
+ }
}
- } else if (mime.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- int profile = format.getInteger(MediaFormat.KEY_PROFILE, HEVCProfileMain);
- if (profile == HEVCProfileMain10HDR10 || profile == HEVCProfileMain10HDR10Plus) {
- isHDR = true;
- break;
+ case MediaFormat.MIMETYPE_VIDEO_HEVC: {
+ int profile = format.getInteger(MediaFormat.KEY_PROFILE, HEVCProfileMain);
+ if (profile == HEVCProfileMain10HDR10 ||
+ profile == HEVCProfileMain10HDR10Plus) {
+ return true;
+ }
}
- } else if (mime.equals(MediaFormat.MIMETYPE_VIDEO_AV1)) {
- int profile = format.getInteger(MediaFormat.KEY_PROFILE, AV1ProfileMain8);
- if (profile == AV1ProfileMain10HDR10 || profile == AV1ProfileMain10HDR10Plus) {
- isHDR = true;
- break;
+ case MediaFormat.MIMETYPE_VIDEO_AV1: {
+ int profile = format.getInteger(MediaFormat.KEY_PROFILE, AV1ProfileMain8);
+ if (profile == AV1ProfileMain10HDR10 || profile == AV1ProfileMain10HDR10Plus) {
+ return true;
+ }
}
}
}
- return isHDR;
+ return false;
}
static boolean canDisplaySupportHDRContent() {
@@ -710,7 +705,7 @@
boolean needVideo) {
Set<String> list = new HashSet<>();
if (!isEncoder) {
- if (hasAudioOutput() && needAudio) {
+ if (MediaUtils.hasAudioOutput() && needAudio) {
// sec 5.1.2
list.add(MediaFormat.MIMETYPE_AUDIO_AAC);
list.add(MediaFormat.MIMETYPE_AUDIO_FLAC);
@@ -719,7 +714,8 @@
list.add(MediaFormat.MIMETYPE_AUDIO_RAW);
list.add(MediaFormat.MIMETYPE_AUDIO_OPUS);
}
- if (isHandheld() || isTv() || isAutomotive()) {
+ if (MediaUtils.isHandheld() || MediaUtils.isTablet() || MediaUtils.isTv() ||
+ MediaUtils.isAutomotive()) {
// sec 2.2.2, 2.3.2, 2.5.2
if (needAudio) {
list.add(MediaFormat.MIMETYPE_AUDIO_AAC);
@@ -732,7 +728,7 @@
list.add(MediaFormat.MIMETYPE_VIDEO_VP9);
}
}
- if (isHandheld()) {
+ if (MediaUtils.isHandheld() || MediaUtils.isTablet()) {
// sec 2.2.2
if (needAudio) {
list.add(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
@@ -742,20 +738,21 @@
list.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
}
}
- if (isTv() && needVideo) {
+ if (MediaUtils.isTv() && needVideo) {
// sec 2.3.2
list.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
list.add(MediaFormat.MIMETYPE_VIDEO_MPEG2);
}
} else {
- if (hasMicrophone() && needAudio) {
+ if (MediaUtils.hasMicrophone() && needAudio) {
// sec 5.1.1
// TODO(b/154423550)
// list.add(MediaFormat.MIMETYPE_AUDIO_RAW);
list.add(MediaFormat.MIMETYPE_AUDIO_FLAC);
list.add(MediaFormat.MIMETYPE_AUDIO_OPUS);
}
- if (isHandheld() || isTv() || isAutomotive()) {
+ if (MediaUtils.isHandheld() || MediaUtils.isTablet() || MediaUtils.isTv() ||
+ MediaUtils.isAutomotive()) {
// sec 2.2.2, 2.3.2, 2.5.2
if (needAudio) {
list.add(MediaFormat.MIMETYPE_AUDIO_AAC);
@@ -765,7 +762,7 @@
list.add(MediaFormat.MIMETYPE_VIDEO_VP8);
}
}
- if (isHandheld() && needAudio) {
+ if ((MediaUtils.isHandheld() || MediaUtils.isTablet()) && needAudio) {
// sec 2.2.2
list.add(MediaFormat.MIMETYPE_AUDIO_AMR_NB);
list.add(MediaFormat.MIMETYPE_AUDIO_AMR_WB);
@@ -794,11 +791,14 @@
}
}
}
- // TODO(b/154423708): add checks for video o/p port and display length >= 2.5"
+ // feature_video_output is not exposed to package manager. Testing for video output
+ // ports, such as VGA, HDMI, DisplayPort, or a wireless port for display is also not
+ // direct.
/* sec 5.2: device implementations include an embedded screen display with the
- diagonal length of at least 2.5inches or include a video output port or declare the
+ diagonal length of at least 2.5 inches or include a video output port or declare the
support of a camera */
- if (isEncoder && hasCamera() && needVideo &&
+ if (isEncoder && needVideo &&
+ (MediaUtils.hasCamera() || MediaUtils.getScreenSizeInInches() >= 2.5) &&
!mimes.contains(MediaFormat.MIMETYPE_VIDEO_AVC) &&
!mimes.contains(MediaFormat.MIMETYPE_VIDEO_VP8)) {
// Add required cdd mimes here so that respective codec tests fail.
@@ -1179,6 +1179,7 @@
private ByteBuffer flatBuffer = ByteBuffer.allocate(4 * Integer.BYTES);
MediaExtractor mExtractor;
+ CodecTestActivity mActivity;
CodecDecoderTestBase(String codecName, String mime, String testFile) {
mCodecName = codecName;
diff --git a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
index 15f5e65..4ffa782 100644
--- a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
@@ -18,10 +18,12 @@
import android.media.MediaFormat;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.filters.SmallTest;
-import androidx.test.rule.ActivityTestRule;
+import org.junit.After;
import org.junit.Assume;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,6 +42,7 @@
private final int mColorStandard;
private final int mColorTransferCurve;
private final boolean mCanIgnoreColorBox;
+
private ArrayList<String> mCheckESList;
public DecoderColorAspectsTest(String decoderName, String mime, String testFile, int range,
@@ -235,8 +238,19 @@
}
@Rule
- public ActivityTestRule<CodecTestActivity> mActivityRule =
- new ActivityTestRule<>(CodecTestActivity.class);
+ public ActivityScenarioRule<CodecTestActivity> mActivityRule =
+ new ActivityScenarioRule<>(CodecTestActivity.class);
+
+ @Before
+ public void setUp() throws IOException, InterruptedException {
+ mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
+ setUpSurface(mActivity);
+ }
+
+ @After
+ public void tearDown() {
+ tearDownSurface();
+ }
@SmallTest
@Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
@@ -249,9 +263,7 @@
if (doesAnyFormatHaveHDRProfile(mMime, formats)) {
Assume.assumeTrue(canDisplaySupportHDRContent());
}
- CodecTestActivity activity = mActivityRule.getActivity();
- setUpSurface(activity);
- activity.setScreenParams(getWidth(format), getHeight(format), true);
+ mActivity.setScreenParams(getWidth(format), getHeight(format), true);
{
validateColorAspects(mCodecName, mInpPrefix, mTestFile, mColorRange, mColorStandard,
mColorTransferCurve, false);
@@ -262,6 +274,5 @@
mColorStandard, mColorTransferCurve, true);
}
}
- tearDownSurface();
}
}
diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java
index b5b0d24..5edbff1 100644
--- a/tests/media/src/android/mediav2/cts/WorkDir.java
+++ b/tests/media/src/android/mediav2/cts/WorkDir.java
@@ -40,7 +40,7 @@
// user has specified the mediaDirString via instrumentation-arg
return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
} else {
- return (getTopDirString() + "test/CtsMediaV2TestCases-2.0/");
+ return (getTopDirString() + "test/CtsMediaV2TestCases-2.1/");
}
}
}
diff --git a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
index 056f7a4..23760fc 100644
--- a/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
+++ b/tests/mediapc/src/android/mediapc/cts/PerformanceClassTest.java
@@ -16,11 +16,20 @@
package android.mediapc.cts;
+import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback;
+import static android.mediapc.cts.Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
+import static android.mediapc.cts.Utils.MIN_MEMORY_PERF_CLASS_T_MB;
import static android.util.DisplayMetrics.DENSITY_400;
+import static org.junit.Assert.assertTrue;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaDrm;
+import android.media.MediaFormat;
+import android.media.UnsupportedSchemeException;
import android.os.Build;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -28,6 +37,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
@@ -35,16 +45,26 @@
import org.junit.Assume;
import org.junit.Test;
-import org.junit.experimental.runners.Enclosed;
-import org.junit.runner.RunWith;
-import static org.junit.Assert.assertTrue;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.UUID;
/**
* Tests the basic aspects of the media performance class.
*/
public class PerformanceClassTest {
private static final String TAG = "PerformanceClassTest";
+ private static final UUID WIDEVINE_UUID = new UUID(0xEDEF8BA979D64ACEL, 0xA3C827DCD51D21EDL);
+ static ArrayList<String> mMimeSecureSupport = new ArrayList<>();
+
+ static {
+ mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_AVC);
+ mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ mMimeSecureSupport.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+ }
+
private boolean isHandheld() {
// handheld nature is not exposed to package manager, for now
@@ -59,14 +79,107 @@
@SmallTest
@Test
+ // TODO(b/218771970) Add @CddTest annotation
+ public void testSecureHwDecodeSupport() throws IOException {
+ ArrayList<String> noSecureHwDecoderForMimes = new ArrayList<>();
+ for (String mime : mMimeSecureSupport) {
+ boolean isSecureHwDecoderFoundForMime = false;
+ boolean isHwDecoderFoundForMime = false;
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ MediaCodecInfo[] codecInfos = codecList.getCodecInfos();
+ for (MediaCodecInfo info : codecInfos) {
+ if (info.isEncoder() || !info.isHardwareAccelerated() || info.isAlias()) continue;
+ try {
+ MediaCodecInfo.CodecCapabilities caps = info.getCapabilitiesForType(mime);
+ if (caps != null) {
+ isHwDecoderFoundForMime = true;
+ if (caps.isFeatureSupported(FEATURE_SecurePlayback))
+ isSecureHwDecoderFoundForMime = true;
+ }
+ } catch (Exception ignored) {
+ }
+ }
+ if (isHwDecoderFoundForMime && !isSecureHwDecoderFoundForMime)
+ noSecureHwDecoderForMimes.add(mime);
+ }
+ if (Utils.isTPerfClass()) {
+ assertTrue(
+ "For MPC >= Android T, if HW decoder is present for a mime, secure HW decoder" +
+ " must be present for the mime. HW decoder present but secure HW " +
+ "decoder not available for mimes: " + noSecureHwDecoderForMimes,
+ noSecureHwDecoderForMimes.isEmpty());
+ } else {
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "SecureHwDecodeSupport");
+ log.addValue("SecureHwDecodeSupportForMimesWithHwDecoders",
+ noSecureHwDecoderForMimes.isEmpty(), ResultType.NEUTRAL, ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary("MPC 13: Widevine/Secure codec requirements", 0, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
+ @SmallTest
+ @Test
+ // TODO(b/218771970) Add @CddTest annotation
+ public void testWidevineSupport() throws UnsupportedSchemeException {
+ boolean isWidevineSupported = MediaDrm.isCryptoSchemeSupported(WIDEVINE_UUID);
+ boolean isL1Supported = false;
+ boolean isL1Tier3Supported = false;
+ boolean isOemCrypto17Plus = false;
+ boolean isWidevineCdm17Plus = false;
+ if (isWidevineSupported) {
+ MediaDrm mediaDrm = new MediaDrm(WIDEVINE_UUID);
+ isL1Supported = mediaDrm.getPropertyString("securityLevel").equals("L1");
+ int tier = Integer.parseInt(mediaDrm.getPropertyString("resourceRatingTier"));
+ isL1Tier3Supported = tier >= 3;
+
+ String oemCryptoVersionProperty = mediaDrm.getPropertyString("oemCryptoApiVersion");
+ int oemCryptoVersion = Integer.parseInt(oemCryptoVersionProperty);
+ isOemCrypto17Plus = oemCryptoVersion >= 17;
+
+ String cdmVersionProperty = mediaDrm.getPropertyString(MediaDrm.PROPERTY_VERSION);
+ int cdmMajorVersion = Integer.parseInt(cdmVersionProperty.split("\\.", 2)[0]);
+ isWidevineCdm17Plus = cdmMajorVersion >= 17;
+ }
+
+ if (Utils.isTPerfClass()) {
+ assertTrue("Widevine support required for MPC >= Android T", isWidevineSupported);
+ assertTrue("Widevine L1 support required for MPC >= Android T", isL1Supported);
+ assertTrue("Widevine L1 Resource Rating Tier 3 support required for MPC >= Android T",
+ isL1Tier3Supported);
+ assertTrue("OEMCrypto min version 17.x required for MPC >= Android T",
+ isOemCrypto17Plus);
+ assertTrue("Widevine CDM min version 17.x required for MPC >= Android T",
+ isWidevineCdm17Plus);
+ } else {
+ DeviceReportLog log =
+ new DeviceReportLog("MediaPerformanceClassLogs", "WidevineSupport");
+ log.addValue("Widevine Support", isWidevineSupported, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ log.addValue("Widevine L1 Support", isL1Supported, ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("Widevine L1 Resource Rating Tier 3 Support", isL1Tier3Supported,
+ ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("OEMCrypto min version 17.x Support", isOemCrypto17Plus,
+ ResultType.NEUTRAL, ResultUnit.NONE);
+ log.addValue("Widevine CDM min version 17.x Support", isWidevineCdm17Plus,
+ ResultType.NEUTRAL, ResultUnit.NONE);
+ // TODO(b/218771970) Log CDD sections
+ log.setSummary("MPC 13: Widevine/Secure codec requirements", 0, ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ log.submit(InstrumentationRegistry.getInstrumentation());
+ }
+ }
+
+ @SmallTest
+ @Test
public void testMediaPerformanceClassScope() throws Exception {
// if device is not of a performance class, we are done.
Assume.assumeTrue("not a device of a valid media performance class", Utils.isPerfClass());
- if (Utils.isRPerfClass()
- || Utils.isSPerfClass()) {
- assertTrue("performance class is only defined for Handheld devices",
- isHandheld());
+ if (Utils.isPerfClass()) {
+ assertTrue("performance class is only defined for Handheld devices", isHandheld());
}
}
@@ -78,7 +191,7 @@
// Verify minimum screen density and resolution
assertMinDpiAndPixels(context, DENSITY_400, 1920, 1080);
// Verify minimum memory
- assertMinMemoryMb(context, Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB);
+ assertMinMemoryMb(context);
}
/** Asserts that the given values conform to the specs in CDD */
@@ -105,35 +218,39 @@
int pc = density >= minDpi && longPix >= minLong && shortPix >= minShort
? Build.VERSION_CODES.S : 0;
DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", "Display");
- log.addValue("DisplayDensity", density, ResultType.LOWER_BETTER, ResultUnit.NONE);
- log.addValue("ResolutionLong", longPix, ResultType.LOWER_BETTER, ResultUnit.NONE);
- log.addValue("ResolutionShort", shortPix, ResultType.LOWER_BETTER, ResultUnit.NONE);
+ log.addValue("DisplayDensity", density, ResultType.HIGHER_BETTER, ResultUnit.NONE);
+ log.addValue("ResolutionLong", longPix, ResultType.HIGHER_BETTER, ResultUnit.NONE);
+ log.addValue("ResolutionShort", shortPix, ResultType.HIGHER_BETTER, ResultUnit.NONE);
log.setSummary("CDD 2.2.7.3/7.1.1.1,7.1.1.3/H-1-1,H-2-1 performance_class", pc,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ ResultType.HIGHER_BETTER, ResultUnit.NONE);
log.submit(InstrumentationRegistry.getInstrumentation());
}
}
/** Asserts that the given values conform to the specs in CDD 7.6.1 */
- private void assertMinMemoryMb(Context context, long minMb) {
- ActivityManager activityManager =
- (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ private void assertMinMemoryMb(Context context) {
+ ActivityManager activityManager = context.getSystemService(ActivityManager.class);
long totalMemoryMb = getTotalMemory(activityManager) / 1024 / 1024;
- Log.i(TAG, String.format("minMb=%,d", minMb));
- Log.i(TAG, String.format("totalMemoryMb=%,d", totalMemoryMb));
+ Log.i(TAG, String.format("Total device memory = %,d MB", totalMemoryMb));
if (Utils.isPerfClass()) {
+ long minMb = Utils.isTPerfClass() ? MIN_MEMORY_PERF_CLASS_T_MB :
+ Utils.MIN_MEMORY_PERF_CLASS_CANDIDATE_MB;
+ Log.i(TAG, String.format("Minimum required memory = %,d MB", minMb));
assertTrue(String.format("Does not meet minimum memory requirements (CDD 7.6.1)."
+ "Found = %d, Minimum = %d", totalMemoryMb, minMb), totalMemoryMb >= minMb);
} else {
- int pc = totalMemoryMb >= minMb ? Build.VERSION_CODES.S : 0;
- DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", "MinMemory");
- log.addValue("MemoryMB", totalMemoryMb, ResultType.LOWER_BETTER, ResultUnit.NONE);
+ int pc = 0;
+ if (totalMemoryMb >= MIN_MEMORY_PERF_CLASS_T_MB)
+ pc = Build.VERSION_CODES.TIRAMISU;
+ else if (totalMemoryMb >= MIN_MEMORY_PERF_CLASS_CANDIDATE_MB)
+ pc = Build.VERSION_CODES.S;
+ DeviceReportLog log = new DeviceReportLog("MediaPerformanceClassLogs", "MinMemory");
+ log.addValue("MemoryMB", totalMemoryMb, ResultType.HIGHER_BETTER, ResultUnit.NONE);
log.setSummary("CDD 2.2.7.3/7.6.1/H-1-1,H-2-1 performance_class", pc,
- ResultType.NEUTRAL, ResultUnit.NONE);
+ ResultType.HIGHER_BETTER, ResultUnit.NONE);
log.submit(InstrumentationRegistry.getInstrumentation());
}
-
}
/**
diff --git a/tests/mediapc/src/android/mediapc/cts/Utils.java b/tests/mediapc/src/android/mediapc/cts/Utils.java
index ec50c22..6ad6146 100644
--- a/tests/mediapc/src/android/mediapc/cts/Utils.java
+++ b/tests/mediapc/src/android/mediapc/cts/Utils.java
@@ -17,6 +17,7 @@
package android.mediapc.cts;
import static android.util.DisplayMetrics.DENSITY_400;
+import static org.junit.Assume.assumeTrue;
import android.app.ActivityManager;
import android.content.Context;
@@ -27,12 +28,10 @@
import android.util.Log;
import android.view.WindowManager;
-import com.android.compatibility.common.util.ApiLevelUtil;
-
-import static org.junit.Assume.assumeTrue;
-
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiLevelUtil;
+
/**
* Test utilities.
@@ -53,6 +52,8 @@
// Media performance requires 6 GB minimum RAM, but keeping the following to 5 GB
// as activityManager.getMemoryInfo() returns around 5.4 GB on a 6 GB device.
public static final long MIN_MEMORY_PERF_CLASS_CANDIDATE_MB = 5 * 1024;
+ // Android T Media performance requires 8 GB min RAM, so setting lower as above
+ public static final long MIN_MEMORY_PERF_CLASS_T_MB = 7 * 1024;
static {
sPc = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S) ? Build.VERSION.MEDIA_PERFORMANCE_CLASS
diff --git a/tests/sample/AndroidTest.xml b/tests/sample/AndroidTest.xml
index c3731f3..408fccc 100644
--- a/tests/sample/AndroidTest.xml
+++ b/tests/sample/AndroidTest.xml
@@ -15,6 +15,8 @@
-->
<configuration description="Config for CTS Sample test cases">
<option name="test-suite-tag" value="cts" />
+ <!-- Change the value field of `component` into an appropriate one.
+ See README for the full list. -->
<option name="config-descriptor:metadata" key="component" value="misc" />
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/tests/sample/OWNERS b/tests/sample/OWNERS
index 7782fbe..d354e30 100644
--- a/tests/sample/OWNERS
+++ b/tests/sample/OWNERS
@@ -1,10 +1,7 @@
# Bug component: 346961
diqian@google.com
+fangqiu@google.com
fdeng@google.com
-moonk@google.com
normancheung@google.com
-williamgoh@google.com
peykov@google.com
-yichunli@google.com
-yimingpan@google.com
-
+yimingpan@google.com
\ No newline at end of file
diff --git a/tests/sample/README b/tests/sample/README
new file mode 100644
index 0000000..3ab3544
--- /dev/null
+++ b/tests/sample/README
@@ -0,0 +1,15 @@
+This 'sample' folder is a sample which illustrates the basic structure and contents of a CTS module.
+
+Future users can refer to this folder to create their own CTS modules.
+
+Several things to notice:
+ 1. The users should update the `misc` value in
+ `<option name="config-descriptor:metadata" key="component" value="misc" />`
+ of the 'AndroidTest.xml' file into an appropriate group for the module they created.
+
+ The list of all available groups:
+ <https://cs.android.com/android/platform/superproject/+/master:cts/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/CtsConfigLoadingTest.java;l=66>.
+
+ 2. If the module is added outside the 'cts/' folder, the user should also 1) add the module
+ directory into the ayeaye checker (as shown in cl/423435565), and 2) add an OWNERS file in the
+ module directory accordingly.
\ No newline at end of file
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java b/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
index 0970b2a..5fa5252 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceReportLogTest.java
@@ -16,24 +16,27 @@
package android.sample.cts;
import android.sample.SampleDeviceActivity;
-import android.test.ActivityInstrumentationTestCase2;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
/**
- * WARNING: This sample test is out of date. Newer tests should be written using
- * androidx testing libraries. See SampleJUnit4DeviceTest.java
- *
- * TODO(b/211678773): Update the test to use androidx testing libraries.
- *
* A simple compatibility test which includes results in the report.
*
* This class has 3 no-op tests that create report logs and log fake metrics.
*/
-public class SampleDeviceReportLogTest
- extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
+@RunWith(AndroidJUnit4.class)
+public class SampleDeviceReportLogTest {
/**
* Name of the report log. Test metrics will be written out to ths report. The name must match
@@ -56,19 +59,13 @@
private static final String END_TAG = "actual_end";
/**
- * Constructor which passes the class of the activity to be instrumented.
- */
- public SampleDeviceReportLogTest() {
- super(SampleDeviceActivity.class);
- }
-
- /**
* Sample test that creates and logs test metrics into a report log.
*/
+ @Test
public void testMultiplication() {
// Perform test.
int product = MULTIPLICATION_NUMBER_1 * MULTIPLICATION_NUMBER_2;
- assertTrue("Multiplication result do not match", product == MULTIPLICATION_RESULT);
+ Assert.assertTrue("Multiplication result do not match", product == MULTIPLICATION_RESULT);
// Log metrics from the test.
String streamName = "test_multiplication";
@@ -77,12 +74,13 @@
ResultUnit.NONE);
reportLog.addValue(ACTUAL_PRODUCT_TAG, 1.0 * product, ResultType.NEUTRAL, ResultUnit.NONE);
reportLog.setSummary(ACTUAL_PRODUCT_TAG, 1.0 * product, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.submit(getInstrumentation());
+ reportLog.submit(InstrumentationRegistry.getInstrumentation());
}
/**
* Sample test to check counting up.
*/
+ @Test
public void testCountUp() {
String streamName = "test_count_up";
countHelper(1, streamName);
@@ -91,6 +89,7 @@
/**
* Sample test to check counting down.
*/
+ @Test
public void testCountDown() {
String streamName = "test_count_down";
countHelper(2, streamName);
@@ -125,6 +124,6 @@
reportLog.addValue(START_TAG, 1.0 * start, ResultType.NEUTRAL, ResultUnit.NONE);
reportLog.addValue(END_TAG, 1.0 * end, ResultType.NEUTRAL, ResultUnit.NONE);
reportLog.setSummary(END_TAG, 1.0 * end, ResultType.NEUTRAL, ResultUnit.NONE);
- reportLog.submit(getInstrumentation());
+ reportLog.submit(InstrumentationRegistry.getInstrumentation());
}
}
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
index 8c4a97d..4798f5e 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceResultTest.java
@@ -16,7 +16,15 @@
package android.sample.cts;
import android.sample.SampleDeviceActivity;
-import android.test.ActivityInstrumentationTestCase2;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.MeasureRun;
@@ -29,18 +37,12 @@
import java.util.Random;
/**
- * WARNING: This sample test is out of date. Newer tests should be written using
- * androidx testing libraries. See SampleJUnit4DeviceTest.java
- *
- * TODO(b/211678773): Update the test to use androidx testing libraries.
- *
- * A simple compatibility test which includes results in the report.
- *
* A simple compatibility test which includes results in the report.
*
* This test measures the time taken to run a workload and adds in the report.
*/
-public class SampleDeviceResultTest extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
+@RunWith(AndroidJUnit4.class)
+public class SampleDeviceResultTest {
/**
* Name of the report log to store test metrics.
@@ -58,15 +60,9 @@
private static final Random random = new Random(12345);
/**
- * Constructor which passes the class of the activity to be instrumented.
- */
- public SampleDeviceResultTest() {
- super(SampleDeviceActivity.class);
- }
-
- /**
* Measures the time taken to sort an array.
*/
+ @Test
public void testSort() throws Exception {
// MeasureTime runs the workload N times and records the time taken by each run.
double[] result = MeasureTime.measure(REPEAT, new MeasureRun() {
@@ -82,7 +78,7 @@
@Override
public void run(int i) throws Exception {
Arrays.sort(array);
- assertTrue("Array not sorted", isSorted(array));
+ Assert.assertTrue("Array not sorted", isSorted(array));
}
});
// Compute the stats.
@@ -97,7 +93,7 @@
// Set a summary.
reportLog.setSummary("average", stat.mAverage, ResultType.LOWER_BETTER, ResultUnit.MS);
// Submit the report to the given instrumentation.
- reportLog.submit(getInstrumentation());
+ reportLog.submit(InstrumentationRegistry.getInstrumentation());
}
/**
diff --git a/tests/sample/src/android/sample/cts/SampleDeviceTest.java b/tests/sample/src/android/sample/cts/SampleDeviceTest.java
index 653bb47..3ea4881 100644
--- a/tests/sample/src/android/sample/cts/SampleDeviceTest.java
+++ b/tests/sample/src/android/sample/cts/SampleDeviceTest.java
@@ -16,20 +16,23 @@
package android.sample.cts;
import android.sample.SampleDeviceActivity;
-import android.test.ActivityInstrumentationTestCase2;
+
+import androidx.test.rule.ActivityTestRule;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Assert;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
- * WARNING: This sample test is out of date. Newer tests should be written using
- * androidx testing libraries. See SampleJUnit4DeviceTest.java
- *
- * TODO(b/211678773): This test can be probably removed.
- *
* A simple compatibility test which tests the SharedPreferences API.
*
- * This test uses {@link android.test.ActivityInstrumentationTestCase2} to instrument the
+ * This test uses {@link ActivityTestRule} to instrument the
* {@link android.sample.SampleDeviceActivity}.
*/
-public class SampleDeviceTest extends ActivityInstrumentationTestCase2<SampleDeviceActivity> {
+@RunWith(AndroidJUnit4.class)
+public class SampleDeviceTest {
private static final String KEY = "foo";
@@ -38,28 +41,9 @@
/**
* A reference to the activity whose shared preferences are being tested.
*/
- private SampleDeviceActivity mActivity;
-
- public SampleDeviceTest() {
- super(SampleDeviceActivity.class);
- }
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- // Start the activity and get a reference to it.
- mActivity = getActivity();
- // Wait for the UI Thread to become idle.
- getInstrumentation().waitForIdleSync();
- }
-
- @Override
- protected void tearDown() throws Exception {
- // Scrub the activity so it can be freed. The next time the setUp will create a new activity
- // rather than reusing the old one.
- mActivity = null;
- super.tearDown();
- }
+ @Rule
+ public ActivityTestRule<SampleDeviceActivity> mActivityRule =
+ new ActivityTestRule(SampleDeviceActivity.class);
/**
* Tests the SharedPreferences API.
@@ -69,13 +53,16 @@
*
* @throws Exception
*/
+ @Test
public void testSharedPreferences() throws Exception {
// Save the key value pair to the preferences and assert they were saved.
- mActivity.savePreference(KEY, VALUE);
- assertEquals("Preferences were not saved", VALUE, mActivity.getPreference(KEY));
+ mActivityRule.getActivity().savePreference(KEY, VALUE);
+ Assert.assertEquals("Preferences were not saved", VALUE,
+ mActivityRule.getActivity().getPreference(KEY));
// Clear the shared preferences and assert the data was removed.
- mActivity.clearPreferences();
- assertNull("Preferences were not cleared", mActivity.getPreference(KEY));
+ mActivityRule.getActivity().clearPreferences();
+ Assert.assertNull("Preferences were not cleared",
+ mActivityRule.getActivity().getPreference(KEY));
}
}
diff --git a/tests/sample/src/android/sample/cts/SampleJUnit4DeviceTest.java b/tests/sample/src/android/sample/cts/SampleJUnit4DeviceTest.java
deleted file mode 100755
index 3aa0cb0..0000000
--- a/tests/sample/src/android/sample/cts/SampleJUnit4DeviceTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.sample.cts;
-
-import android.sample.SampleDeviceActivity;
-
-import androidx.test.rule.ActivityTestRule;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Assert;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * A simple compatibility test which tests the SharedPreferences API.
- *
- * This test uses {@link ActivityTestRule} to instrument the
- * {@link android.sample.SampleDeviceActivity}.
- */
-@RunWith(AndroidJUnit4.class)
-public class SampleJUnit4DeviceTest {
-
- private static final String KEY = "foo";
-
- private static final String VALUE = "bar";
-
- @Rule
- public ActivityTestRule<SampleDeviceActivity> mActivityRule =
- new ActivityTestRule(SampleDeviceActivity.class);
-
-
- /**
- * This inserts the key value pair and assert they can be retrieved. Then it clears the
- * preferences and asserts they can no longer be retrieved.
- *
- * @throws Exception
- */
- @Test
- public void shouldSaveSharedPreferences() throws Exception {
- // Save the key value pair to the preferences and assert they were saved.
- mActivityRule.getActivity().savePreference(KEY, VALUE);
- Assert.assertEquals("Preferences were not saved", VALUE,
- mActivityRule.getActivity().getPreference(KEY));
-
- // Clear the shared preferences and assert the data was removed.
- mActivityRule.getActivity().clearPreferences();
- Assert.assertNull("Preferences were not cleared",
- mActivityRule.getActivity().getPreference(KEY));
- }
-}
diff --git a/tests/signature/api-check/Android.bp b/tests/signature/api-check/Android.bp
index b3fd278..c95cf4a 100644
--- a/tests/signature/api-check/Android.bp
+++ b/tests/signature/api-check/Android.bp
@@ -33,6 +33,7 @@
// androidx.test.runner depends on android.test classes from this library.
"android.test.base-minus-junit",
"androidx.test.runner",
+ "compatibility-device-util-axt",
"cts-signature-common",
],
}
@@ -54,18 +55,6 @@
compile_multilib: "both",
}
-// Defaults for signature api checks with dynamic config.
-java_defaults {
- name: "signature-api-check-dynamic-config-defaults",
- defaults: ["signature-api-check-defaults"],
- defaults_visibility: [
- "//cts/tests/signature:__subpackages__",
- ],
- static_libs: [
- "cts-signature-with-dynamic-config",
- ],
-}
-
// Filegroup containing the jarjar rules that need to be applied to any test that checks for
// accessibility (or inaccesibility) of android.test and junit classes from the android.test.base
// and android.test.runner libraries.
@@ -103,7 +92,7 @@
// Defaults for hiddenapi blocklist checks.
java_defaults {
name: "hiddenapi-blocklist-check-defaults",
- defaults: ["signature-api-check-dynamic-config-defaults"],
+ defaults: ["signature-api-check-defaults"],
java_resources: [
":platform-bootclasspath{hiddenapi-flags.csv}",
":cts-api-hiddenapi-filter-csv"
diff --git a/tests/signature/api-check/android-test-base-29-api/Android.bp b/tests/signature/api-check/android-test-base-29-api/Android.bp
index d151a19..a4def69 100644
--- a/tests/signature/api-check/android-test-base-29-api/Android.bp
+++ b/tests/signature/api-check/android-test-base-29-api/Android.bp
@@ -33,6 +33,14 @@
],
min_sdk_version: "29",
+ // Prevent android.test.runner and android.test.mock classes being available at runtime by
+ // excluding them from the list of libraries that are implicitly added to the manifest.
+ // Otherwise, the test would break as it is not expecting those classes to be available.
+ exclude_uses_libs: [
+ "android.test.mock",
+ "android.test.runner",
+ ],
+
use_embedded_native_libs: false,
test_suites: [
"cts",
diff --git a/tests/signature/api-check/android-test-base-29-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-29-api/AndroidTest.xml
index d7986be..ff65060 100644
--- a/tests/signature/api-check/android-test-base-29-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-29-api/AndroidTest.xml
@@ -34,7 +34,16 @@
<option name="package" value="android.signature.cts.api.android_test_base_29" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.api29.test.SignatureTest" />
+ <!--
+ ! android.test.base classes must be accessible to this test as this test's targetSdkVersion
+ ! is 29 which provided the classes by default on the bootclasspath.
+ !-->
<option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api.gz" />
+ <!--
+ ! android.test.mock and android.test.runner classes must not be accessible to this test as
+ ! they are only provided when specifically requested using a <uses-library> element in the
+ ! manifest.
+ !-->
<option name="instrumentation-arg" key="unexpected-api-files" value="android-test-runner-current.api.gz,android-test-mock-current.api.gz" />
<option name="runtime-hint" value="5s" />
<!-- Disable hidden API checks (http://b/171459260). -->
diff --git a/tests/signature/api-check/android-test-base-current-api/Android.bp b/tests/signature/api-check/android-test-base-current-api/Android.bp
index cdf3b45..737dde0 100644
--- a/tests/signature/api-check/android-test-base-current-api/Android.bp
+++ b/tests/signature/api-check/android-test-base-current-api/Android.bp
@@ -32,6 +32,16 @@
":cts-android-test-runner-current-api-gz",
],
+ // Prevent android.test.base, android.test.runner and android.test.mock classes being available
+ // at runtime by excluding them from the list of libraries that are implicitly added to the
+ // manifest. Otherwise, the test would break as it is not expecting those classes to be
+ // available.
+ exclude_uses_libs: [
+ "android.test.base",
+ "android.test.runner",
+ "android.test.mock",
+ ],
+
use_embedded_native_libs: false,
test_suites: [
"cts",
diff --git a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
index ad566a4..dc72d87 100644
--- a/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-current-api/AndroidTest.xml
@@ -31,6 +31,11 @@
<option name="package" value="android.signature.cts.api.android_test_base_current" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.current.test.SignatureTest" />
+ <!--
+ ! android.test.base, android.test.mock and android.test.runner classes must NOT be
+ ! accessible to this test as the android.test.base classes are no longer provided by
+ ! default and the other libraries were never provided by default.
+ !-->
<option name="instrumentation-arg" key="unexpected-api-files" value="android-test-base-current.api.gz,android-test-runner-current.api.gz,android-test-mock-current.api.gz" />
<option name="runtime-hint" value="5s" />
<!-- Disable hidden API checks (http://b/171459260). -->
diff --git a/tests/signature/api-check/android-test-base-uses-library-api/Android.bp b/tests/signature/api-check/android-test-base-uses-library-api/Android.bp
index b38c0d5..708d430 100644
--- a/tests/signature/api-check/android-test-base-uses-library-api/Android.bp
+++ b/tests/signature/api-check/android-test-base-uses-library-api/Android.bp
@@ -33,6 +33,14 @@
],
min_sdk_version: "30",
+ // Prevent android.test.mock and android.test.runner classes being available at runtime by
+ // excluding them from the list of libraries that are implicitly added to the manifest.
+ // Otherwise, the test would break as it is not expecting those classes to be available.
+ exclude_uses_libs: [
+ "android.test.mock",
+ "android.test.runner",
+ ],
+
use_embedded_native_libs: false,
test_suites: [
"cts",
diff --git a/tests/signature/api-check/android-test-base-uses-library-api/AndroidTest.xml b/tests/signature/api-check/android-test-base-uses-library-api/AndroidTest.xml
index dd32c49..c945e3f 100644
--- a/tests/signature/api-check/android-test-base-uses-library-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-base-uses-library-api/AndroidTest.xml
@@ -32,7 +32,16 @@
<option name="package" value="android.signature.cts.api.android_test_base_uses_library" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.uses_library.test.base.SignatureTest" />
+ <!--
+ ! android.test.base classes must be accessible to this test as this test specifically
+ ! requests them using a <uses-library android:name="android.test.base"/> in its manifest.
+ !-->
<option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api.gz" />
+ <!--
+ ! android.test.mock and android.test.runner classes must not be accessible to this test as
+ ! they are only provided when specifically requested using a <uses-library> element in the
+ ! manifest.
+ !-->
<option name="instrumentation-arg" key="unexpected-api-files" value="android-test-runner-current.api.gz,android-test-mock-current.api.gz" />
<option name="runtime-hint" value="5s" />
<!-- Disable hidden API checks (http://b/171459260). -->
diff --git a/tests/signature/api-check/android-test-mock-current-api/Android.bp b/tests/signature/api-check/android-test-mock-current-api/Android.bp
index 52fbe50..63e6bf6 100644
--- a/tests/signature/api-check/android-test-mock-current-api/Android.bp
+++ b/tests/signature/api-check/android-test-mock-current-api/Android.bp
@@ -21,8 +21,23 @@
defaults: [
"signature-api-check-defaults",
],
+
+ // Ensure that any android.test and junit classes embedded within this test do not conflict with
+ // the classes provided by the android.test.base or android.test.runner shared libraries.
+ jarjar_rules: ":cts-android-test-jarjar-rules",
+
java_resources: [
+ ":cts-android-test-base-current-api-gz",
":cts-android-test-mock-current-api-gz",
+ ":cts-android-test-runner-current-api-gz",
+ ],
+
+ // Prevent android.test.base and android.test.runner classes being available at runtime by
+ // excluding them from the list of libraries that are implicitly added to the manifest.
+ // Otherwise, the test would break as it is not expecting those classes to be available.
+ exclude_uses_libs: [
+ "android.test.base",
+ "android.test.runner",
],
use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
index a312b8a..6c7c2a7 100644
--- a/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-mock-current-api/AndroidTest.xml
@@ -27,7 +27,17 @@
<option name="package" value="android.signature.cts.api.android_test_mock_current" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.current.mock.SignatureTest" />
+ <!--
+ ! android.test.mock classes must be accessible to this test as this test specifically
+ ! requests them using a <uses-library android:name="android.test.mock"/> in its manifest.
+ !-->
<option name="instrumentation-arg" key="expected-api-files" value="android-test-mock-current.api.gz" />
+ <!--
+ ! android.test.base and android.test.runner classes must not be accessible to this test as
+ ! they are only provided when specifically requested using a <uses-library> element in the
+ ! manifest.
+ !-->
+ <option name="instrumentation-arg" key="unexpected-api-files" value="android-test-base-current.api.gz,android-test-runner-current.api.gz" />
<option name="runtime-hint" value="5s" />
<!-- Disable hidden API checks (http://b/171459260). -->
<option name="hidden-api-checks" value="false" />
diff --git a/tests/signature/api-check/android-test-runner-current-api/Android.bp b/tests/signature/api-check/android-test-runner-current-api/Android.bp
index 45b3d4f..f6e3e63 100644
--- a/tests/signature/api-check/android-test-runner-current-api/Android.bp
+++ b/tests/signature/api-check/android-test-runner-current-api/Android.bp
@@ -32,6 +32,15 @@
":cts-android-test-runner-current-api-gz",
],
+ // Prevent android.test.base and android.test.mock libraries from being implicitly added to
+ // the manifest. Their classes should still be available at runtime as a dependency on
+ // android.test.runner should automatically add a dependency on android.test.base and
+ // android.test.mock.
+ exclude_uses_libs: [
+ "android.test.base",
+ "android.test.mock",
+ ],
+
use_embedded_native_libs: false,
test_suites: [
"cts",
diff --git a/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml b/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
index 550e70e..1c406b3 100644
--- a/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
+++ b/tests/signature/api-check/android-test-runner-current-api/AndroidTest.xml
@@ -27,6 +27,11 @@
<option name="package" value="android.signature.cts.api.android_test_runner_current" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.current.runner.SignatureTest" />
+ <!--
+ ! android.test.base, android.test.mock and android.test.runner classes must NOT be
+ ! accessible to this test as the android.test.base classes are no longer provided by
+ ! default and the other libraries were never provided by default.
+ !-->
<option name="instrumentation-arg" key="expected-api-files" value="android-test-base-current.api.gz,android-test-mock-current.api.gz,android-test-runner-current.api.gz" />
<option name="runtime-hint" value="5s" />
<!-- Disable hidden API checks (http://b/171459260). -->
diff --git a/tests/signature/api-check/current-api/Android.bp b/tests/signature/api-check/current-api/Android.bp
index 4114272..88bce59 100644
--- a/tests/signature/api-check/current-api/Android.bp
+++ b/tests/signature/api-check/current-api/Android.bp
@@ -23,9 +23,6 @@
],
java_resources: [
":cts-current-api-gz",
- ":cts-android-test-base-current-api-gz",
- ":cts-android-test-mock-current-api-gz",
- ":cts-android-test-runner-current-api-gz",
],
use_embedded_native_libs: false,
diff --git a/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java
index 13ea0f1..c940aac 100644
--- a/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-27-api/src/android/signature/cts/api/api27/HiddenApiTest.java
@@ -16,7 +16,5 @@
package android.signature.cts.api.api27;
-import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
-
-public class HiddenApiTest extends DynamicConfigHiddenApiTest {
+public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
}
diff --git a/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java
index 091a25f..f85dda3 100644
--- a/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-28-api/src/android/signature/cts/api/api28/HiddenApiTest.java
@@ -16,7 +16,5 @@
package android.signature.cts.api.api28;
-import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
-
-public class HiddenApiTest extends DynamicConfigHiddenApiTest {
+public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
}
diff --git a/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java
index 7726489..34f33fe 100644
--- a/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-current-api/src/android/signature/cts/api/current/HiddenApiTest.java
@@ -16,7 +16,5 @@
package android.signature.cts.api.current;
-import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
-
-public class HiddenApiTest extends DynamicConfigHiddenApiTest {
+public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
}
diff --git a/tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java
index 9266976..c8dcfca 100644
--- a/tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-debug-class/src/android/signature/cts/api/blocklist/debug/DebugClassHiddenApiTest.java
@@ -17,11 +17,12 @@
package android.signature.cts.api.blocklist.debug;
import android.signature.cts.DexMemberChecker;
-import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
-public class DebugClassHiddenApiTest extends DynamicConfigHiddenApiTest {
+import static org.junit.Assert.assertFalse;
+
+public class DebugClassHiddenApiTest extends android.signature.cts.api.HiddenApiTest {
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
// Try to exempt DexMemberChecker class from hidden API checks.
diff --git a/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java b/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
index 3fe708c..b30bbcb 100644
--- a/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
+++ b/tests/signature/api-check/hidden-api-blocklist-test-api/src/android/signature/cts/api/test/HiddenApiTest.java
@@ -17,10 +17,9 @@
package android.signature.cts.api.test;
import android.signature.cts.DexMember;
-import android.signature.cts.api.dynamic.DynamicConfigHiddenApiTest;
import java.util.Set;
-public class HiddenApiTest extends DynamicConfigHiddenApiTest {
+public class HiddenApiTest extends android.signature.cts.api.HiddenApiTest {
/**
* Override to match only those members that specify both test-api and blocked.
@@ -30,5 +29,4 @@
Set<String> flags = member.getHiddenapiFlags();
return flags.contains("test-api") && flags.contains("blocked");
}
-
}
diff --git a/tests/signature/api-check/shared-libs-api/Android.bp b/tests/signature/api-check/shared-libs-api/Android.bp
index 42db95c..afab2f3 100644
--- a/tests/signature/api-check/shared-libs-api/Android.bp
+++ b/tests/signature/api-check/shared-libs-api/Android.bp
@@ -36,7 +36,8 @@
jarjar_rules: ":cts-android-test-jarjar-rules",
java_resources: [
- ":CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all.api",
+ ":CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all-current.api",
+ ":CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all-previous.api",
],
static_libs: [
"cts-api-signature-multilib-test",
@@ -59,8 +60,57 @@
srcs: ["src/**/*.java"],
}
+// Generates a zip file containing the current public and system API files for shared libraries.
genrule {
- name: "CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all.api",
+ name: "CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all-current.api",
+ srcs: [
+ ":android.net.ipsec.ike{.public.api.txt}",
+ ":android.net.ipsec.ike{.system.api.txt}",
+ ":com.android.future.usb.accessory{.public.api.txt}",
+ ":com.android.future.usb.accessory{.system.api.txt}",
+ ":com.android.libraries.tv.tvsystem{.public.api.txt}",
+ ":com.android.libraries.tv.tvsystem{.system.api.txt}",
+ ":com.android.location.provider{.public.api.txt}",
+ ":com.android.location.provider{.system.api.txt}",
+ ":com.android.mediadrm.signer{.public.api.txt}",
+ ":com.android.mediadrm.signer{.system.api.txt}",
+ ":com.android.media.remotedisplay{.public.api.txt}",
+ ":com.android.media.remotedisplay{.system.api.txt}",
+ ":com.android.media.tv.remoteprovider{.public.api.txt}",
+ ":com.android.media.tv.remoteprovider{.system.api.txt}",
+ ":com.android.nfc_extras{.public.api.txt}",
+ ":com.android.nfc_extras{.system.api.txt}",
+ ":javax.obex{.public.api.txt}",
+ ":javax.obex{.system.api.txt}",
+ ],
+ tools: [
+ "soong_zip",
+ "metalava",
+ ],
+ out: [
+ "shared-libs-all-current.api.zip",
+ ],
+ cmd: "mkdir -p $(genDir)/list && " +
+ "for f in $(in); do " +
+ // Extract the module name from the path.
+ " fileName=$$(basename $${f} .txt) && " +
+ " fileName=$${fileName%%.stubs.source*} && " +
+ // Extract the api level, i.e. public|system from the path.
+ " apiLevel=$${f##*.stubs.source} && " +
+ " apiLevel=$${apiLevel#.} && " +
+ " apiLevel=$${apiLevel%_api.txt} && " +
+ " if [ -z $${apiLevel} ]; then apiLevel=public; fi && " +
+ // Convert the .txt file into its XML representation.
+ " $(location metalava) -J--add-opens=java.base/java.util=ALL-UNNAMED --no-banner " +
+ " -convert2xmlnostrip $${f} $(genDir)/list/$${fileName}-current-$${apiLevel}.api; " +
+ "done && " +
+ "$(location soong_zip) -o $(out) -C $(genDir)/list -D $(genDir)/list",
+}
+
+// Generates a zip file containing all the API files from previous releases >= 28 excluding the
+// android.txt and removed files.
+genrule {
+ name: "CtsSharedLibsApiSignatureTestCases_cts-shared-libs-all-previous.api",
srcs: [
":prebuilt_sdk_system_public_api_txt",
],
@@ -69,7 +119,7 @@
"metalava",
],
out: [
- "shared-libs-all.api.zip",
+ "shared-libs-all-previous.api.zip",
],
cmd: "for f in $(in); do " +
" fileName=$$(basename $${f} .txt) && " +
@@ -82,4 +132,4 @@
" -convert2xmlnostrip $${f} $(genDir)/list/$${fileName}-$${platformSdkVersion}-$${apiLevel}.api; " +
"done && " +
"$(location soong_zip) -o $(out) -C $(genDir)/list -D $(genDir)/list",
-}
\ No newline at end of file
+}
diff --git a/tests/signature/api-check/shared-libs-api/AndroidTest.xml b/tests/signature/api-check/shared-libs-api/AndroidTest.xml
index 7203269..bef3c0a 100644
--- a/tests/signature/api-check/shared-libs-api/AndroidTest.xml
+++ b/tests/signature/api-check/shared-libs-api/AndroidTest.xml
@@ -27,7 +27,8 @@
<option name="package" value="android.signature.cts.api.shared_libs" />
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="class" value="android.signature.cts.api.SignatureMultiLibsTest" />
- <option name="instrumentation-arg" key="expected-api-files" value="shared-libs-all.api.zip" />
+ <option name="instrumentation-arg" key="expected-api-files" value="shared-libs-all-current.api.zip" />
+ <option name="instrumentation-arg" key="previous-api-files" value="shared-libs-all-previous.api.zip" />
<option name="runtime-hint" value="30s" />
<!-- Disable hidden API checks (http://b/171459260). -->
<option name="hidden-api-checks" value="false" />
diff --git a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
index 651c2de..c16bd04 100644
--- a/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
+++ b/tests/signature/api-check/shared-libs-api/src/android/signature/cts/api/SignatureMultiLibsTest.java
@@ -16,13 +16,20 @@
package android.signature.cts.api;
+import android.app.Instrumentation;
import android.signature.cts.ApiComplianceChecker;
import android.signature.cts.ApiDocumentParser;
import android.signature.cts.VirtualPath;
import android.signature.cts.VirtualPath.LocalFilePath;
+import androidx.test.platform.app.InstrumentationRegistry;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
+import org.junit.BeforeClass;
+import org.junit.Test;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
@@ -38,22 +45,35 @@
private static final String TAG = SignatureMultiLibsTest.class.getSimpleName();
+ private static Set<String> libraries;
+
+ /**
+ * Obtain a list of shared libraries from the device.
+ */
+ @BeforeClass
+ public static void retrieveListOfSharedLibrariesOnDevice() throws Exception {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ String result = runShellCommand(instrumentation, "cmd package list libraries");
+ libraries = Arrays.stream(result.split("\n")).map(line -> line.split(":")[1])
+ .peek(library -> System.out.printf("%s: Found library: %s%n",
+ SignatureMultiLibsTest.class.getSimpleName(), library))
+ .collect(Collectors.toCollection(TreeSet::new));
+ }
+
/**
* Tests that the device's API matches the expected set defined in xml.
* <p/>
* Will check the entire API, and then report the complete list of failures
*/
+ @Test
public void testSignature() {
runWithTestResultObserver(mResultObserver -> {
-
ApiComplianceChecker complianceChecker =
new ApiComplianceChecker(mResultObserver, mClassProvider);
ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
- parseApiResourcesAsStream(apiDocumentParser,
- Stream.concat(Arrays.stream(expectedApiFiles), Arrays.stream(previousApiFiles))
- .toArray(String[]::new))
+ parseApiResourcesAsStream(apiDocumentParser, expectedApiFiles)
.forEach(complianceChecker::checkSignatureCompliance);
// After done parsing all expected API files, perform any deferred checks.
@@ -62,17 +82,23 @@
}
/**
- * Get all the shared libraries available on the device.
- *
- * @return a stream of available shared library names.
+ * Tests that the device's API matches the previous APIs defined in xml.
*/
- private Stream<String> getLibraries() {
- try {
- String result = runShellCommand(getInstrumentation(), "cmd package list libraries");
- return Arrays.stream(result.split("\n")).map(line -> line.split(":")[1]);
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ @Test
+ public void testPreviousSignatures() {
+ runWithTestResultObserver(mResultObserver -> {
+ ApiComplianceChecker complianceChecker =
+ new ApiComplianceChecker(mResultObserver, mClassProvider);
+
+ ApiDocumentParser apiDocumentParser = new ApiDocumentParser(TAG);
+
+ parseApiResourcesAsStream(apiDocumentParser, previousApiFiles)
+ .map(clazz -> clazz.setPreviousApiFlag(true))
+ .forEach(complianceChecker::checkSignatureCompliance);
+
+ // After done parsing all expected API files, perform any deferred checks.
+ complianceChecker.checkDeferred();
+ });
}
/**
@@ -84,7 +110,17 @@
*/
private boolean checkLibrary (String name) {
String libraryName = name.substring(name.lastIndexOf('/') + 1).split("-")[0];
- return getLibraries().anyMatch(libraryName::equals);
+ boolean matched = libraries.contains(libraryName);
+ if (matched) {
+ System.out.printf("%s: Processing API file %s, from library %s as it does match a"
+ + " shared library on this device%n",
+ getClass().getSimpleName(), name, libraryName);
+ } else {
+ System.out.printf("%s: Ignoring API file %s, from library %s as it does not match a"
+ + " shared library on this device%n",
+ getClass().getSimpleName(), name, libraryName);
+ }
+ return matched;
}
/**
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
index 8150904..5bfe0bb 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/AbstractApiTest.java
@@ -31,23 +31,35 @@
import android.util.Log;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.compatibility.common.util.DynamicConfigDeviceSide;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.StandardOpenOption;
import java.util.Collection;
import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
import java.util.stream.Stream;
import java.util.zip.ZipFile;
-import junit.framework.TestCase;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
/**
+ * Base class for the signature tests.
*/
-public class AbstractApiTest extends TestCase {
+@RunWith(AndroidJUnit4.class)
+public abstract class AbstractApiTest {
+
+ /**
+ * The name of the optional instrumentation option that contains the name of the dynamic config
+ * data set that contains the expected failures.
+ */
+ private static final String DYNAMIC_CONFIG_NAME_OPTION = "dynamic-config-name";
private static final String TAG = "SignatureTest";
@@ -76,9 +88,8 @@
Settings.Global.HIDDEN_API_POLICY);
}
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mResultObserver = new TestResultObserver();
// Get the arguments passed to the instrumentation.
@@ -90,10 +101,9 @@
Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS),
getExpectedBlocklistExemptions(),
getGlobalExemptions());
- assertEquals(
+ assertNull(
String.format("Device in bad state: %s is not as expected",
Settings.Global.HIDDEN_API_POLICY),
- null,
getGlobalHiddenApiPolicy());
@@ -105,17 +115,25 @@
new BootClassPathClassesProvider(),
name -> name != null && name.startsWith("com.android.internal.R."));
+ String dynamicConfigName = instrumentationArgs.getString(DYNAMIC_CONFIG_NAME_OPTION);
+ if (dynamicConfigName != null) {
+ // Get the DynamicConfig.xml contents and extract the expected failures list.
+ DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(dynamicConfigName);
+ Collection<String> expectedFailures = dcds.getValues("expected_failures");
+ initExpectedFailures(expectedFailures);
+ }
+
initializeFromArgs(instrumentationArgs);
}
/**
* Initialize the expected failures.
*
- * <p>Call from with {@code #initializeFromArgs}</p>
+ * <p>Call from with {@link #setUp()}</p>
*
* @param expectedFailures the expected failures.
*/
- protected void initExpectedFailures(Collection<String> expectedFailures) {
+ private void initExpectedFailures(Collection<String> expectedFailures) {
this.expectedFailures = expectedFailures;
String tag = getClass().getName();
Log.d(tag, "Expected failure count: " + expectedFailures.size());
@@ -129,7 +147,6 @@
}
protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
-
}
protected interface RunnableWithResultObserver {
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
index 427f62d..2f77728 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/BaseKillswitchTest.java
@@ -23,13 +23,14 @@
import android.signature.cts.DexMemberChecker;
import android.signature.cts.DexMethod;
import android.signature.cts.FailureType;
+import org.junit.Test;
public abstract class BaseKillswitchTest extends AbstractApiTest {
protected String mErrorMessageAppendix;
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
DexMemberChecker.init();
}
@@ -43,18 +44,22 @@
private final static Predicate<DexMember> FIELD_FILTER =
dexMember -> (dexMember instanceof DexField);
+ @Test
public void testKillswitchMechanismMethodsThroughReflection() {
doTestKillswitchMechanism(METHOD_FILTER, /* reflection= */ true, /* jni= */ false);
}
+ @Test
public void testKillswitchMechanismMethodsThroughJni() {
doTestKillswitchMechanism(METHOD_FILTER, /* reflection= */ false, /* jni= */ true);
}
+ @Test
public void testKillswitchMechanismFieldsThroughReflection() {
doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ true, /* jni= */ false);
}
+ @Test
public void testKillswitchMechanismFieldsThroughJni() {
doTestKillswitchMechanism(FIELD_FILTER, /* reflection= */ false, /* jni= */ true);
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java
index 7a5e900..84fabca 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/DebugClassKillswitchTest.java
@@ -18,9 +18,11 @@
import android.signature.cts.DexMemberChecker;
+import static org.junit.Assert.assertTrue;
+
public class DebugClassKillswitchTest extends BaseKillswitchTest {
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mErrorMessageAppendix = " to exempted DexMemberChecker class";
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
index 97ae404..9082c47 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/HiddenApiTest.java
@@ -31,6 +31,7 @@
import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;
+import org.junit.Test;
/**
* Checks that it is not possible to access hidden APIs.
@@ -51,7 +52,7 @@
}
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
DexMemberChecker.init();
loadFilters();
@@ -65,18 +66,22 @@
private final static Predicate<DexMember> FIELD_FILTER =
dexMember -> (dexMember instanceof DexField);
+ @Test
public void testSignatureMethodsThroughReflection() {
doTestSignature(METHOD_FILTER,/* reflection= */ true, /* jni= */ false);
}
+ @Test
public void testSignatureMethodsThroughJni() {
doTestSignature(METHOD_FILTER, /* reflection= */ false, /* jni= */ true);
}
+ @Test
public void testSignatureFieldsThroughReflection() {
doTestSignature(FIELD_FILTER, /* reflection= */ true, /* jni= */ false);
}
+ @Test
public void testSignatureFieldsThroughJni() {
doTestSignature(FIELD_FILTER, /* reflection= */ false, /* jni= */ true);
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SdkListKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SdkListKillswitchTest.java
index 9e85b92..fc667eb 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SdkListKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SdkListKillswitchTest.java
@@ -18,7 +18,7 @@
public class SdkListKillswitchTest extends BaseKillswitchTest {
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mErrorMessageAppendix = " when global setting hidden_api_blacklist_exemptions is \"L\"";
}
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
index 4a0e2c2..1be75ca 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/SignatureTest.java
@@ -28,6 +28,7 @@
import java.util.TreeSet;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import org.junit.Test;
/**
* Performs the signature check via a JUnit test.
@@ -60,6 +61,7 @@
* <p/>
* Will check the entire API, and then report the complete list of failures
*/
+ @Test
public void testSignature() {
runWithTestResultObserver(mResultObserver -> {
Set<JDiffClassDescription> unexpectedClasses = loadUnexpectedClasses();
diff --git a/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java b/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java
index 1cdd7d9..8eb31c6 100644
--- a/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java
+++ b/tests/signature/api-check/src/java/android/signature/cts/api/WildcardKillswitchTest.java
@@ -18,7 +18,7 @@
public class WildcardKillswitchTest extends BaseKillswitchTest {
@Override
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
super.setUp();
mErrorMessageAppendix = " when global setting hidden_api_blacklist_exemptions is \"*\"";
}
diff --git a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
index bdc5b2a..e6d5b06 100644
--- a/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
+++ b/tests/signature/api-check/system-annotation/src/java/android/signature/cts/api/AnnotationTest.java
@@ -32,6 +32,7 @@
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.function.Predicate;
+import org.junit.Test;
/**
* Checks that parts of the device's API that are annotated (e.g. with android.annotation.SystemApi)
@@ -40,7 +41,6 @@
public class AnnotationTest extends AbstractApiTest {
private static final String TAG = AnnotationTest.class.getSimpleName();
- private static final String MODULE_NAME = "CtsSystemApiAnnotationTestCases";
private String[] mExpectedApiFiles;
private String mAnnotationForExactMatch;
@@ -49,11 +49,6 @@
protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
mExpectedApiFiles = getCommaSeparatedListRequired(instrumentationArgs, "expected-api-files");
mAnnotationForExactMatch = instrumentationArgs.getString("annotation-for-exact-match");
-
- // Get the DynamicConfig.xml contents and extract the expected failures list.
- DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(MODULE_NAME);
- List<String> expectedFailures = dcds.getValues("expected_failures");
- initExpectedFailures(expectedFailures);
}
private Predicate<? super JDiffClassDescription> androidAutoClassesFilter() {
@@ -69,6 +64,7 @@
* Tests that the parts of the device's API that are annotated (e.g. with
* android.annotation.SystemApi) match the API definition.
*/
+ @Test
public void testAnnotation() {
AnnotationChecker.ResultFilter filter = new AnnotationChecker.ResultFilter() {
@Override
diff --git a/tests/signature/api-check/system-api/Android.bp b/tests/signature/api-check/system-api/Android.bp
index 0c3d2a5..7263c84 100644
--- a/tests/signature/api-check/system-api/Android.bp
+++ b/tests/signature/api-check/system-api/Android.bp
@@ -19,14 +19,12 @@
android_test {
name: "CtsSystemApiSignatureTestCases",
- defaults: ["signature-api-check-dynamic-config-defaults"],
+ defaults: ["signature-api-check-defaults"],
java_resources: [
":CtsSystemApiSignatureTestCases_system-all.api",
":cts-current-api-gz",
":cts-system-current-api-gz",
":cts-system-removed-api-gz",
- ":cts-android-test-mock-current-api-gz",
- ":cts-android-test-runner-current-api-gz",
],
test_suites: [
"cts",
diff --git a/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java b/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java
index e523152..1997826 100644
--- a/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java
+++ b/tests/signature/api-check/system-api/src/android/signature/cts/api/system/SignatureTest.java
@@ -16,7 +16,5 @@
package android.signature.cts.api.system;
-import java.android.signature.cts.api.dynamic.DynamicConfigSignatureTest;
-
-public class SignatureTest extends DynamicConfigSignatureTest {
+public class SignatureTest extends android.signature.cts.api.SignatureTest {
}
diff --git a/tests/signature/api-check/with-dynamic-config/Android.bp b/tests/signature/api-check/with-dynamic-config/Android.bp
deleted file mode 100644
index bdeb878..0000000
--- a/tests/signature/api-check/with-dynamic-config/Android.bp
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2021 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Compat.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-java_library {
- name: "cts-signature-with-dynamic-config",
- visibility: [
- "//cts/tests/signature:__subpackages__",
- ],
- static_libs: [
- "cts-api-signature-test",
- "compatibility-device-util-axt",
- ],
- srcs: ["src/java/**/*.java"],
-}
diff --git a/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigHiddenApiTest.java b/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigHiddenApiTest.java
deleted file mode 100644
index 1c3dfbc..0000000
--- a/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigHiddenApiTest.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.signature.cts.api.dynamic;
-
-import android.os.Bundle;
-import android.signature.cts.api.HiddenApiTest;
-import android.signature.cts.api.SignatureTest;
-import androidx.test.InstrumentationRegistry;
-import com.android.compatibility.common.util.DynamicConfigDeviceSide;
-import java.util.Collection;
-
-/**
- * A hidden API test that supports the use of dynamic config.
- */
-public class DynamicConfigHiddenApiTest extends HiddenApiTest {
-
- /**
- * The name of the optional instrumentation option that contains the name of the dynamic config
- * data set that contains the expected failures.
- */
- private static final String DYNAMIC_CONFIG_NAME_OPTION = "dynamic-config-name";
-
- @Override
- protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
- super.initializeFromArgs(instrumentationArgs);
-
- String dynamicConfigName = instrumentationArgs.getString(DYNAMIC_CONFIG_NAME_OPTION);
- if (dynamicConfigName != null) {
- // Get the DynamicConfig.xml contents and extract the expected failures list.
- DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(dynamicConfigName);
- Collection<String> expectedFailures = dcds.getValues("expected_failures");
- initExpectedFailures(expectedFailures);
- }
- }
-}
diff --git a/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigSignatureTest.java b/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigSignatureTest.java
deleted file mode 100644
index 9c57a1e..0000000
--- a/tests/signature/api-check/with-dynamic-config/src/java/android/signature/cts/api/dynamic/DynamicConfigSignatureTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package java.android.signature.cts.api.dynamic;
-
-import android.os.Bundle;
-import android.signature.cts.api.SignatureTest;
-import androidx.test.InstrumentationRegistry;
-import com.android.compatibility.common.util.DynamicConfigDeviceSide;
-import java.util.Collection;
-
-/**
- * A signature test that supports the use of dynamic config.
- */
-public class DynamicConfigSignatureTest extends SignatureTest {
-
- /**
- * The name of the optional instrumentation option that contains the name of the dynamic config
- * data set that contains the expected failures.
- */
- private static final String DYNAMIC_CONFIG_NAME_OPTION = "dynamic-config-name";
-
- @Override
- protected void initializeFromArgs(Bundle instrumentationArgs) throws Exception {
- super.initializeFromArgs(instrumentationArgs);
-
- String dynamicConfigName = instrumentationArgs.getString(DYNAMIC_CONFIG_NAME_OPTION);
- if (dynamicConfigName != null) {
- // Get the DynamicConfig.xml contents and extract the expected failures list.
- DynamicConfigDeviceSide dcds = new DynamicConfigDeviceSide(dynamicConfigName);
- Collection<String> expectedFailures = dcds.getValues("expected_failures");
- initExpectedFailures(expectedFailures);
- }
- }
-}
diff --git a/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java b/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
index fe67157..d38e51e 100644
--- a/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/ApiComplianceChecker.java
@@ -31,23 +31,6 @@
*/
public class ApiComplianceChecker extends ApiPresenceChecker {
- /**
- * A set of method signatures whose abstract modifier should be ignored.
- *
- * <p>If a class is not intended to be created or extended by application developers and all
- * instances are created and supplied by Android itself then the abstract modifier has no
- * impact on runtime compatibility.
- */
- private static final Set<String> IGNORE_METHOD_ABSTRACT_MODIFIER_WHITE_LIST = new HashSet<>();
- static {
- // This method was previously abstract and is now not abstract. As the
- // CtsSystemApiSignatureTestCases package tests both the old and new specifications, with
- // and without the abstract modifier this needs to ignore the abstract modifier.
- IGNORE_METHOD_ABSTRACT_MODIFIER_WHITE_LIST.add(
- "public int android.service.euicc.EuiccService.onDownloadSubscription("
- + "int,android.telephony.euicc.DownloadableSubscription,boolean,boolean)");
- }
-
/** Indicates that the class is an annotation. */
private static final int CLASS_MODIFIER_ANNOTATION = 0x00002000;
@@ -120,21 +103,89 @@
}
/**
- * Check if it is allowed that a class is in previous system Api and changed to abstract class
- * in current API.
+ * Check if the class definition is from a previous API and was neither instantiable nor
+ * extensible through that API.
+ *
+ * <p>Such a class is more flexible in how it can be modified than other classes as there is
+ * no way to either create or extend the class.</p>
+ *
+ * <p>A class that has no constructors in the API cannot be instantiated or extended. Such a
+ * class has a lot more flexibility when it comes to making forwards compatible changes than
+ * other classes. e.g. Normally, a non-final class cannot be made final as that would break any
+ * code that extended the class but if there are no constructors in the API then it is
+ * impossible to extend it through the API so making it final is forwards compatible.</p>
+ *
+ * <p>Similarly, a concrete class cannot normally be made abstract as that would break any code
+ * that attempted to instantiate it but if there are no constructors in the API then it is
+ * impossible to instantiate it so making it abstract is forwards compatible.</p>
+ *
+ * <p>Finally, a non-static class cannot normally be made static (or vice versa) as that would
+ * break any code that attemped to instantiate it but if there are no constructors in the API
+ * then it is impossible to instantiate so changing the static flag is forwards compatible.</p>
+ *
+ * <p>In a similar fashion the abstract and final (but not static) modifier can be added to a
+ * method on this type of class.</p>
+ *
+ * <p>In this case forwards compatible is restricted to compile time and runtime behavior. It
+ * does not cover testing. e.g. making a class that was previously non-final could break tests
+ * that relied on mocking that class. However, that is a non-standard use of the API and so we
+ * are not strictly required to maintain compatibility in that case. It should also only be a
+ * minor issue as most mocking libraries support mocking final classes now.</p>
+ *
* @param classDescription a description of a class in an API.
- * @param runtimeClass the runtime class corresponding to {@code classDescription}.
- * @return true if the change is allowed.
*/
- private static boolean isAllowedClassAbstractionFromPreviousSystemApi(
- JDiffClassDescription classDescription, Class<?> runtimeClass) {
- // Allow a class that was previously final and had no visible constructors,
- // (so could not be instantiated or extended) to be changed to an abstract class.
+ private static boolean classIsNotInstantiableOrExtensibleInPreviousApi(
+ JDiffClassDescription classDescription) {
return classDescription.getConstructors().isEmpty()
- && (classDescription.getModifier() & Modifier.FINAL) != 0
- && (classDescription.getModifier() & Modifier.ABSTRACT) == 0
- && classDescription.isPreviousApi()
- && (runtimeClass.getModifiers() & Modifier.ABSTRACT) != 0;
+ && classDescription.isPreviousApi();
+ }
+
+ /**
+ * If a modifier (final or abstract) has been removed since the previous API was published then
+ * it is forwards compatible so clear the modifier flag in the previous API modifiers so that it
+ * does not cause a mismatch.
+ *
+ * @param previousModifiers The set of modifiers for the previous API.
+ * @param currentModifiers The set of modifiers for the current implementation class.
+ * @return the normalized previous modifiers.
+ */
+ private static int normalizePreviousModifiersIfModifierIsRemoved(
+ int previousModifiers, int currentModifiers, int... flags) {
+ for (int flag : flags) {
+ // If the flag was present in the previous API but is no longer present then the
+ // modifier has been removed.
+ if ((previousModifiers & flag) != 0 && (currentModifiers & flag) == 0) {
+ previousModifiers &= ~flag;
+ }
+ }
+
+ return previousModifiers;
+ }
+
+ /**
+ * If a modifier (final or abstract) has been added since the previous API was published then
+ * this treats it as forwards compatible and clears the modifier flag in the current API
+ * modifiers so that it does not cause a mismatch.
+ *
+ * <p>This must only be called when adding one of the supplied modifiers is forwards compatible,
+ * e.g. when called on a class or methods from a class that returns true for
+ * {@link #classIsNotInstantiableOrExtensibleInPreviousApi(JDiffClassDescription)}.</p>
+ *
+ * @param previousModifiers The set of modifiers for the previous API.
+ * @param currentModifiers The set of modifiers for the current implementation class.
+ * @return the normalized current modifiers.
+ */
+ private static int normalizeCurrentModifiersIfModifierIsAdded(
+ int previousModifiers, int currentModifiers, int... flags) {
+ for (int flag : flags) {
+ // If the flag was not present in the previous API but is present then the modifier has
+ // been added.
+ if ((previousModifiers & flag) == 0 && (currentModifiers & flag) != 0) {
+ currentModifiers &= ~flag;
+ }
+ }
+
+ return currentModifiers;
}
/**
@@ -149,22 +200,11 @@
int reflectionModifiers = runtimeClass.getModifiers();
int apiModifiers = classDescription.getModifier();
- // If the api class isn't abstract
- if (((apiModifiers & Modifier.ABSTRACT) == 0) &&
- // but the reflected class is
- ((reflectionModifiers & Modifier.ABSTRACT) != 0) &&
- // interfaces are implicitly abstract (JLS 9.1.1.1)
- classDescription.getClassType() != JDiffClassDescription.JDiffType.INTERFACE &&
- // and it isn't an enum
- !classDescription.isEnumType() &&
- // and it isn't allowed previous api final class with no visible ctor
- !isAllowedClassAbstractionFromPreviousSystemApi(classDescription, runtimeClass)) {
- // that is a problem
- return "description is abstract but class is not and is not an enum";
+ // If the api class is an interface then always treat it as abstract.
+ // interfaces are implicitly abstract (JLS 9.1.1.1)
+ if (classDescription.getClassType() == JDiffClassDescription.JDiffType.INTERFACE) {
+ apiModifiers |= Modifier.ABSTRACT;
}
- // ABSTRACT check passed, so mask off ABSTRACT
- reflectionModifiers &= ~Modifier.ABSTRACT;
- apiModifiers &= ~Modifier.ABSTRACT;
if (classDescription.isAnnotation()) {
reflectionModifiers &= ~CLASS_MODIFIER_ANNOTATION;
@@ -179,21 +219,32 @@
// override a method from the class cannot be marked as final because those constants
// are represented as a subclass. As enum classes cannot be extended (except for its own
// constants) there is no benefit in checking final modifier so just ignore them.
- reflectionModifiers &= ~Modifier.FINAL;
- apiModifiers &= ~Modifier.FINAL;
+ //
+ // Ditto for abstract.
+ reflectionModifiers &= ~(Modifier.FINAL | Modifier.ABSTRACT);
+ apiModifiers &= ~(Modifier.FINAL | Modifier.ABSTRACT);
}
- // Allow previous final API to be changed to abstract or static, and other modifiers should
- // not be changed.
- boolean isAllowedPreviousApiModifierChange =
- isAllowedClassAbstractionFromPreviousSystemApi(classDescription, runtimeClass)
- && (apiModifiers & ~Modifier.FINAL) != 0
- && (reflectionModifiers & ~(Modifier.ABSTRACT | Modifier.STATIC))
- == (apiModifiers & ~Modifier.FINAL);
+ if (classDescription.isPreviousApi()) {
+ // If the final and/or abstract modifiers have been removed since the previous API was
+ // published then that is forwards compatible so remove the modifier in the previous API
+ // modifiers so they match the runtime modifiers.
+ apiModifiers = normalizePreviousModifiersIfModifierIsRemoved(
+ apiModifiers, reflectionModifiers, Modifier.FINAL, Modifier.ABSTRACT);
+
+ if (classIsNotInstantiableOrExtensibleInPreviousApi(classDescription)) {
+ // Adding the final, abstract or static flags to the runtime class is forwards
+ // compatible as the class cannot be instantiated or extended. Clear the flags for
+ // any such added modifier from the current implementation's modifiers so that it
+ // does not cause a mismatch.
+ reflectionModifiers = normalizeCurrentModifiersIfModifierIsAdded(
+ apiModifiers, reflectionModifiers,
+ Modifier.FINAL, Modifier.ABSTRACT, Modifier.STATIC);
+ }
+ }
if ((reflectionModifiers == apiModifiers)
- && (classDescription.isEnumType() == runtimeClass.isEnum())
- || isAllowedPreviousApiModifierChange) {
+ && (classDescription.isEnumType() == runtimeClass.isEnum())) {
return null;
} else {
return String.format("modifier mismatch - description (%s), class (%s)",
@@ -473,16 +524,6 @@
@Override
protected void checkMethod(JDiffClassDescription classDescription, Class<?> runtimeClass,
JDiffClassDescription.JDiffMethod methodDescription, Method method) {
- if (method.isVarArgs()) {
- methodDescription.mModifier |= METHOD_MODIFIER_VAR_ARGS;
- }
- if (method.isBridge()) {
- methodDescription.mModifier |= METHOD_MODIFIER_BRIDGE;
- }
- if (method.isSynthetic()) {
- methodDescription.mModifier |= METHOD_MODIFIER_SYNTHETIC;
- }
-
// FIXME: A workaround to fix the final mismatch on enumeration
if (runtimeClass.isEnum() && methodDescription.mName.equals("values")) {
return;
@@ -491,12 +532,6 @@
String reason;
if ((reason = areMethodsModifierCompatible(
classDescription, methodDescription, method)) != null) {
- // Allow previous API method to be changed to abstract
- if (isAllowedClassAbstractionFromPreviousSystemApi(classDescription, runtimeClass)
- && (method.getModifiers() & ~(Modifier.ABSTRACT))
- == methodDescription.mModifier) {
- return;
- }
resultObserver.notifyFailure(FailureType.MISMATCH_METHOD,
methodDescription.toReadableString(classDescription.getAbsoluteClassName()),
String.format("Non-compatible method found when looking for %s - because %s",
@@ -520,17 +555,15 @@
JDiffClassDescription.JDiffMethod apiMethod,
Method reflectedMethod) {
- // Mask off NATIVE since it is a don't care. Also mask off
- // SYNCHRONIZED since it is not considered API significant (b/112626813)
- int ignoredMods = (Modifier.NATIVE | Modifier.SYNCHRONIZED | Modifier.STRICT);
+ // Mask off NATIVE since it is a don't care.
+ // Mask off SYNCHRONIZED since it is not considered API significant (b/112626813)
+ // Mask off STRICT as it has no effect (b/26082535)
+ // Mask off SYNTHETIC, VARARGS and BRIDGE as they are not represented in the API.
+ int ignoredMods = (Modifier.NATIVE | Modifier.SYNCHRONIZED | Modifier.STRICT |
+ METHOD_MODIFIER_SYNTHETIC | METHOD_MODIFIER_VAR_ARGS | METHOD_MODIFIER_BRIDGE);
int reflectionModifiers = reflectedMethod.getModifiers() & ~ignoredMods;
int apiModifiers = apiMethod.mModifier & ~ignoredMods;
- // A method can become non-abstract
- if ((reflectionModifiers & Modifier.ABSTRACT) == 0) {
- apiModifiers &= ~Modifier.ABSTRACT;
- }
-
// We can ignore FINAL for classes
if ((classDescription.getModifier() & Modifier.FINAL) != 0) {
reflectionModifiers &= ~Modifier.FINAL;
@@ -538,9 +571,21 @@
}
String genericString = reflectedMethod.toGenericString();
- if (IGNORE_METHOD_ABSTRACT_MODIFIER_WHITE_LIST.contains(genericString)) {
- reflectionModifiers &= ~Modifier.ABSTRACT;
- apiModifiers &= ~Modifier.ABSTRACT;
+ if (classDescription.isPreviousApi()) {
+ // If the final and/or abstract modifiers have been removed since the previous API was
+ // published then that is forwards compatible so remove the modifier in the previous API
+ // modifiers so they match the runtime modifiers.
+ apiModifiers = normalizePreviousModifiersIfModifierIsRemoved(
+ apiModifiers, reflectionModifiers, Modifier.FINAL, Modifier.ABSTRACT);
+
+ if (classIsNotInstantiableOrExtensibleInPreviousApi(classDescription)) {
+ // Adding the final, or abstract flags to the runtime method is forwards compatible
+ // as the class cannot be instantiated or extended. Clear the flags for any such
+ // added modifier from the current implementation's modifiers so that it does not
+ // cause a mismatch.
+ reflectionModifiers = normalizeCurrentModifiersIfModifierIsAdded(
+ apiModifiers, reflectionModifiers, Modifier.FINAL, Modifier.ABSTRACT);
+ }
}
if (reflectionModifiers == apiModifiers) {
diff --git a/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java b/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java
index 7c590e1..ab66aa8 100644
--- a/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java
+++ b/tests/signature/lib/common/src/android/signature/cts/JDiffClassDescription.java
@@ -516,7 +516,7 @@
*
* @param extendsClass the class being extended.
*/
- void setExtendsClass(String extendsClass) {
+ public void setExtendsClass(String extendsClass) {
mExtendedClass = extendsClass;
}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java
index 13b5fd9..aa0da74 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/AnnotationCheckerTest.java
@@ -83,29 +83,29 @@
*/
@Test
public void testDetectUnauthorizedConstructorApi() {
- ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_CONSTRUCTOR);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_CONSTRUCTOR)) {
+ JDiffClassDescription clz = createClass("SystemApiClass");
+ // (omitted) addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
- JDiffClassDescription clz = createClass("SystemApiClass");
- // (omitted) addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.PublicApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.PublicApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_CONSTRUCTOR)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
- observer = new ExpectFailure(FailureType.EXTRA_CONSTRUCTOR);
+ // (omitted) addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
- clz = createClass("PublicApiClass");
- // (omitted) addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
+ addPublicBooleanField(clz, "apiField");
- checkSignatureCompliance(clz, observer,
+ checkSignatureCompliance(clz, observer,
"android.signature.cts.tests.data.SystemApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
}
/**
@@ -113,29 +113,27 @@
*/
@Test
public void testDetectUnauthorizedMethodApi() {
- ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_METHOD);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_METHOD)) {
+ JDiffClassDescription clz = createClass("SystemApiClass");
+ addConstructor(clz);
+ // (omitted) addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
- JDiffClassDescription clz = createClass("SystemApiClass");
- addConstructor(clz);
- // (omitted) addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.PublicApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.PublicApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_METHOD)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
+ addConstructor(clz);
+ // (omitted) addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
- observer = new ExpectFailure(FailureType.EXTRA_METHOD);
-
- clz = createClass("PublicApiClass");
- addConstructor(clz);
- // (omitted) addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
-
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.SystemApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.SystemApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
}
/**
@@ -143,29 +141,27 @@
*/
@Test
public void testDetectUnauthorizedFieldApi() {
- ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_FIELD);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_FIELD)) {
+ JDiffClassDescription clz = createClass("SystemApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ // (omitted) addPublicBooleanField(clz, "apiField");
- JDiffClassDescription clz = createClass("SystemApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- // (omitted) addPublicBooleanField(clz, "apiField");
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.PublicApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.PublicApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_FIELD)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ // (omitted) addPublicBooleanField(clz, "apiField");
- observer = new ExpectFailure(FailureType.EXTRA_FIELD);
-
- clz = createClass("PublicApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- // (omitted) addPublicBooleanField(clz, "apiField");
-
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.SystemApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.SystemApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
}
/**
@@ -173,28 +169,27 @@
*/
@Test
public void testDetectUnauthorizedClassApi() {
- ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_CLASS);
- JDiffClassDescription clz = createClass("SystemApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_CLASS)) {
+ JDiffClassDescription clz = createClass("SystemApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.PublicApiClass");
- // Note that ForciblyPublicizedPrivateClass is now included in the runtime classes
- observer.validate();
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.PublicApiClass");
+ // Note that ForciblyPublicizedPrivateClass is now included in the runtime classes
+ }
- observer = new ExpectFailure(FailureType.EXTRA_CLASS);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.EXTRA_CLASS)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
- clz = createClass("PublicApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
-
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.SystemApiClass");
- // Note that ForciblyPublicizedPrivateClass is now included in the runtime classes
- observer.validate();
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.SystemApiClass");
+ // Note that ForciblyPublicizedPrivateClass is now included in the runtime classes
+ }
}
/**
@@ -243,44 +238,41 @@
*/
@Test
public void testDetectMissingAnnotation() {
- ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
+ addConstructor(clz, "int"); // this is not annotated
- JDiffClassDescription clz = createClass("PublicApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
- addConstructor(clz, "int"); // this is not annotated
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.SystemApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.SystemApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
+ addPublicVoidMethod(clz, "privateMethod"); // this is not annotated
- observer = new ExpectFailure(FailureType.MISSING_ANNOTATION);
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.SystemApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
- clz = createClass("PublicApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
- addPublicVoidMethod(clz, "privateMethod"); // this is not annotated
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION)) {
+ JDiffClassDescription clz = createClass("PublicApiClass");
+ addConstructor(clz);
+ addPublicVoidMethod(clz, "apiMethod");
+ addPublicBooleanField(clz, "apiField");
+ addPublicBooleanField(clz, "privateField"); // this is not annotated
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.SystemApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
-
- observer = new ExpectFailure(FailureType.MISSING_ANNOTATION);
-
- clz = createClass("PublicApiClass");
- addConstructor(clz);
- addPublicVoidMethod(clz, "apiMethod");
- addPublicBooleanField(clz, "apiField");
- addPublicBooleanField(clz, "privateField"); // this is not annotated
-
- checkSignatureCompliance(clz, observer,
- "android.signature.cts.tests.data.SystemApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
- observer.validate();
+ checkSignatureCompliance(clz, observer,
+ "android.signature.cts.tests.data.SystemApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
}
/**
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
index c4c87f5..7de9c9d 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ApiComplianceCheckerTest.java
@@ -25,6 +25,8 @@
import android.signature.cts.JDiffClassDescription;
import android.signature.cts.ResultObserver;
import android.signature.cts.tests.data.AbstractClass;
+import android.signature.cts.tests.data.AbstractClassWithCtor;
+import android.signature.cts.tests.data.ComplexEnum;
import android.signature.cts.tests.data.ExtendedNormalInterface;
import android.signature.cts.tests.data.NormalClass;
import android.signature.cts.tests.data.NormalInterface;
@@ -68,19 +70,18 @@
@Test
public void testMissingClass() {
- ExpectFailure observer = new ExpectFailure(FailureType.MISSING_CLASS);
- JDiffClassDescription clz = new JDiffClassDescription(
- "android.signature.cts.tests.data", "NoSuchClass");
- clz.setType(JDiffClassDescription.JDiffType.CLASS);
- checkSignatureCompliance(clz, observer);
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISSING_CLASS)) {
+ JDiffClassDescription clz = new JDiffClassDescription(
+ "android.signature.cts.tests.data", "NoSuchClass");
+ clz.setType(JDiffClassDescription.JDiffType.CLASS);
+ checkSignatureCompliance(clz, observer);
+ }
}
@Test
public void testSimpleConstructor() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
- JDiffClassDescription.JDiffConstructor constructor =
- new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PUBLIC);
+ JDiffClassDescription.JDiffConstructor constructor = ctor("NormalClass", Modifier.PUBLIC);
clz.addConstructor(constructor);
checkSignatureCompliance(clz);
assertEquals(constructor.toSignatureString(), "public NormalClass()");
@@ -89,8 +90,7 @@
@Test
public void testOneArgConstructor() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
- JDiffClassDescription.JDiffConstructor constructor =
- new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PRIVATE);
+ JDiffClassDescription.JDiffConstructor constructor = ctor("NormalClass", Modifier.PRIVATE);
constructor.addParam("java.lang.String");
clz.addConstructor(constructor);
checkSignatureCompliance(clz);
@@ -100,8 +100,7 @@
@Test
public void testConstructorThrowsException() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
- JDiffClassDescription.JDiffConstructor constructor =
- new JDiffClassDescription.JDiffConstructor("NormalClass", Modifier.PROTECTED);
+ JDiffClassDescription.JDiffConstructor constructor = ctor("NormalClass", Modifier.PROTECTED);
constructor.addParam("java.lang.String");
constructor.addParam("java.lang.String");
constructor.addException("android.signature.cts.tests.data.NormalException");
@@ -115,8 +114,7 @@
@Test
public void testPackageProtectedConstructor() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
- JDiffClassDescription.JDiffConstructor constructor =
- new JDiffClassDescription.JDiffConstructor("NormalClass", 0);
+ JDiffClassDescription.JDiffConstructor constructor = ctor("NormalClass", 0);
constructor.addParam("java.lang.String");
constructor.addParam("java.lang.String");
constructor.addParam("java.lang.String");
@@ -196,6 +194,51 @@
assertEquals(method.toSignatureString(), "public native void nativeMethod()");
}
+ /**
+ * Check that a varargs method is treated as compliant.
+ */
+ @Test
+ public void testVarargsMethod() {
+ JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
+ JDiffClassDescription.JDiffMethod method = method("varargs",
+ Modifier.PUBLIC, "void");
+ method.addParam("java.lang.String...");
+ clz.addMethod(method);
+ assertEquals(method.toSignatureString(), "public void varargs(java.lang.String...)");
+
+ checkSignatureCompliance(clz);
+ }
+
+ /**
+ * Check that a clone method (which produces a special method that is marked as {@code bridge}
+ * and {@code synthetic}) is treated as compliant.
+ */
+ @Test
+ public void testCloneMethod() {
+ JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
+ // The generic method:
+ // NormalClass clone() throws CloneNotSupportedException
+ JDiffClassDescription.JDiffMethod method = method("clone",
+ Modifier.PUBLIC, NormalClass.class.getName());
+ method.addException(CloneNotSupportedException.class.getName());
+ clz.addMethod(method);
+ assertEquals(method.toSignatureString(),
+ "public android.signature.cts.tests.data.NormalClass clone()"
+ + " throws java.lang.CloneNotSupportedException");
+
+ // The synthetic bridge method:
+ // Object clone() throws CloneNotSupportedException
+ method = method("clone",
+ Modifier.PUBLIC, Object.class.getName());
+ method.addException(CloneNotSupportedException.class.getName());
+ clz.addMethod(method);
+ assertEquals(method.toSignatureString(),
+ "public java.lang.Object clone()"
+ + " throws java.lang.CloneNotSupportedException");
+
+ checkSignatureCompliance(clz);
+ }
+
@Test
public void testFinalField() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
@@ -281,15 +324,16 @@
@Test
public void testFieldValueChanged() {
- ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_FIELD);
- JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
- JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
- "VALUE_FIELD", "java.lang.String",
- Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC, "\"✈\"");
- clz.addField(field);
- checkSignatureCompliance(clz, observer);
- assertEquals(field.toSignatureString(), "public static final java.lang.String VALUE_FIELD");
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_FIELD)) {
+ JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
+ JDiffClassDescription.JDiffField field = new JDiffClassDescription.JDiffField(
+ "VALUE_FIELD", "java.lang.String",
+ Modifier.PUBLIC | Modifier.FINAL | Modifier.STATIC, "\"✈\"");
+ clz.addField(field);
+ checkSignatureCompliance(clz, observer);
+ assertEquals(field.toSignatureString(),
+ "public static final java.lang.String VALUE_FIELD");
+ }
}
@Test
@@ -335,6 +379,25 @@
assertEquals(clz.toSignatureString(), "public interface NormalInterface");
}
+ /**
+ * Always treat interfaces as if they are abstract, even when the modifiers do not specify that.
+ */
+ @Test
+ public void testInterfaceAlwaysTreatAsAbstract() {
+ JDiffClassDescription clz = createInterface("NormalInterface");
+ clz.setModifier(Modifier.PUBLIC);
+ clz.addMethod(method("doSomething", Modifier.ABSTRACT | Modifier.PUBLIC, "void"));
+ checkSignatureCompliance(clz);
+ }
+
+ @Test
+ public void testComplexEnum() {
+ JDiffClassDescription clz = createClass(ComplexEnum.class.getSimpleName());
+ clz.setExtendsClass(Enum.class.getName());
+ clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+ checkSignatureCompliance(clz);
+ }
+
@Test
public void testFinalClass() {
JDiffClassDescription clz = new JDiffClassDescription(
@@ -345,6 +408,70 @@
assertEquals(clz.toSignatureString(), "public final class FinalClass");
}
+ @Test
+ public void testRemovingFinalFromAClass() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
+ clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ @Test
+ public void testRemovingFinalFromAClass_PreviousApi() {
+ JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
+ clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+ clz.setPreviousApiFlag(true);
+ checkSignatureCompliance(clz);
+ }
+
+ /**
+ * Test that if the API class is final but the runtime is abstract (and not final) that it is
+ * an error.
+ *
+ * http://b/181019981
+ */
+ @Test
+ public void testRemovingFinalFromAClassSwitchToAbstract() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ JDiffClassDescription clz = createClass(AbstractClass.class.getSimpleName());
+ clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * Test that if the API class in a previous release is final but the runtime is abstract (and
+ * not final) that it is not an error.
+ *
+ * http://b/181019981
+ */
+ @Test
+ public void testRemovingFinalFromAClassSwitchToAbstract_PreviousApi() {
+ JDiffClassDescription clz = createClass(AbstractClass.class.getSimpleName());
+ clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+ clz.setPreviousApiFlag(true);
+ checkSignatureCompliance(clz);
+ }
+
+ /**
+ * Test that if the API class in a previous release is final but the runtime is abstract (and
+ * not final) and has constructors then it is an error.
+ *
+ * http://b/181019981
+ */
+ @Test
+ public void testRemovingFinalFromAClassWithCtorSwitchToAbstract_PreviousApi() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ String simpleName = AbstractClassWithCtor.class.getSimpleName();
+ JDiffClassDescription clz = createClass(simpleName);
+ clz.setModifier(Modifier.PUBLIC | Modifier.FINAL);
+ clz.setPreviousApiFlag(true);
+ clz.addConstructor(ctor(simpleName, Modifier.PUBLIC));
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
/**
* Test the case where the API declares the method is synchronized, but it
* actually is not.
@@ -396,10 +523,25 @@
*/
@Test
public void testRemovingAbstractFromAClass() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ JDiffClassDescription clz = new JDiffClassDescription(
+ "android.signature.cts.tests.data", "NormalClass");
+ clz.setType(JDiffClassDescription.JDiffType.CLASS);
+ clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * Previous API lists class as abstract, reflection does not. http://b/1839622
+ */
+ @Test
+ public void testRemovingAbstractFromAClass_PreviousApi() {
JDiffClassDescription clz = new JDiffClassDescription(
"android.signature.cts.tests.data", "NormalClass");
clz.setType(JDiffClassDescription.JDiffType.CLASS);
clz.setModifier(Modifier.PUBLIC | Modifier.ABSTRACT);
+ clz.setPreviousApiFlag(true);
checkSignatureCompliance(clz);
}
@@ -408,10 +550,98 @@
*/
@Test
public void testAddingAbstractToAClass() {
- ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS);
- JDiffClassDescription clz = createClass("AbstractClass");
- checkSignatureCompliance(clz, observer);
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ JDiffClassDescription clz = createClass("AbstractClass");
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * The current API lists the class as being final but the runtime class does not so they are
+ * incompatible.
+ */
+ @Test
+ public void testAddingFinalToAClass() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ JDiffClassDescription clz = createClass("FinalClass");
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * A previously released API lists the class as being final but the runtime class does not.
+ *
+ * <p>While adding a final modifier to a class is not strictly backwards compatible it is when
+ * the class has no accessible constructors and so cannot be instantiated or extended, as is the
+ * case in this test.</p>
+ */
+ @Test
+ public void testAddingFinalToAClassNoCtor_PreviousApi() {
+ JDiffClassDescription clz = createClass("FinalClass");
+ clz.setPreviousApiFlag(true);
+ checkSignatureCompliance(clz);
+ }
+
+ /**
+ * A previously released API lists the class as being final but the runtime class does not.
+ *
+ * <p>Adding a final modifier to a class is not backwards compatible when the class has some
+ * accessible constructors and so could be instantiated and/or extended, as is the case of this
+ * class.</p>
+ */
+ @Test
+ public void testAddingFinalToAClassWithCtor_PreviousApi() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ String simpleName = "FinalClassWithCtor";
+ JDiffClassDescription clz = createClass(simpleName);
+ clz.setPreviousApiFlag(true);
+ clz.addConstructor(ctor(simpleName, Modifier.PUBLIC));
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * The current API lists the class as being static but the runtime class does not so they are
+ * incompatible.
+ */
+ @Test
+ public void testAddingStaticToInnerClass() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ JDiffClassDescription clz = createClass("AbstractClass.StaticNestedClass");
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * A previously released API lists the class as being static but the runtime class does not.
+ *
+ * <p>While adding a static modifier to a class is not strictly backwards compatible it is when
+ * the class has no accessible constructors and so cannot be instantiated or extended, as is the
+ * case in this test.</p>
+ */
+ @Test
+ public void testAddingStaticToInnerClassNoCtor_PreviousApi() {
+ JDiffClassDescription clz = createClass("AbstractClass.StaticNestedClass");
+ clz.setPreviousApiFlag(true);
+ checkSignatureCompliance(clz);
+ }
+
+ /**
+ * A previously released API lists the class as being static but the runtime class does not.
+ *
+ * <p>Adding a static modifier to a class is not backwards compatible when the class has some
+ * accessible constructors and so could be instantiated and/or extended, as is the case of this
+ * class.</p>
+ */
+ @Test
+ public void testAddingStaticToInnerClassWithCtor_PreviousApi() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_CLASS)) {
+ String simpleName = "AbstractClass.StaticNestedClassWithCtor";
+ JDiffClassDescription clz = createClass(simpleName);
+ clz.setPreviousApiFlag(true);
+ clz.addConstructor(ctor(simpleName, Modifier.PUBLIC));
+ checkSignatureCompliance(clz, observer);
+ }
}
/**
@@ -430,17 +660,36 @@
}
/**
- * Compatible (provide implementation for previous abstract method):
+ * Incompatible (provide implementation for abstract method):
*
* public abstract void Normal#notSyncMethod()
* -> public void Normal#notSyncMethod()
*/
@Test
public void testRemovingAbstractFromMethod() {
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD)) {
+ JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
+ JDiffClassDescription.JDiffMethod method = method("notSyncMethod",
+ Modifier.PUBLIC | Modifier.ABSTRACT, "void");
+ clz.addMethod(method);
+ checkSignatureCompliance(clz, observer);
+ }
+ }
+
+ /**
+ * A previously released API lists the method as being abstract but the runtime class does not.
+ *
+ * <p>While adding an abstract modifier to a method is not strictly backwards compatible it is
+ * when the class has no accessible constructors and so cannot be instantiated or extended, as
+ * is the case in this test.</p>
+ */
+ @Test
+ public void testRemovingAbstractFromMethodOnClassNoCtor_PreviousApi() {
JDiffClassDescription clz = createClass(NormalClass.class.getSimpleName());
JDiffClassDescription.JDiffMethod method = method("notSyncMethod",
Modifier.PUBLIC | Modifier.ABSTRACT, "void");
clz.addMethod(method);
+ clz.setPreviousApiFlag(true);
checkSignatureCompliance(clz);
}
@@ -456,8 +705,9 @@
JDiffClassDescription.JDiffMethod method = method("finalMethod",
Modifier.PUBLIC | Modifier.ABSTRACT, "void");
clz.addMethod(method);
- ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD);
- checkSignatureCompliance(clz, observer);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD)) {
+ checkSignatureCompliance(clz, observer);
+ }
}
/**
@@ -472,8 +722,9 @@
JDiffClassDescription.JDiffMethod method = method("abstractMethod",
Modifier.PUBLIC, "void");
clz.addMethod(method);
- ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD);
- checkSignatureCompliance(clz, observer);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD)) {
+ checkSignatureCompliance(clz, observer);
+ }
}
@Test
@@ -523,12 +774,13 @@
*/
@Test
public void testAddingFinalToAMethodInANonFinalClass() {
- ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD);
- JDiffClassDescription clz = createClass("NormalClass");
- JDiffClassDescription.JDiffMethod method = method("finalMethod", Modifier.PUBLIC, "void");
- clz.addMethod(method);
- checkSignatureCompliance(clz, observer);
- observer.validate();
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISMATCH_METHOD)) {
+ JDiffClassDescription clz = createClass("NormalClass");
+ JDiffClassDescription.JDiffMethod method = method("finalMethod", Modifier.PUBLIC,
+ "void");
+ clz.addMethod(method);
+ checkSignatureCompliance(clz, observer);
+ }
}
@Test
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java
index 2783bba..d7d5602 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ApiPresenceCheckerTest.java
@@ -112,6 +112,10 @@
return clz;
}
+ protected static JDiffClassDescription.JDiffConstructor ctor(String name, int modifiers) {
+ return new JDiffClassDescription.JDiffConstructor(name, modifiers);
+ }
+
protected static JDiffClassDescription.JDiffMethod method(
String name, int modifiers, String returnType) {
return new JDiffClassDescription.JDiffMethod(name, modifiers, returnType);
@@ -127,7 +131,7 @@
}
}
- protected static class ExpectFailure implements ResultObserver {
+ protected static class ExpectFailure implements ResultObserver, AutoCloseable {
private FailureType expectedType;
@@ -152,6 +156,11 @@
}
}
+ @Override
+ public void close() {
+ validate();
+ }
+
void validate() {
Assert.assertTrue(failureSeen);
}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java b/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java
index 789d54f..2251c9a 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/ExpectedFailuresFilterAnnotationCheckerTest.java
@@ -69,23 +69,23 @@
@Test
public void testIgnoreExpectedFailures_TestStillFails() {
- ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION);
+ try (ExpectFailure observer = new ExpectFailure(FailureType.MISSING_ANNOTATION)) {
+ ResultObserver filter = new ExpectedFailuresFilter(observer, Arrays.asList(
+ "extra_method:public void android.signature.cts.tests.data.SystemApiClass.apiMethod()",
+ "extra_field:public boolean android.signature.cts.tests.data.SystemApiClass.apiField"
+ ));
- ResultObserver filter = new ExpectedFailuresFilter(observer, Arrays.asList(
- "extra_method:public void android.signature.cts.tests.data.SystemApiClass.apiMethod()",
- "extra_field:public boolean android.signature.cts.tests.data.SystemApiClass.apiField"
- ));
+ // Define the API that is expected to be provided by the SystemApiClass. Omitted members
+ // are actually provided by the SytstemApiClass definition and so will result in an
+ // extra_... error.
+ JDiffClassDescription clz = createClass("SystemApiClass");
+ addConstructor(clz);
+ // (omitted) addPublicVoidMethod(clz, "apiMethod");
+ // (omitted) addPublicBooleanField(clz, "apiField");
- // Define the API that is expected to be provided by the SystemApiClass. Omitted members
- // are actually provided by the SytstemApiClass definition and so will result in an
- // extra_... error.
- JDiffClassDescription clz = createClass("SystemApiClass");
- addConstructor(clz);
- // (omitted) addPublicVoidMethod(clz, "apiMethod");
- // (omitted) addPublicBooleanField(clz, "apiField");
-
- checkSignatureCompliance(clz, filter,
- "android.signature.cts.tests.data.PublicApiClass",
- "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ checkSignatureCompliance(clz, filter,
+ "android.signature.cts.tests.data.PublicApiClass",
+ "android.signature.cts.tests.data.ForciblyPublicizedPrivateClass");
+ }
}
}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClass.java b/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClass.java
index 5fbbac1..25b90b7 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClass.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClass.java
@@ -22,4 +22,12 @@
public abstract class AbstractClass {
public abstract void abstractMethod();
public final void finalMethod() {};
+
+ public static class StaticNestedClass {
+ }
+
+ public static class StaticNestedClassWithCtor {
+ public StaticNestedClassWithCtor() {
+ }
+ }
}
diff --git a/tests/tests/media/src/android/media/cts/MockActivity.java b/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClassWithCtor.java
similarity index 61%
copy from tests/tests/media/src/android/media/cts/MockActivity.java
copy to tests/signature/tests/src/android/signature/cts/tests/data/AbstractClassWithCtor.java
index 028cfae..eb9c88a 100644
--- a/tests/tests/media/src/android/media/cts/MockActivity.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/data/AbstractClassWithCtor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 The Android Open Source Project
+ * Copyright (C) 2009 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,9 +14,13 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.signature.cts.tests.data;
-import android.app.Activity;
-
-public class MockActivity extends Activity {
+/**
+* This class is used as reference data for the JDiffClassDescriptionTest tests.
+*/
+public abstract class AbstractClassWithCtor {
+ public AbstractClassWithCtor() {}
+ public abstract void abstractMethod();
+ public final void finalMethod() {};
}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/data/ComplexEnum.java b/tests/signature/tests/src/android/signature/cts/tests/data/ComplexEnum.java
new file mode 100644
index 0000000..24e0f26
--- /dev/null
+++ b/tests/signature/tests/src/android/signature/cts/tests/data/ComplexEnum.java
@@ -0,0 +1,34 @@
+/*
+ * 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.signature.cts.tests.data;
+
+/**
+ * A complex enum that looks like it is concrete and final but is actually implemented at runtime
+ * as an abstract class.
+ */
+public enum ComplexEnum {
+
+ ONE() {
+ @Override
+ public void doSomething() {}
+ },
+ TWO() {
+ @Override
+ public void doSomething() {}
+ };
+
+ public abstract void doSomething();
+}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/data/FinalClassWithCtor.java b/tests/signature/tests/src/android/signature/cts/tests/data/FinalClassWithCtor.java
new file mode 100644
index 0000000..d46d39c
--- /dev/null
+++ b/tests/signature/tests/src/android/signature/cts/tests/data/FinalClassWithCtor.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2007 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.signature.cts.tests.data;
+
+/**
+ * This class is used as reference data for the
+ * JDiffClassDescriptionTest tests. These classes will actually be
+ * examined through reflection and Class.forName as part of testing
+ * JDiffClassDescription. That is why there is no implementation for
+ * any of these methods.
+ */
+public final class FinalClassWithCtor {
+ public FinalClassWithCtor() { }
+ public final void finalMethod() { }
+ public void nonFinalMethod() { }
+}
diff --git a/tests/signature/tests/src/android/signature/cts/tests/data/NormalClass.java b/tests/signature/tests/src/android/signature/cts/tests/data/NormalClass.java
index 4016bf6..b18cb54 100644
--- a/tests/signature/tests/src/android/signature/cts/tests/data/NormalClass.java
+++ b/tests/signature/tests/src/android/signature/cts/tests/data/NormalClass.java
@@ -41,6 +41,11 @@
public native void nativeMethod();
public void notNativeMethod() { }
public final void finalMethod() { }
+ public void varargs(String...args) { }
+ // Generate a synthetic bridge method.
+ public NormalClass clone() throws CloneNotSupportedException {
+ return (NormalClass) super.clone();
+ }
// Fields to test.
public final String FINAL_FIELD = "";
diff --git a/tests/tests/animation/src/android/animation/cts/AnimatorTest.java b/tests/tests/animation/src/android/animation/cts/AnimatorTest.java
index 7812478..7ba460a 100644
--- a/tests/tests/animation/src/android/animation/cts/AnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/AnimatorTest.java
@@ -26,6 +26,7 @@
import android.animation.ValueAnimator;
import android.app.Instrumentation;
import android.os.SystemClock;
+import android.platform.test.annotations.FlakyTest;
import android.view.animation.AccelerateInterpolator;
import androidx.test.InstrumentationRegistry;
@@ -101,6 +102,7 @@
assertTrue(mAnimator.isRunning());
}
+ @FlakyTest
@Test
public void testIsStarted() throws Throwable {
assertFalse(mAnimator.isRunning());
@@ -146,6 +148,7 @@
assertEquals(y, endY, 0.0f);
}
+ @FlakyTest
@Test
public void testSetListener() throws Throwable {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
index b9ffd34..eca0d96 100644
--- a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -38,6 +38,7 @@
import android.graphics.Path;
import android.graphics.PointF;
import android.os.SystemClock;
+import android.platform.test.annotations.FlakyTest;
import android.util.Property;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
@@ -141,6 +142,7 @@
assertEquals(animator.getPropertyName(), objAnimator.getPropertyName());
}
+ @FlakyTest
@Test
public void testOfInt() throws Throwable {
Object object = mActivity.view.newBall;
@@ -165,6 +167,7 @@
verify(mockListener, timeout(400)).onAnimationEnd(intAnimator, false);
}
+ @FlakyTest
@Test
public void testOfObject() throws Throwable {
Object object = mActivity.view.newBall;
@@ -296,6 +299,7 @@
assertEquals(propertyName, actualPropertyName);
}
+ @FlakyTest
@Test
public void testSetFloatValues() throws Throwable {
Object object = mActivity.view.newBall;
diff --git a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
index c82be8e..4dbdc51 100644
--- a/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
+++ b/tests/tests/animation/src/android/animation/cts/PropertyValuesHolderTest.java
@@ -37,6 +37,7 @@
import android.graphics.PointF;
import android.graphics.drawable.ShapeDrawable;
import android.os.SystemClock;
+import android.platform.test.annotations.FlakyTest;
import android.util.FloatProperty;
import android.util.Property;
import android.view.View;
@@ -116,6 +117,7 @@
assertEquals(pVHolder.getPropertyName(), cloneHolder.getPropertyName());
}
+ @FlakyTest
@Test
public void testSetValues() throws Throwable {
float[] dummyValues = {100, 150};
@@ -157,6 +159,7 @@
mActivityRule.runOnUiThread(() -> mActivity.startSingleAnimation(animator));
}
+ @FlakyTest
@Test
public void testResetValues() throws Throwable {
final float initialY = mActivity.view.newBall.getY();
@@ -227,6 +230,7 @@
assertEquals("Animation should run as expected", 100f, mActivity.view.newBall.getY(), 0.0f);
}
+ @FlakyTest
@Test
public void testOfFloat() throws Throwable {
float[] values = {mStartY, mEndY};
@@ -242,6 +246,7 @@
assertResults(yArray, mStartY, mEndY);
}
+ @FlakyTest
@Test
public void testOfFloat_Property() throws Throwable {
float[] values = {mStartY, mEndY};
@@ -259,6 +264,7 @@
assertResults(yArray, mStartY, mEndY);
}
+ @FlakyTest
@Test
public void testOfInt() throws Throwable {
int start = 0;
@@ -680,6 +686,7 @@
assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS));
}
+ @FlakyTest
@Test
public void testSetProperty() throws Throwable {
float[] values = {mStartY, mEndY};
diff --git a/tests/tests/appop/Android.bp b/tests/tests/appop/Android.bp
index 70b1a57..11fdcd6 100644
--- a/tests/tests/appop/Android.bp
+++ b/tests/tests/appop/Android.bp
@@ -82,7 +82,6 @@
"libbase",
"libbinder",
"libbpf_bcc",
- "libbpf_android",
"libc++",
"libcgrouprc",
"libcrypto",
diff --git a/tests/tests/batterysaving/AndroidManifest.xml b/tests/tests/batterysaving/AndroidManifest.xml
index 55e9050..c28fd40 100755
--- a/tests/tests/batterysaving/AndroidManifest.xml
+++ b/tests/tests/batterysaving/AndroidManifest.xml
@@ -19,7 +19,7 @@
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION"/>
- <!-- Needed to whitelist package to be able to avoid request throttling. -->
+ <!-- Needed to allowlist package to be able to avoid request throttling. -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
diff --git a/tests/tests/binder_ndk/AndroidTest.xml b/tests/tests/binder_ndk/AndroidTest.xml
index 48bf70d..6578635 100644
--- a/tests/tests/binder_ndk/AndroidTest.xml
+++ b/tests/tests/binder_ndk/AndroidTest.xml
@@ -19,6 +19,7 @@
<option name="config-descriptor:metadata" key="parameter" value="instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
index 5d3611a..7dc1288 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/Android.bp
@@ -161,6 +161,9 @@
cc_test_library {
name: "libbinder_ndk_test",
defaults: ["libbinder_ndk_test_defaults"],
+ tidy_timeout_srcs: [
+ "test_native_aidl_client.cpp",
+ ],
srcs: [
"test_ibinder.cpp",
"test_ibinder_jni.cpp",
diff --git a/tests/tests/bluetooth/Android.bp b/tests/tests/bluetooth/Android.bp
index ee27a18..eb6e0e0 100644
--- a/tests/tests/bluetooth/Android.bp
+++ b/tests/tests/bluetooth/Android.bp
@@ -23,6 +23,7 @@
"ctstestrunner-axt",
"bluetooth-test-util-lib",
"compatibility-device-util-axt",
+ "PlatformProperties",
],
libs: [
"android.test.runner",
diff --git a/tests/tests/bluetooth/AndroidManifest.xml b/tests/tests/bluetooth/AndroidManifest.xml
index 7b702d7..e624d2b 100644
--- a/tests/tests/bluetooth/AndroidManifest.xml
+++ b/tests/tests/bluetooth/AndroidManifest.xml
@@ -20,7 +20,7 @@
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
+ <!-- <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/> -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
deleted file mode 100644
index e465005..0000000
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
+++ /dev/null
@@ -1,391 +0,0 @@
-/*
- * Copyright (C) 2009 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.bluetooth.cts;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothServerSocket;
-import android.bluetooth.BluetoothStatusCodes;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.os.SystemProperties;
-import android.test.AndroidTestCase;
-import android.util.Log;
-
-import java.io.IOException;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Very basic test, just of the static methods of {@link
- * BluetoothAdapter}.
- */
-public class BasicAdapterTest extends AndroidTestCase {
- private static final String TAG = "BasicAdapterTest";
- private static final int SET_NAME_TIMEOUT = 5000; // ms timeout for setting adapter name
-
- private boolean mHasBluetooth;
- private ReentrantLock mAdapterNameChangedlock;
- private Condition mConditionAdapterNameChanged;
- private boolean mIsAdapterNameChanged;
-
- public void setUp() throws Exception {
- super.setUp();
-
- mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_BLUETOOTH);
- mAdapterNameChangedlock = new ReentrantLock();
- mConditionAdapterNameChanged = mAdapterNameChangedlock.newCondition();
- mIsAdapterNameChanged = false;
- }
-
- public void test_getDefaultAdapter() {
- /*
- * Note: If the target doesn't support Bluetooth at all, then
- * this method should return null.
- */
- if (mHasBluetooth) {
- assertNotNull(BluetoothAdapter.getDefaultAdapter());
- } else {
- assertNull(BluetoothAdapter.getDefaultAdapter());
- }
- }
-
- public void test_checkBluetoothAddress() {
- // Can't be null.
- assertFalse(BluetoothAdapter.checkBluetoothAddress(null));
-
- // Must be 17 characters long.
- assertFalse(BluetoothAdapter.checkBluetoothAddress(""));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("0"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:0"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:0"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:0"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:0"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00:00:00:00:0"));
-
- // Must have colons between octets.
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00x00:00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00.00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00:00-00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00:00:00900:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00:00:00:00?00"));
-
- // Hex letters must be uppercase.
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "a0:00:00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "0b:00:00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:c0:00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:0d:00:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00:e0:00:00:00"));
- assertFalse(BluetoothAdapter.checkBluetoothAddress(
- "00:00:0f:00:00:00"));
-
- assertTrue(BluetoothAdapter.checkBluetoothAddress(
- "00:00:00:00:00:00"));
- assertTrue(BluetoothAdapter.checkBluetoothAddress(
- "12:34:56:78:9A:BC"));
- assertTrue(BluetoothAdapter.checkBluetoothAddress(
- "DE:F0:FE:DC:B8:76"));
- }
-
- /** Checks enable(), disable(), getState(), isEnabled() */
- public void test_enableDisable() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
-
- for (int i=0; i<5; i++) {
- assertTrue(BTAdapterUtils.disableAdapter(adapter, mContext));
- assertTrue(BTAdapterUtils.enableAdapter(adapter, mContext));
- }
- }
-
- public void test_getAddress() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.enableAdapter(adapter, mContext));
-
- assertTrue(BluetoothAdapter.checkBluetoothAddress(adapter.getAddress()));
- }
-
- public void test_setName_getName() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.enableAdapter(adapter, mContext));
-
- IntentFilter filter = new IntentFilter();
- filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
- filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
- mContext.registerReceiver(mAdapterNameChangeReceiver, filter);
-
- String name = adapter.getName();
- assertNotNull(name);
-
- // Check renaming the adapter
- String genericName = "Generic Device 1";
- mIsAdapterNameChanged = false;
- assertTrue(adapter.setName(genericName));
- assertTrue(waitForAdapterNameChange());
- mIsAdapterNameChanged = false;
- assertEquals(genericName, adapter.getName());
-
- // Check setting adapter back to original name
- assertTrue(adapter.setName(name));
- assertTrue(waitForAdapterNameChange());
- mIsAdapterNameChanged = false;
- assertEquals(name, adapter.getName());
- }
-
- public void test_getBondedDevices() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.enableAdapter(adapter, mContext));
-
- Set<BluetoothDevice> devices = adapter.getBondedDevices();
- assertNotNull(devices);
- for (BluetoothDevice device : devices) {
- assertTrue(BluetoothAdapter.checkBluetoothAddress(device.getAddress()));
- }
- }
-
- public void test_getRemoteDevice() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- // getRemoteDevice() should work even with Bluetooth disabled
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.disableAdapter(adapter, mContext));
-
- // test bad addresses
- try {
- adapter.getRemoteDevice((String)null);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) {}
- try {
- adapter.getRemoteDevice("00:00:00:00:00:00:00:00");
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) {}
- try {
- adapter.getRemoteDevice((byte[])null);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) {}
- try {
- adapter.getRemoteDevice(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00});
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) {}
-
- // test success
- BluetoothDevice device = adapter.getRemoteDevice("00:11:22:AA:BB:CC");
- assertNotNull(device);
- assertEquals("00:11:22:AA:BB:CC", device.getAddress());
- device = adapter.getRemoteDevice(
- new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06});
- assertNotNull(device);
- assertEquals("01:02:03:04:05:06", device.getAddress());
- }
-
- public void test_getRemoteLeDevice() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- // getRemoteLeDevice() should work even with Bluetooth disabled
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.disableAdapter(adapter, mContext));
-
- // test bad addresses
- try {
- adapter.getRemoteLeDevice((String) null, BluetoothDevice.ADDRESS_TYPE_PUBLIC);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) { }
- try {
- adapter.getRemoteLeDevice("01:02:03:04:05:06:07:08",
- BluetoothDevice.ADDRESS_TYPE_PUBLIC);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) { }
- try {
- adapter.getRemoteLeDevice("01:02:03:04:05", BluetoothDevice.ADDRESS_TYPE_PUBLIC);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) { }
- try {
- adapter.getRemoteLeDevice("00:01:02:03:04:05", BluetoothDevice.ADDRESS_TYPE_RANDOM + 1);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) { }
- try {
- adapter.getRemoteLeDevice("00:01:02:03:04:05", BluetoothDevice.ADDRESS_TYPE_PUBLIC - 1);
- fail("IllegalArgumentException not thrown");
- } catch (IllegalArgumentException e) { }
-
- // test success
- BluetoothDevice device = adapter.getRemoteLeDevice("00:11:22:AA:BB:CC",
- BluetoothDevice.ADDRESS_TYPE_PUBLIC);
- assertNotNull(device);
- assertEquals("00:11:22:AA:BB:CC", device.getAddress());
- device = adapter.getRemoteLeDevice("01:02:03:04:05:06",
- BluetoothDevice.ADDRESS_TYPE_RANDOM);
- assertNotNull(device);
- assertEquals("01:02:03:04:05:06", device.getAddress());
- }
-
- public void test_isLeAudioSupported() throws IOException {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, adapter.isLeAudioSupported());
- }
-
- public void test_isLeAudioBroadcastSourceSupported() throws IOException {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, adapter.isLeAudioBroadcastSourceSupported());
- }
-
- public void test_isLeAudioBroadcastAssistantSupported() throws IOException {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, adapter.isLeAudioBroadcastAssistantSupported());
- }
-
- public void test_getMaxConnectedAudioDevices() {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
-
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.enableAdapter(adapter, mContext));
- int maxConnectedAudioDevicesConfig = 0;
- try {
- Resources bluetoothRes = mContext.getPackageManager()
- .getResourcesForApplication("com.android.bluetooth");
- maxConnectedAudioDevicesConfig = bluetoothRes.getInteger(
- bluetoothRes.getIdentifier("config_bluetooth_max_connected_audio_devices",
- "integer", "com.android.bluetooth"));
- } catch (PackageManager.NameNotFoundException e) {
- e.printStackTrace();
- }
-
- maxConnectedAudioDevicesConfig =
- SystemProperties.getInt("persist.bluetooth.maxconnectedaudiodevices",
- maxConnectedAudioDevicesConfig);
- assertEquals(maxConnectedAudioDevicesConfig, adapter.getMaxConnectedAudioDevices());
- }
-
- public void test_listenUsingRfcommWithServiceRecord() throws IOException {
- if (!mHasBluetooth) {
- // Skip the test if bluetooth is not present.
- return;
- }
- BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
- assertTrue(BTAdapterUtils.enableAdapter(adapter, mContext));
-
- BluetoothServerSocket socket = adapter.listenUsingRfcommWithServiceRecord(
- "test", UUID.randomUUID());
- assertNotNull(socket);
- socket.close();
- }
-
- private static void sleep(long t) {
- try {
- Thread.sleep(t);
- } catch (InterruptedException e) {}
- }
-
- private boolean waitForAdapterNameChange() {
- mAdapterNameChangedlock.lock();
- try {
- // Wait for the Adapter name to be changed
- while (!mIsAdapterNameChanged) {
- if (!mConditionAdapterNameChanged.await(
- SET_NAME_TIMEOUT, TimeUnit.MILLISECONDS)) {
- Log.e(TAG, "Timeout while waiting for adapter name change");
- break;
- }
- }
- } catch (InterruptedException e) {
- Log.e(TAG, "waitForAdapterNameChange: interrrupted");
- } finally {
- mAdapterNameChangedlock.unlock();
- }
- return mIsAdapterNameChanged;
- }
-
- private final BroadcastReceiver mAdapterNameChangeReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
- mAdapterNameChangedlock.lock();
- mIsAdapterNameChanged = true;
- try {
- mConditionAdapterNameChanged.signal();
- } catch (IllegalMonitorStateException ex) {
- } finally {
- mAdapterNameChangedlock.unlock();
- }
- }
- }
- };
-}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java
index 1e67d2a..f9531fb 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java
@@ -24,6 +24,8 @@
import android.bluetooth.BluetoothManager;
import android.test.AndroidTestCase;
+import androidx.test.InstrumentationRegistry;
+
import java.util.List;
/**
@@ -41,6 +43,8 @@
if (!TestUtils.isBleSupported(getContext())) {
return;
}
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
mBluetoothAdapter = mContext.getSystemService(BluetoothManager.class).getAdapter();
if (!mBluetoothAdapter.isEnabled()) {
@@ -59,6 +63,8 @@
}
mBluetoothGatt.disconnect();
assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
}
public void testGetServices() throws Exception {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
new file mode 100644
index 0000000..b013b63
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
@@ -0,0 +1,228 @@
+/*
+ * 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.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCodecConfig;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class BluetoothA2dpTest extends AndroidTestCase {
+ private static final String TAG = BluetoothA2dpTest.class.getSimpleName();
+
+ private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
+ private static final String PROFILE_SUPPORTED_A2DP = "profile_supported_a2dp";
+
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private UiAutomation mUiAutomation;;
+
+ private BluetoothA2dp mBluetoothA2dp;
+ private boolean mIsA2dpSupported;
+ private boolean mIsProfileReady;
+ private Condition mConditionProfileIsConnected;
+ private ReentrantLock mProfileConnectedlock;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH);
+
+ if (!mHasBluetooth) return;
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+
+ BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
+ mAdapter = manager.getAdapter();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mProfileConnectedlock = new ReentrantLock();
+ mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+ mIsProfileReady = false;
+ mBluetoothA2dp = null;
+
+ Resources bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
+ "com.android.bluetooth");
+ int a2dpSupportId = bluetoothResources.getIdentifier(
+ PROFILE_SUPPORTED_A2DP, "bool", "com.android.bluetooth");
+ assertTrue("resource profile_supported_a2dp not found", a2dpSupportId != 0);
+ mIsA2dpSupported = bluetoothResources.getBoolean(a2dpSupportId);
+ if (!mIsA2dpSupported) return;
+
+ mAdapter.getProfileProxy(getContext(), new BluetoothA2dpServiceListener(),
+ BluetoothProfile.A2DP);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (mHasBluetooth) {
+ if (mAdapter != null && mBluetoothA2dp != null) {
+ mAdapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp);
+ mBluetoothA2dp = null;
+ mIsProfileReady = false;
+ }
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ public void test_getConnectedDevices() {
+ if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothA2dp);
+
+ assertEquals(mBluetoothA2dp.getConnectedDevices(),
+ new ArrayList<BluetoothDevice>());
+ }
+
+ public void test_getDevicesMatchingConnectionStates() {
+ if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothA2dp);
+
+ assertEquals(mBluetoothA2dp.getDevicesMatchingConnectionStates(
+ new int[]{BluetoothProfile.STATE_CONNECTED}),
+ new ArrayList<BluetoothDevice>());
+ }
+
+ public void test_getConnectionState() {
+ if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothA2dp);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertEquals(mBluetoothA2dp.getConnectionState(testDevice),
+ BluetoothProfile.STATE_DISCONNECTED);
+ }
+
+ public void test_isA2dpPlaying() {
+ if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothA2dp);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertFalse(mBluetoothA2dp.isA2dpPlaying(testDevice));
+ }
+
+ public void test_getCodecStatus() {
+ if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothA2dp);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertNull(mBluetoothA2dp.getCodecStatus(testDevice));
+ assertThrows(IllegalArgumentException.class, () -> {
+ mBluetoothA2dp.getCodecStatus(null);
+ });
+ }
+
+ public void test_setCodecConfigPreference() {
+ if (!(mHasBluetooth && mIsA2dpSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothA2dp);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ BluetoothCodecConfig codecConfig = new BluetoothCodecConfig.Builder()
+ .setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC)
+ .setCodecPriority(0)
+ .build();
+ mBluetoothA2dp.setCodecConfigPreference(testDevice, codecConfig);
+ assertNull(mBluetoothA2dp.getCodecStatus(testDevice));
+ assertThrows(IllegalArgumentException.class, () -> {
+ mBluetoothA2dp.setCodecConfigPreference(null, null);
+ });
+ }
+
+ private static <T extends Exception> void assertThrows(Class<T> clazz, Runnable r) {
+ try {
+ r.run();
+ } catch (Exception e) {
+ if (!clazz.isAssignableFrom(e.getClass())) {
+ throw e;
+ }
+ }
+ }
+
+ private boolean waitForProfileConnect() {
+ mProfileConnectedlock.lock();
+ try {
+ // Wait for the Adapter to be disabled
+ while (!mIsProfileReady) {
+ if (!mConditionProfileIsConnected.await(
+ PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ // Timeout
+ Log.e(TAG, "Timeout while waiting for Profile Connect");
+ break;
+ } // else spurious wakeups
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "waitForProfileConnect: interrrupted");
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ return mIsProfileReady;
+ }
+
+ private final class BluetoothA2dpServiceListener implements
+ BluetoothProfile.ServiceListener {
+
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ mProfileConnectedlock.lock();
+ mBluetoothA2dp = (BluetoothA2dp) proxy;
+ mIsProfileReady = true;
+ try {
+ mConditionProfileIsConnected.signal();
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ }
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
new file mode 100644
index 0000000..460af3e
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) 2009 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.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import static org.junit.Assert.assertThrows;
+
+import android.annotation.NonNull;
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothServerSocket;
+import android.bluetooth.BluetoothStatusCodes;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.SystemProperties;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Very basic test, just of the static methods of {@link
+ * BluetoothAdapter}.
+ */
+public class BluetoothAdapterTest extends AndroidTestCase {
+ private static final String TAG = "BasicAdapterTest";
+ private static final int SET_NAME_TIMEOUT = 5000; // ms timeout for setting adapter name
+
+ private boolean mHasBluetooth;
+ private ReentrantLock mAdapterNameChangedlock;
+ private Condition mConditionAdapterNameChanged;
+ private boolean mIsAdapterNameChanged;
+
+ private BluetoothAdapter mAdapter;
+ private UiAutomation mUiAutomation;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH);
+ if (mHasBluetooth) {
+ mAdapter = getContext().getSystemService(BluetoothManager.class).getAdapter();
+ assertNotNull(mAdapter);
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ }
+ mAdapterNameChangedlock = new ReentrantLock();
+ mConditionAdapterNameChanged = mAdapterNameChangedlock.newCondition();
+ mIsAdapterNameChanged = false;
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ if (mHasBluetooth) {
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ public void test_getDefaultAdapter() {
+ /*
+ * Note: If the target doesn't support Bluetooth at all, then
+ * this method should return null.
+ */
+ if (mHasBluetooth) {
+ assertNotNull(BluetoothAdapter.getDefaultAdapter());
+ } else {
+ assertNull(BluetoothAdapter.getDefaultAdapter());
+ }
+ }
+
+ public void test_checkBluetoothAddress() {
+ // Can't be null.
+ assertFalse(BluetoothAdapter.checkBluetoothAddress(null));
+
+ // Must be 17 characters long.
+ assertFalse(BluetoothAdapter.checkBluetoothAddress(""));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("0"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:0"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:0"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:0"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:0"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:0"));
+
+ // Must have colons between octets.
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00x00:00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00.00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00-00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00900:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00?00"));
+
+ // Hex letters must be uppercase.
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("a0:00:00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("0b:00:00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:c0:00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:0d:00:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:e0:00:00:00"));
+ assertFalse(BluetoothAdapter.checkBluetoothAddress("00:00:0f:00:00:00"));
+
+ assertTrue(BluetoothAdapter.checkBluetoothAddress("00:00:00:00:00:00"));
+ assertTrue(BluetoothAdapter.checkBluetoothAddress("12:34:56:78:9A:BC"));
+ assertTrue(BluetoothAdapter.checkBluetoothAddress("DE:F0:FE:DC:B8:76"));
+ }
+
+ /** Checks enable(), disable(), getState(), isEnabled() */
+ public void test_enableDisable() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+
+ for (int i = 0; i < 5; i++) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ }
+ }
+
+ public void test_getAddress() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ assertTrue(BluetoothAdapter.checkBluetoothAddress(mAdapter.getAddress()));
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> mAdapter.getAddress());
+
+ }
+
+ public void test_setName_getName() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED);
+ filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ mContext.registerReceiver(mAdapterNameChangeReceiver, filter);
+
+ String name = mAdapter.getName();
+ assertNotNull(name);
+
+ // Check renaming the adapter
+ String genericName = "Generic Device 1";
+ mIsAdapterNameChanged = false;
+ assertTrue(mAdapter.setName(genericName));
+ assertTrue(waitForAdapterNameChange());
+ mIsAdapterNameChanged = false;
+ assertEquals(genericName, mAdapter.getName());
+
+ // Check setting adapter back to original name
+ assertTrue(mAdapter.setName(name));
+ assertTrue(waitForAdapterNameChange());
+ mIsAdapterNameChanged = false;
+ assertEquals(name, mAdapter.getName());
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> mAdapter.setName("The name"));
+ assertThrows(SecurityException.class, () -> mAdapter.getName());
+ }
+
+ public void test_getBondedDevices() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+
+ // empty value is returned when Bluetooth is disabled
+ Set<BluetoothDevice> devices = mAdapter.getBondedDevices();
+ assertNotNull(devices);
+ assertTrue(devices.isEmpty());
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ devices = mAdapter.getBondedDevices();
+ assertNotNull(devices);
+ for (BluetoothDevice device : devices) {
+ assertTrue(BluetoothAdapter.checkBluetoothAddress(device.getAddress()));
+ }
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> mAdapter.getBondedDevices());
+
+ }
+
+ public void test_getRemoteDevice() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ // getRemoteDevice() should work even with Bluetooth disabled
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mUiAutomation.dropShellPermissionIdentity();
+
+ // test bad addresses
+ assertThrows(IllegalArgumentException.class, () -> mAdapter.getRemoteDevice((String) null));
+ assertThrows(IllegalArgumentException.class, () ->
+ mAdapter.getRemoteDevice("00:00:00:00:00:00:00:00"));
+ assertThrows(IllegalArgumentException.class, () -> mAdapter.getRemoteDevice((byte[]) null));
+ assertThrows(IllegalArgumentException.class, () ->
+ mAdapter.getRemoteDevice(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00}));
+
+ // test success
+ BluetoothDevice device = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+ assertNotNull(device);
+ assertEquals("00:11:22:AA:BB:CC", device.getAddress());
+ device = mAdapter.getRemoteDevice(
+ new byte[] {0x01, 0x02, 0x03, 0x04, 0x05, 0x06});
+ assertNotNull(device);
+ assertEquals("01:02:03:04:05:06", device.getAddress());
+ }
+
+ public void test_getRemoteLeDevice() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ // getRemoteLeDevice() should work even with Bluetooth disabled
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mUiAutomation.dropShellPermissionIdentity();
+
+ // test bad addresses
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.getRemoteLeDevice((String) null,
+ BluetoothDevice.ADDRESS_TYPE_PUBLIC));
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.getRemoteLeDevice("01:02:03:04:05:06:07:08",
+ BluetoothDevice.ADDRESS_TYPE_PUBLIC));
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.getRemoteLeDevice("01:02:03:04:05",
+ BluetoothDevice.ADDRESS_TYPE_PUBLIC));
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.getRemoteLeDevice("00:01:02:03:04:05",
+ BluetoothDevice.ADDRESS_TYPE_RANDOM + 1));
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.getRemoteLeDevice("00:01:02:03:04:05",
+ BluetoothDevice.ADDRESS_TYPE_PUBLIC - 1));
+
+ // test success
+ BluetoothDevice device = mAdapter.getRemoteLeDevice("00:11:22:AA:BB:CC",
+ BluetoothDevice.ADDRESS_TYPE_PUBLIC);
+ assertNotNull(device);
+ assertEquals("00:11:22:AA:BB:CC", device.getAddress());
+ device = mAdapter.getRemoteLeDevice("01:02:03:04:05:06",
+ BluetoothDevice.ADDRESS_TYPE_RANDOM);
+ assertNotNull(device);
+ assertEquals("01:02:03:04:05:06", device.getAddress());
+ }
+
+ public void test_isLeAudioSupported() throws IOException {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN, mAdapter.isLeAudioSupported());
+ }
+
+ public void test_isLeAudioBroadcastSourceSupported() throws IOException {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN,
+ mAdapter.isLeAudioBroadcastSourceSupported());
+ }
+
+ public void test_isLeAudioBroadcastAssistantSupported() throws IOException {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertNotSame(BluetoothStatusCodes.ERROR_UNKNOWN,
+ mAdapter.isLeAudioBroadcastAssistantSupported());
+ }
+
+ public void test_getMaxConnectedAudioDevices() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+
+ int maxConnectedAudioDevicesConfig = 0;
+ try {
+ Resources bluetoothRes = mContext.getPackageManager()
+ .getResourcesForApplication("com.android.bluetooth");
+ maxConnectedAudioDevicesConfig = bluetoothRes.getInteger(
+ bluetoothRes.getIdentifier("config_bluetooth_max_connected_audio_devices",
+ "integer", "com.android.bluetooth"));
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ maxConnectedAudioDevicesConfig =
+ SystemProperties.getInt("persist.bluetooth.maxconnectedaudiodevices",
+ maxConnectedAudioDevicesConfig);
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ assertEquals(maxConnectedAudioDevicesConfig, mAdapter.getMaxConnectedAudioDevices());
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> mAdapter.getMaxConnectedAudioDevices());
+ }
+
+ public void test_listenUsingRfcommWithServiceRecord() throws IOException {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ BluetoothServerSocket socket = mAdapter.listenUsingRfcommWithServiceRecord(
+ "test", UUID.randomUUID());
+ assertNotNull(socket);
+ socket.close();
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> mAdapter.listenUsingRfcommWithServiceRecord(
+ "test", UUID.randomUUID()));
+ }
+
+ public void test_discoverableTimeout() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth is not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertEquals(-1, mAdapter.getDiscoverableTimeout());
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertEquals(120, mAdapter.getDiscoverableTimeout());
+ }
+
+ public void test_getConnectionState() {
+ if (!mHasBluetooth) return;
+
+ // Verify return value if Bluetooth is not enabled
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertEquals(BluetoothProfile.STATE_DISCONNECTED, mAdapter.getConnectionState());
+ }
+
+ public void test_getMostRecentlyConnectedDevices() {
+ if (!mHasBluetooth) return;
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED
+ assertThrows(SecurityException.class, () -> mAdapter.getMostRecentlyConnectedDevices());
+
+ // Verify return value if Bluetooth is not enabled
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ List<BluetoothDevice> devices = mAdapter.getMostRecentlyConnectedDevices();
+ assertTrue(devices.isEmpty());
+ }
+
+ public void test_getUuids() {
+ if (!mHasBluetooth) return;
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ // Verify return value without permission.BLUETOOTH_CONNECT
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> mAdapter.getUuids());
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+
+ assertNotNull(mAdapter.getUuids());
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+
+ // Verify return value if Bluetooth is not enabled
+ assertNull(mAdapter.getUuids());
+
+ }
+
+ public void test_nameForState() {
+ assertEquals("ON", BluetoothAdapter.nameForState(BluetoothAdapter.STATE_ON));
+ assertEquals("OFF", BluetoothAdapter.nameForState(BluetoothAdapter.STATE_OFF));
+ assertEquals("TURNING_ON",
+ BluetoothAdapter.nameForState(BluetoothAdapter.STATE_TURNING_ON));
+ assertEquals("TURNING_OFF",
+ BluetoothAdapter.nameForState(BluetoothAdapter.STATE_TURNING_OFF));
+
+ assertEquals("BLE_ON", BluetoothAdapter.nameForState(BluetoothAdapter.STATE_BLE_ON));
+
+ // Check value before state range
+ for (int state = 0; state < BluetoothAdapter.STATE_OFF; state++) {
+ assertEquals("?!?!? (" + state + ")", BluetoothAdapter.nameForState(state));
+ }
+ // Check value after state range (skip TURNING_OFF)
+ for (int state = BluetoothAdapter.STATE_BLE_ON + 2; state < 100; state++) {
+ assertEquals("?!?!? (" + state + ")", BluetoothAdapter.nameForState(state));
+ }
+ }
+
+ public void test_BluetoothConnectionCallback_disconnectReasonText() {
+ assertEquals("Reason unknown", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_UNKNOWN));
+ assertEquals("Local request", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST));
+ assertEquals("Remote request", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE_REQUEST));
+ assertEquals("Local error", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL));
+ assertEquals("Remote error", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_REMOTE));
+ assertEquals("Timeout", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_TIMEOUT));
+ assertEquals("Security", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SECURITY));
+ assertEquals("System policy", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_SYSTEM_POLICY));
+ assertEquals("Resource constrained", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_RESOURCE_LIMIT_REACHED));
+ assertEquals("Connection already exists", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(
+ BluetoothStatusCodes.ERROR_DISCONNECT_REASON_CONNECTION_ALREADY_EXISTS));
+ assertEquals("Bad parameters", BluetoothAdapter.BluetoothConnectionCallback
+ .disconnectReasonText(BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS));
+ final int min_reason = BluetoothStatusCodes.ERROR_DISCONNECT_REASON_LOCAL_REQUEST - 1;
+ for (int reason = 0; reason < min_reason; reason++) {
+ assertEquals("Unrecognized disconnect reason: " + reason,
+ BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
+ }
+ final int max_reason = BluetoothStatusCodes.ERROR_DISCONNECT_REASON_BAD_PARAMETERS + 1;
+ // Check value after state range (skip TURNING_OFF)
+ for (int reason = max_reason; reason < max_reason + 100; reason++) {
+ assertEquals("Unrecognized disconnect reason: " + reason,
+ BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
+ }
+ }
+
+ public void test_registerBluetoothConnectionCallback() {
+ if (!mHasBluetooth) return;
+
+ Executor executor = mContext.getMainExecutor();
+ BluetoothAdapter.BluetoothConnectionCallback callback =
+ new BluetoothAdapter.BluetoothConnectionCallback() {
+ @Override
+ public void onDeviceConnected(@NonNull BluetoothDevice device) {}
+ @Override
+ public void onDeviceDisconnected(BluetoothDevice device, int reason) {}
+
+ };
+
+ // Verify parameter
+ assertFalse(mAdapter.registerBluetoothConnectionCallback(null, callback));
+ assertFalse(mAdapter.registerBluetoothConnectionCallback(executor, null));
+ assertFalse(mAdapter.unregisterBluetoothConnectionCallback(null));
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED
+ assertThrows(SecurityException.class,
+ () -> mAdapter.registerBluetoothConnectionCallback(executor, callback));
+
+ mUiAutomation.dropShellPermissionIdentity();
+ // Verify throws SecurityException without permission.BLUETOOTH_CONNECT
+ assertThrows(SecurityException.class, () ->
+ mAdapter.registerBluetoothConnectionCallback(executor, callback));
+ assertThrows(SecurityException.class, () ->
+ mAdapter.unregisterBluetoothConnectionCallback(callback));
+ }
+
+ public void test_registerServiceLifecycleCallback() {
+ if (!mHasBluetooth) return;
+
+ BluetoothAdapter.ServiceLifecycleCallback callback =
+ new BluetoothAdapter.ServiceLifecycleCallback() {
+ @Override
+ public void onBluetoothServiceUp() {}
+ @Override
+ public void onBluetoothServiceDown() {}
+ };
+
+ // Verify parameter
+ assertThrows(NullPointerException.class,
+ () -> mAdapter.registerServiceLifecycleCallback(null));
+
+ assertThrows(NullPointerException.class,
+ () -> mAdapter.unregisterServiceLifecycleCallback(null));
+ }
+
+ public void test_requestControllerActivityEnergyInfo() {
+ if (!mHasBluetooth) return;
+
+ // Verify parameter
+ assertThrows(NullPointerException.class,
+ () -> mAdapter.requestControllerActivityEnergyInfo(null));
+ }
+
+ public void test_factoryReset() {
+ if (!mHasBluetooth) return;
+
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ // Verify throws SecurityException without permission.BLUETOOTH_PRIVILEGED
+ assertThrows(SecurityException.class, () -> mAdapter.factoryReset());
+ mUiAutomation.dropShellPermissionIdentity();
+ // Verify throws SecurityException without permission.BLUETOOTH_CONNECT
+ assertThrows(SecurityException.class, () -> mAdapter.factoryReset());
+
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ // Verify throws RuntimeException when trying to save sysprop for later (permission denied)
+ assertThrows(RuntimeException.class, () -> mAdapter.factoryReset());
+ }
+
+ public void test_BluetoothProfile_getConnectionStateName() {
+ if (!mHasBluetooth) return;
+
+ assertEquals("STATE_DISCONNECTED",
+ BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_DISCONNECTED));
+ assertEquals("STATE_CONNECTED",
+ BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_CONNECTED));
+ assertEquals("STATE_CONNECTING",
+ BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_CONNECTING));
+ assertEquals("STATE_CONNECTED",
+ BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_CONNECTED));
+ assertEquals("STATE_DISCONNECTING",
+ BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_DISCONNECTING));
+ assertEquals("STATE_UNKNOWN",
+ BluetoothProfile.getConnectionStateName(BluetoothProfile.STATE_DISCONNECTING + 1));
+ }
+
+ public void test_BluetoothProfile_getProfileName() {
+ if (!mHasBluetooth) return;
+ assertEquals("HEADSET",
+ BluetoothProfile.getProfileName(BluetoothProfile.HEADSET));
+ assertEquals("A2DP",
+ BluetoothProfile.getProfileName(BluetoothProfile.A2DP));
+ assertEquals("HID_HOST",
+ BluetoothProfile.getProfileName(BluetoothProfile.HID_HOST));
+ assertEquals("PAN",
+ BluetoothProfile.getProfileName(BluetoothProfile.PAN));
+ assertEquals("PBAP",
+ BluetoothProfile.getProfileName(BluetoothProfile.PBAP));
+ assertEquals("GATT",
+ BluetoothProfile.getProfileName(BluetoothProfile.GATT));
+ assertEquals("GATT_SERVER",
+ BluetoothProfile.getProfileName(BluetoothProfile.GATT_SERVER));
+ assertEquals("MAP",
+ BluetoothProfile.getProfileName(BluetoothProfile.MAP));
+ assertEquals("SAP",
+ BluetoothProfile.getProfileName(BluetoothProfile.SAP));
+ assertEquals("A2DP_SINK",
+ BluetoothProfile.getProfileName(BluetoothProfile.A2DP_SINK));
+ assertEquals("AVRCP_CONTROLLER",
+ BluetoothProfile.getProfileName(BluetoothProfile.AVRCP_CONTROLLER));
+ assertEquals("AVRCP",
+ BluetoothProfile.getProfileName(BluetoothProfile.AVRCP));
+ assertEquals("HEADSET_CLIENT",
+ BluetoothProfile.getProfileName(BluetoothProfile.HEADSET_CLIENT));
+ assertEquals("PBAP_CLIENT",
+ BluetoothProfile.getProfileName(BluetoothProfile.PBAP_CLIENT));
+ assertEquals("MAP_CLIENT",
+ BluetoothProfile.getProfileName(BluetoothProfile.MAP_CLIENT));
+ assertEquals("HID_DEVICE",
+ BluetoothProfile.getProfileName(BluetoothProfile.HID_DEVICE));
+ assertEquals("OPP",
+ BluetoothProfile.getProfileName(BluetoothProfile.OPP));
+ assertEquals("HEARING_AID",
+ BluetoothProfile.getProfileName(BluetoothProfile.HEARING_AID));
+ assertEquals("LE_AUDIO",
+ BluetoothProfile.getProfileName(BluetoothProfile.LE_AUDIO));
+ assertEquals("HAP_CLIENT",
+ BluetoothProfile.getProfileName(BluetoothProfile.HAP_CLIENT));
+ assertEquals("UNKNOWN_PROFILE",
+ BluetoothProfile.getProfileName(BluetoothProfile.HAP_CLIENT + 1));
+ }
+
+ private static void sleep(long t) {
+ try {
+ Thread.sleep(t);
+ } catch (InterruptedException e) { }
+ }
+
+ private boolean waitForAdapterNameChange() {
+ mAdapterNameChangedlock.lock();
+ try {
+ // Wait for the Adapter name to be changed
+ while (!mIsAdapterNameChanged) {
+ if (!mConditionAdapterNameChanged.await(
+ SET_NAME_TIMEOUT, TimeUnit.MILLISECONDS)) {
+ Log.e(TAG, "Timeout while waiting for adapter name change");
+ break;
+ }
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "waitForAdapterNameChange: interrrupted");
+ } finally {
+ mAdapterNameChangedlock.unlock();
+ }
+ return mIsAdapterNameChanged;
+ }
+
+ private final BroadcastReceiver mAdapterNameChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED)) {
+ mAdapterNameChangedlock.lock();
+ mIsAdapterNameChanged = true;
+ try {
+ mConditionAdapterNameChanged.signal();
+ } catch (IllegalMonitorStateException ex) {
+ } finally {
+ mAdapterNameChangedlock.unlock();
+ }
+ }
+ }
+ };
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothClassTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothClassTest.java
index 3d407df..a22c2c8 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothClassTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothClassTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package android.bluetooth.cts;
import android.bluetooth.BluetoothClass;
+import android.os.Parcel;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
@@ -32,11 +33,21 @@
private BluetoothClass mBluetoothClassPhone;
private BluetoothClass mBluetoothClassService;
+ private BluetoothClass createBtClass(int deviceClass) {
+ Parcel p = Parcel.obtain();
+ p.writeInt(deviceClass);
+ p.setDataPosition(0); // reset position of parcel before passing to constructor
+
+ BluetoothClass bluetoothClass = BluetoothClass.CREATOR.createFromParcel(p);
+ p.recycle();
+ return bluetoothClass;
+ }
+
@Override
protected void setUp() {
- mBluetoothClassHeadphones = new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
- mBluetoothClassPhone = new BluetoothClass(BluetoothClass.Device.Major.PHONE);
- mBluetoothClassService = new BluetoothClass(BluetoothClass.Service.NETWORKING);
+ mBluetoothClassHeadphones = createBtClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+ mBluetoothClassPhone = createBtClass(BluetoothClass.Device.Major.PHONE);
+ mBluetoothClassService = createBtClass(BluetoothClass.Service.NETWORKING);
}
@SmallTest
@@ -47,20 +58,27 @@
@SmallTest
public void testGetMajorDeviceClass() {
- assertEquals(mBluetoothClassHeadphones.getMajorDeviceClass(), BluetoothClass.Device.Major.AUDIO_VIDEO);
+ assertEquals(
+ mBluetoothClassHeadphones.getMajorDeviceClass(),
+ BluetoothClass.Device.Major.AUDIO_VIDEO);
assertEquals(mBluetoothClassPhone.getMajorDeviceClass(), BluetoothClass.Device.Major.PHONE);
}
@SmallTest
public void testGetDeviceClass() {
- assertEquals(mBluetoothClassHeadphones.getDeviceClass(), BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
- assertEquals(mBluetoothClassPhone.getDeviceClass(), BluetoothClass.Device.PHONE_UNCATEGORIZED);
+ assertEquals(
+ mBluetoothClassHeadphones.getDeviceClass(),
+ BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+ assertEquals(
+ mBluetoothClassPhone.getDeviceClass(),
+ BluetoothClass.Device.PHONE_UNCATEGORIZED);
}
@SmallTest
public void testGetClassOfDevice() {
- assertEquals(mBluetoothClassHeadphones.getClassOfDevice(), BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
- assertEquals(mBluetoothClassPhone.getClassOfDevice(), BluetoothClass.Device.Major.PHONE);
+ assertEquals(mBluetoothClassHeadphones.getDeviceClass(),
+ BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+ assertEquals(mBluetoothClassPhone.getMajorDeviceClass(), BluetoothClass.Device.Major.PHONE);
}
@SmallTest
@@ -74,4 +92,13 @@
assertTrue(mBluetoothClassService.doesClassMatch(BluetoothClass.PROFILE_PANU));
assertFalse(mBluetoothClassService.doesClassMatch(BluetoothClass.PROFILE_OPP));
}
+
+ @SmallTest
+ public void testInnerClasses() {
+ // Just instantiate static inner classes for exposing constants
+ // to make test coverage tool happy.
+ BluetoothClass.Device device = new BluetoothClass.Device();
+ BluetoothClass.Device.Major major = new BluetoothClass.Device.Major();
+ BluetoothClass.Service service = new BluetoothClass.Service();
+ }
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
index 7f1a487..a615df3 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
@@ -16,20 +16,29 @@
package android.bluetooth.cts;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+import static org.junit.Assert.assertThrows;
+
+import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothStatusCodes;
+import android.content.AttributionSource;
import android.content.pm.PackageManager;
import android.test.AndroidTestCase;
+import androidx.test.InstrumentationRegistry;
+
public class BluetoothDeviceTest extends AndroidTestCase {
private boolean mHasBluetooth;
private boolean mHasCompanionDevice;
private BluetoothAdapter mAdapter;
+ private UiAutomation mUiAutomation;;
@Override
public void setUp() throws Exception {
@@ -43,6 +52,8 @@
if (mHasBluetooth && mHasCompanionDevice) {
BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
mAdapter = manager.getAdapter();
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
}
}
@@ -53,6 +64,7 @@
if (mHasBluetooth && mHasCompanionDevice) {
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
+ mUiAutomation.dropShellPermissionIdentity();
}
}
@@ -66,20 +78,21 @@
String packageName = mContext.getOpPackageName();
String deviceAddress = "00:11:22:AA:BB:CC";
+ AttributionSource source = AttributionSource.myAttributionSource();
+ assertEquals("android.bluetooth.cts", source.getPackageName());
+
BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
// Verifies that when there is no alias, we return the device name
assertNull(device.getAlias());
+ assertThrows(IllegalArgumentException.class, () -> device.setAlias(""));
+
String testDeviceAlias = "Test Device Alias";
// This should throw a SecurityException because there is no CDM association
- try {
- device.setAlias(testDeviceAlias);
- fail("BluetoothDevice alias was able to be set without a CDM association or "
- + "BLUETOOTH_PRIVILEGED permission");
- } catch (SecurityException ex) {
- assertNull(device.getAlias());
- }
+ assertThrows("BluetoothDevice.setAlias without"
+ + " a CDM association or BLUETOOTH_PRIVILEGED permission",
+ SecurityException.class, () -> device.setAlias(testDeviceAlias));
runShellCommand(String.format(
"cmd companiondevice associate %d %s %s", userId, packageName, deviceAddress));
@@ -102,4 +115,111 @@
runShellCommand(String.format(
"cmd companiondevice disassociate %d %s %s", userId, packageName, deviceAddress));
}
+
+ public void test_getAnonymizedAddress() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+ assertEquals(device.getAnonymizedAddress(), "XX:XX:XX:AA:BB:CC");
+ }
+
+ public void test_getBatteryLevel() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+ assertEquals(BluetoothDevice.BATTERY_LEVEL_UNKNOWN, device.getBatteryLevel());
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> device.getBatteryLevel());
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ }
+
+ public void test_getMessageAccessPermission() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+ assertEquals(BluetoothDevice.ACCESS_UNKNOWN, device.getMessageAccessPermission());
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> device.getMessageAccessPermission());
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ }
+
+ public void test_getPhonebookAccessPermission() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+ assertEquals(BluetoothDevice.ACCESS_UNKNOWN, device.getPhonebookAccessPermission());
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> device.getPhonebookAccessPermission());
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ }
+
+ public void test_isBondingInitiatedLocally() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+ assertFalse(device.isBondingInitiatedLocally());
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> device.isBondingInitiatedLocally());
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ }
+
+ public void test_prepareToEnterProcess() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+ device.prepareToEnterProcess(null);
+ }
+
+ public void test_setPin() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+
+ assertFalse(device.setPin((String) null));
+ assertFalse(device.setPin("12345678901234567")); // check PIN too big
+
+ assertFalse(device.setPin("123456")); //device is not bonding
+
+ mUiAutomation.dropShellPermissionIdentity();
+ assertThrows(SecurityException.class, () -> device.setPin("123456"));
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+ }
+
+ public void test_connect_disconnect() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+
+ // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
+ assertThrows(SecurityException.class, () -> device.connect());
+ assertThrows(SecurityException.class, () -> device.disconnect());
+ }
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
index f4d6c3b..0b2dd82 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
@@ -19,6 +19,7 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
+import android.bluetooth.BluetoothHapPresetInfo;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.pm.PackageManager;
@@ -27,6 +28,8 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
import com.android.compatibility.common.util.ApiLevelUtil;
import java.util.List;
@@ -57,6 +60,8 @@
PackageManager.FEATURE_BLUETOOTH);
if (!mHasBluetooth) return;
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
mAdapter = manager.getAdapter();
assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
@@ -90,6 +95,8 @@
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
}
}
@@ -139,21 +146,6 @@
mBluetoothHapClient.getConnectionState(testDevice));
}
- public void testGetHapGroup() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
- assertTrue(waitForProfileConnect());
- assertNotNull(mBluetoothHapClient);
-
- BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
-
- // Verify returns BluetoothHapClient.HAP_GROUP_UNAVAILABLE if bluetooth is not enabled
- assertEquals(BluetoothHapClient.HAP_GROUP_UNAVAILABLE,
- mBluetoothHapClient.getHapGroup(testDevice));
- }
-
public void testGetActivePresetIndex() {
if (!(mHasBluetooth && mIsHapClientSupported)) return;
@@ -164,11 +156,11 @@
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- // Verify returns false if bluetooth is not enabled
- mBluetoothHapClient.getActivePresetIndex(testDevice);
+ // Verify returns null if bluetooth is not enabled
+ assertNull(mBluetoothHapClient.getActivePresetInfo(testDevice));
}
- public void testSelectActivePreset() {
+ public void testSelectPreset() {
if (!(mHasBluetooth && mIsHapClientSupported)) return;
assertTrue(waitForProfileConnect());
@@ -178,25 +170,21 @@
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- // Verify returns false if bluetooth is not enabled
mBluetoothHapClient.selectPreset(testDevice, 1);
}
- public void testGroupSelectActivePreset() {
+ public void testSelectPresetForGroup() {
if (!(mHasBluetooth && mIsHapClientSupported)) return;
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
- BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- // Verify returns false if bluetooth is not enabled
mBluetoothHapClient.selectPresetForGroup(1, 1);
}
- public void testGetPresetInfo() {
+ public void testGetAllPresetInfo() {
if (!(mHasBluetooth && mIsHapClientSupported)) return;
assertTrue(waitForProfileConnect());
@@ -206,36 +194,9 @@
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- // Verify returns false if bluetooth is not enabled
- mBluetoothHapClient.getPresetInfo(testDevice, 1);
- }
-
- public void testGetAllPresetsInfo() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
- assertTrue(waitForProfileConnect());
- assertNotNull(mBluetoothHapClient);
-
- BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
-
- // Verify returns false if bluetooth is not enabled
- mBluetoothHapClient.getAllPresetInfo(testDevice);
- }
-
- public void testGetFeatures() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
- assertTrue(waitForProfileConnect());
- assertNotNull(mBluetoothHapClient);
-
- BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
-
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
-
- // Verify returns false if bluetooth is not enabled
- assertFalse(mBluetoothHapClient.getFeatures(testDevice));
+ // Verify returns empty list if bluetooth is not enabled
+ List<BluetoothHapPresetInfo> presets = mBluetoothHapClient.getAllPresetInfo(testDevice);
+ assertTrue(presets.isEmpty());
}
public void testSetPresetName() {
@@ -248,11 +209,10 @@
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- // Verify returns false if bluetooth is not enabled
mBluetoothHapClient.setPresetName(testDevice, 1 , "New Name");
}
- public void testGroupSetPresetName() {
+ public void testSetPresetNameForGroup() {
if (!(mHasBluetooth && mIsHapClientSupported)) return;
assertTrue(waitForProfileConnect());
@@ -260,7 +220,6 @@
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- // Verify returns false if bluetooth is not enabled
mBluetoothHapClient.setPresetNameForGroup(1, 1 , "New Name");
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecStatusTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecStatusTest.java
index 5f8ccb7..2ffb577 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecStatusTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecStatusTest.java
@@ -61,14 +61,14 @@
assertTrue(LE_MONO_CODEC_STATUS.getCodecConfig().equals(LC3_MONO_CONFIG));
}
- public void testGetCodecsLocalCapabilities() {
+ public void testGetCodecLocalCapabilities() {
assertTrue(
- LE_STEREO_CODEC_STATUS.getCodecsLocalCapabilities().equals(CAPABILITIES_CONFIG));
+ LE_STEREO_CODEC_STATUS.getCodecLocalCapabilities().equals(CAPABILITIES_CONFIG));
}
- public void testGetCodecsSelectableCapabilities() {
+ public void testGetCodecSelectableCapabilities() {
assertTrue(
- LE_STEREO_CODEC_STATUS.getCodecsSelectableCapabilities().equals(SELECTABLE_CONFIG));
+ LE_STEREO_CODEC_STATUS.getCodecSelectableCapabilities().equals(SELECTABLE_CONFIG));
}
public void testIsCodecConfigSelectable() {
@@ -88,8 +88,8 @@
BluetoothLeAudioCodecStatus.CREATOR.createFromParcel(parcel);
assertTrue(codecStatusFromParcel.getCodecConfig().equals(LC3_STEREO_CONFIG));
assertTrue(
- codecStatusFromParcel.getCodecsLocalCapabilities().equals(CAPABILITIES_CONFIG));
+ codecStatusFromParcel.getCodecLocalCapabilities().equals(CAPABILITIES_CONFIG));
assertTrue(
- codecStatusFromParcel.getCodecsSelectableCapabilities().equals(SELECTABLE_CONFIG));
+ codecStatusFromParcel.getCodecSelectableCapabilities().equals(SELECTABLE_CONFIG));
}
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java
index 38599f5..c51142e 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecTest.java
@@ -85,16 +85,6 @@
}
}
- public void testGetMaxCodecType() {
- try {
- // Checks the supported codec is greater than zero
- // Keeps the flexibility to allow custom codec.
- assertTrue(BluetoothLeAudioCodecConfig.getMaxCodecType() > 0);
- } catch (Exception e) {
- fail(e.getMessage());
- }
- }
-
public void testGetCodecPriority() {
for (int priorityIdx = 0; priorityIdx < mCodecPriorityArray.length; priorityIdx++) {
int codecPriority = mCodecPriorityArray[priorityIdx];
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
index 214645f..6b349e7 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
@@ -16,9 +16,12 @@
package android.bluetooth.cts;
+import static org.junit.Assert.assertThrows;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeAudio;
+import android.bluetooth.BluetoothLeAudioCodecConfig;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.pm.PackageManager;
@@ -27,6 +30,8 @@
import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
import com.android.compatibility.common.util.ApiLevelUtil;
import java.util.List;
@@ -58,6 +63,9 @@
PackageManager.FEATURE_BLUETOOTH);
if (!mHasBluetooth) return;
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
+
BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
mAdapter = manager.getAdapter();
assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
@@ -90,6 +98,8 @@
mIsProfileReady = false;
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
mAdapter = null;
}
}
@@ -155,6 +165,60 @@
mBluetoothLeAudio.getAudioLocation(testDevice));
}
+ public void test_setgetConnectionPolicy() {
+ if (!(mHasBluetooth && mIsLeAudioSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeAudio);
+
+ assertFalse(mBluetoothLeAudio.setConnectionPolicy(null, 0));
+ assertEquals(BluetoothProfile.CONNECTION_POLICY_FORBIDDEN,
+ mBluetoothLeAudio.getConnectionPolicy(null));
+ }
+
+ public void test_setVolume() {
+ if (!(mHasBluetooth && mIsLeAudioSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeAudio);
+
+ // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
+ assertThrows(SecurityException.class, () -> mBluetoothLeAudio.setVolume(42));
+ }
+
+ public void testGetCodecStatus() {
+ if (!(mHasBluetooth && mIsLeAudioSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeAudio);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertNull(mBluetoothLeAudio.getCodecStatus(testDevice));
+ assertThrows(IllegalArgumentException.class, () -> {
+ mBluetoothLeAudio.getCodecStatus(null);
+ });
+ }
+
+ public void testSetCodecConfigPreference() {
+ if (!(mHasBluetooth && mIsLeAudioSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeAudio);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ BluetoothLeAudioCodecConfig codecConfig = new BluetoothLeAudioCodecConfig.Builder()
+ .setCodecType(BluetoothLeAudioCodecConfig.SOURCE_CODEC_TYPE_LC3)
+ .setCodecPriority(0)
+ .build();
+ mBluetoothLeAudio.setCodecConfigPreference(testDevice, codecConfig);
+ assertNull(mBluetoothLeAudio.getCodecStatus(testDevice));
+ assertThrows(IllegalArgumentException.class, () -> {
+ mBluetoothLeAudio.setCodecConfigPreference(null, null);
+ });
+ }
+
private boolean waitForProfileConnect() {
mProfileConnectedlock.lock();
try {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
index 4894546..1118fd8 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
@@ -33,9 +33,9 @@
import android.os.Build;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
@@ -81,6 +81,8 @@
if (!mHasBluetooth) {
return;
}
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
mAdapter = manager.getAdapter();
assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
@@ -123,6 +125,8 @@
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
}
}
@@ -182,7 +186,7 @@
return;
}
if (mAdapter.isLeAudioBroadcastAssistantSupported()
- == BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED) {
+ == BluetoothStatusCodes.FEATURE_NOT_SUPPORTED) {
assertFalse(mIsLeBroadcastAssistantSupported);
return;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
index 0aeff6f..1ad8e3b 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
@@ -179,7 +179,7 @@
return;
}
if (mAdapter.isLeAudioBroadcastSourceSupported()
- == BluetoothStatusCodes.ERROR_FEATURE_NOT_SUPPORTED) {
+ == BluetoothStatusCodes.FEATURE_NOT_SUPPORTED) {
assertFalse(mIsLeBroadcastSupported);
return;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
index 1036095..828de6a 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
@@ -27,7 +27,6 @@
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.os.ParcelUuid;
import android.os.SystemClock;
import android.test.AndroidTestCase;
@@ -76,6 +75,8 @@
if (!TestUtils.isBleSupported(getContext())) {
return;
}
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
BluetoothManager manager = (BluetoothManager) mContext.getSystemService(
Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();
@@ -102,6 +103,8 @@
TestUtils.disableLocation(getContext());
}
assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
}
/**
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
new file mode 100644
index 0000000..dfe22d1
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static org.junit.Assert.assertThrows;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothSap;
+import android.content.pm.PackageManager;
+import android.sysprop.BluetoothProperties;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class BluetoothSapTest extends AndroidTestCase {
+ private static final String TAG = BluetoothLeAudioTest.class.getSimpleName();
+
+ private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
+
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+
+ private BluetoothSap mBluetoothSap;
+ private boolean mIsProfileReady;
+ private Condition mConditionProfileIsConnected;
+ private ReentrantLock mProfileConnectedlock;
+
+ private boolean mIsSapSupported;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH);
+
+ if (!mHasBluetooth) return;
+
+ mIsSapSupported = BluetoothProperties.isProfileSapServerEnabled().orElse(false);
+ if (!mIsSapSupported) return;
+
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
+
+ mAdapter = getContext().getSystemService(BluetoothManager.class).getAdapter();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mProfileConnectedlock = new ReentrantLock();
+ mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+ mIsProfileReady = false;
+ mBluetoothSap = null;
+
+ mAdapter.getProfileProxy(getContext(), new BluetoothSapServiceListener(),
+ BluetoothProfile.SAP);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (mHasBluetooth && mIsSapSupported) {
+ if (mAdapter != null && mBluetoothSap != null) {
+ mBluetoothSap.close();
+ mBluetoothSap = null;
+ mIsProfileReady = false;
+ }
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ mAdapter = null;
+ }
+ }
+
+ public void test_setgetConnectionPolicy() {
+ if (!mHasBluetooth || !mIsSapSupported) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothSap);
+
+ assertThrows(NullPointerException.class, () -> mBluetoothSap.setConnectionPolicy(null, 0));
+ assertThrows(NullPointerException.class, () -> mBluetoothSap.getConnectionPolicy(null));
+ }
+
+ private boolean waitForProfileConnect() {
+ mProfileConnectedlock.lock();
+ try {
+ // Wait for the Adapter to be disabled
+ while (!mIsProfileReady) {
+ if (!mConditionProfileIsConnected.await(
+ PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ // Timeout
+ Log.e(TAG, "Timeout while waiting for Profile Connect");
+ break;
+ } // else spurious wakeups
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "waitForProfileConnect: interrrupted");
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ return mIsProfileReady;
+ }
+
+ private final class BluetoothSapServiceListener implements BluetoothProfile.ServiceListener {
+
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ mProfileConnectedlock.lock();
+ mBluetoothSap = (BluetoothSap) proxy;
+ mIsProfileReady = true;
+ try {
+ mConditionProfileIsConnected.signal();
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ }
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BufferConstraintsTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BufferConstraintsTest.java
index cc29ccf..1e0ff7b 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BufferConstraintsTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BufferConstraintsTest.java
@@ -60,7 +60,7 @@
}
mBufferConstraints = new BufferConstraints(mBufferConstraintList);
- for (int i = 0; i < BluetoothCodecConfig.getMaxCodecType(); i++) {
+ for (int i = 0; i < 6; i++) {
assertEquals(DEFAULT_BUFFER_TIME, mBufferConstraints.forCodec(i).getDefaultMillis());
assertEquals(MAXIMUM_BUFFER_TIME, mBufferConstraints.forCodec(i).getMaxMillis());
assertEquals(MINIMUM_BUFFER_TIME, mBufferConstraints.forCodec(i).getMinMillis());
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
index 4e1419a..570633e 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
@@ -16,6 +16,11 @@
package android.bluetooth.cts;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import static org.junit.Assert.assertThrows;
+
+import android.app.UiAutomation;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHearingAid;
@@ -30,13 +35,14 @@
import android.test.suitebuilder.annotation.MediumTest;
import android.util.Log;
-import java.io.IOException;
-import java.util.List;
+import androidx.test.InstrumentationRegistry;
+
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.TimeUnit;
/**
* Unit test cases for {@link BluetoothHearingAid}.
@@ -61,6 +67,7 @@
private BluetoothHearingAid mService;
private BluetoothAdapter mBluetoothAdapter;
private BroadcastReceiver mIntentReceiver;
+ private UiAutomation mUiAutomation;;
private Condition mConditionProfileIsConnected;
private ReentrantLock mProfileConnectedlock;
@@ -76,15 +83,14 @@
if (!isBleSupported()) return;
mIsBleSupported = true;
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+
BluetoothManager manager = (BluetoothManager) mContext.getSystemService(
Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = manager.getAdapter();
- if (!BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext)) {
- Log.e(TAG, "Unable to enable Bluetooth Adapter!");
- assertTrue(mBluetoothAdapter.isEnabled());
- }
-
+ assertTrue(BTAdapterUtils.enableAdapter(mBluetoothAdapter, mContext));
mProfileConnectedlock = new ReentrantLock();
mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
mIsProfileReady = false;
@@ -99,10 +105,8 @@
public void tearDown() {
if (!mIsBleSupported) return;
- if (!BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext)) {
- Log.e(TAG, "Unable to disable Bluetooth Adapter!");
- assertTrue(mBluetoothAdapter.isEnabled());
- }
+ assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
+ mUiAutomation.dropShellPermissionIdentity();
}
/**
@@ -140,6 +144,24 @@
}
/**
+ * Basic test case to make sure that a fictional device is disconnected.
+ */
+ @MediumTest
+ public void test_setVolume() {
+ if (!(mIsBleSupported && mIsHearingAidSupported)) {
+ return;
+ }
+
+ waitForProfileConnect();
+ assertTrue(mIsProfileReady);
+ assertNotNull(mService);
+
+ // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
+ assertThrows(SecurityException.class, () -> mService.setVolume(42));
+ }
+
+
+ /**
* Basic test case to get the list of connected Hearing Aid devices.
*/
@MediumTest
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java
index b9a93a1..d152d84 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java
@@ -19,7 +19,8 @@
import android.bluetooth.BluetoothServerSocket;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
import java.io.IOException;
@@ -35,6 +36,8 @@
if (!TestUtils.isBleSupported(getContext())) {
return;
}
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
mAdapter = BluetoothAdapter.getDefaultAdapter();
assertNotNull("BluetoothAdapter.getDefaultAdapter() returned null. "
+ "Does this device have a Bluetooth adapter?", mAdapter);
@@ -50,6 +53,8 @@
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
super.tearDown();
}
diff --git a/tests/tests/content/OWNERS b/tests/tests/content/OWNERS
index 5f3add2..41e033d 100644
--- a/tests/tests/content/OWNERS
+++ b/tests/tests/content/OWNERS
@@ -1,7 +1,8 @@
# Bug component: 36137
+alexbuy@google.com
+chiuwinson@google.com
patb@google.com
schfan@google.com
-alexbuy@google.com
zyy@google.com
per-file ContextTest.java = jacobhobbie@google.com,mpgroover@google.com
per-file ClipboardAutoClearTest.java = olekarg@google.com,ewol@google.com
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/cts/LocusIdTest.java b/tests/tests/content/src/android/content/cts/LocusIdTest.java
index e386f47..c0636e0 100644
--- a/tests/tests/content/src/android/content/cts/LocusIdTest.java
+++ b/tests/tests/content/src/android/content/cts/LocusIdTest.java
@@ -81,7 +81,7 @@
try {
// Write to parcel
- parcel.setDataPosition(0); // Sanity / paranoid check
+ parcel.setDataPosition(0); // Initial check
original.writeToParcel(parcel, 0);
// Read from parcel
diff --git a/tests/tests/dreams/OWNERS b/tests/tests/dreams/OWNERS
index f70efe9..f8c069e 100644
--- a/tests/tests/dreams/OWNERS
+++ b/tests/tests/dreams/OWNERS
@@ -1,3 +1,6 @@
# Bug component: 345010
+brycelee@google.com
+galinap@google.com
+jjaggi@google.com
michaelwr@google.com
santoscordon@google.com
diff --git a/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java b/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java
index c6e4b96..1bb1106 100644
--- a/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/OpenGlEsDeqpLevelTest.java
@@ -16,16 +16,16 @@
package android.graphics.cts;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
+import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.platform.test.annotations.AppModeFull;
-import android.util.Log;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.PropertyUtil;
@@ -42,31 +42,37 @@
@AppModeFull(reason = "Instant apps cannot access ro.board.* system properties")
public class OpenGlEsDeqpLevelTest {
- private static final String TAG = OpenGlEsDeqpLevelTest.class.getSimpleName();
- private static final boolean DEBUG = false;
-
private static final int MINIMUM_OPENGLES_DEQP_LEVEL = 0x07E40301; // Corresponds to 2020-03-01
- private PackageManager mPm;
+ private FeatureInfo mFeatureGlesDeqpLevel = null;
@Before
public void setup() {
- mPm = InstrumentationRegistry.getTargetContext().getPackageManager();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+ final FeatureInfo[] features = pm.getSystemAvailableFeatures();
+ if (features != null) {
+ for (FeatureInfo feature : features) {
+ if (PackageManager.FEATURE_OPENGLES_DEQP_LEVEL.equals(feature.name)) {
+ mFeatureGlesDeqpLevel = feature;
+ }
+ }
+ }
}
@Test
public void testOpenGlEsDeqpLevel() {
assumeTrue(
- "Test only applies for vendor image with API level >= 31 (Android 12)",
- PropertyUtil.isVendorApiLevelNewerThan(30));
- if (DEBUG) {
- Log.d(TAG, "Checking whether " + PackageManager.FEATURE_OPENGLES_DEQP_LEVEL
- + " has an acceptable value");
- }
- assertTrue("Feature " + PackageManager.FEATURE_OPENGLES_DEQP_LEVEL + " must be present "
- + "and have at least version " + MINIMUM_OPENGLES_DEQP_LEVEL,
- mPm.hasSystemFeature(PackageManager.FEATURE_OPENGLES_DEQP_LEVEL,
- MINIMUM_OPENGLES_DEQP_LEVEL));
- }
+ "Test only applies for API level >= 31 (Android 12)",
+ PropertyUtil.getVsrApiLevel() >= 31);
+ if (mFeatureGlesDeqpLevel == null
+ || mFeatureGlesDeqpLevel.version < MINIMUM_OPENGLES_DEQP_LEVEL) {
+ String message = String.format(
+ "Feature %s must be present and have at least version %d.",
+ PackageManager.FEATURE_OPENGLES_DEQP_LEVEL, MINIMUM_OPENGLES_DEQP_LEVEL);
+ message += "\nActual feature value: " + mFeatureGlesDeqpLevel;
+ fail(message);
+ }
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java b/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
index 1b41d09..379a732 100644
--- a/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/SetFrameRateTest.java
@@ -20,16 +20,16 @@
import static org.junit.Assert.assertTrue;
-import android.app.UiAutomation;
+import android.Manifest;
import android.content.Context;
-import android.util.Log;
+import android.hardware.display.DisplayManager;
import android.view.Surface;
-import android.view.SurfaceControl;
import androidx.test.filters.MediumTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import com.android.compatibility.common.util.DisplayUtil;
import org.junit.After;
@@ -46,38 +46,39 @@
@Rule
public ActivityTestRule<FrameRateCtsActivity> mActivityRule =
new ActivityTestRule<>(FrameRateCtsActivity.class);
- private long mFrameRateFlexibilityToken;
+
+ @Rule
+ public final AdoptShellPermissionsRule mShellPermissionsRule =
+ new AdoptShellPermissionsRule(getInstrumentation().getUiAutomation(),
+ Manifest.permission.HDMI_CEC,
+ Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+ Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE);
+
+ private DisplayManager mDisplayManager;
+ private int mInitialRefreshRateSwitchingType;
@Before
public void setUp() throws Exception {
- // Surface flinger requires the ACCESS_SURFACE_FLINGER permission to acquire a frame
- // rate flexibility token. Switch to shell permission identity so we'll have the
- // necessary permission when surface flinger checks.
- UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
- uiAutomation.adoptShellPermissionIdentity();
-
Context context = getInstrumentation().getTargetContext();
assertTrue("Physical display is expected.", DisplayUtil.isDisplayConnected(context));
- try {
- // Take ownership of the frame rate flexibility token, if we were able
- // to get one - we'll release it in tearDown().
- mFrameRateFlexibilityToken = SurfaceControl.acquireFrameRateFlexibilityToken();
- } finally {
- uiAutomation.dropShellPermissionIdentity();
- }
+ FrameRateCtsActivity activity = mActivityRule.getActivity();
- if (mFrameRateFlexibilityToken == 0) {
- Log.e(TAG, "Failed to acquire frame rate flexibility token."
- + " SetFrameRate tests may fail.");
- }
+ // Prevent DisplayManager from limiting the allowed refresh rate range based on
+ // non-app policies (e.g. low battery, user settings, etc).
+ mDisplayManager = activity.getSystemService(DisplayManager.class);
+ mDisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
+
+ mInitialRefreshRateSwitchingType = DisplayUtil.getRefreshRateSwitchingType(mDisplayManager);
+ mDisplayManager.setRefreshRateSwitchingType(
+ DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS);
}
@After
public void tearDown() {
- if (mFrameRateFlexibilityToken != 0) {
- SurfaceControl.releaseFrameRateFlexibilityToken(mFrameRateFlexibilityToken);
- mFrameRateFlexibilityToken = 0;
+ if (mDisplayManager != null) {
+ mDisplayManager.setRefreshRateSwitchingType(mInitialRefreshRateSwitchingType);
+ mDisplayManager.setShouldAlwaysRespectAppRequestedMode(false);
}
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java b/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
index 277ca80..178a449 100644
--- a/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/VulkanDeqpLevelTest.java
@@ -16,17 +16,16 @@
package android.graphics.cts;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.platform.test.annotations.AppModeFull;
-import android.util.Log;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.PropertyUtil;
@@ -44,29 +43,26 @@
@AppModeFull(reason = "Instant apps cannot access ro.board.* system properties")
public class VulkanDeqpLevelTest {
- private static final String TAG = VulkanDeqpLevelTest.class.getSimpleName();
- private static final boolean DEBUG = false;
-
private static final int MINIMUM_VULKAN_DEQP_LEVEL = 0x07E30301; // Corresponds to 2019-03-01
// Require patch version 3 for Vulkan 1.0: It was the first publicly available version,
// and there was an important bugfix relative to 1.0.2.
private static final int VULKAN_1_0 = 0x00400003; // 1.0.3
- private PackageManager mPm;
private FeatureInfo mVulkanHardwareVersion = null;
+ private FeatureInfo mFeatureVulkanDeqpLevel = null;
@Before
public void setup() {
- mPm = InstrumentationRegistry.getTargetContext().getPackageManager();
- FeatureInfo[] features = mPm.getSystemAvailableFeatures();
+ final PackageManager pm =
+ InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
+ final FeatureInfo[] features = pm.getSystemAvailableFeatures();
if (features != null) {
for (FeatureInfo feature : features) {
if (PackageManager.FEATURE_VULKAN_HARDWARE_VERSION.equals(feature.name)) {
mVulkanHardwareVersion = feature;
- if (DEBUG) {
- Log.d(TAG, feature.name + "=0x" + Integer.toHexString(feature.version));
- }
+ } else if (PackageManager.FEATURE_VULKAN_DEQP_LEVEL.equals(feature.name)) {
+ mFeatureVulkanDeqpLevel = feature;
}
}
}
@@ -76,19 +72,20 @@
@Test
public void testVulkanDeqpLevel() {
assumeTrue(
- "Test only applies for vendor image with API level >= 30 (Android 11)",
- PropertyUtil.isVendorApiLevelNewerThan(29));
+ "Test only applies for API level >= 30 (Android 11)",
+ PropertyUtil.getVsrApiLevel() >= 30);
+
assumeTrue(
"Test does not apply if Vulkan 1.0 or higher is not supported",
mVulkanHardwareVersion != null && mVulkanHardwareVersion.version >= VULKAN_1_0);
- if (DEBUG) {
- Log.d(TAG, "Checking whether " + PackageManager.FEATURE_VULKAN_DEQP_LEVEL
- + " has an acceptable value");
- }
- assertTrue("Feature " + PackageManager.FEATURE_VULKAN_DEQP_LEVEL + " must be present "
- + "and have at least version " + MINIMUM_VULKAN_DEQP_LEVEL,
- mPm.hasSystemFeature(PackageManager.FEATURE_VULKAN_DEQP_LEVEL,
- MINIMUM_VULKAN_DEQP_LEVEL));
- }
+ if (mFeatureVulkanDeqpLevel == null
+ || mFeatureVulkanDeqpLevel.version < MINIMUM_VULKAN_DEQP_LEVEL) {
+ String message = String.format(
+ "Feature %s must be present and have at least version %d.",
+ PackageManager.FEATURE_VULKAN_DEQP_LEVEL, MINIMUM_VULKAN_DEQP_LEVEL);
+ message += "\nActual feature value: " + mFeatureVulkanDeqpLevel;
+ fail(message);
+ }
+ }
}
diff --git a/tests/tests/jni/Android.bp b/tests/tests/jni/Android.bp
index ddb21ce..5aa391f 100644
--- a/tests/tests/jni/Android.bp
+++ b/tests/tests/jni/Android.bp
@@ -44,6 +44,7 @@
srcs: ["src/**/*.java"],
sdk_version: "test_current",
use_embedded_native_libs: false,
+ per_testcase_directory: true,
}
cc_test_library {
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
index 45b2683..a1cb4bc 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
+++ b/tests/tests/jni/libjnitest/android_jni_cts_LinkerNamespacesTest.cpp
@@ -80,15 +80,6 @@
static const std::string kWebViewPlatSupportLib = "libwebviewchromium_plat_support.so";
-static bool is_directory(const char* path) {
- struct stat sb;
- if (stat(path, &sb) != -1) {
- return S_ISDIR(sb.st_mode);
- }
-
- return false;
-}
-
static bool not_accessible(const std::string& err) {
return err.find("dlopen failed: library \"") == 0 &&
err.find("is not accessible for the namespace \"classloader-namespace\"") != std::string::npos;
@@ -305,11 +296,19 @@
}
std::string path = dir + "/" + dp->d_name;
- if (is_directory(path.c_str())) {
- dirs.push(path);
- } else if (!check_lib(env, clazz, path, library_search_paths, public_library_basenames,
- test_system_load_library, check_absence, errors)) {
- success = false;
+ struct stat sb;
+ // Use lstat to not dereference a symlink. If it links out of library_path
+ // it can be ignored because the Bionic linker derefences symlinks before
+ // checking the path. If it links inside library_path we'll get to the
+ // link target anyway.
+ if (lstat(path.c_str(), &sb) != -1) {
+ if (S_ISDIR(sb.st_mode)) {
+ dirs.push(path);
+ } else if (!S_ISLNK(sb.st_mode) &&
+ !check_lib(env, clazz, path, library_search_paths, public_library_basenames,
+ test_system_load_library, check_absence, errors)) {
+ success = false;
+ }
}
}
}
diff --git a/tests/tests/keystore/OWNERS b/tests/tests/keystore/OWNERS
index 30685c8..21e2825 100644
--- a/tests/tests/keystore/OWNERS
+++ b/tests/tests/keystore/OWNERS
@@ -2,3 +2,5 @@
swillden@google.com
jdanis@google.com
jbires@google.com
+eranm@google.com
+drysdale@google.com
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index 94dd585..e6de053 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -16,6 +16,8 @@
package android.keystore.cts;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -42,6 +44,9 @@
import com.google.common.collect.ObjectArrays;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.security.AlgorithmParameters;
@@ -49,10 +54,10 @@
import java.security.Key;
import java.security.KeyStoreException;
import java.security.Provider;
+import java.security.Provider.Service;
import java.security.Security;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec;
-import java.security.Provider.Service;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
@@ -74,9 +79,6 @@
import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
/**
* Tests for algorithm-agnostic functionality of {@code Cipher} implementations backed by Android
* Keystore.
@@ -1205,6 +1207,7 @@
fail("Importing auth bound keys to an insecure device should fail");
} catch (KeyStoreException e) {
// Expected behavior
+ assertThat(e.getCause()).isInstanceOf(IllegalStateException.class);
}
}
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java b/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
index 4b66992..e61d2b3 100644
--- a/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/ImportWrappedKeyTest.java
@@ -25,16 +25,16 @@
import static android.security.keymaster.KeymasterDefs.KM_PAD_PKCS7;
import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_DECRYPT;
import static android.security.keymaster.KeymasterDefs.KM_PURPOSE_ENCRYPT;
-import static android.security.keystore.KeyProperties.PURPOSE_WRAP_KEY;
+
+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.assertTrue;
import static org.junit.Assert.fail;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.keystore.cts.util.TestUtils;
-import android.os.SystemProperties;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
import android.security.keystore.SecureKeyImportUnavailableException;
@@ -52,6 +52,8 @@
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERSet;
import org.bouncycastle.asn1.DERTaggedObject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
import java.security.Key;
import java.security.KeyPair;
@@ -63,7 +65,6 @@
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec;
-import java.security.spec.RSAKeyGenParameterSpec;
import java.util.Arrays;
import javax.crypto.Cipher;
@@ -74,16 +75,6 @@
import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
-import java.lang.Process;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.lang.InterruptedException;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
@RunWith(AndroidJUnit4.class)
public class ImportWrappedKeyTest {
private static final String TAG = "ImportWrappedKeyTest";
@@ -146,20 +137,24 @@
@Test
public void testKeyStore_ImportWrappedKeyWrappingKeyMissing() throws Exception {
final String EXPECTED_FAILURE = "Failed to import wrapped key. Keystore error code: 7";
- String failureMessage = null;
+ KeyStoreException exception = null;
try {
byte [] fakeWrappedKey = new byte[1];
importWrappedKey(fakeWrappedKey, WRAPPING_KEY_ALIAS + "_Missing");
} catch (KeyStoreException e) {
- failureMessage = e.getMessage();
+ exception = e;
+
}
- if (failureMessage == null) {
- fail("Did not hit a failure but expected one");
- }
+ assertWithMessage("Did not hit a failure but expected one").that(exception).isNotNull();
- assertEquals(failureMessage, EXPECTED_FAILURE);
+ assertThat(exception.getMessage()).isEqualTo(EXPECTED_FAILURE);
+ assertThat(exception.getCause()).isInstanceOf(android.security.KeyStoreException.class);
+ android.security.KeyStoreException ksException =
+ (android.security.KeyStoreException) exception.getCause();
+ assertThat(ksException.getNumericErrorCode()).isEqualTo(
+ android.security.KeyStoreException.ERROR_KEY_DOES_NOT_EXIST);
}
@Test
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 27e2f30..d182cfc 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -46,7 +46,6 @@
import static android.security.keystore.KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
import static android.security.keystore.KeyProperties.SIGNATURE_PADDING_RSA_PSS;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.either;
@@ -54,7 +53,6 @@
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -77,18 +75,22 @@
import android.security.keystore.KeyProperties;
import android.util.ArraySet;
import android.util.Log;
+
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.RequiresDevice;
import androidx.test.runner.AndroidJUnit4;
import com.google.common.collect.ImmutableSet;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.io.File;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
-import java.security.Key;
-import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
@@ -106,14 +108,9 @@
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+
import javax.crypto.KeyGenerator;
-import org.bouncycastle.asn1.x500.X500Name;
-import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
/**
* Tests for Android Keystore attestation.
*/
@@ -211,10 +208,11 @@
curves[curveIndex], keySizes[curveIndex],
purposes[purposeIndex], devicePropertiesAttestation);
} catch (Throwable e) {
- if (devicePropertiesAttestation
- && (e.getCause() instanceof KeyStoreException)
- && KM_ERROR_CANNOT_ATTEST_IDS ==
- ((KeyStoreException) e.getCause()).getErrorCode()) {
+ boolean isIdAttestationFailure =
+ (e.getCause() instanceof KeyStoreException)
+ && KeyStoreException.ERROR_ID_ATTESTATION_FAILURE
+ == ((KeyStoreException) e.getCause()).getNumericErrorCode();
+ if (devicePropertiesAttestation && isIdAttestationFailure) {
Log.i(TAG, "key attestation with device IDs not supported; "
+ "test skipped");
continue;
@@ -232,6 +230,19 @@
}
}
+ private void assertPublicAttestationError(KeyStoreException keyStoreException,
+ boolean devicePropertiesAttestation) {
+ // Assert public failure information.
+ int errorCode = keyStoreException.getNumericErrorCode();
+ String assertMessage = String.format(
+ "Error code was %d, device properties attestation? %b",
+ errorCode, devicePropertiesAttestation);
+ assertTrue(assertMessage, KeyStoreException.ERROR_INCORRECT_USAGE == errorCode
+ || (devicePropertiesAttestation
+ && KeyStoreException.ERROR_ID_ATTESTATION_FAILURE == errorCode));
+ assertFalse(keyStoreException.isTransientFailure());
+ }
+
@Test
public void testEcAttestation_TooLargeChallenge() throws Exception {
if (!TestUtils.isAttestationSupported()) {
@@ -250,6 +261,7 @@
(devicePropertiesAttestation
&& KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
);
+ assertPublicAttestationError(cause, devicePropertiesAttestation);
}
}
}
@@ -452,6 +464,9 @@
// Attestation is expected to fail because of lack of permissions.
KeyStoreException cause = (KeyStoreException) e.getCause();
assertEquals(KM_ERROR_PERMISSION_DENIED, cause.getErrorCode());
+ // Assert public failure information.
+ assertEquals(KeyStoreException.ERROR_PERMISSION_DENIED, cause.getNumericErrorCode());
+ assertFalse(cause.isTransientFailure());
} finally {
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
@@ -547,6 +562,7 @@
(devicePropertiesAttestation
&& KM_ERROR_CANNOT_ATTEST_IDS == cause.getErrorCode())
);
+ assertPublicAttestationError(cause, devicePropertiesAttestation);
}
}
}
@@ -685,9 +701,11 @@
testRsaAttestation(challenge, false /* includeValidityDates */, keySize, purpose,
paddings, devicePropertiesAttestation);
} catch (Throwable e) {
- if (devicePropertiesAttestation && (e.getCause() instanceof KeyStoreException)
- && KM_ERROR_CANNOT_ATTEST_IDS ==
- ((KeyStoreException) e.getCause()).getErrorCode()) {
+ boolean isIdAttestationFailure =
+ (e.getCause() instanceof KeyStoreException)
+ && KeyStoreException.ERROR_ID_ATTESTATION_FAILURE
+ == ((KeyStoreException) e.getCause()).getNumericErrorCode();
+ if (devicePropertiesAttestation && isIdAttestationFailure) {
Log.i(TAG, "key attestation with device IDs not supported; test skipped");
continue;
}
@@ -708,6 +726,21 @@
testDeviceIdAttestationFailure(AttestationUtils.ID_TYPE_MEID, "Unable to retrieve MEID");
}
+ @Test
+ public void testMandatoryDeviceidAttestation() {
+ // ID attestation is only mandatory on devices that have shipped with T and
+ // above.
+ if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.S) {
+ return;
+ }
+ // ID attestation is tested by other tests (outside of this class), including negative
+ // tests that ID attestation is failing if the platform does not declare support.
+ // Hence, it's safe to only test here that the feature is supported.
+ PackageManager pm = getContext().getPackageManager();
+ assertThat("As of Android T, devices must support ID attestation",
+ pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ID_ATTESTATION),is(true));
+ }
+
@SuppressWarnings("deprecation")
private void testRsaAttestation(byte[] challenge, boolean includeValidityDates, int keySize,
int purposes, String[] paddingModes, boolean devicePropertiesAttestation)
@@ -1151,9 +1184,6 @@
+ attestation.getAttestationSecurityLevel());
break;
}
-
- assertNull("Software-enforced list must not contain root of trust",
- softwareEnforced.getRootOfTrust());
}
private void checkDeviceLocked(Attestation attestation) {
@@ -1191,7 +1221,9 @@
assertTrue("Verified boot key is only " + rootOfTrust.getVerifiedBootKey().length +
" bytes long", rootOfTrust.getVerifiedBootKey().length >= 32);
if (requireLocked) {
- assertTrue(rootOfTrust.isDeviceLocked());
+ final String unlockedDeviceMessage = "The device's bootloader must be locked. This may "
+ + "not be the default for pre-production devices.";
+ assertTrue(unlockedDeviceMessage, rootOfTrust.isDeviceLocked());
checkEntropy(rootOfTrust.getVerifiedBootKey());
assertEquals(KM_VERIFIED_BOOT_VERIFIED, rootOfTrust.getVerifiedBootState());
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java
new file mode 100644
index 0000000..b79f443
--- /dev/null
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyStoreExceptionTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.keystore.cts;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.security.KeyStoreException;
+import android.security.keymaster.KeymasterDefs;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.lang.reflect.Field;
+
+@RunWith(AndroidJUnit4.class)
+public class KeyStoreExceptionTest {
+ @Test
+ public void testAllKeymasterDefsAreCovered() throws IllegalAccessException {
+ ImmutableList<Field> kmErrors = getKeymasterDefsFields();
+ assertTrue("Test bug: there should be errors to look up",
+ kmErrors.size() > 0);
+
+ for (Field f : kmErrors) {
+ assertTrue(String.format("Missing entry for field %s", f.getName()),
+ KeyStoreException.hasFailureInfoForError(f.getInt(null)));
+ }
+ }
+
+ @Test
+ public void testSystemErrorFlaggedCorrectly() {
+ final int[] someSystemErrors = {-4, -6, -7, -9, -28, -64, -66, -67, -72, -1000, 3, 4};
+ for (int i : someSystemErrors) {
+ KeyStoreException systemEx = new KeyStoreException(i, null);
+ assertTrue("Error code " + i + " is not correctly marked as system error.",
+ systemEx.isSystemError());
+ }
+
+ final int[] someNonSystemErrors = {-3, -5, -8, -11, -29, 6};
+ for (int i : someNonSystemErrors) {
+ KeyStoreException nonSystemEx = new KeyStoreException(i, null);
+ assertFalse("Error code " + i + " is incorrectly marked as system error.",
+ nonSystemEx.isSystemError());
+ }
+ }
+
+ @Test
+ public void testRequiresUserAuthenticationFlaggedCorrectly() {
+ final int[] errorsRequiringAuthentication = {-26, -72, 2};
+
+ for (int i : errorsRequiringAuthentication) {
+ KeyStoreException ex = new KeyStoreException(i, null);
+ assertTrue("Error code " + i + " is not correctly marked as requiring user auth.",
+ ex.requiresUserAuthentication());
+ }
+
+ KeyStoreException regularEx = new KeyStoreException(6 /* permission denied */, null);
+ assertFalse(regularEx.requiresUserAuthentication());
+ }
+
+ public static ImmutableList<Field> getKeymasterDefsFields() {
+ ImmutableList.Builder<Field> errorFieldsBuilder = new ImmutableList.Builder<>();
+
+ Class kmDefsClass = KeymasterDefs.class;
+ for (Field f : kmDefsClass.getDeclaredFields()) {
+ if (f.getName().startsWith("KM_ERROR") && f.getType().equals(int.class)) {
+ errorFieldsBuilder.add(f);
+ }
+ }
+
+ return errorFieldsBuilder.build();
+ }
+}
diff --git a/tests/tests/media/Android.bp b/tests/tests/media/Android.bp
index 7ee7d2a..6e6c902 100644
--- a/tests/tests/media/Android.bp
+++ b/tests/tests/media/Android.bp
@@ -25,161 +25,3 @@
license_kinds: ["SPDX-license-identifier-CC-BY-3.0"],
license_text: ["LICENSE_CC_BY"],
}
-
-java_library {
- name: "ctsmediautil",
- srcs: [
- "common/src/android/media/cts/CodecImage.java",
- "common/src/android/media/cts/YUVImage.java",
- "common/src/android/media/cts/CodecUtils.java",
- "common/src/android/media/cts/CodecState.java",
- "common/src/android/media/cts/MediaCodecTunneledPlayer.java",
- "common/src/android/media/cts/MediaTimeProvider.java",
- "common/src/android/media/cts/NonBlockingAudioTrack.java",
- ],
- static_libs: [
- "compatibility-device-util-axt",
- "platform-test-annotations",
- ],
- platform_apis: true,
- min_sdk_version: "29",
- target_sdk_version: "31",
-}
-
-cc_test_library {
- name: "libctscodecutils_jni",
- srcs: [
- "common/jni/codec-utils-jni.cpp",
- "common/jni/md5_utils.cpp",
- ],
- shared_libs: [
- "libnativehelper_compat_libc++",
- "liblog",
- ],
- header_libs: ["liblog_headers"],
- // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
- // (revisit if/when we add features to this library that require newer sdk.
- sdk_version: "29",
- cflags: [
- "-Werror",
- "-Wall",
- "-DEGL_EGLEXT_PROTOTYPES",
- ],
- stl: "libc++_static",
- gtest: false,
-}
-
-cc_test_library {
- name: "libctsmediacommon_jni",
- srcs: [
- "common/jni/NdkInputSurface-jni.cpp",
- "common/jni/NdkMediaCodec-jni.cpp",
- ],
- shared_libs: [
- "libandroid",
- "libnativehelper_compat_libc++",
- "liblog",
- "libmediandk",
- "libEGL",
- ],
- header_libs: ["liblog_headers"],
- stl: "libc++_static",
- cflags: [
- "-Werror",
- "-Wall",
- "-DEGL_EGLEXT_PROTOTYPES",
- ],
- gtest: false,
- // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
- // (revisit if/when we add features to this library that require newer sdk.
- sdk_version: "29",
-}
-
-android_library {
- name: "cts-media-common",
- srcs: [
- "common/src/**/*.java",
- ],
- static_libs: [
- "androidx.heifwriter_heifwriter",
- "androidx.test.core",
- "androidx.test.ext.junit",
- "compatibility-device-util-axt",
- "junit",
- "platform-test-annotations",
- ],
- platform_apis: true,
- libs: [
- "org.apache.http.legacy",
- "android.test.base",
- "android.test.runner",
- ],
- min_sdk_version: "29",
- target_sdk_version: "31",
-}
-
-android_test {
- name: "CtsMediaTestCases",
- defaults: ["cts_defaults"],
- // include both the 32 and 64 bit versions
- compile_multilib: "both",
- static_libs: [
- "androidx.test.core",
- "androidx.test.ext.junit",
- "compatibility-device-util-axt",
- "ctsdeviceutillegacy-axt",
- "ctsmediautil",
- "ctstestrunner-axt",
- "hamcrest-library",
- "ctstestserver",
- "cts-media-common",
- "junit",
- "junit-params",
- "testng",
- "truth-prebuilt",
- "mockito-target-minus-junit4",
- "androidx.heifwriter_heifwriter",
- "CtsCameraUtils",
- ],
- jni_libs: [
- "libctscodecutils_jni",
- "libctsimagereader_jni",
- "libctsmediacodec_jni",
- "libctsmediacommon_jni",
- "libnativehelper_compat_libc++",
- ],
- asset_dirs: ["assets"],
- resource_dirs: ["res"],
- aaptflags: [
- "--auto-add-overlay",
-
- // Do not compress these files:
- "-0 .vp9",
- "-0 .ts",
- "-0 .heic",
- "-0 .trp",
- "-0 .ota",
- "-0 .mxmf",
- ],
- srcs: [
- "src/**/*.java",
- "aidl/**/*.aidl",
- ],
- // This test uses private APIs
- platform_apis: true,
- jni_uses_sdk_apis: true,
- libs: [
- "org.apache.http.legacy",
- "android.test.base",
- "android.test.runner",
- ],
- // Tag this module as a cts test artifact
- test_suites: [
- "cts",
- "general-tests",
- "mts-media",
- ],
- host_required: ["cts-dynamic-config"],
- min_sdk_version: "29",
- target_sdk_version: "31",
-}
diff --git a/tests/tests/media/DynamicConfig.xml b/tests/tests/media/DynamicConfig.xml
deleted file mode 100644
index 62ba6b7..0000000
--- a/tests/tests/media/DynamicConfig.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<dynamicConfig>
- <entry key="streaming_media_player_test_http_h263_amr_video1">
- <value>http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=13&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=5729247E22691EBB3E804DDD523EC42DC17DD8CE.443B81C1E8E6D64E4E1555F568BA46C206507D78&key=ik0&user=android-device-test</value>
- </entry>
- <entry key="streaming_media_player_test_http_h263_amr_video2">
- <value>http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=13&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=508D82AB36939345BF6B8D0623CB6CABDD9C64C3.9B3336A96846DF38E5343C46AA57F6CF2956E427&key=ik0&user=android-device-test</value>
- </entry>
- <entry key="streaming_media_player_test_http_h264_base_aac_video1">
- <value>http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=667AEEF54639926662CE62361400B8F8C1753B3F.15F46C382C68A9F121BA17BF1F56BEDEB4B06091&key=ik0&user=android-device-test</value>
- </entry>
- <entry key="streaming_media_player_test_http_h264_base_aac_video2">
- <value>http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=18&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=46A04ED550CA83B79B60060BA80C79FDA5853D26.49582D382B4A9AFAA163DED38D2AE531D85603C0&key=ik0&user=android-device-test</value>
- </entry>
- <entry key="streaming_media_player_test_http_mpeg4_sp_aac_video1">
- <value>http://redirector.gvt1.com/videoplayback?id=271de9756065677e&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=837198AAADF6F36BA6B2D324F690A7C5B7AFE3FF.7138CE5E36D718220726C1FC305497FF2D082249&key=ik0&user=android-device-test</value>
- </entry>
- <entry key="streaming_media_player_test_http_mpeg4_sp_aac_video2">
- <value>http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=70E979A621001201BC18622BDBF914FA870BDA40.6E78890B80F4A33A18835F775B1FF64F0A4D0003&key=ik0&user=android-device-test</value>
- </entry>
- <entry key="media_files_url">
- <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/CtsMediaTestCases-1.4.zip</value>
- </entry>
-</dynamicConfig>
diff --git a/tests/tests/media/audio/AndroidManifest.xml b/tests/tests/media/audio/AndroidManifest.xml
index bc7fc4b..9ee8519 100644
--- a/tests/tests/media/audio/AndroidManifest.xml
+++ b/tests/tests/media/audio/AndroidManifest.xml
@@ -23,6 +23,8 @@
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
diff --git a/tests/tests/media/codec/AndroidManifest.xml b/tests/tests/media/codec/AndroidManifest.xml
index 4ff8f2d..328929a 100644
--- a/tests/tests/media/codec/AndroidManifest.xml
+++ b/tests/tests/media/codec/AndroidManifest.xml
@@ -23,7 +23,7 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
-
+ <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
index 00b2e82..4a023a0 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
@@ -31,7 +31,6 @@
import android.opengl.GLES20;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresDevice;
-import android.test.AndroidTestCase;
import android.util.Log;
import androidx.test.filters.FlakyTest;
@@ -42,10 +41,23 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
import javax.microedition.khronos.opengles.GL10;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
/**
* Generates a series of video frames, encodes them, decodes them, and tests for significant
* divergence from the original.
@@ -63,16 +75,14 @@
@RequiresDevice
// TODO: b/186001256
@FlakyTest
-public class EncodeDecodeTest extends AndroidTestCase {
+@RunWith(Parameterized.class)
+public class EncodeDecodeTest {
private static final String TAG = "EncodeDecodeTest";
private static final boolean VERBOSE = false; // lots of logging
private static final boolean DEBUG_SAVE_FILE = false; // save copy of encoded movie
private static final String DEBUG_FILE_NAME_BASE = "/sdcard/test.";
// parameters for the encoder
- // H.264 Advanced Video Coding
- private static final String MIME_TYPE_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final String MIME_TYPE_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
private static final int FRAME_RATE = 15; // 15fps
private static final int IFRAME_INTERVAL = 10; // 10 seconds between I-frames
@@ -96,97 +106,80 @@
private static final int TEST_B1_BT709 = 189;
private static final boolean USE_NDK = true;
+ // component names
+ private final String mEncoderName;
+ private final String mDecoderName;
+ // mime
+ private final String mMimeType;
// size of a frame, in pixels
- private int mWidth = -1;
- private int mHeight = -1;
+ private final int mWidth;
+ private final int mHeight;
// bit rate, in bits per second
- private int mBitRate = -1;
- private String mMimeType = MIME_TYPE_AVC;
-
- // largest color component delta seen (i.e. actual vs. expected)
- private int mLargestColorDelta;
-
+ private final int mBitRate;
// validate YUV->RGB decoded frames against BT.601 and/or BT.709
private boolean mAllowBT601 = true;
private boolean mAllowBT709 = false;
- /**
- * Tests streaming of AVC video through the encoder and decoder. Data is encoded from
- * a series of byte[] buffers and decoded into ByteBuffers. The output is checked for
- * validity.
- */
- public void testEncodeDecodeVideoFromBufferToBufferQCIF() throws Exception {
- setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
- encodeDecodeVideoFromBuffer(false);
- }
- public void testEncodeDecodeVideoFromBufferToBufferQVGA() throws Exception {
- setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
- encodeDecodeVideoFromBuffer(false);
- }
- public void testEncodeDecodeVideoFromBufferToBuffer720p() throws Exception {
- setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
- encodeDecodeVideoFromBuffer(false);
+ // largest color component delta seen (i.e. actual vs. expected)
+ private int mLargestColorDelta;
+
+ static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ int argLength = exhaustiveArgsList.get(0).length;
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (Object[] arg : exhaustiveArgsList) {
+ MediaFormat format = MediaFormat.createVideoFormat((String)arg[0], (Integer)arg[1],
+ (Integer)arg[2]);
+
+ String eName = mcl.findEncoderForFormat(format);
+ String dName = mcl.findDecoderForFormat(format);
+
+ Object[] testArgs = new Object[argLength + 2];
+ testArgs[0] = eName;
+ testArgs[1] = dName;
+ System.arraycopy(arg, 0, testArgs, 2, argLength);
+ argsList.add(testArgs);
+ }
+ return argsList;
}
- /**
- * Tests streaming of VP8 video through the encoder and decoder. Data is encoded from
- * a series of byte[] buffers and decoded into ByteBuffers. The output is checked for
- * validity.
- */
- public void testVP8EncodeDecodeVideoFromBufferToBufferQCIF() throws Exception {
- setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
- encodeDecodeVideoFromBuffer(false);
- }
- public void testVP8EncodeDecodeVideoFromBufferToBufferQVGA() throws Exception {
- setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
- encodeDecodeVideoFromBuffer(false);
- }
- public void testVP8EncodeDecodeVideoFromBufferToBuffer720p() throws Exception {
- setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
- encodeDecodeVideoFromBuffer(false);
+ @Before
+ public void shouldSkip() {
+ MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
+ format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
+ format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
+ assumeTrue(MediaUtils.supports(mEncoderName, format));
+ assumeTrue(MediaUtils.supports(mDecoderName, format));
}
- /**
- * Tests streaming of AVC video through the encoder and decoder. Data is encoded from
- * a series of byte[] buffers and decoded into Surfaces. The output is checked for
- * validity.
- * <p>
- * Because of the way SurfaceTexture.OnFrameAvailableListener works, we need to run this
- * test on a thread that doesn't have a Looper configured. If we don't, the test will
- * pass, but we won't actually test the output because we'll never receive the "frame
- * available" notifications". The CTS test framework seems to be configuring a Looper on
- * the test thread, so we have to hand control off to a new thread for the duration of
- * the test.
- */
- public void testEncodeDecodeVideoFromBufferToSurfaceQCIF() throws Throwable {
- setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
- BufferToSurfaceWrapper.runTest(this);
- }
- public void testEncodeDecodeVideoFromBufferToSurfaceQVGA() throws Throwable {
- setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
- BufferToSurfaceWrapper.runTest(this);
- }
- public void testEncodeDecodeVideoFromBufferToSurface720p() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, true);
- BufferToSurfaceWrapper.runTest(this);
+ @Parameterized.Parameters(name = "{index}({0}:{1})")
+ public static Collection<Object[]> input() {
+ final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+ // Mime, width, height, bit-rate, allow bt601, allow bt709
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 176, 144, 1000000, true, false},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 320, 240, 2000000, true, false},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 6000000, true, true},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 176, 144, 1000000, true, false},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 320, 240, 2000000, true, false},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720, 6000000, true, true},
+ });
+ return prepareParamList(exhaustiveArgsList);
}
- /**
- * Tests streaming of VP8 video through the encoder and decoder. Data is encoded from
- * a series of byte[] buffers and decoded into Surfaces. The output is checked for
- * validity.
- */
- public void testVP8EncodeDecodeVideoFromBufferToSurfaceQCIF() throws Throwable {
- setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
- BufferToSurfaceWrapper.runTest(this);
- }
- public void testVP8EncodeDecodeVideoFromBufferToSurfaceQVGA() throws Throwable {
- setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
- BufferToSurfaceWrapper.runTest(this);
- }
- public void testVP8EncodeDecodeVideoFromBufferToSurface720p() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, true);
- BufferToSurfaceWrapper.runTest(this);
+ public EncodeDecodeTest(String encoder, String decoder, String mimeType, int width, int height,
+ int bitRate, boolean allowBT601, boolean allowBT709) {
+ if ((width % 16) != 0 || (height % 16) != 0) {
+ Log.w(TAG, "WARNING: width or height not multiple of 16");
+ }
+ mEncoderName = encoder;
+ mDecoderName = decoder;
+ mMimeType = mimeType;
+ mWidth = width;
+ mHeight = height;
+ mBitRate = bitRate;
+ mAllowBT601 = allowBT601;
+ mAllowBT709 = allowBT709;
}
/** Wraps testEncodeDecodeVideoFromBuffer(true) */
@@ -221,90 +214,6 @@
}
}
- /**
- * Tests streaming of AVC video through the encoder and decoder. Data is provided through
- * a Surface and decoded onto a Surface. The output is checked for validity.
- */
- public void testEncodeDecodeVideoFromSurfaceToSurfaceQCIF() throws Throwable {
- setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, false);
- }
- public void testEncodeDecodeVideoFromSurfaceToSurfaceQVGA() throws Throwable {
- setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, false);
- }
- public void testEncodeDecodeVideoFromSurfaceToSurface720p() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, false);
- }
- public void testEncodeDecodeVideoFromSurfaceToSurface720pNdk() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, USE_NDK);
- }
-
- /**
- * Tests streaming of AVC video through the encoder and decoder. Data is provided through
- * a PersistentSurface and decoded onto a Surface. The output is checked for validity.
- */
- public void testEncodeDecodeVideoFromPersistentSurfaceToSurfaceQCIF() throws Throwable {
- setParameters(176, 144, 1000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, false);
- }
- public void testEncodeDecodeVideoFromPersistentSurfaceToSurfaceQVGA() throws Throwable {
- setParameters(320, 240, 2000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, false);
- }
- public void testEncodeDecodeVideoFromPersistentSurfaceToSurface720p() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, false);
- }
- public void testEncodeDecodeVideoFromPersistentSurfaceToSurface720pNdk() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_AVC, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, USE_NDK);
- }
-
- /**
- * Tests streaming of VP8 video through the encoder and decoder. Data is provided through
- * a Surface and decoded onto a Surface. The output is checked for validity.
- */
- public void testVP8EncodeDecodeVideoFromSurfaceToSurfaceQCIF() throws Throwable {
- setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, false);
- }
- public void testVP8EncodeDecodeVideoFromSurfaceToSurfaceQVGA() throws Throwable {
- setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, false);
- }
- public void testVP8EncodeDecodeVideoFromSurfaceToSurface720p() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, false);
- }
- public void testVP8EncodeDecodeVideoFromSurfaceToSurface720pNdk() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, false, USE_NDK);
- }
-
- /**
- * Tests streaming of VP8 video through the encoder and decoder. Data is provided through
- * a PersistentSurface and decoded onto a Surface. The output is checked for validity.
- */
- public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurfaceQCIF() throws Throwable {
- setParameters(176, 144, 1000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, false);
- }
- public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurfaceQVGA() throws Throwable {
- setParameters(320, 240, 2000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, false);
- }
- public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurface720p() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, false);
- }
- public void testVP8EncodeDecodeVideoFromPersistentSurfaceToSurface720pNdk() throws Throwable {
- setParameters(1280, 720, 6000000, MIME_TYPE_VP8, true, false);
- SurfaceToSurfaceWrapper.runTest(this, true, USE_NDK);
- }
-
/** Wraps testEncodeDecodeVideoFromSurfaceToSurface() */
private static class SurfaceToSurfaceWrapper implements Runnable {
private Throwable mThrowable;
@@ -320,10 +229,6 @@
@Override
public void run() {
- if (mTest.shouldSkip()) {
- return;
- }
-
InputSurfaceInterface inputSurface = null;
try {
if (!mUsePersistentInput) {
@@ -367,38 +272,6 @@
}
/**
- * Sets the desired frame size and bit rate.
- */
- protected void setParameters(int width, int height, int bitRate, String mimeType,
- boolean allowBT601, boolean allowBT709) {
- if ((width % 16) != 0 || (height % 16) != 0) {
- Log.w(TAG, "WARNING: width or height not multiple of 16");
- }
- mWidth = width;
- mHeight = height;
- mBitRate = bitRate;
- mMimeType = mimeType;
- mAllowBT601 = allowBT601;
- mAllowBT709 = allowBT709;
- }
-
- private boolean shouldSkip() {
- if (!MediaUtils.hasEncoder(mMimeType)) {
- return true;
- }
-
- MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
- format.setInteger(MediaFormat.KEY_BIT_RATE, mBitRate);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
- format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
- if (!MediaUtils.checkEncoderForFormat(format)) {
- return true;
- }
-
- return false;
- }
-
- /**
* Tests encoding and subsequently decoding video from frames generated into a buffer.
* <p>
* We encode several frames of a video test pattern using MediaCodec, then decode the
@@ -407,10 +280,6 @@
* See http://b.android.com/37769 for a discussion of input format pitfalls.
*/
private void encodeDecodeVideoFromBuffer(boolean toSurface) throws Exception {
- if (shouldSkip()) {
- return;
- }
-
MediaCodec encoder = null;
MediaCodec decoder = null;
@@ -420,24 +289,10 @@
// We avoid the device-specific limitations on width and height by using values that
// are multiples of 16, which all tested devices seem to be able to handle.
MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
- MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- String codec = mcl.findEncoderForFormat(format);
- if (codec == null) {
- // Don't fail CTS if they don't have an AVC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + format);
- return;
- }
- if (VERBOSE) Log.d(TAG, "found codec: " + codec);
-
- String codec_decoder = mcl.findDecoderForFormat(format);
- if (codec_decoder == null) {
- Log.e(TAG, "Unable to find an appropriate codec for " + format);
- return;
- }
// Create a MediaCodec for the desired codec, then configure it as an encoder with
// our desired properties.
- encoder = MediaCodec.createByCodecName(codec);
+ encoder = MediaCodec.createByCodecName(mEncoderName);
int colorFormat = selectColorFormat(encoder.getCodecInfo(), mMimeType);
if (VERBOSE) Log.d(TAG, "found colorFormat: " + colorFormat);
@@ -455,7 +310,7 @@
// Create a MediaCodec for the decoder, just based on the MIME type. The various
// format details will be passed through the csd-0 meta-data later on.
- decoder = MediaCodec.createByCodecName(codec_decoder);
+ decoder = MediaCodec.createByCodecName(mDecoderName);
if (VERBOSE) Log.d(TAG, "got decoder: " + decoder.getName());
doEncodeDecodeVideoFromBuffer(encoder, colorFormat, decoder, toSurface);
@@ -492,14 +347,6 @@
// We avoid the device-specific limitations on width and height by using values that
// are multiples of 16, which all tested devices seem to be able to handle.
MediaFormat format = MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
- MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- String codec = mcl.findEncoderForFormat(format);
- if (codec == null) {
- // Don't fail CTS if they don't have an AVC codec (not here, anyway).
- Log.e(TAG, "Unable to find an appropriate codec for " + format);
- return;
- }
- if (VERBOSE) Log.d(TAG, "found codec: " + codec);
int colorFormat = MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
@@ -520,14 +367,7 @@
// Create the output surface.
outputSurface = new OutputSurface(mWidth, mHeight);
- // Create a MediaCodec for the decoder, just based on the MIME type. The various
- // format details will be passed through the csd-0 meta-data later on.
- String codec_decoder = mcl.findDecoderForFormat(format);
- if (codec_decoder == null) {
- Log.e(TAG, "Unable to find an appropriate codec for " + format);
- return;
- }
- decoder = MediaCodec.createByCodecName(codec_decoder);
+ decoder = MediaCodec.createByCodecName(mDecoderName);
if (VERBOSE) Log.d(TAG, "got decoder: " + decoder.getName());
decoder.configure(format, outputSurface.getSurface(), null, 0);
decoder.start();
@@ -535,9 +375,9 @@
// Create a MediaCodec for the desired codec, then configure it as an encoder with
// our desired properties. Request a Surface to use for input.
if (useNdk) {
- encoder = new NdkMediaCodec(codec);
+ encoder = new NdkMediaCodec(mEncoderName);
}else {
- encoder = new SdkMediaCodec(MediaCodec.createByCodecName(codec));
+ encoder = new SdkMediaCodec(MediaCodec.createByCodecName(mEncoderName));
}
encoder.configure(format, MediaCodec.CONFIGURE_FLAG_ENCODE);
if (inSurf != null) {
@@ -759,7 +599,7 @@
// For codecs that don't have codec config data (such as VP8),
// initialize the decoder before trying to decode the first packet.
assertTrue((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 ||
- mMimeType.equals(MIME_TYPE_VP8));
+ mMimeType.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
MediaFormat format =
MediaFormat.createVideoFormat(mMimeType, mWidth, mHeight);
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0)
@@ -1389,4 +1229,59 @@
private static long computePresentationTime(int frameIndex) {
return 132 + frameIndex * 1000000 / FRAME_RATE;
}
+
+ /**
+ * Tests streaming of video through the encoder and decoder. Data is encoded from
+ * a series of byte[] buffers and decoded into ByteBuffers. The output is checked for
+ * validity.
+ */
+ @Test
+ public void testEncodeDecodeVideoFromBufferToBuffer() throws Exception {
+ encodeDecodeVideoFromBuffer(false);
+ }
+
+ /**
+ * Tests streaming of video through the encoder and decoder. Data is encoded from
+ * a series of byte[] buffers and decoded into Surfaces. The output is checked for
+ * validity.
+ * <p>
+ * Because of the way SurfaceTexture.OnFrameAvailableListener works, we need to run this
+ * test on a thread that doesn't have a Looper configured. If we don't, the test will
+ * pass, but we won't actually test the output because we'll never receive the "frame
+ * available" notifications". The CTS test framework seems to be configuring a Looper on
+ * the test thread, so we have to hand control off to a new thread for the duration of
+ * the test.
+ */
+ @Test
+ public void testEncodeDecodeVideoFromBufferToSurface() throws Throwable {
+ BufferToSurfaceWrapper.runTest(this);
+ }
+
+ /**
+ * Tests streaming of AVC through the encoder and decoder. Data is provided through
+ * a Surface and decoded onto a Surface. The output is checked for validity.
+ */
+ @Test
+ public void testEncodeDecodeVideoFromSurfaceToSurface() throws Throwable {
+ SurfaceToSurfaceWrapper.runTest(this, false, false);
+ }
+
+ @Test
+ public void testEncodeDecodeVideoFromSurfaceToSurfaceNdk() throws Throwable {
+ SurfaceToSurfaceWrapper.runTest(this, false, USE_NDK);
+ }
+
+ /**
+ * Tests streaming of video through the encoder and decoder. Data is provided through
+ * a PersistentSurface and decoded onto a Surface. The output is checked for validity.
+ */
+ @Test
+ public void testEncodeDecodeVideoFromSurfaceToPersistentSurface() throws Throwable {
+ SurfaceToSurfaceWrapper.runTest(this, true, false);
+ }
+
+ @Test
+ public void testEncodeDecodeVideoFromSurfaceToPersistentSurfaceNdk() throws Throwable {
+ SurfaceToSurfaceWrapper.runTest(this, true, USE_NDK);
+ }
}
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
index 2ee1137..1dd7651 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
@@ -17,7 +17,6 @@
package android.media.codec.cts;
import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.media.cts.MediaCodecWrapper;
@@ -25,10 +24,23 @@
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
/**
* Verification test for video encoder and decoder.
@@ -40,6 +52,7 @@
*/
@MediaHeavyPresubmitTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
+@RunWith(Parameterized.class)
public class VideoCodecTest extends VideoCodecTestBase {
private static final String ENCODED_IVF_BASE = "football";
@@ -83,6 +96,56 @@
// Maximum allowed key frame interval variation from the target value.
private static final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
+ private static final String CODEC_PREFIX_KEY = "codec-prefix";
+ private static final String mCodecPrefix;
+
+ @Parameterized.Parameter(0)
+ public String mCodecName;
+
+ @Parameterized.Parameter(1)
+ public String mCodecMimeType;
+
+ @Parameterized.Parameter(2)
+ public int mBitRateMode;
+
+ static {
+ android.os.Bundle args = InstrumentationRegistry.getArguments();
+ mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+ }
+
+ static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ int argLength = exhaustiveArgsList.get(0).length;
+ for (Object[] arg : exhaustiveArgsList) {
+ String[] encodersForMime = MediaUtils.getEncoderNamesForMime((String) arg[0]);
+ for (String encoder : encodersForMime) {
+ if (mCodecPrefix != null && !encoder.startsWith(mCodecPrefix)) {
+ continue;
+ }
+ Object[] testArgs = new Object[argLength + 1];
+ testArgs[0] = encoder;
+ System.arraycopy(arg, 0, testArgs, 1, argLength);
+ argsList.add(testArgs);
+ }
+ }
+ return argsList;
+ }
+
+ @Parameterized.Parameters(name = "{index}({0}:{1}:{2})")
+ public static Collection<Object[]> input() {
+ final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+ {VP8_MIME, VIDEO_ControlRateConstant},
+ {VP8_MIME, VIDEO_ControlRateVariable},
+ {VP9_MIME, VIDEO_ControlRateConstant},
+ {VP9_MIME, VIDEO_ControlRateVariable},
+ {AVC_MIME, VIDEO_ControlRateConstant},
+ {AVC_MIME, VIDEO_ControlRateVariable},
+ {HEVC_MIME, VIDEO_ControlRateConstant},
+ {HEVC_MIME, VIDEO_ControlRateVariable},
+ });
+ return prepareParamList(exhaustiveArgsList);
+ }
+
/**
* A basic test for Video encoder.
*
@@ -91,7 +154,8 @@
* Verifies the average bitrate is within allowed MAX_BITRATE_VARIATIONS[] of
* the target value.
*/
- private void internalTestBasic(String codecMimeType, int bitRateMode) throws Exception {
+ private void internalTestBasic(String codecName, String codecMimeType, int bitRateMode)
+ throws Exception {
int encodeSeconds = 9;
boolean skipped = true;
@@ -101,6 +165,7 @@
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -110,7 +175,8 @@
targetBitrate,
true);
ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
- ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params, codecConfigs);
+ VideoEncodeOutput videoEncodeOutput = encode(params, codecConfigs);
+ ArrayList<MediaCodec.BufferInfo> bufInfo = videoEncodeOutput.bufferInfo;
if (bufInfo == null) {
continue;
}
@@ -137,8 +203,7 @@
allowedVariance * targetBitrate);
}
- decode(params.outputIvfFilename, null, codecMimeType, FPS,
- params.forceGoogleEncoder, codecConfigs);
+ decode(params.outputIvfFilename, null, codecMimeType, FPS, codecConfigs);
}
if (skipped) {
@@ -153,7 +218,8 @@
* Checks the PSNR difference between the encoded and decoded output and reference yuv input
* does not change much for two different ways of the encoder call.
*/
- private void internalTestAsyncEncoding(String codecMimeType, int bitRateMode) throws Exception {
+ private void internalTestAsyncEncoding(String codecName, String codecMimeType, int bitRateMode)
+ throws Exception {
int encodeSeconds = 9;
// First test the encoder running in a looper thread with buffer callbacks enabled.
@@ -161,6 +227,7 @@
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -170,14 +237,14 @@
BITRATE,
syncEncoding);
ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
- ArrayList<MediaCodec.BufferInfo> bufInfos = encodeAsync(params, codecConfigs);
+ VideoEncodeOutput videoEncodeOutput = encodeAsync(params, codecConfigs);
+ ArrayList<MediaCodec.BufferInfo> bufInfos = videoEncodeOutput.bufferInfo;
if (bufInfos == null) {
Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
return;
}
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
- params.forceGoogleEncoder, codecConfigs);
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, codecConfigs);
VideoDecodingStatistics statisticsAsync = computeDecodingStatistics(
params.inputYuvFilename, "football_qvga.yuv", OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -188,6 +255,7 @@
params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -197,14 +265,14 @@
BITRATE,
syncEncoding);
codecConfigs.clear();
- bufInfos = encode(params, codecConfigs);
+ videoEncodeOutput = encode(params, codecConfigs);
+ bufInfos = videoEncodeOutput.bufferInfo;
if (bufInfos == null) {
Log.i(TAG, "SKIPPING testAsyncEncoding(): no suitable encoder found");
return;
}
computeEncodingStatistics(bufInfos);
- decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
- params.forceGoogleEncoder, codecConfigs);
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, codecConfigs);
VideoDecodingStatistics statisticsSync = computeDecodingStatistics(
params.inputYuvFilename, "football_qvga.yuv", OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -228,13 +296,14 @@
* Encodes 9 seconds of raw stream and requests a sync frame every second (30 frames).
* The test does not verify the output stream.
*/
- private void internalTestSyncFrame(
- String codecMimeType, int bitRateMode, boolean useNdk) throws Exception {
+ private void internalTestSyncFrame(String codecName, String codecMimeType, int bitRateMode,
+ boolean useNdk) throws Exception {
int encodeSeconds = 9;
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -246,7 +315,8 @@
params.syncFrameInterval = encodeSeconds * FPS;
params.syncForceFrameInterval = FPS;
params.useNdk = useNdk;
- ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ VideoEncodeOutput videoEncodeOutput = encode(params);
+ ArrayList<MediaCodec.BufferInfo> bufInfo = videoEncodeOutput.bufferInfo;
if (bufInfo == null) {
Log.i(TAG, "SKIPPING testSyncFrame(): no suitable encoder found");
return;
@@ -280,14 +350,15 @@
* Run the the encoder for 12 seconds. Request changes to the
* bitrate after 6 seconds and ensure the encoder responds.
*/
- private void internalTestDynamicBitrateChange(
- String codecMimeType, int bitRateMode, boolean useNdk) throws Exception {
+ private void internalTestDynamicBitrateChange(String codecName, String codecMimeType,
+ int bitRateMode, boolean useNdk) throws Exception {
int encodeSeconds = 12; // Encoding sequence duration in seconds.
int[] bitrateTargetValues = { 400000, 800000 }; // List of bitrates to test.
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -309,7 +380,8 @@
}
params.useNdk = useNdk;
- ArrayList<MediaCodec.BufferInfo> bufInfo = encode(params);
+ VideoEncodeOutput videoEncodeOutput = encode(params);
+ ArrayList<MediaCodec.BufferInfo> bufInfo = videoEncodeOutput.bufferInfo;
if (bufInfo == null) {
Log.i(TAG, "SKIPPING testDynamicBitrateChange(): no suitable encoder found");
return;
@@ -350,7 +422,8 @@
* and then run parallel encoding and decoding of the same streams.
* Compares average bitrate and PSNR for sequential and parallel runs.
*/
- private void internalTestParallelEncodingAndDecoding(String codecMimeType) throws Exception {
+ private void internalTestParallelEncodingAndDecoding(String codecName, String codecMimeType)
+ throws Exception {
// check for encoder up front, as by the time we detect lack of
// encoder support, we may have already started decoding.
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -368,6 +441,7 @@
final EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -384,9 +458,11 @@
try {
ArrayList<MediaCodec.BufferInfo> bufInfo;
if (codecConfigs.isEmpty()) {
- bufInfo = encode(params, codecConfigs);
+ VideoEncodeOutput videoEncodeOutput = encode(params, codecConfigs);
+ bufInfo = videoEncodeOutput.bufferInfo;
} else {
- bufInfo = encode(params);
+ VideoEncodeOutput videoEncodeOutput = encode(params);
+ bufInfo = videoEncodeOutput.bufferInfo;
}
VideoEncodingStatistics statistics = computeEncodingStatistics(bufInfo);
bitrate[0] = statistics.mAverageBitrate;
@@ -399,8 +475,7 @@
Runnable runDecoder = new Runnable() {
public void run() {
try {
- decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
- params.forceGoogleEncoder, codecConfigs);
+ decode(inputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, codecConfigs);
VideoDecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, "football_qvga.yuv", OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -459,7 +534,7 @@
* Video streams with higher bitrates should have higher PSNRs.
* Also compares average and minimum PSNR of codec with PSNR values of reference Google codec.
*/
- private void internalTestEncoderQuality(String codecMimeType, int bitRateMode)
+ private void internalTestEncoderQuality(String codecName, String codecMimeType, int bitRateMode)
throws Exception {
int encodeSeconds = 9; // Encoding sequence duration in seconds for each bitrate.
double[] psnrPlatformCodecAverage = new double[TEST_BITRATES_SET.length];
@@ -473,6 +548,7 @@
EncoderOutputStreamParameters params = getDefaultEncodingParameters(
INPUT_YUV,
ENCODED_IVF_BASE,
+ codecName,
codecMimeType,
encodeSeconds,
WIDTH,
@@ -490,8 +566,7 @@
completed[i] = true;
skipped = false;
- decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS,
- params.forceGoogleEncoder, codecConfigs);
+ decode(params.outputIvfFilename, OUTPUT_YUV, codecMimeType, FPS, codecConfigs);
VideoDecodingStatistics statistics = computeDecodingStatistics(
params.inputYuvFilename, "football_qvga.yuv", OUTPUT_YUV,
params.frameWidth, params.frameHeight);
@@ -554,203 +629,46 @@
}
}
- public void testBasicVP8CBR() throws Exception {
- internalTestBasic(VP8_MIME, VIDEO_ControlRateConstant);
- }
- public void testBasicVP8VBR() throws Exception {
- internalTestBasic(VP8_MIME, VIDEO_ControlRateVariable);
+ @Test
+ public void testBasic() throws Exception {
+ internalTestBasic(mCodecName, mCodecMimeType, mBitRateMode);
}
- public void testBasicVP9CBR() throws Exception {
- internalTestBasic(VP9_MIME, VIDEO_ControlRateConstant);
- }
- public void testBasicVP9VBR() throws Exception {
- internalTestBasic(VP9_MIME, VIDEO_ControlRateVariable);
+ @Test
+ public void testAsyncEncode() throws Exception {
+ internalTestAsyncEncoding(mCodecName, mCodecMimeType, mBitRateMode);
}
- public void testBasicAVCCBR() throws Exception {
- internalTestBasic(AVC_MIME, VIDEO_ControlRateConstant);
- }
- public void testBasicAVCVBR() throws Exception {
- internalTestBasic(AVC_MIME, VIDEO_ControlRateVariable);
- }
- public void testBasicHEVCCBR() throws Exception {
- internalTestBasic(HEVC_MIME, VIDEO_ControlRateConstant);
- }
- public void testBasicHEVCVBR() throws Exception {
- internalTestBasic(HEVC_MIME, VIDEO_ControlRateVariable);
- }
- public void testAsyncEncodingVP8CBR() throws Exception {
- internalTestAsyncEncoding(VP8_MIME, VIDEO_ControlRateConstant);
- }
- public void testAsyncEncodingVP8VBR() throws Exception {
- internalTestAsyncEncoding(VP8_MIME, VIDEO_ControlRateVariable);
+ @Test
+ public void testSyncFrame() throws Exception {
+ internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, false);
}
- public void testAsyncEncodingVP9CBR() throws Exception {
- internalTestAsyncEncoding(VP9_MIME, VIDEO_ControlRateConstant);
- }
- public void testAsyncEncodingVP9VBR() throws Exception {
- internalTestAsyncEncoding(VP9_MIME, VIDEO_ControlRateVariable);
+ @Test
+ public void testSyncFrameNdk() throws Exception {
+ internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, true);
}
- public void testAsyncEncodingAVCCBR() throws Exception {
- internalTestAsyncEncoding(AVC_MIME, VIDEO_ControlRateConstant);
- }
- public void testAsyncEncodingAVCVBR() throws Exception {
- internalTestAsyncEncoding(AVC_MIME, VIDEO_ControlRateVariable);
- }
- public void testAsyncEncodingHEVCCBR() throws Exception {
- internalTestAsyncEncoding(HEVC_MIME, VIDEO_ControlRateConstant);
- }
- public void testAsyncEncodingHEVCVBR() throws Exception {
- internalTestAsyncEncoding(HEVC_MIME, VIDEO_ControlRateVariable);
+ @Test
+ public void testDynamicBitrateChange() throws Exception {
+ internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, false);
}
- public void testSyncFrameVP8CBR() throws Exception {
- internalTestSyncFrame(VP8_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testSyncFrameVP8VBR() throws Exception {
- internalTestSyncFrame(VP8_MIME, VIDEO_ControlRateVariable, false);
+ @Test
+ public void testDynamicBitrateChangeNdk() throws Exception {
+ internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, true);
}
- public void testSyncFrameVP8NdkCBR() throws Exception {
- internalTestSyncFrame(VP8_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testSyncFrameVP8NdkVBR() throws Exception {
- internalTestSyncFrame(VP8_MIME, VIDEO_ControlRateVariable, true);
+ @Test
+ public void testEncoderQuality() throws Exception {
+ internalTestEncoderQuality(mCodecName, mCodecMimeType, mBitRateMode);
}
- public void testSyncFrameVP9CBR() throws Exception {
- internalTestSyncFrame(VP9_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testSyncFrameVP9VBR() throws Exception {
- internalTestSyncFrame(VP9_MIME, VIDEO_ControlRateVariable, false);
- }
-
- public void testSyncFrameVP9NdkCBR() throws Exception {
- internalTestSyncFrame(VP9_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testSyncFrameVP9NdkVBR() throws Exception {
- internalTestSyncFrame(VP9_MIME, VIDEO_ControlRateVariable, true);
- }
-
- public void testSyncFrameAVCCBR() throws Exception {
- internalTestSyncFrame(AVC_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testSyncFrameAVCVBR() throws Exception {
- internalTestSyncFrame(AVC_MIME, VIDEO_ControlRateVariable, false);
- }
-
- public void testSyncFrameAVCNdkCBR() throws Exception {
- internalTestSyncFrame(AVC_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testSyncFrameAVCNdkVBR() throws Exception {
- internalTestSyncFrame(AVC_MIME, VIDEO_ControlRateVariable, true);
- }
-
- public void testSyncFrameHEVCCBR() throws Exception {
- internalTestSyncFrame(HEVC_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testSyncFrameHEVCVBR() throws Exception {
- internalTestSyncFrame(HEVC_MIME, VIDEO_ControlRateVariable, false);
- }
-
- public void testSyncFrameHEVCNdkCBR() throws Exception {
- internalTestSyncFrame(HEVC_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testSyncFrameHEVCNdkVBR() throws Exception {
- internalTestSyncFrame(HEVC_MIME, VIDEO_ControlRateVariable, true);
- }
-
- public void testDynamicBitrateChangeVP8CBR() throws Exception {
- internalTestDynamicBitrateChange(VP8_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testDynamicBitrateChangeVP8VBR() throws Exception {
- internalTestDynamicBitrateChange(VP8_MIME, VIDEO_ControlRateVariable, false);
- }
- public void testDynamicBitrateChangeVP8NdkCBR() throws Exception {
- internalTestDynamicBitrateChange(VP8_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testDynamicBitrateChangeVP8NdkVBR() throws Exception {
- internalTestDynamicBitrateChange(VP8_MIME, VIDEO_ControlRateVariable, true);
- }
- public void testDynamicBitrateChangeVP9CBR() throws Exception {
- internalTestDynamicBitrateChange(VP9_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testDynamicBitrateChangeVP9VBR() throws Exception {
- internalTestDynamicBitrateChange(VP9_MIME, VIDEO_ControlRateVariable, false);
- }
- public void testDynamicBitrateChangeVP9NdkCBR() throws Exception {
- internalTestDynamicBitrateChange(VP9_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testDynamicBitrateChangeVP9NdkVBR() throws Exception {
- internalTestDynamicBitrateChange(VP9_MIME, VIDEO_ControlRateVariable, true);
- }
- public void testDynamicBitrateChangeAVCCBR() throws Exception {
- internalTestDynamicBitrateChange(AVC_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testDynamicBitrateChangeAVCVBR() throws Exception {
- internalTestDynamicBitrateChange(AVC_MIME, VIDEO_ControlRateVariable, false);
- }
- public void testDynamicBitrateChangeAVCNdkCBR() throws Exception {
- internalTestDynamicBitrateChange(AVC_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testDynamicBitrateChangeAVCNdkVBR() throws Exception {
- internalTestDynamicBitrateChange(AVC_MIME, VIDEO_ControlRateVariable, true);
- }
- public void testDynamicBitrateChangeHEVCCBR() throws Exception {
- internalTestDynamicBitrateChange(HEVC_MIME, VIDEO_ControlRateConstant, false);
- }
- public void testDynamicBitrateChangeHEVCVBR() throws Exception {
- internalTestDynamicBitrateChange(HEVC_MIME, VIDEO_ControlRateVariable, false);
- }
- public void testDynamicBitrateChangeHEVCNdkCBR() throws Exception {
- internalTestDynamicBitrateChange(HEVC_MIME, VIDEO_ControlRateConstant, true);
- }
- public void testDynamicBitrateChangeHEVCNdkVBR() throws Exception {
- internalTestDynamicBitrateChange(HEVC_MIME, VIDEO_ControlRateVariable, true);
- }
-
- public void testEncoderQualityVP8CBR() throws Exception {
- internalTestEncoderQuality(VP8_MIME, VIDEO_ControlRateConstant);
- }
- public void testEncoderQualityVP8VBR() throws Exception {
- internalTestEncoderQuality(VP8_MIME, VIDEO_ControlRateVariable);
- }
-
- public void testEncoderQualityVP9CBR() throws Exception {
- internalTestEncoderQuality(VP9_MIME, VIDEO_ControlRateConstant);
- }
- public void testEncoderQualityVP9VBR() throws Exception {
- internalTestEncoderQuality(VP9_MIME, VIDEO_ControlRateVariable);
- }
-
- public void testEncoderQualityAVCCBR() throws Exception {
- internalTestEncoderQuality(AVC_MIME, VIDEO_ControlRateConstant);
- }
- public void testEncoderQualityAVCVBR() throws Exception {
- internalTestEncoderQuality(AVC_MIME, VIDEO_ControlRateVariable);
- }
-
- public void testEncoderQualityHEVCCBR() throws Exception {
- internalTestEncoderQuality(HEVC_MIME, VIDEO_ControlRateConstant);
- }
- public void testEncoderQualityHEVCVBR() throws Exception {
- internalTestEncoderQuality(HEVC_MIME, VIDEO_ControlRateVariable);
- }
-
- public void testParallelEncodingAndDecodingVP8() throws Exception {
- internalTestParallelEncodingAndDecoding(VP8_MIME);
- }
- public void testParallelEncodingAndDecodingVP9() throws Exception {
- internalTestParallelEncodingAndDecoding(VP9_MIME);
- }
- public void testParallelEncodingAndDecodingAVC() throws Exception {
- internalTestParallelEncodingAndDecoding(AVC_MIME);
- }
- public void testParallelEncodingAndDecodingHEVC() throws Exception {
- internalTestParallelEncodingAndDecoding(HEVC_MIME);
+ @Test
+ public void testParallelEncodingAndDecoding() throws Exception {
+ Assume.assumeTrue("Parallel Encode Decode test is run only for VBR mode",
+ mBitRateMode == VIDEO_ControlRateVariable);
+ internalTestParallelEncodingAndDecoding(mCodecName, mCodecMimeType);
}
}
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java
index 02754ab..cbe3966 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTestBase.java
@@ -16,13 +16,12 @@
package android.media.codec.cts;
-import android.content.Context;
import android.content.res.Resources;
import android.media.MediaCodec;
import android.media.MediaCodec.CodecException;
+import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaCodecList;
-import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.cts.MediaCodecWrapper;
import android.media.cts.NdkMediaCodec;
@@ -30,12 +29,13 @@
import android.media.cts.SdkMediaCodec;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Looper;
import android.os.Handler;
+import android.os.Looper;
import android.platform.test.annotations.AppModeFull;
-import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.compatibility.common.util.MediaUtils;
import java.io.File;
@@ -48,6 +48,9 @@
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
+
/**
* Verification test for video encoder and decoder.
*
@@ -57,7 +60,7 @@
* calculate PSNR values for various bitrates.
*/
@AppModeFull(reason = "Instant apps cannot access the SD card")
-public class VideoCodecTestBase extends AndroidTestCase {
+public class VideoCodecTestBase {
protected static final String TAG = "VideoCodecTestBase";
protected static final String VP8_MIME = MediaFormat.MIMETYPE_VIDEO_VP8;
@@ -91,14 +94,6 @@
// were calculated and were written to yuv file.
ArrayList<Integer> mScaledImages = new ArrayList<Integer>();
- private Resources mResources;
-
- @Override
- public void setContext(Context context) {
- super.setContext(context);
- mResources = mContext.getResources();
- }
-
/**
* Video codec properties generated by getVideoCodecProperties() function.
*/
@@ -116,19 +111,11 @@
*
* Iterates through the list of available codecs and tries to find
* Video codec, which can support either YUV420 planar or NV12 color formats.
- * If forceGoogleCodec parameter set to true the function always returns
- * Google Video codec.
- * If forceGoogleCodec parameter set to false the functions looks for platform
- * specific Video codec first. If no platform specific codec exist, falls back to
- * Google Video codec.
*
* @param isEncoder Flag if encoder is requested.
- * @param forceGoogleCodec Forces to use Google codec.
*/
- private CodecProperties getVideoCodecProperties(
- boolean isEncoder,
- MediaFormat format,
- boolean forceGoogleCodec) throws Exception {
+ private CodecProperties getVideoCodecProperties(boolean isEncoder, MediaFormat format)
+ throws Exception {
CodecProperties codecProperties = null;
String mime = format.getString(MediaFormat.KEY_MIME);
@@ -140,11 +127,6 @@
continue;
}
Log.v(TAG, codecInfo.getName());
- // TODO: remove dependence of Google from the test
- // Check if this is Google codec - we should ignore it.
- if (codecInfo.isVendor() && forceGoogleCodec) {
- continue;
- }
for (String type : codecInfo.getSupportedTypes()) {
if (!type.equalsIgnoreCase(mime)) {
@@ -179,12 +161,43 @@
}
}
if (codecProperties == null) {
- Log.i(TAG, "no suitable " + (forceGoogleCodec ? "google " : "")
- + (isEncoder ? "encoder " : "decoder ") + "found for " + format);
+ Log.i(TAG, "no suitable " + (isEncoder ? "encoder " : "decoder ") + "found for " +
+ format);
}
return codecProperties;
}
+ private CodecProperties getEncoderProperties(String codecName, MediaFormat format)
+ throws Exception {
+ assumeTrue("Media format " + format + " is not supported by " + codecName,
+ MediaUtils.supports(codecName, format));
+ CodecProperties codecProperties = null;
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
+ if (!codecInfo.isEncoder() || !codecName.equals(codecInfo.getName())) {
+ continue;
+ }
+ Log.v(TAG, codecInfo.getName());
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ Log.d(TAG, "Name : " + codecInfo.getName() + " mime: " + mime);
+ CodecCapabilities capabilities = codecInfo.getCapabilitiesForType(mime);
+ for (int supportedColorFormat : mSupportedColorList) {
+ for (int codecColorFormat : capabilities.colorFormats) {
+ if (codecColorFormat == supportedColorFormat) {
+ codecProperties = new CodecProperties(codecInfo.getName(),
+ codecColorFormat);
+ Log.v(TAG, "Found target codec " + codecProperties.codecName +
+ ". Color: 0x" + Integer.toHexString(codecColorFormat));
+ return codecProperties;
+ }
+ }
+ }
+ }
+ assumeTrue("Codec " + codecName + " doesn't support color YUV 420 color formats",
+ codecProperties != null);
+ return codecProperties;
+ }
+
/**
* Parameters for encoded video stream.
*/
@@ -202,8 +215,8 @@
public String outputIvfFilename;
// Mime Type of the Encoded content.
public String codecMimeType;
- // Force to use Google Video encoder.
- boolean forceGoogleEncoder;
+ // Component Name.
+ public String codecName;
// Number of frames to encode.
int frameCount;
// Frame rate of input file in frames per second.
@@ -234,6 +247,33 @@
boolean runInLooperThread;
// Flag if use NdkMediaCodec
boolean useNdk;
+ // Encoding Statistics Level
+ // 0: None, 1: Average block QP and picture type of a frame
+ public int encodingStatisticsLevel;
+ }
+
+ /**
+ * Encoding Statistics for a whole sequence
+ */
+ protected class EncodingStatisticsInfo {
+ public float averageSeqQp = 0; // Average qp of a whole sequence,
+ // i.e. average of 'per-frame average block QP'
+ public int encodedFrames = 0; // # of encoded frames,
+ // i.e. # of average_block_qp is reported
+ }
+
+ /**
+ * Encoding Statistics for a whole sequence
+ */
+ protected class VideoEncodeOutput{
+ public ArrayList<MediaCodec.BufferInfo> bufferInfo;
+ public EncodingStatisticsInfo encStat;
+
+ VideoEncodeOutput(ArrayList<MediaCodec.BufferInfo> bufferInfo,
+ EncodingStatisticsInfo encStat) {
+ bufferInfo = bufferInfo;
+ encStat = encStat;
+ }
}
private String getCodecSuffix(String codecMimeType) {
@@ -259,6 +299,7 @@
protected ArrayList<EncoderOutputStreamParameters> getDefaultEncodingParameterList(
String inputYuvName,
String outputIvfBaseName,
+ String codecName,
String codecMimeType,
int encodeSeconds,
int[] resolutionScales,
@@ -286,7 +327,7 @@
String codecSuffix = getCodecSuffix(codecMimeType);
params.outputIvfFilename = SDCARD_DIR + File.separator +
outputIvfBaseName + resolutionScales[i] + "_" + codecSuffix + ".ivf";
- params.forceGoogleEncoder = false;
+ params.codecName = codecName;
params.frameCount = encodeSeconds * frameRate;
params.frameRate = frameRate;
params.frameWidth = Math.min(frameWidth * resolutionScales[i], 1280);
@@ -312,6 +353,7 @@
protected EncoderOutputStreamParameters getDefaultEncodingParameters(
String inputYuvName,
String outputIvfBaseName,
+ String codecName,
String codecMimeType,
int encodeSeconds,
int frameWidth,
@@ -325,6 +367,7 @@
return getDefaultEncodingParameterList(
inputYuvName,
outputIvfBaseName,
+ codecName,
codecMimeType,
encodeSeconds,
scaleValues,
@@ -537,7 +580,6 @@
* @param inputIvfFilename The name of the IVF file containing encoded bitsream.
* @param outputYuvFilename The name of the output YUV file (optional).
* @param frameRate Frame rate of input file in frames per second
- * @param forceGoogleDecoder Force to use Google Video decoder.
* @param codecConfigs Codec config buffers to be added to the format
*/
protected ArrayList<MediaCodec.BufferInfo> decode(
@@ -545,7 +587,6 @@
String outputYuvFilename,
String codecMimeType,
int frameRate,
- boolean forceGoogleDecoder,
ArrayList<ByteBuffer> codecConfigs) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
@@ -567,8 +608,7 @@
// Create decoder.
MediaFormat format = MediaFormat.createVideoFormat(
codecMimeType, ivf.getWidth(), ivf.getHeight());
- CodecProperties properties = getVideoCodecProperties(
- false /* encoder */, format, forceGoogleDecoder);
+ CodecProperties properties = getVideoCodecProperties(false /* encoder */, format);
if (properties == null) {
ivf.close();
return null;
@@ -782,19 +822,22 @@
private InputStream mYuvStream;
private int mInputFrameIndex;
+ private final EncodingStatisticsInfo mEncStatInfo;
MediaEncoderAsyncHelper(
EncoderOutputStreamParameters streamParams,
CodecProperties properties,
ArrayList<MediaCodec.BufferInfo> bufferInfos,
IvfWriter ivf,
- ArrayList<ByteBuffer> codecConfigs)
+ ArrayList<ByteBuffer> codecConfigs,
+ EncodingStatisticsInfo encStatInfo)
throws Exception {
mStreamParams = streamParams;
mProperties = properties;
mBufferInfos = bufferInfos;
mIvf = ivf;
mCodecConfigs = codecConfigs;
+ mEncStatInfo = encStatInfo;
int srcFrameSize = streamParams.frameWidth * streamParams.frameHeight * 3 / 2;
mSrcFrame = new byte[srcFrameSize];
@@ -871,6 +914,11 @@
}
return false;
}
+
+ public void saveAvgQp(int avg_qp) {
+ mEncStatInfo.averageSeqQp += (float) avg_qp;
+ ++mEncStatInfo.encodedFrames; // Note: Duplicated info to mOutputFrameIndex
+ }
}
/**
@@ -999,6 +1047,13 @@
out.flags = info.flags;
out.outputGenerated = true;
+ MediaFormat format = codec.getOutputFormat(index);
+ if (format.containsKey(MediaFormat.KEY_VIDEO_QP_AVERAGE)) {
+ int avgQp = format.getInteger(MediaFormat.KEY_VIDEO_QP_AVERAGE);
+ // Copy per-frame avgQp to sequence level buffer
+ mHelper.saveAvgQp(avgQp);
+ }
+
if (mHelper.saveOutputFrame(out)) {
// output EOS
signalCompletion();
@@ -1334,7 +1389,7 @@
/**
* @see #encode(EncoderOutputStreamParameters, ArrayList<ByteBuffer>)
*/
- protected ArrayList<MediaCodec.BufferInfo> encode(
+ protected VideoEncodeOutput encode(
EncoderOutputStreamParameters streamParams) throws Exception {
return encode(streamParams, new ArrayList<ByteBuffer>());
}
@@ -1354,13 +1409,16 @@
*
* @param streamParams Structure with encoder parameters
* @param codecConfigs List to be filled with codec config buffers
- * @return Returns array of encoded frames information for each frame.
+ * @return Returns VideoEncodeOutput, which consists of
+ * array of encoded frames information for each frame and Encoding
+ * Statistics Information.
*/
- protected ArrayList<MediaCodec.BufferInfo> encode(
+ protected VideoEncodeOutput encode(
EncoderOutputStreamParameters streamParams,
ArrayList<ByteBuffer> codecConfigs) throws Exception {
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+ EncodingStatisticsInfo encStatInfo = new EncodingStatisticsInfo();
Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
streamParams.frameHeight);
int bitrate = streamParams.bitrateSet[0];
@@ -1370,11 +1428,7 @@
streamParams.codecMimeType, streamParams.frameWidth,
streamParams.frameHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
- CodecProperties properties = getVideoCodecProperties(
- true, format, streamParams.forceGoogleEncoder);
- if (properties == null) {
- return null;
- }
+ CodecProperties properties = getEncoderProperties(streamParams.codecName, format);
// Open input/output
InputStream yuvStream = OpenFileOrResource(
@@ -1395,6 +1449,11 @@
int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
streamParams.frameRate;
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
+ if (streamParams.encodingStatisticsLevel !=
+ MediaFormat.VIDEO_ENCODING_STATISTICS_LEVEL_NONE) {
+ format.setInteger(MediaFormat.KEY_VIDEO_ENCODING_STATISTICS_LEVEL,
+ streamParams.encodingStatisticsLevel);
+ }
// Create encoder
Log.d(TAG, "Creating encoder " + properties.codecName +
@@ -1520,7 +1579,7 @@
ivf.close();
yuvStream.close();
- return bufferInfos;
+ return new VideoEncodeOutput(bufferInfos, encStatInfo);
}
/**
@@ -1537,9 +1596,11 @@
*
* @param streamParams Structure with encoder parameters
* @param codecConfigs List to be filled with codec config buffers
- * @return Returns array of encoded frames information for each frame.
+ * @return Returns VideoEncodeOutput, which consists of
+ * array of encoded frames information for each frame and Encoding
+ * Statistics Information.
*/
- protected ArrayList<MediaCodec.BufferInfo> encodeAsync(
+ protected VideoEncodeOutput encodeAsync(
EncoderOutputStreamParameters streamParams,
ArrayList<ByteBuffer> codecConfigs) throws Exception {
if (!streamParams.runInLooperThread) {
@@ -1547,6 +1608,7 @@
}
ArrayList<MediaCodec.BufferInfo> bufferInfos = new ArrayList<MediaCodec.BufferInfo>();
+ EncodingStatisticsInfo encStatInfo = new EncodingStatisticsInfo();
Log.d(TAG, "Source resolution: "+streamParams.frameWidth + " x " +
streamParams.frameHeight);
int bitrate = streamParams.bitrateSet[0];
@@ -1556,11 +1618,7 @@
streamParams.codecMimeType, streamParams.frameWidth,
streamParams.frameHeight);
format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
- CodecProperties properties = getVideoCodecProperties(
- true, format, streamParams.forceGoogleEncoder);
- if (properties == null) {
- return null;
- }
+ CodecProperties properties = getEncoderProperties(streamParams.codecName, format);
// Open input/output
IvfWriter ivf = new IvfWriter(
@@ -1579,7 +1637,11 @@
int syncFrameInterval = (streamParams.syncFrameInterval + streamParams.frameRate/2) /
streamParams.frameRate;
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, syncFrameInterval);
-
+ if (streamParams.encodingStatisticsLevel !=
+ MediaFormat.VIDEO_ENCODING_STATISTICS_LEVEL_NONE) {
+ format.setInteger(MediaFormat.KEY_VIDEO_ENCODING_STATISTICS_LEVEL,
+ MediaFormat.VIDEO_ENCODING_STATISTICS_LEVEL_1);
+ }
// Create encoder
Log.d(TAG, "Creating encoder " + properties.codecName +
". Color format: 0x" + Integer.toHexString(properties.colorFormat)+ " : " +
@@ -1593,7 +1655,7 @@
MediaEncoderAsync codec = new MediaEncoderAsync();
MediaEncoderAsyncHelper helper = new MediaEncoderAsyncHelper(
- streamParams, properties, bufferInfos, ivf, codecConfigs);
+ streamParams, properties, bufferInfos, ivf, codecConfigs, encStatInfo);
codec.setAsyncHelper(helper);
codec.createCodec(0, properties.codecName, format,
@@ -1603,7 +1665,7 @@
codec.deleteCodec();
ivf.close();
- return bufferInfos;
+ return new VideoEncodeOutput(bufferInfos, encStatInfo);
}
/**
@@ -1664,11 +1726,7 @@
params.codecMimeType, params.frameWidth,
params.frameHeight);
format[i].setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
- CodecProperties properties = getVideoCodecProperties(
- true, format[i], params.forceGoogleEncoder);
- if (properties == null) {
- continue;
- }
+ CodecProperties properties = getEncoderProperties(params.codecName, format[i]);
// Check if scaled image was created
int scale = params.frameWidth / srcFrameWidth;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
new file mode 100644
index 0000000..10a18dd
--- /dev/null
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
@@ -0,0 +1,211 @@
+/*
+ * 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.media.codec.cts;
+
+import android.media.MediaCodec;
+import android.media.MediaCodecInfo;
+import android.media.MediaCodecInfo.CodecCapabilities;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
+import android.media.cts.MediaCodecWrapper;
+import android.media.cts.MediaHeavyPresubmitTest;
+import android.platform.test.annotations.AppModeFull;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.MediaUtils;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Verification test for video encoding statistics.
+ *
+ * Check whether a higher bitrate gives a lower average QP reported from encoder
+ *
+ */
+@MediaHeavyPresubmitTest
+@AppModeFull(reason = "TODO: evaluate and port to instant")
+@RunWith(Parameterized.class)
+public class VideoEncodingStatisticsTest extends VideoCodecTestBase {
+
+ private static final String ENCODED_IVF_BASE = "football";
+ private static final String INPUT_YUV = null;
+ private static final String OUTPUT_YUV = SDCARD_DIR + File.separator +
+ ENCODED_IVF_BASE + "_out.yuv";
+
+ // YUV stream properties.
+ private static final int WIDTH = 320;
+ private static final int HEIGHT = 240;
+ private static final int FPS = 30;
+ // Default encoding bitrate.
+ private static final int BITRATE = 400000;
+ // List of bitrates used in quality and basic bitrate tests.
+ private static final int[] TEST_BITRATES_SET = { 300000, 500000, 700000, 900000 };
+
+ private static final String CODEC_PREFIX_KEY = "codec-prefix";
+ private static final String mCodecPrefix;
+
+ @Parameterized.Parameter(0)
+ public String mCodecName;
+
+ @Parameterized.Parameter(1)
+ public String mCodecMimeType;
+
+ @Parameterized.Parameter(2)
+ public int mBitRateMode;
+
+ static {
+ android.os.Bundle args = InstrumentationRegistry.getArguments();
+ mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+ }
+
+ static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ int argLength = exhaustiveArgsList.get(0).length;
+ for (Object[] arg : exhaustiveArgsList) {
+ String[] encodersForMime = MediaUtils.getEncoderNamesForMime((String) arg[0]);
+ for (String encoder : encodersForMime) {
+ if (mCodecPrefix != null && !encoder.startsWith(mCodecPrefix)) {
+ continue;
+ }
+ Object[] testArgs = new Object[argLength + 1];
+ testArgs[0] = encoder;
+ System.arraycopy(arg, 0, testArgs, 1, argLength);
+ argsList.add(testArgs);
+ }
+ }
+ return argsList;
+ }
+
+ @Parameterized.Parameters(name = "{index}({0}:{1}:{2})")
+ public static Collection<Object[]> input() {
+ final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+ {AVC_MIME, VIDEO_ControlRateConstant},
+ {AVC_MIME, VIDEO_ControlRateVariable},
+ {HEVC_MIME, VIDEO_ControlRateConstant},
+ {HEVC_MIME, VIDEO_ControlRateVariable},
+ });
+ return prepareParamList(exhaustiveArgsList);
+ }
+
+ private static CodecCapabilities getCodecCapabilities(
+ String encoderName, String mime, boolean isEncoder) {
+ MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
+ if (isEncoder != codecInfo.isEncoder()) {
+ continue;
+ }
+ if (encoderName.equals(codecInfo.getName())) {
+ return codecInfo.getCapabilitiesForType(mime);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Check whethera a higher bitrate gives a lower average QP
+ *
+ * Video streams with higher bitrate should have lower average qp.
+ */
+ private void testEncStatRateAvgQp(String codecName, String codecMimeType, int bitRateMode)
+ throws Exception {
+ int encodeSeconds = 9; // Encoding sequence duration in seconds for each bitrate.
+ float[] avgSeqQp = new float[TEST_BITRATES_SET.length];
+ boolean[] completed = new boolean[TEST_BITRATES_SET.length];
+ boolean skipped = true;
+ ArrayList<MediaCodec.BufferInfo> bufInfos;
+
+ CodecCapabilities caps = getCodecCapabilities(codecName, codecMimeType, true);
+ Assume.assumeTrue(codecName + " does not support FEATURE_EncodingStatistics",
+ caps.isFeatureSupported(CodecCapabilities.FEATURE_EncodingStatistics));
+
+ for (int i = 0; i < TEST_BITRATES_SET.length; i++) {
+ EncoderOutputStreamParameters params = getDefaultEncodingParameters(
+ INPUT_YUV,
+ ENCODED_IVF_BASE,
+ codecName,
+ codecMimeType,
+ encodeSeconds,
+ WIDTH,
+ HEIGHT,
+ FPS,
+ bitRateMode,
+ TEST_BITRATES_SET[i],
+ true);
+ // Enable encoding statistics at VIDEO_ENCODING_STATISTICS_LEVEL_1
+ params.encodingStatisticsLevel = MediaFormat.VIDEO_ENCODING_STATISTICS_LEVEL_1;
+ ArrayList<ByteBuffer> codecConfigs = new ArrayList<>();
+ VideoEncodeOutput videoEncodeOutput = encode(params, codecConfigs);
+ bufInfos = videoEncodeOutput.bufferInfo;
+ if (bufInfos == null) {
+ // parameters not supported, try other bitrates
+ completed[i] = false;
+ continue;
+ }
+ completed[i] = true;
+ skipped = false;
+ if (videoEncodeOutput.encStat.encodedFrames > 0) {
+ avgSeqQp[i] = (float) videoEncodeOutput.encStat.averageSeqQp
+ / videoEncodeOutput.encStat.encodedFrames;
+ }
+ }
+
+ if (skipped) {
+ Log.i(TAG, "SKIPPING testEncodingStatisticsAvgQp(): no bitrates supported");
+ return;
+ }
+
+ // First do a validity check - higher bitrates should results in lower QP.
+ for (int i = 1; i < TEST_BITRATES_SET.length; i++) {
+ if (!completed[i]) {
+ continue;
+ }
+ for (int j = 0; j < i; j++) {
+ if (!completed[j]) {
+ continue;
+ }
+ double differenceBitrate = TEST_BITRATES_SET[i] - TEST_BITRATES_SET[j];
+ double differenceAvgQp = avgSeqQp[i] - avgSeqQp[j];
+ if (differenceBitrate * differenceAvgQp > 0) {
+ throw new RuntimeException("Target bitrates: " +
+ TEST_BITRATES_SET[j] + ", " + TEST_BITRATES_SET[i] +
+ ". Average QP: "
+ + avgSeqQp[j] + ", " + avgSeqQp[i]);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void testEncodingStatisticsAvgQp() throws Exception {
+ testEncStatRateAvgQp(mCodecName, mCodecMimeType, mBitRateMode);
+ }
+}
+
diff --git a/tests/tests/media/common/Android.bp b/tests/tests/media/common/Android.bp
new file mode 100644
index 0000000..be689bc
--- /dev/null
+++ b/tests/tests/media/common/Android.bp
@@ -0,0 +1,121 @@
+// 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",
+ "cts_tests_tests_media_common_license",
+ ],
+}
+
+// See: http://go/android-license-faq
+license {
+ name: "cts_tests_tests_media_common_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "legacy_unencumbered",
+ ],
+}
+
+java_library {
+ name: "ctsmediautil",
+ srcs: [
+ "src/android/media/cts/CodecImage.java",
+ "src/android/media/cts/YUVImage.java",
+ "src/android/media/cts/CodecUtils.java",
+ "src/android/media/cts/CodecState.java",
+ "src/android/media/cts/MediaCodecTunneledPlayer.java",
+ "src/android/media/cts/MediaTimeProvider.java",
+ "src/android/media/cts/NonBlockingAudioTrack.java",
+ ],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "platform-test-annotations",
+ ],
+ platform_apis: true,
+ min_sdk_version: "29",
+ target_sdk_version: "31",
+}
+
+cc_test_library {
+ name: "libctscodecutils_jni",
+ srcs: [
+ "jni/codec-utils-jni.cpp",
+ "jni/md5_utils.cpp",
+ ],
+ shared_libs: [
+ "libnativehelper_compat_libc++",
+ "liblog",
+ ],
+ header_libs: ["liblog_headers"],
+ // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
+ // (revisit if/when we add features to this library that require newer sdk.
+ sdk_version: "29",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ stl: "libc++_static",
+ gtest: false,
+}
+
+cc_test_library {
+ name: "libctsmediacommon_jni",
+ srcs: [
+ "jni/NdkInputSurface-jni.cpp",
+ "jni/NdkMediaCodec-jni.cpp",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libnativehelper_compat_libc++",
+ "liblog",
+ "libmediandk",
+ "libEGL",
+ ],
+ header_libs: ["liblog_headers"],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ gtest: false,
+ // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
+ // (revisit if/when we add features to this library that require newer sdk.
+ sdk_version: "29",
+}
+
+android_library {
+ name: "cts-media-common",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.heifwriter_heifwriter",
+ "androidx.test.core",
+ "androidx.test.ext.junit",
+ "compatibility-device-util-axt",
+ "junit",
+ "platform-test-annotations",
+ ],
+ platform_apis: true,
+ libs: [
+ "org.apache.http.legacy",
+ "android.test.base",
+ "android.test.runner",
+ ],
+ min_sdk_version: "29",
+ target_sdk_version: "31",
+}
diff --git a/tests/tests/media/common/AndroidManifest.xml b/tests/tests/media/common/AndroidManifest.xml
new file mode 100644
index 0000000..651a22d
--- /dev/null
+++ b/tests/tests/media/common/AndroidManifest.xml
@@ -0,0 +1,62 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.media.cts"
+ android:targetSandboxVersion="2">
+
+ <uses-sdk android:minSdkVersion="29"
+ android:targetSdkVersion="31"/>
+
+ <application android:networkSecurityConfig="@xml/network_security_config"
+ android:largeHeap="true">
+ <uses-library android:name="android.test.runner"/>
+
+ <activity android:name="android.media.cts.MediaProjectionActivity"
+ android:label="MediaProjectionActivity"
+ android:screenOrientation="locked"/>
+ <activity android:name="android.media.cts.AudioManagerStub"
+ android:label="AudioManagerStub"/>
+ <activity android:name="android.media.cts.AudioManagerStubHelper"
+ android:label="AudioManagerStubHelper"/>
+
+ <activity android:name="android.media.cts.MediaStubActivity"
+ android:label="MediaStubActivity"
+ android:screenOrientation="nosensor"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+ <activity android:name="android.media.cts.MediaStubActivity2"
+ android:label="MediaStubActivity2"
+ android:screenOrientation="nosensor"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+
+ <service android:name="android.media.cts.LocalMediaProjectionService"
+ android:foregroundServiceType="mediaProjection"
+ android:enabled="true">
+ </service>
+ </application>
+</manifest>
diff --git a/tests/tests/media/res/layout/composition_layout.xml b/tests/tests/media/common/res/layout/composition_layout.xml
similarity index 100%
rename from tests/tests/media/res/layout/composition_layout.xml
rename to tests/tests/media/common/res/layout/composition_layout.xml
diff --git a/tests/tests/media/res/layout/mediacodecplayer.xml b/tests/tests/media/common/res/layout/mediacodecplayer.xml
similarity index 100%
rename from tests/tests/media/res/layout/mediacodecplayer.xml
rename to tests/tests/media/common/res/layout/mediacodecplayer.xml
diff --git a/tests/tests/media/res/layout/mediaplayer.xml b/tests/tests/media/common/res/layout/mediaplayer.xml
similarity index 100%
rename from tests/tests/media/res/layout/mediaplayer.xml
rename to tests/tests/media/common/res/layout/mediaplayer.xml
diff --git a/tests/tests/media/res/layout/test_runner_activity.xml b/tests/tests/media/common/res/layout/test_runner_activity.xml
similarity index 100%
rename from tests/tests/media/res/layout/test_runner_activity.xml
rename to tests/tests/media/common/res/layout/test_runner_activity.xml
diff --git a/tests/tests/media/res/raw/sine1khzs40dblong.mp3 b/tests/tests/media/common/res/raw/sine1khzs40dblong.mp3
similarity index 100%
copy from tests/tests/media/res/raw/sine1khzs40dblong.mp3
copy to tests/tests/media/common/res/raw/sine1khzs40dblong.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/testmp3.mp3 b/tests/tests/media/common/res/raw/testmp3.mp3
similarity index 100%
copy from tests/tests/media/res/raw/testmp3.mp3
copy to tests/tests/media/common/res/raw/testmp3.mp3
Binary files differ
diff --git a/tests/tests/media/res/xml/network_security_config.xml b/tests/tests/media/common/res/xml/network_security_config.xml
similarity index 100%
rename from tests/tests/media/res/xml/network_security_config.xml
rename to tests/tests/media/common/res/xml/network_security_config.xml
diff --git a/tests/tests/media/common/src/android/media/cts/TestUtils.java b/tests/tests/media/common/src/android/media/cts/TestUtils.java
index 79aaada..d6c898b2 100644
--- a/tests/tests/media/common/src/android/media/cts/TestUtils.java
+++ b/tests/tests/media/common/src/android/media/cts/TestUtils.java
@@ -102,7 +102,7 @@
* {@link #assumeMainlineModuleAtLeast(String, long)} instead.
*/
@Deprecated
- static boolean skipTestIfMainlineLessThan(String module, long minVersion) {
+ public static boolean skipTestIfMainlineLessThan(String module, long minVersion) {
try {
long actualVersion = getModuleVersion(module);
if (actualVersion < minVersion) {
diff --git a/tests/tests/media/common/src/android/media/cts/Utils.java b/tests/tests/media/common/src/android/media/cts/Utils.java
index 1524e26..42a813f 100644
--- a/tests/tests/media/common/src/android/media/cts/Utils.java
+++ b/tests/tests/media/common/src/android/media/cts/Utils.java
@@ -132,7 +132,7 @@
nm.isNotificationPolicyAccessGranted());
}
- static boolean compareRemoteUserInfo(RemoteUserInfo a, RemoteUserInfo b) {
+ public static boolean compareRemoteUserInfo(RemoteUserInfo a, RemoteUserInfo b) {
if (a == null && b == null) {
return true;
} else if (a == null || b == null) {
@@ -148,7 +148,7 @@
* is created once. The playback will be stopped immediately after that.
* <p>For a media session to receive media button events, an actual playback is needed.
*/
- static void assertMediaPlaybackStarted(Context context) {
+ public static void assertMediaPlaybackStarted(Context context) {
final AudioManager am = new AudioManager(context);
final HandlerThread handlerThread = new HandlerThread(TAG);
handlerThread.start();
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
index 01e29b9..1600e9a 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/AdaptivePlaybackTest.java
@@ -39,27 +39,35 @@
import android.opengl.GLES20;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
+import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import javax.microedition.khronos.opengles.GL10;
-import java.lang.System;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.zip.CRC32;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+
@MediaHeavyPresubmitTest
@AppModeFull
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class AdaptivePlaybackTest extends MediaTestBase {
private static final boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
@@ -82,7 +90,21 @@
super.tearDown();
}
- public Iterable<Codec> H264(CodecFactory factory) {
+ private static final String CODEC_PREFIX_KEY = "codec-prefix";
+ private static final String mCodecPrefix;
+
+ @Parameterized.Parameter(0)
+ public String mCodecName;
+
+ @Parameterized.Parameter(1)
+ public CodecList mCodecs;
+
+ static {
+ android.os.Bundle args = InstrumentationRegistry.getArguments();
+ mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+ }
+
+ public static Iterable<Codec> H264(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_AVC,
"video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
@@ -90,7 +112,7 @@
"bbb_s1_720x480_mp4_h264_mp3_2mbps_30fps_aac_lc_5ch_320kbps_48000hz.mp4");
}
- public Iterable<Codec> HEVC(CodecFactory factory) {
+ public static Iterable<Codec> HEVC(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_HEVC,
"bbb_s1_720x480_mp4_hevc_mp3_1600kbps_30fps_aac_he_6ch_240kbps_48000hz.mp4",
@@ -98,21 +120,21 @@
"bbb_s1_352x288_mp4_hevc_mp2_600kbps_30fps_aac_he_stereo_96kbps_48000hz.mp4");
}
- public Iterable<Codec> Mpeg2(CodecFactory factory) {
+ public static Iterable<Codec> Mpeg2(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_MPEG2,
"video_640x360_mp4_mpeg2_2000kbps_30fps_aac_stereo_128kbps_48000hz.mp4",
"video_1280x720_mp4_mpeg2_3000kbps_30fps_aac_stereo_128kbps_48000hz.mp4");
}
- public Iterable<Codec> H263(CodecFactory factory) {
+ public static Iterable<Codec> H263(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_H263,
"video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp",
"video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp");
}
- public Iterable<Codec> Mpeg4(CodecFactory factory) {
+ public static Iterable<Codec> Mpeg4(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_MPEG4,
"video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
@@ -120,7 +142,7 @@
"video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4");
}
- public Iterable<Codec> VP8(CodecFactory factory) {
+ public static Iterable<Codec> VP8(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_VP8,
"video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm",
@@ -128,7 +150,7 @@
"bbb_s1_320x180_webm_vp8_800kbps_30fps_opus_5ch_320kbps_48000hz.webm");
}
- public Iterable<Codec> VP9(CodecFactory factory) {
+ public static Iterable<Codec> VP9(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_VP9,
"video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_48000hz.webm",
@@ -136,7 +158,7 @@
"bbb_s1_320x180_webm_vp9_0p11_600kbps_30fps_vorbis_mono_64kbps_48000hz.webm");
}
- public Iterable<Codec> AV1(CodecFactory factory) {
+ public static Iterable<Codec> AV1(CodecFactory factory) {
return factory.createCodecList(
MediaFormat.MIMETYPE_VIDEO_AV1,
"video_480x360_webm_av1_400kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
@@ -144,18 +166,18 @@
"video_320x180_webm_av1_200kbps_30fps_vorbis_stereo_128kbps_48000hz.webm");
}
- CodecFactory ALL = new CodecFactory();
- CodecFactory SW = new SWCodecFactory();
- CodecFactory HW = new HWCodecFactory();
+ static CodecFactory ALL = new CodecFactory();
+ static CodecFactory SW = new SWCodecFactory();
+ static CodecFactory HW = new HWCodecFactory();
- public Iterable<Codec> H264() { return H264(ALL); }
- public Iterable<Codec> HEVC() { return HEVC(ALL); }
- public Iterable<Codec> VP8() { return VP8(ALL); }
- public Iterable<Codec> VP9() { return VP9(ALL); }
- public Iterable<Codec> AV1() { return AV1(ALL); }
- public Iterable<Codec> Mpeg2() { return Mpeg2(ALL); }
- public Iterable<Codec> Mpeg4() { return Mpeg4(ALL); }
- public Iterable<Codec> H263() { return H263(ALL); }
+ public static Iterable<Codec> H264() { return H264(ALL); }
+ public static Iterable<Codec> HEVC() { return HEVC(ALL); }
+ public static Iterable<Codec> VP8() { return VP8(ALL); }
+ public static Iterable<Codec> VP9() { return VP9(ALL); }
+ public static Iterable<Codec> AV1() { return AV1(ALL); }
+ public static Iterable<Codec> Mpeg2() { return Mpeg2(ALL); }
+ public static Iterable<Codec> Mpeg4() { return Mpeg4(ALL); }
+ public static Iterable<Codec> H263() { return H263(ALL); }
public Iterable<Codec> AllCodecs() {
return chain(H264(ALL), HEVC(ALL), VP8(ALL), VP9(ALL), AV1(ALL), Mpeg2(ALL), Mpeg4(ALL), H263(ALL));
@@ -170,23 +192,23 @@
}
/* tests for adaptive codecs */
- Test adaptiveEarlyEos = new EarlyEosTest().adaptive();
- Test adaptiveEosFlushSeek = new EosFlushSeekTest().adaptive();
- Test adaptiveSkipAhead = new AdaptiveSkipTest(true /* forward */);
- Test adaptiveSkipBack = new AdaptiveSkipTest(false /* forward */);
+ MediaTest adaptiveEarlyEos = new EarlyEosTest().adaptive();
+ MediaTest adaptiveEosFlushSeek = new EosFlushSeekTest().adaptive();
+ MediaTest adaptiveSkipAhead = new AdaptiveSkipTest(true /* forward */);
+ MediaTest adaptiveSkipBack = new AdaptiveSkipTest(false /* forward */);
/* DRC tests for adaptive codecs */
- Test adaptiveReconfigDrc = new ReconfigDrcTest().adaptive();
- Test adaptiveSmallReconfigDrc = new ReconfigDrcTest().adaptiveSmall();
- Test adaptiveDrc = new AdaptiveDrcTest(); /* adaptive */
- Test adaptiveSmallDrc = new AdaptiveDrcTest().adaptiveSmall();
+ MediaTest adaptiveReconfigDrc = new ReconfigDrcTest().adaptive();
+ MediaTest adaptiveSmallReconfigDrc = new ReconfigDrcTest().adaptiveSmall();
+ MediaTest adaptiveDrc = new AdaptiveDrcTest(); /* adaptive */
+ MediaTest adaptiveSmallDrc = new AdaptiveDrcTest().adaptiveSmall();
/* tests for regular codecs */
- Test earlyEos = new EarlyEosTest();
- Test eosFlushSeek = new EosFlushSeekTest();
- Test flushConfigureDrc = new ReconfigDrcTest();
+ MediaTest earlyEos = new EarlyEosTest();
+ MediaTest eosFlushSeek = new EosFlushSeekTest();
+ MediaTest flushConfigureDrc = new ReconfigDrcTest();
- Test[] allTests = {
+ MediaTest[] allTests = {
adaptiveEarlyEos,
adaptiveEosFlushSeek,
adaptiveSkipAhead,
@@ -201,7 +223,7 @@
};
/* helpers to run sets of tests */
- public void runEOS() { ex(AllCodecs(), new Test[] {
+ public void runEOS() { ex(AllCodecs(), new MediaTest[] {
adaptiveEarlyEos,
adaptiveEosFlushSeek,
adaptiveReconfigDrc,
@@ -249,209 +271,108 @@
public void bytebuffer() { ex(H264(SW), new EarlyEosTest().byteBuffer()); }
public void onlyTexture() { ex(H264(HW), new EarlyEosTest().texture()); }
- /* Individual tests. */
- @org.junit.Test
- public void testH264_adaptiveEarlyEos() { ex(H264(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testHEVC_adaptiveEarlyEos() { ex(HEVC(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testVP8_adaptiveEarlyEos() { ex(VP8(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testVP9_adaptiveEarlyEos() { ex(VP9(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testAV1_adaptiveEarlyEos() { ex(AV1(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testMpeg2_adaptiveEarlyEos() { ex(Mpeg2(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testMpeg4_adaptiveEarlyEos() { ex(Mpeg4(), adaptiveEarlyEos); }
- @org.junit.Test
- public void testH263_adaptiveEarlyEos() { ex(H263(), adaptiveEarlyEos); }
-
- @org.junit.Test
- public void testH264_adaptiveEosFlushSeek() { ex(H264(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testHEVC_adaptiveEosFlushSeek() { ex(HEVC(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testVP8_adaptiveEosFlushSeek() { ex(VP8(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testVP9_adaptiveEosFlushSeek() { ex(VP9(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testAV1_adaptiveEosFlushSeek() { ex(AV1(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testMpeg2_adaptiveEosFlushSeek() { ex(Mpeg2(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testMpeg4_adaptiveEosFlushSeek() { ex(Mpeg4(), adaptiveEosFlushSeek); }
- @org.junit.Test
- public void testH263_adaptiveEosFlushSeek() { ex(H263(), adaptiveEosFlushSeek); }
-
- @org.junit.Test
- public void testH264_adaptiveSkipAhead() { ex(H264(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testHEVC_adaptiveSkipAhead() { ex(HEVC(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testVP8_adaptiveSkipAhead() { ex(VP8(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testVP9_adaptiveSkipAhead() { ex(VP9(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testAV1_adaptiveSkipAhead() { ex(AV1(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testMpeg2_adaptiveSkipAhead() { ex(Mpeg2(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testMpeg4_adaptiveSkipAhead() { ex(Mpeg4(), adaptiveSkipAhead); }
- @org.junit.Test
- public void testH263_adaptiveSkipAhead() { ex(H263(), adaptiveSkipAhead); }
-
- @org.junit.Test
- public void testH264_adaptiveSkipBack() { ex(H264(), adaptiveSkipBack); }
- @org.junit.Test
- public void testHEVC_adaptiveSkipBack() { ex(HEVC(), adaptiveSkipBack); }
- @org.junit.Test
- public void testVP8_adaptiveSkipBack() { ex(VP8(), adaptiveSkipBack); }
- @org.junit.Test
- public void testVP9_adaptiveSkipBack() { ex(VP9(), adaptiveSkipBack); }
- @org.junit.Test
- public void testAV1_adaptiveSkipBack() { ex(AV1(), adaptiveSkipBack); }
- @org.junit.Test
- public void testMpeg2_adaptiveSkipBack() { ex(Mpeg2(), adaptiveSkipBack); }
- @org.junit.Test
- public void testMpeg4_adaptiveSkipBack() { ex(Mpeg4(), adaptiveSkipBack); }
- @org.junit.Test
- public void testH263_adaptiveSkipBack() { ex(H263(), adaptiveSkipBack); }
-
- @org.junit.Test
- public void testH264_adaptiveReconfigDrc() { ex(H264(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testHEVC_adaptiveReconfigDrc() { ex(HEVC(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testVP8_adaptiveReconfigDrc() { ex(VP8(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testVP9_adaptiveReconfigDrc() { ex(VP9(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testAV1_adaptiveReconfigDrc() { ex(AV1(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testMpeg2_adaptiveReconfigDrc() { ex(Mpeg2(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testMpeg4_adaptiveReconfigDrc() { ex(Mpeg4(), adaptiveReconfigDrc); }
- @org.junit.Test
- public void testH263_adaptiveReconfigDrc() { ex(H263(), adaptiveReconfigDrc); }
-
- @org.junit.Test
- public void testH264_adaptiveSmallReconfigDrc() { ex(H264(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testHEVC_adaptiveSmallReconfigDrc() { ex(HEVC(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testVP8_adaptiveSmallReconfigDrc() { ex(VP8(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testVP9_adaptiveSmallReconfigDrc() { ex(VP9(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testAV1_adaptiveSmallReconfigDrc() { ex(AV1(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testMpeg2_adaptiveSmallReconfigDrc() { ex(Mpeg2(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testMpeg4_adaptiveSmallReconfigDrc() { ex(Mpeg4(), adaptiveSmallReconfigDrc); }
- @org.junit.Test
- public void testH263_adaptiveSmallReconfigDrc() { ex(H263(), adaptiveSmallReconfigDrc); }
-
- @org.junit.Test
- public void testH264_adaptiveDrc() { ex(H264(), adaptiveDrc); }
- @org.junit.Test
- public void testHEVC_adaptiveDrc() { ex(HEVC(), adaptiveDrc); }
- @org.junit.Test
- public void testVP8_adaptiveDrc() { ex(VP8(), adaptiveDrc); }
- @org.junit.Test
- public void testVP9_adaptiveDrc() { ex(VP9(), adaptiveDrc); }
- @org.junit.Test
- public void testAV1_adaptiveDrc() { ex(AV1(), adaptiveDrc); }
- @org.junit.Test
- public void testMpeg2_adaptiveDrc() { ex(Mpeg2(), adaptiveDrc); }
- @org.junit.Test
- public void testMpeg4_adaptiveDrc() { ex(Mpeg4(), adaptiveDrc); }
- @org.junit.Test
- public void testH263_adaptiveDrc() { ex(H263(), adaptiveDrc); }
-
- @org.junit.Test
- public void testH264_adaptiveDrcEarlyEos() { ex(H264(), new AdaptiveDrcEarlyEosTest()); }
- @org.junit.Test
- public void testHEVC_adaptiveDrcEarlyEos() { ex(HEVC(), new AdaptiveDrcEarlyEosTest()); }
- @org.junit.Test
- public void testVP8_adaptiveDrcEarlyEos() { ex(VP8(), new AdaptiveDrcEarlyEosTest()); }
- @org.junit.Test
- public void testVP9_adaptiveDrcEarlyEos() { ex(VP9(), new AdaptiveDrcEarlyEosTest()); }
- @org.junit.Test
- public void testAV1_adaptiveDrcEarlyEos() { ex(AV1(), new AdaptiveDrcEarlyEosTest()); }
- @org.junit.Test
- public void testMpeg2_adaptiveDrcEarlyEos(){ ex(Mpeg2(), new AdaptiveDrcEarlyEosTest()); }
-
- @org.junit.Test
- public void testH264_adaptiveSmallDrc() { ex(H264(), adaptiveSmallDrc); }
- @org.junit.Test
- public void testHEVC_adaptiveSmallDrc() { ex(HEVC(), adaptiveSmallDrc); }
- @org.junit.Test
- public void testVP8_adaptiveSmallDrc() { ex(VP8(), adaptiveSmallDrc); }
- @org.junit.Test
- public void testVP9_adaptiveSmallDrc() { ex(VP9(), adaptiveSmallDrc); }
- @org.junit.Test
- public void testAV1_adaptiveSmallDrc() { ex(AV1(), adaptiveSmallDrc); }
- @org.junit.Test
- public void testMpeg2_adaptiveSmallDrc() { ex(Mpeg2(), adaptiveSmallDrc); }
-
- @org.junit.Test
- public void testH264_earlyEos() { ex(H264(), earlyEos); }
- @org.junit.Test
- public void testHEVC_earlyEos() { ex(HEVC(), earlyEos); }
- @org.junit.Test
- public void testVP8_earlyEos() { ex(VP8(), earlyEos); }
- @org.junit.Test
- public void testVP9_earlyEos() { ex(VP9(), earlyEos); }
- @org.junit.Test
- public void testAV1_earlyEos() { ex(AV1(), earlyEos); }
- @org.junit.Test
- public void testMpeg2_earlyEos() { ex(Mpeg2(), earlyEos); }
- @org.junit.Test
- public void testMpeg4_earlyEos() { ex(Mpeg4(), earlyEos); }
- @org.junit.Test
- public void testH263_earlyEos() { ex(H263(), earlyEos); }
-
- @org.junit.Test
- public void testH264_eosFlushSeek() { ex(H264(), eosFlushSeek); }
- @org.junit.Test
- public void testHEVC_eosFlushSeek() { ex(HEVC(), eosFlushSeek); }
- @org.junit.Test
- public void testVP8_eosFlushSeek() { ex(VP8(), eosFlushSeek); }
- @org.junit.Test
- public void testVP9_eosFlushSeek() { ex(VP9(), eosFlushSeek); }
- @org.junit.Test
- public void testAV1_eosFlushSeek() { ex(AV1(), eosFlushSeek); }
- @org.junit.Test
- public void testMpeg2_eosFlushSeek() { ex(Mpeg2(), eosFlushSeek); }
- @org.junit.Test
- public void testMpeg4_eosFlushSeek() { ex(Mpeg4(), eosFlushSeek); }
- @org.junit.Test
- public void testH263_eosFlushSeek() { ex(H263(), eosFlushSeek); }
-
- @org.junit.Test
- public void testH264_flushConfigureDrc() { ex(H264(), flushConfigureDrc); }
- @org.junit.Test
- public void testHEVC_flushConfigureDrc() { ex(HEVC(), flushConfigureDrc); }
- @org.junit.Test
- public void testVP8_flushConfigureDrc() { ex(VP8(), flushConfigureDrc); }
- @org.junit.Test
- public void testVP9_flushConfigureDrc() { ex(VP9(), flushConfigureDrc); }
- @org.junit.Test
- public void testAV1_flushConfigureDrc() { ex(AV1(), flushConfigureDrc); }
- @org.junit.Test
- public void testMpeg2_flushConfigureDrc() { ex(Mpeg2(), flushConfigureDrc); }
- @org.junit.Test
- public void testMpeg4_flushConfigureDrc() { ex(Mpeg4(), flushConfigureDrc); }
- @org.junit.Test
- public void testH263_flushConfigureDrc() { ex(H263(), flushConfigureDrc); }
-
- /* only use unchecked exceptions to allow brief test methods */
- private void ex(Iterable<Codec> codecList, Test test) {
- ex(codecList, new Test[] { test } );
+ static private List<Object[]> prepareParamList(List<Object> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ for (Object arg : exhaustiveArgsList) {
+ if (arg instanceof CodecList) {
+ CodecList codecList = (CodecList)arg;
+ for (Codec codec : codecList) {
+ if (mCodecPrefix != null && !codec.name.startsWith(mCodecPrefix)) {
+ continue;
+ }
+ Object[] testArgs = new Object[2];
+ testArgs[0] = codec.name;
+ CodecList subList = new CodecList();
+ subList.add(codec);
+ testArgs[1] = subList;
+ argsList.add(testArgs);
+ }
+ }
+ }
+ return argsList;
}
- private void ex(Iterable<Codec> codecList, Test[] testList) {
+ @Parameterized.Parameters(name = "{index}({0})")
+ public static Collection<Object[]> input() {
+ final List<Object> exhaustiveArgsList = Arrays.asList(new Object[]{
+ H264(), HEVC(), VP8(), VP9(), AV1(), Mpeg2(), Mpeg4(), H263()
+ });
+ return prepareParamList(exhaustiveArgsList);
+ }
+
+ /* individual tests */
+ @Test
+ public void test_adaptiveEarlyEos() {
+ ex(mCodecs, adaptiveEarlyEos);
+ }
+
+ @Test
+ public void test_adaptiveEosFlushSeek() {
+ ex(mCodecs, adaptiveEosFlushSeek);
+ }
+
+ @Test
+ public void test_adaptiveSkipAhead() {
+ ex(mCodecs, adaptiveSkipAhead);
+ }
+
+ @Test
+ public void test_adaptiveSkipBack() {
+ ex(mCodecs, adaptiveSkipBack);
+ }
+
+ @Test
+ public void test_adaptiveReconfigDrc() {
+ ex(mCodecs, adaptiveReconfigDrc);
+ }
+
+ @Test
+ public void test_adaptiveSmallReconfigDrc() {
+ ex(mCodecs, adaptiveSmallReconfigDrc);
+ }
+
+ @Test
+ public void test_adaptiveDrc() {
+ ex(mCodecs, adaptiveDrc);
+ }
+
+ @Test
+ public void test_AdaptiveDrcEarlyEosTest() {
+ String mime = mCodecs.get(0).mediaList[0].getMime();
+ assumeFalse(mime.equals(MediaFormat.MIMETYPE_VIDEO_H263) ||
+ mime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4));
+ ex(mCodecs, new AdaptiveDrcEarlyEosTest());
+ }
+
+ @Test
+ public void test_adaptiveSmallDrc() {
+ String mime = mCodecs.get(0).mediaList[0].getMime();
+ assumeFalse(mime.equals(MediaFormat.MIMETYPE_VIDEO_H263) ||
+ mime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4));
+ ex(mCodecs, adaptiveSmallDrc);
+ }
+
+ @Test
+ public void test_earlyEos() {
+ ex(mCodecs, earlyEos);
+ }
+
+ @Test
+ public void test_eosFlushSeek() {
+ ex(mCodecs, eosFlushSeek);
+ }
+
+ @Test
+ public void test_flushConfigureDrc() {
+ ex(mCodecs, flushConfigureDrc);
+ }
+
+ /* only use unchecked exceptions to allow brief test methods */
+ private void ex(Iterable<Codec> codecList, MediaTest test) {
+ ex(codecList, new MediaTest[] { test } );
+ }
+
+ private void ex(Iterable<Codec> codecList, MediaTest[] testList) {
if (codecList == null) {
Log.i(TAG, "CodecList was empty. Skipping test.");
return;
@@ -459,7 +380,7 @@
TestList tests = new TestList();
for (Codec c : codecList) {
- for (Test test : testList) {
+ for (MediaTest test : testList) {
if (test.isValid(c)) {
test.addTests(tests, c);
}
@@ -473,7 +394,7 @@
}
/* need an inner class to have access to the activity */
- abstract class ActivityTest extends Test {
+ abstract class ActivityTest extends MediaTest {
TestSurface mNullSurface = new ActivitySurface(null);
protected TestSurface getSurface() {
if (mUseSurface) {
@@ -1759,7 +1680,7 @@
private int mWarnings;
}
-abstract class Test {
+abstract class MediaTest {
public static final int FORMAT_ADAPTIVE_LARGEST = 1;
public static final int FORMAT_ADAPTIVE_FIRST = 2;
public static final int FORMAT_REGULAR = 3;
@@ -1768,29 +1689,29 @@
protected boolean mUseSurface;
protected boolean mUseSurfaceTexture;
- public Test() {
+ public MediaTest() {
mFormatType = FORMAT_REGULAR;
mUseSurface = true;
mUseSurfaceTexture = false;
}
- public Test adaptive() {
+ public MediaTest adaptive() {
mFormatType = FORMAT_ADAPTIVE_LARGEST;
return this;
}
- public Test adaptiveSmall() {
+ public MediaTest adaptiveSmall() {
mFormatType = FORMAT_ADAPTIVE_FIRST;
return this;
}
- public Test byteBuffer() {
+ public MediaTest byteBuffer() {
mUseSurface = false;
mUseSurfaceTexture = false;
return this;
}
- public Test texture() {
+ public MediaTest texture() {
mUseSurface = false;
mUseSurfaceTexture = true;
return this;
@@ -1852,17 +1773,17 @@
abstract class Step {
private static final String TAG = "AdaptiveStep";
- public Step(String title, Test instance, Codec codec, Media media) {
+ public Step(String title, MediaTest instance, Codec codec, Media media) {
mTest = instance;
mCodec = codec;
mMedia = media;
mDescription = title + " on " + stepSurface().getSurface() + " using " +
mCodec.name + " and " + stepFormat();
}
- public Step(String title, Test instance, Codec codec, int mediaIx) {
+ public Step(String title, MediaTest instance, Codec codec, int mediaIx) {
this(title, instance, codec, codec.mediaList[mediaIx]);
}
- public Step(String title, Test instance, Codec codec) {
+ public Step(String title, MediaTest instance, Codec codec) {
this(title, instance, codec, 0);
}
public Step(String description) {
@@ -1873,7 +1794,7 @@
public abstract void run() throws Throwable;
private String mDescription;
- private Test mTest;
+ private MediaTest mTest;
private Codec mCodec;
private Media mMedia;
private int mWarnings;
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
index f9355f5..61acac7 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/ImageReaderDecoderTest.java
@@ -78,7 +78,8 @@
* test. For decoder test, hw and sw decoders are tested,
* </p>
*/
-@Presubmit
+// TODO(b/210947256) Enable presubmit once this test works on Pixel 4
+//@Presubmit
@SmallTest
@RequiresDevice
@AppModeFull(reason = "Instant apps cannot access the SD card")
diff --git a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
index c182ab0..3464193 100644
--- a/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
+++ b/tests/tests/media/decoder/src/android/media/decoder/cts/VideoDecoderPerfTest.java
@@ -30,9 +30,9 @@
import android.media.cts.Preconditions;
import android.os.Bundle;
import android.platform.test.annotations.AppModeFull;
+import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
-import android.text.TextUtils;
import android.view.Surface;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -47,15 +47,19 @@
import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import org.junit.Test;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.LinkedList;
+import java.util.List;
@MediaHeavyPresubmitTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class VideoDecoderPerfTest extends MediaTestBase {
private static final String TAG = "VideoDecoderPerfTest";
private static final String REPORT_LOG_NAME = "CtsMediaDecoderTestCases";
@@ -78,6 +82,14 @@
private static final boolean OTHER = false;
private static final int MAX_SIZE_SAMPLES_IN_MEMORY_BYTES = 12 << 20; // 12MB
+
+ private static final String CODEC_PREFIX_KEY = "codec-prefix";
+ private static final String mCodecPrefix;
+
+ private final String mDecoderName;
+ private final String mMediaType;
+ private final String[] mResources;
+
// each sample contains the buffer and the PTS offset from the frame index
LinkedList<Pair<ByteBuffer, Double>> mSamplesInMemory = new LinkedList<Pair<ByteBuffer, Double>>();
private MediaFormat mDecInputFormat;
@@ -87,6 +99,74 @@
private boolean mSkipRateChecking = false;
static final String mInpPrefix = WorkDir.getMediaDirString();
+ static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ int argLength = exhaustiveArgsList.get(0).length;
+ for (Object[] arg : exhaustiveArgsList) {
+ String[] decoders = MediaUtils.getDecoderNamesForMime((String) arg[0]);
+ for (String decoder : decoders) {
+ if (mCodecPrefix != null && !decoder.startsWith(mCodecPrefix)) {
+ continue;
+ }
+ Object[] testArgs = new Object[argLength + 1];
+ // Add codec name as first argument and then copy all other arguments passed
+ testArgs[0] = decoder;
+ System.arraycopy(arg, 0, testArgs, 1, argLength);
+ argsList.add(testArgs);
+ }
+ }
+ return argsList;
+ }
+
+ static {
+ android.os.Bundle args = InstrumentationRegistry.getArguments();
+ mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+ }
+
+ @Parameterized.Parameters(name = "{index}({0}:{3})")
+ public static Collection<Object[]> input() {
+ final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+ // MediaType, resources, graphics display resolution
+ {AVC, sAvcMedia0320x0240, "qvga"},
+ {AVC, sAvcMedia0720x0480, "sd"},
+ {AVC, sAvcMedia1280x0720, "hd"},
+ {AVC, sAvcMedia1920x1080, "fullhd"},
+
+ {H263, sH263Media0176x0144, "qcif"},
+ {H263, sH263Media0352x0288, "cif"},
+
+ {HEVC, sHevcMedia0352x0288, "cif"},
+ {HEVC, sHevcMedia0640x0360, "vga"},
+ {HEVC, sHevcMedia0720x0480, "sd"},
+ {HEVC, sHevcMedia1280x0720, "hd"},
+ {HEVC, sHevcMedia1920x1080, "fullhd"},
+ {HEVC, sHevcMedia3840x2160, "uhd"},
+
+ {MPEG4, sMpeg4Media0176x0144, "qcif"},
+ {MPEG4, sMpeg4Media0480x0360, "360p"},
+ {MPEG4, sMpeg4Media1280x0720, "hd"},
+
+ {VP8, sVp8Media0320x0180, "qvga"},
+ {VP8, sVp8Media0640x0360, "vga"},
+ {VP8, sVp8Media1280x0720, "hd"},
+ {VP8, sVp8Media1920x1080, "fullhd"},
+
+ {VP9, sVp9Media0320x0180, "qvga"},
+ {VP9, sVp9Media0640x0360, "vga"},
+ {VP9, sVp9Media1280x0720, "hd"},
+ {VP9, sVp9Media1920x1080, "fullhd"},
+ {VP9, sVp9Media3840x2160, "uhd"},
+ });
+ return prepareParamList(exhaustiveArgsList);
+ }
+
+ public VideoDecoderPerfTest(String decodername, String mediaType, String[] resources,
+ @SuppressWarnings("unused") String gfxcode) {
+ mDecoderName = decodername;
+ mMediaType = mediaType;
+ mResources = resources;
+ }
+
@Before
@Override
public void setUp() throws Throwable {
@@ -308,7 +388,7 @@
MediaUtils.Stats stats = new MediaUtils.Stats(frameTimeUsDiff);
fps = MediaPerfUtils.addPerformanceStatsToLog(log, stats, message);
- log.submit(getInstrumentation());
+ log.submit(InstrumentationRegistry.getInstrumentation());
return fps;
}
@@ -321,26 +401,8 @@
return formats;
}
- private void count(final String[] resources, int numGoog, int numOther) throws Exception {
+ private void perf(final String decoderName, final String[] resources) throws Exception {
MediaFormat[] formats = getVideoTrackFormats(resources);
- MediaUtils.verifyNumCodecs(numGoog, false /* isEncoder */, true /* isGoog */, formats);
- MediaUtils.verifyNumCodecs(numOther, false /* isEncoder */, false /* isGoog */, formats);
- }
-
- private void perf(final String[] resources, boolean isGoog, int ix) throws Exception {
- MediaFormat[] formats = getVideoTrackFormats(resources);
- String[] decoders = MediaUtils.getDecoderNames(isGoog, formats);
- String kind = isGoog ? "Google" : "non-Google";
- if (decoders.length == 0) {
- MediaUtils.skipTest("No " + kind + " decoders for " + Arrays.toString(formats));
- return;
- } else if (ix >= decoders.length) {
- Log.i(TAG, "No more " + kind + " decoders for " + Arrays.toString(formats));
- return;
- }
-
- String decoderName = decoders[ix];
-
// Decode/measure the first supported video resource
for (int i = 0; i < resources.length; ++i) {
if (MediaUtils.supports(decoderName, formats[i])) {
@@ -350,51 +412,16 @@
}
}
- // Poor man's Parametrized test as this test must still run on CTSv1 runner.
-
- // The count tests are to ensure this Cts test covers all decoders. Add further
- // tests and change the count if there can be more decoders.
-
// AVC tests
private static final String[] sAvcMedia0320x0240 = {
"bbb_s1_320x240_mp4_h264_mp2_800kbps_30fps_aac_lc_5ch_240kbps_44100hz.mp4",
};
- @Test
- public void testAvcCount0320x0240() throws Exception { count(sAvcMedia0320x0240, 2, 4); }
- @Test
- public void testAvcGoog0Perf0320x0240() throws Exception { perf(sAvcMedia0320x0240, GOOG, 0); }
- @Test
- public void testAvcGoog1Perf0320x0240() throws Exception { perf(sAvcMedia0320x0240, GOOG, 1); }
- @Test
- public void testAvcOther0Perf0320x0240() throws Exception { perf(sAvcMedia0320x0240, OTHER, 0); }
- @Test
- public void testAvcOther1Perf0320x0240() throws Exception { perf(sAvcMedia0320x0240, OTHER, 1); }
- @Test
- public void testAvcOther2Perf0320x0240() throws Exception { perf(sAvcMedia0320x0240, OTHER, 2); }
- @Test
- public void testAvcOther3Perf0320x0240() throws Exception { perf(sAvcMedia0320x0240, OTHER, 3); }
-
private static final String[] sAvcMedia0720x0480 = {
"bbb_s1_720x480_mp4_h264_mp3_2mbps_30fps_aac_lc_5ch_320kbps_48000hz.mp4",
};
- @Test
- public void testAvcCount0720x0480() throws Exception { count(sAvcMedia0720x0480, 2, 4); }
- @Test
- public void testAvcGoog0Perf0720x0480() throws Exception { perf(sAvcMedia0720x0480, GOOG, 0); }
- @Test
- public void testAvcGoog1Perf0720x0480() throws Exception { perf(sAvcMedia0720x0480, GOOG, 1); }
- @Test
- public void testAvcOther0Perf0720x0480() throws Exception { perf(sAvcMedia0720x0480, OTHER, 0); }
- @Test
- public void testAvcOther1Perf0720x0480() throws Exception { perf(sAvcMedia0720x0480, OTHER, 1); }
- @Test
- public void testAvcOther2Perf0720x0480() throws Exception { perf(sAvcMedia0720x0480, OTHER, 2); }
- @Test
- public void testAvcOther3Perf0720x0480() throws Exception { perf(sAvcMedia0720x0480, OTHER, 3); }
-
// prefer highest effective bitrate, then high profile
private static final String[] sAvcMedia1280x0720 = {
"bbb_s4_1280x720_mp4_h264_mp31_8mbps_30fps_aac_he_mono_40kbps_44100hz.mp4",
@@ -402,21 +429,6 @@
"bbb_s3_1280x720_mp4_h264_mp32_8mbps_60fps_aac_he_v2_6ch_144kbps_44100hz.mp4",
};
- @Test
- public void testAvcCount1280x0720() throws Exception { count(sAvcMedia1280x0720, 2, 4); }
- @Test
- public void testAvcGoog0Perf1280x0720() throws Exception { perf(sAvcMedia1280x0720, GOOG, 0); }
- @Test
- public void testAvcGoog1Perf1280x0720() throws Exception { perf(sAvcMedia1280x0720, GOOG, 1); }
- @Test
- public void testAvcOther0Perf1280x0720() throws Exception { perf(sAvcMedia1280x0720, OTHER, 0); }
- @Test
- public void testAvcOther1Perf1280x0720() throws Exception { perf(sAvcMedia1280x0720, OTHER, 1); }
- @Test
- public void testAvcOther2Perf1280x0720() throws Exception { perf(sAvcMedia1280x0720, OTHER, 2); }
- @Test
- public void testAvcOther3Perf1280x0720() throws Exception { perf(sAvcMedia1280x0720, OTHER, 3); }
-
// prefer highest effective bitrate, then high profile
private static final String[] sAvcMedia1920x1080 = {
"bbb_s4_1920x1080_wide_mp4_h264_hp4_20mbps_30fps_aac_lc_6ch_384kbps_44100hz.mp4",
@@ -425,53 +437,16 @@
"bbb_s2_1920x1080_mp4_h264_mp42_20mbps_60fps_aac_he_v2_5ch_160kbps_48000hz.mp4",
};
- @Test
- public void testAvcCount1920x1080() throws Exception { count(sAvcMedia1920x1080, 2, 4); }
- @Test
- public void testAvcGoog0Perf1920x1080() throws Exception { perf(sAvcMedia1920x1080, GOOG, 0); }
- @Test
- public void testAvcGoog1Perf1920x1080() throws Exception { perf(sAvcMedia1920x1080, GOOG, 1); }
- @Test
- public void testAvcOther0Perf1920x1080() throws Exception { perf(sAvcMedia1920x1080, OTHER, 0); }
- @Test
- public void testAvcOther1Perf1920x1080() throws Exception { perf(sAvcMedia1920x1080, OTHER, 1); }
- @Test
- public void testAvcOther2Perf1920x1080() throws Exception { perf(sAvcMedia1920x1080, OTHER, 2); }
- @Test
- public void testAvcOther3Perf1920x1080() throws Exception { perf(sAvcMedia1920x1080, OTHER, 3); }
-
// H263 tests
private static final String[] sH263Media0176x0144 = {
"video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp",
};
- @Test
- public void testH263Count0176x0144() throws Exception { count(sH263Media0176x0144, 2, 2); }
- @Test
- public void testH263Goog0Perf0176x0144() throws Exception { perf(sH263Media0176x0144, GOOG, 0); }
- @Test
- public void testH263Goog1Perf0176x0144() throws Exception { perf(sH263Media0176x0144, GOOG, 1); }
- @Test
- public void testH263Other0Perf0176x0144() throws Exception { perf(sH263Media0176x0144, OTHER, 0); }
- @Test
- public void testH263Other1Perf0176x0144() throws Exception { perf(sH263Media0176x0144, OTHER, 1); }
-
private static final String[] sH263Media0352x0288 = {
"video_352x288_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz.3gp",
};
- @Test
- public void testH263Count0352x0288() throws Exception { count(sH263Media0352x0288, 2, 2); }
- @Test
- public void testH263Goog0Perf0352x0288() throws Exception { perf(sH263Media0352x0288, GOOG, 0); }
- @Test
- public void testH263Goog1Perf0352x0288() throws Exception { perf(sH263Media0352x0288, GOOG, 1); }
- @Test
- public void testH263Other0Perf0352x0288() throws Exception { perf(sH263Media0352x0288, OTHER, 0); }
- @Test
- public void testH263Other1Perf0352x0288() throws Exception { perf(sH263Media0352x0288, OTHER, 1); }
-
// No media for H263 704x576
// No media for H263 1408x1152
@@ -482,118 +457,28 @@
"bbb_s1_352x288_mp4_hevc_mp2_600kbps_30fps_aac_he_stereo_96kbps_48000hz.mp4",
};
- @Test
- public void testHevcCount0352x0288() throws Exception { count(sHevcMedia0352x0288, 2, 4); }
- @Test
- public void testHevcGoog0Perf0352x0288() throws Exception { perf(sHevcMedia0352x0288, GOOG, 0); }
- @Test
- public void testHevcGoog1Perf0352x0288() throws Exception { perf(sHevcMedia0352x0288, GOOG, 1); }
- @Test
- public void testHevcOther0Perf0352x0288() throws Exception { perf(sHevcMedia0352x0288, OTHER, 0); }
- @Test
- public void testHevcOther1Perf0352x0288() throws Exception { perf(sHevcMedia0352x0288, OTHER, 1); }
- @Test
- public void testHevcOther2Perf0352x0288() throws Exception { perf(sHevcMedia0352x0288, OTHER, 2); }
- @Test
- public void testHevcOther3Perf0352x0288() throws Exception { perf(sHevcMedia0352x0288, OTHER, 3); }
-
private static final String[] sHevcMedia0640x0360 = {
"bbb_s1_640x360_mp4_hevc_mp21_1600kbps_30fps_aac_he_6ch_288kbps_44100hz.mp4",
};
- @Test
- public void testHevcCount0640x0360() throws Exception { count(sHevcMedia0640x0360, 2, 4); }
- @Test
- public void testHevcGoog0Perf0640x0360() throws Exception { perf(sHevcMedia0640x0360, GOOG, 0); }
- @Test
- public void testHevcGoog1Perf0640x0360() throws Exception { perf(sHevcMedia0640x0360, GOOG, 1); }
- @Test
- public void testHevcOther0Perf0640x0360() throws Exception { perf(sHevcMedia0640x0360, OTHER, 0); }
- @Test
- public void testHevcOther1Perf0640x0360() throws Exception { perf(sHevcMedia0640x0360, OTHER, 1); }
- @Test
- public void testHevcOther2Perf0640x0360() throws Exception { perf(sHevcMedia0640x0360, OTHER, 2); }
- @Test
- public void testHevcOther3Perf0640x0360() throws Exception { perf(sHevcMedia0640x0360, OTHER, 3); }
-
private static final String[] sHevcMedia0720x0480 = {
"bbb_s1_720x480_mp4_hevc_mp3_1600kbps_30fps_aac_he_6ch_240kbps_48000hz.mp4",
};
- @Test
- public void testHevcCount0720x0480() throws Exception { count(sHevcMedia0720x0480, 2, 4); }
- @Test
- public void testHevcGoog0Perf0720x0480() throws Exception { perf(sHevcMedia0720x0480, GOOG, 0); }
- @Test
- public void testHevcGoog1Perf0720x0480() throws Exception { perf(sHevcMedia0720x0480, GOOG, 1); }
- @Test
- public void testHevcOther0Perf0720x0480() throws Exception { perf(sHevcMedia0720x0480, OTHER, 0); }
- @Test
- public void testHevcOther1Perf0720x0480() throws Exception { perf(sHevcMedia0720x0480, OTHER, 1); }
- @Test
- public void testHevcOther2Perf0720x0480() throws Exception { perf(sHevcMedia0720x0480, OTHER, 2); }
- @Test
- public void testHevcOther3Perf0720x0480() throws Exception { perf(sHevcMedia0720x0480, OTHER, 3); }
-
private static final String[] sHevcMedia1280x0720 = {
"bbb_s4_1280x720_mp4_hevc_mp31_4mbps_30fps_aac_he_stereo_80kbps_32000hz.mp4",
};
- @Test
- public void testHevcCount1280x0720() throws Exception { count(sHevcMedia1280x0720, 2, 4); }
- @Test
- public void testHevcGoog0Perf1280x0720() throws Exception { perf(sHevcMedia1280x0720, GOOG, 0); }
- @Test
- public void testHevcGoog1Perf1280x0720() throws Exception { perf(sHevcMedia1280x0720, GOOG, 1); }
- @Test
- public void testHevcOther0Perf1280x0720() throws Exception { perf(sHevcMedia1280x0720, OTHER, 0); }
- @Test
- public void testHevcOther1Perf1280x0720() throws Exception { perf(sHevcMedia1280x0720, OTHER, 1); }
- @Test
- public void testHevcOther2Perf1280x0720() throws Exception { perf(sHevcMedia1280x0720, OTHER, 2); }
- @Test
- public void testHevcOther3Perf1280x0720() throws Exception { perf(sHevcMedia1280x0720, OTHER, 3); }
-
private static final String[] sHevcMedia1920x1080 = {
"bbb_s2_1920x1080_mp4_hevc_mp41_10mbps_60fps_aac_lc_6ch_384kbps_22050hz.mp4",
};
- @Test
- public void testHevcCount1920x1080() throws Exception { count(sHevcMedia1920x1080, 2, 4); }
- @Test
- public void testHevcGoog0Perf1920x1080() throws Exception { perf(sHevcMedia1920x1080, GOOG, 0); }
- @Test
- public void testHevcGoog1Perf1920x1080() throws Exception { perf(sHevcMedia1920x1080, GOOG, 1); }
- @Test
- public void testHevcOther0Perf1920x1080() throws Exception { perf(sHevcMedia1920x1080, OTHER, 0); }
- @Test
- public void testHevcOther1Perf1920x1080() throws Exception { perf(sHevcMedia1920x1080, OTHER, 1); }
- @Test
- public void testHevcOther2Perf1920x1080() throws Exception { perf(sHevcMedia1920x1080, OTHER, 2); }
- @Test
- public void testHevcOther3Perf1920x1080() throws Exception { perf(sHevcMedia1920x1080, OTHER, 3); }
-
// prefer highest effective bitrate
private static final String[] sHevcMedia3840x2160 = {
"bbb_s4_3840x2160_mp4_hevc_mp5_20mbps_30fps_aac_lc_6ch_384kbps_24000hz.mp4",
"bbb_s2_3840x2160_mp4_hevc_mp51_20mbps_60fps_aac_lc_6ch_384kbps_32000hz.mp4",
};
- @Test
- public void testHevcCount3840x2160() throws Exception { count(sHevcMedia3840x2160, 2, 4); }
- @Test
- public void testHevcGoog0Perf3840x2160() throws Exception { perf(sHevcMedia3840x2160, GOOG, 0); }
- @Test
- public void testHevcGoog1Perf3840x2160() throws Exception { perf(sHevcMedia3840x2160, GOOG, 1); }
- @Test
- public void testHevcOther0Perf3840x2160() throws Exception { perf(sHevcMedia3840x2160, OTHER, 0); }
- @Test
- public void testHevcOther1Perf3840x2160() throws Exception { perf(sHevcMedia3840x2160, OTHER, 1); }
- @Test
- public void testHevcOther2Perf3840x2160() throws Exception { perf(sHevcMedia3840x2160, OTHER, 2); }
- @Test
- public void testHevcOther3Perf3840x2160() throws Exception { perf(sHevcMedia3840x2160, OTHER, 3); }
-
// MPEG2 tests
// No media for MPEG2 176x144
@@ -612,205 +497,56 @@
"video_176x144_mp4_mpeg4_300kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
};
- @Test
- public void testMpeg4Count0176x0144() throws Exception { count(sMpeg4Media0176x0144, 2, 4); }
- @Test
- public void testMpeg4Goog0Perf0176x0144() throws Exception { perf(sMpeg4Media0176x0144, GOOG, 0); }
- @Test
- public void testMpeg4Goog1Perf0176x0144() throws Exception { perf(sMpeg4Media0176x0144, GOOG, 1); }
- @Test
- public void testMpeg4Other0Perf0176x0144() throws Exception { perf(sMpeg4Media0176x0144, OTHER, 0); }
- @Test
- public void testMpeg4Other1Perf0176x0144() throws Exception { perf(sMpeg4Media0176x0144, OTHER, 1); }
- @Test
- public void testMpeg4Other2Perf0176x0144() throws Exception { perf(sMpeg4Media0176x0144, OTHER, 2); }
- @Test
- public void testMpeg4Other3Perf0176x0144() throws Exception { perf(sMpeg4Media0176x0144, OTHER, 3); }
-
private static final String[] sMpeg4Media0480x0360 = {
"video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
};
- @Test
- public void testMpeg4Count0480x0360() throws Exception { count(sMpeg4Media0480x0360, 2, 4); }
- @Test
- public void testMpeg4Goog0Perf0480x0360() throws Exception { perf(sMpeg4Media0480x0360, GOOG, 0); }
- @Test
- public void testMpeg4Goog1Perf0480x0360() throws Exception { perf(sMpeg4Media0480x0360, GOOG, 1); }
- @Test
- public void testMpeg4Other0Perf0480x0360() throws Exception { perf(sMpeg4Media0480x0360, OTHER, 0); }
- @Test
- public void testMpeg4Other1Perf0480x0360() throws Exception { perf(sMpeg4Media0480x0360, OTHER, 1); }
- @Test
- public void testMpeg4Other2Perf0480x0360() throws Exception { perf(sMpeg4Media0480x0360, OTHER, 2); }
- @Test
- public void testMpeg4Other3Perf0480x0360() throws Exception { perf(sMpeg4Media0480x0360, OTHER, 3); }
-
- // No media for MPEG4 640x480
+ // No media for MPEG4 640x480
private static final String[] sMpeg4Media1280x0720 = {
"video_1280x720_mp4_mpeg4_1000kbps_25fps_aac_stereo_128kbps_44100hz.mp4",
};
- @Test
- public void testMpeg4Count1280x0720() throws Exception { count(sMpeg4Media1280x0720, 2, 4); }
- @Test
- public void testMpeg4Goog0Perf1280x0720() throws Exception { perf(sMpeg4Media1280x0720, GOOG, 0); }
- @Test
- public void testMpeg4Goog1Perf1280x0720() throws Exception { perf(sMpeg4Media1280x0720, GOOG, 1); }
- @Test
- public void testMpeg4Other0Perf1280x0720() throws Exception { perf(sMpeg4Media1280x0720, OTHER, 0); }
- @Test
- public void testMpeg4Other1Perf1280x0720() throws Exception { perf(sMpeg4Media1280x0720, OTHER, 1); }
- @Test
- public void testMpeg4Other2Perf1280x0720() throws Exception { perf(sMpeg4Media1280x0720, OTHER, 2); }
- @Test
- public void testMpeg4Other3Perf1280x0720() throws Exception { perf(sMpeg4Media1280x0720, OTHER, 3); }
-
// VP8 tests
private static final String[] sVp8Media0320x0180 = {
"bbb_s1_320x180_webm_vp8_800kbps_30fps_opus_5ch_320kbps_48000hz.webm",
};
- @Test
- public void testVp8Count0320x0180() throws Exception { count(sVp8Media0320x0180, 2, 2); }
- @Test
- public void testVp8Goog0Perf0320x0180() throws Exception { perf(sVp8Media0320x0180, GOOG, 0); }
- @Test
- public void testVp8Goog1Perf0320x0180() throws Exception { perf(sVp8Media0320x0180, GOOG, 1); }
- @Test
- public void testVp8Other0Perf0320x0180() throws Exception { perf(sVp8Media0320x0180, OTHER, 0); }
- @Test
- public void testVp8Other1Perf0320x0180() throws Exception { perf(sVp8Media0320x0180, OTHER, 1); }
-
private static final String[] sVp8Media0640x0360 = {
"bbb_s1_640x360_webm_vp8_2mbps_30fps_vorbis_5ch_320kbps_48000hz.webm",
};
- @Test
- public void testVp8Count0640x0360() throws Exception { count(sVp8Media0640x0360, 2, 2); }
- @Test
- public void testVp8Goog0Perf0640x0360() throws Exception { perf(sVp8Media0640x0360, GOOG, 0); }
- @Test
- public void testVp8Goog1Perf0640x0360() throws Exception { perf(sVp8Media0640x0360, GOOG, 1); }
- @Test
- public void testVp8Other0Perf0640x0360() throws Exception { perf(sVp8Media0640x0360, OTHER, 0); }
- @Test
- public void testVp8Other1Perf0640x0360() throws Exception { perf(sVp8Media0640x0360, OTHER, 1); }
-
// prefer highest effective bitrate
private static final String[] sVp8Media1280x0720 = {
"bbb_s4_1280x720_webm_vp8_8mbps_30fps_opus_mono_64kbps_48000hz.webm",
"bbb_s3_1280x720_webm_vp8_8mbps_60fps_opus_6ch_384kbps_48000hz.webm",
};
- @Test
- public void testVp8Count1280x0720() throws Exception { count(sVp8Media1280x0720, 2, 2); }
- @Test
- public void testVp8Goog0Perf1280x0720() throws Exception { perf(sVp8Media1280x0720, GOOG, 0); }
- @Test
- public void testVp8Goog1Perf1280x0720() throws Exception { perf(sVp8Media1280x0720, GOOG, 1); }
- @Test
- public void testVp8Other0Perf1280x0720() throws Exception { perf(sVp8Media1280x0720, OTHER, 0); }
- @Test
- public void testVp8Other1Perf1280x0720() throws Exception { perf(sVp8Media1280x0720, OTHER, 1); }
-
// prefer highest effective bitrate
private static final String[] sVp8Media1920x1080 = {
"bbb_s4_1920x1080_wide_webm_vp8_20mbps_30fps_vorbis_6ch_384kbps_44100hz.webm",
"bbb_s2_1920x1080_webm_vp8_20mbps_60fps_vorbis_6ch_384kbps_48000hz.webm",
};
- @Test
- public void testVp8Count1920x1080() throws Exception { count(sVp8Media1920x1080, 2, 2); }
- @Test
- public void testVp8Goog0Perf1920x1080() throws Exception { perf(sVp8Media1920x1080, GOOG, 0); }
- @Test
- public void testVp8Goog1Perf1920x1080() throws Exception { perf(sVp8Media1920x1080, GOOG, 1); }
- @Test
- public void testVp8Other0Perf1920x1080() throws Exception { perf(sVp8Media1920x1080, OTHER, 0); }
- @Test
- public void testVp8Other1Perf1920x1080() throws Exception { perf(sVp8Media1920x1080, OTHER, 1); }
-
// VP9 tests
private static final String[] sVp9Media0320x0180 = {
"bbb_s1_320x180_webm_vp9_0p11_600kbps_30fps_vorbis_mono_64kbps_48000hz.webm",
};
- @Test
- public void testVp9Count0320x0180() throws Exception { count(sVp9Media0320x0180, 2, 4); }
- @Test
- public void testVp9Goog0Perf0320x0180() throws Exception { perf(sVp9Media0320x0180, GOOG, 0); }
- @Test
- public void testVp9Goog1Perf0320x0180() throws Exception { perf(sVp9Media0320x0180, GOOG, 1); }
- @Test
- public void testVp9Other0Perf0320x0180() throws Exception { perf(sVp9Media0320x0180, OTHER, 0); }
- @Test
- public void testVp9Other1Perf0320x0180() throws Exception { perf(sVp9Media0320x0180, OTHER, 1); }
- @Test
- public void testVp9Other2Perf0320x0180() throws Exception { perf(sVp9Media0320x0180, OTHER, 2); }
- @Test
- public void testVp9Other3Perf0320x0180() throws Exception { perf(sVp9Media0320x0180, OTHER, 3); }
-
private static final String[] sVp9Media0640x0360 = {
"bbb_s1_640x360_webm_vp9_0p21_1600kbps_30fps_vorbis_stereo_128kbps_48000hz.webm",
};
- @Test
- public void testVp9Count0640x0360() throws Exception { count(sVp9Media0640x0360, 2, 4); }
- @Test
- public void testVp9Goog0Perf0640x0360() throws Exception { perf(sVp9Media0640x0360, GOOG, 0); }
- @Test
- public void testVp9Goog1Perf0640x0360() throws Exception { perf(sVp9Media0640x0360, GOOG, 1); }
- @Test
- public void testVp9Other0Perf0640x0360() throws Exception { perf(sVp9Media0640x0360, OTHER, 0); }
- @Test
- public void testVp9Other1Perf0640x0360() throws Exception { perf(sVp9Media0640x0360, OTHER, 1); }
- @Test
- public void testVp9Other2Perf0640x0360() throws Exception { perf(sVp9Media0640x0360, OTHER, 2); }
- @Test
- public void testVp9Other3Perf0640x0360() throws Exception { perf(sVp9Media0640x0360, OTHER, 3); }
-
private static final String[] sVp9Media1280x0720 = {
"bbb_s4_1280x720_webm_vp9_0p31_4mbps_30fps_opus_stereo_128kbps_48000hz.webm",
};
- @Test
- public void testVp9Count1280x0720() throws Exception { count(sVp9Media1280x0720, 2, 4); }
- @Test
- public void testVp9Goog0Perf1280x0720() throws Exception { perf(sVp9Media1280x0720, GOOG, 0); }
- @Test
- public void testVp9Goog1Perf1280x0720() throws Exception { perf(sVp9Media1280x0720, GOOG, 1); }
- @Test
- public void testVp9Other0Perf1280x0720() throws Exception { perf(sVp9Media1280x0720, OTHER, 0); }
- @Test
- public void testVp9Other1Perf1280x0720() throws Exception { perf(sVp9Media1280x0720, OTHER, 1); }
- @Test
- public void testVp9Other2Perf1280x0720() throws Exception { perf(sVp9Media1280x0720, OTHER, 2); }
- @Test
- public void testVp9Other3Perf1280x0720() throws Exception { perf(sVp9Media1280x0720, OTHER, 3); }
-
private static final String[] sVp9Media1920x1080 = {
"bbb_s2_1920x1080_webm_vp9_0p41_10mbps_60fps_vorbis_6ch_384kbps_22050hz.webm",
};
- @Test
- public void testVp9Count1920x1080() throws Exception { count(sVp9Media1920x1080, 2, 4); }
- @Test
- public void testVp9Goog0Perf1920x1080() throws Exception { perf(sVp9Media1920x1080, GOOG, 0); }
- @Test
- public void testVp9Goog1Perf1920x1080() throws Exception { perf(sVp9Media1920x1080, GOOG, 1); }
- @Test
- public void testVp9Other0Perf1920x1080() throws Exception { perf(sVp9Media1920x1080, OTHER, 0); }
- @Test
- public void testVp9Other1Perf1920x1080() throws Exception { perf(sVp9Media1920x1080, OTHER, 1); }
- @Test
- public void testVp9Other2Perf1920x1080() throws Exception { perf(sVp9Media1920x1080, OTHER, 2); }
- @Test
- public void testVp9Other3Perf1920x1080() throws Exception { perf(sVp9Media1920x1080, OTHER, 3); }
-
// prefer highest effective bitrate
private static final String[] sVp9Media3840x2160 = {
"bbb_s4_3840x2160_webm_vp9_0p5_20mbps_30fps_vorbis_6ch_384kbps_24000hz.webm",
@@ -818,17 +554,8 @@
};
@Test
- public void testVp9Count3840x2160() throws Exception { count(sVp9Media3840x2160, 2, 4); }
- @Test
- public void testVp9Goog0Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, GOOG, 0); }
- @Test
- public void testVp9Goog1Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, GOOG, 1); }
- @Test
- public void testVp9Other0Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, OTHER, 0); }
- @Test
- public void testVp9Other1Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, OTHER, 1); }
- @Test
- public void testVp9Other2Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, OTHER, 2); }
- @Test
- public void testVp9Other3Perf3840x2160() throws Exception { perf(sVp9Media3840x2160, OTHER, 3); }
+ public void testPerf() throws Exception {
+ perf(mDecoderName, mResources);
+ }
}
+
diff --git a/tests/tests/media/drm/AndroidManifest.xml b/tests/tests/media/drm/AndroidManifest.xml
index 71c2d9d..e7aa4cd 100644
--- a/tests/tests/media/drm/AndroidManifest.xml
+++ b/tests/tests/media/drm/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
index fc3a89f..c95ed69 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
@@ -16,7 +16,6 @@
package android.media.encoder.cts;
-import android.content.Context;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
@@ -24,12 +23,11 @@
import android.media.cts.Preconditions;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.RequiresDevice;
-import android.test.AndroidTestCase;
import android.util.Log;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
-import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import java.io.File;
@@ -42,7 +40,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -50,10 +48,20 @@
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
@SmallTest
@RequiresDevice
@AppModeFull(reason = "Instant apps cannot access the SD card")
-public class EncoderTest extends AndroidTestCase {
+@RunWith(Parameterized.class)
+public class EncoderTest {
private static final String TAG = "EncoderTest";
private static final boolean VERBOSE = false;
@@ -76,17 +84,22 @@
private static boolean sSaveResults = false;
static final Map<String, String> mDefaultEncoders = new HashMap<>();
- @Override
- public void setContext(Context context) {
- super.setContext(context);
- }
+ private static final String CODEC_PREFIX_KEY = "codec-prefix";
+ private static String mCodecPrefix;
+
+ private final String mEncoderName;
+ private final String mMime;
+ private final int[] mProfiles;
+ private final int[] mBitrates;
+ private final int[] mSampleRates;
+ private final int[] mChannelCounts;
+ private ArrayList<MediaFormat> mFormats;
static boolean isDefaultCodec(String codecName, String mime)
throws IOException {
if (mDefaultEncoders.containsKey(mime)) {
return mDefaultEncoders.get(mime).equalsIgnoreCase(codecName);
}
-
MediaCodec codec = MediaCodec.createEncoderByType(mime);
boolean isDefault = codec.getName().equalsIgnoreCase(codecName);
mDefaultEncoders.put(mime, codec.getName());
@@ -94,121 +107,101 @@
return isDefault;
}
- public void testAMRNBEncoders() {
- LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
-
- final int kBitRates[] =
- { 4750, 5150, 5900, 6700, 7400, 7950, 10200, 12200 };
-
- for (int j = 0; j < kBitRates.length; ++j) {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_NB);
- format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
- format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
- formats.push(format);
- }
-
- testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AMR_NB, formats);
- }
-
- public void testAMRWBEncoders() {
- LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
-
- final int kBitRates[] =
- { 6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850 };
-
- for (int j = 0; j < kBitRates.length; ++j) {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
- format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 16000);
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
- format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
- formats.push(format);
- }
-
- testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AMR_WB, formats);
- }
-
- @CddTest(requirement="5.1.3")
- public void testOpusEncoders() {
- LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
-
- final int kBitRates[] =
- { 8000, 12000, 16000, 24000, 48000 };
-
- for (int j = 0; j < kBitRates.length; ++j) {
- for (int nChannels = 1; nChannels <= 2; ++nChannels) {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_OPUS);
- format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 16000);
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, nChannels);
- format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
- formats.push(format);
+ static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ int argLength = exhaustiveArgsList.get(0).length;
+ for (Object[] arg : exhaustiveArgsList) {
+ String[] componentNames = MediaUtils.getEncoderNamesForMime((String)arg[0]);
+ for (String name : componentNames) {
+ if (mCodecPrefix != null && !name.startsWith(mCodecPrefix)) {
+ continue;
+ }
+ Object[] testArgs = new Object[argLength + 1];
+ testArgs[0] = name;
+ System.arraycopy(arg, 0, testArgs, 1, argLength);
+ argsList.add(testArgs);
}
}
-
- testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_OPUS, formats);
+ return argsList;
}
- public void testAACEncoders() {
- LinkedList<MediaFormat> formats = new LinkedList<MediaFormat>();
+ static {
+ android.os.Bundle args = InstrumentationRegistry.getArguments();
+ mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+ }
- final int kAACProfiles[] = {
- 2 /* OMX_AUDIO_AACObjectLC */,
- 5 /* OMX_AUDIO_AACObjectHE */,
- 39 /* OMX_AUDIO_AACObjectELD */
- };
+ @Parameterized.Parameters(name = "{index}({0}_{1})")
+ public static Collection<Object[]> input() {
+ final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+ // Audio - CodecMime, arrays of profiles, bit-rates, sample rates, channel counts
+ {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{2, 5, 39}, new int[]{64000, 128000},
+ new int[]{8000, 11025, 22050, 44100, 48000}, new int[]{1, 2}},
+ {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{-1}, new int[]{8000, 12000, 16000,
+ 24000, 48000}, new int[]{16000}, new int[]{1, 2}},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{-1}, new int[]{4750, 5150, 5900, 6700
+ , 7400, 7950, 10200, 12200}, new int[]{8000}, new int[]{1}},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{-1}, new int[]{6600, 8850, 12650,
+ 14250, 15850, 18250, 19850, 23050, 23850}, new int[]{16000}, new int[]{1}},
+ });
+ return prepareParamList(exhaustiveArgsList);
+ }
- final int kSampleRates[] = { 8000, 11025, 22050, 44100, 48000 };
- final int kBitRates[] = { 64000, 128000 };
+ public EncoderTest(String encodername, String mime, int[] profiles, int[] bitrates,
+ int samplerates[], int channelcounts[]) {
+ mEncoderName = encodername;
+ mMime = mime;
+ mProfiles = profiles;
+ mBitrates = bitrates;
+ mSampleRates = samplerates;
+ mChannelCounts = channelcounts;
+ }
- for (int k = 0; k < kAACProfiles.length; ++k) {
- for (int i = 0; i < kSampleRates.length; ++i) {
- if (kAACProfiles[k] == 5 && kSampleRates[i] < 22050) {
+ private void setUpFormats() {
+ mFormats = new ArrayList<MediaFormat>();
+ // TODO(b/218887182) Explore parameterizing based on the following loop params as well
+ for (int profile : mProfiles) {
+ for (int rate : mSampleRates) {
+ if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_AAC) && profile == 5 && rate < 22050) {
// Is this right? HE does not support sample rates < 22050Hz?
continue;
}
- for (int j = 0; j < kBitRates.length; ++j) {
- for (int ch = 1; ch <= 2; ++ch) {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_AUDIO_AAC);
-
- format.setInteger(
- MediaFormat.KEY_AAC_PROFILE, kAACProfiles[k]);
-
- format.setInteger(
- MediaFormat.KEY_SAMPLE_RATE, kSampleRates[i]);
-
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, ch);
- format.setInteger(MediaFormat.KEY_BIT_RATE, kBitRates[j]);
- formats.push(format);
+ for (int bitrate : mBitrates) {
+ for (int channels : mChannelCounts) {
+ MediaFormat format = new MediaFormat();
+ format.setString(MediaFormat.KEY_MIME, mMime);
+ format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
+ format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
+ format.setInteger(MediaFormat.KEY_AAC_PROFILE, profile);
+ format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
+ mFormats.add(format);
}
}
}
}
-
- testEncoderWithFormats(MediaFormat.MIMETYPE_AUDIO_AAC, formats);
}
- private void testEncoderWithFormatsParallel(String mime, List<MediaFormat> formats,
- List<String> componentNames, int ThreadCount) {
+ @Test
+ public void testEncoders() {
+ setUpFormats();
+ testEncoderWithFormats();
+ }
+
+ private void testEncoderWithFormatsParallel(String mime, ArrayList<MediaFormat> formats,
+ String componentName, int ThreadCount) {
int testsStarted = 0;
int totalDurationSeconds = 0;
ExecutorService pool = Executors.newFixedThreadPool(ThreadCount);
- for (String componentName : componentNames) {
- for (MediaFormat format : formats) {
- assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
- pool.execute(new EncoderRun(componentName, format));
- int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
- int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
- int bytesQueuedPerSecond = 2 * channelCount * sampleRate;
- int durationSeconds =
- (kNumInputBytes + bytesQueuedPerSecond - 1) / bytesQueuedPerSecond;
- totalDurationSeconds += durationSeconds * kNumEncoderTestsPerRun;
- testsStarted++;
- }
+ for (MediaFormat format : formats) {
+ assertEquals(mime, format.getString(MediaFormat.KEY_MIME));
+ pool.execute(new EncoderRun(componentName, format));
+ int sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
+ int channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
+ int bytesQueuedPerSecond = 2 * channelCount * sampleRate;
+ int durationSeconds =
+ (kNumInputBytes + bytesQueuedPerSecond - 1) / bytesQueuedPerSecond;
+ totalDurationSeconds += durationSeconds * kNumEncoderTestsPerRun;
+ testsStarted++;
}
try {
pool.shutdown();
@@ -221,40 +214,28 @@
}
}
- private void testEncoderWithFormats(
- String mime, List<MediaFormat> formatList) {
- MediaFormat[] formats = formatList.toArray(new MediaFormat[formatList.size()]);
- String[] componentNames = MediaUtils.getEncoderNames(formats);
- if (componentNames.length == 0) {
- MediaUtils.skipTest("no encoders found for " + Arrays.toString(formats));
- return;
+ private void testEncoderWithFormats() {
+ for (MediaFormat fmt : mFormats) {
+ if (!MediaUtils.supports(mEncoderName, fmt)) {
+ MediaUtils.skipTest("no encoders found for " + fmt.toString());
+ return;
+ }
}
-
final int ThreadPoolCount = 3;
- List<String>[] componentNamesGrouped = new List[ThreadPoolCount];
- for (int i = 0; i < ThreadPoolCount; i++) {
- componentNamesGrouped[i] = new ArrayList<>();
+ int instances = ThreadPoolCount;
+ MediaCodec codec = null;
+ try {
+ codec = MediaCodec.createByCodecName(mEncoderName);
+ MediaCodecInfo info = codec.getCodecInfo();
+ MediaCodecInfo.CodecCapabilities cap = info.getCapabilitiesForType(mMime);
+ instances = Math.min(cap.getMaxSupportedInstances(), instances);
+ assertTrue(instances >= 1);
+ } catch (Exception e) {
+ fail("codec '" + mEncoderName + "' failed construction.");
+ } finally {
+ codec.release();
}
- for (String componentName : componentNames) {
- MediaCodec codec = null;
- try {
- codec = MediaCodec.createByCodecName(componentName);
- MediaCodecInfo info = codec.getCodecInfo();
- MediaCodecInfo.CodecCapabilities cap = info.getCapabilitiesForType(mime);
- int instances = Math.min(cap.getMaxSupportedInstances(), ThreadPoolCount);
- assertTrue(instances >= 1 && instances <= ThreadPoolCount);
- componentNamesGrouped[instances - 1].add(componentName);
- } catch (Exception e) {
- fail("codec '" + componentName + "' failed construction.");
- } finally {
- codec.release();
- }
- }
- for (int i = 0; i < ThreadPoolCount; i++) {
- if (componentNamesGrouped[i].size() > 0) {
- testEncoderWithFormatsParallel(mime, formatList, componentNamesGrouped[i], i + 1);
- }
- }
+ testEncoderWithFormatsParallel(mMime, mFormats, mEncoderName, instances);
}
// See bug 25843966
@@ -526,4 +507,3 @@
}
}
}
-
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
index 707bde2..d7cfbaa 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
@@ -44,8 +44,6 @@
import android.media.cts.Preconditions;
import android.net.Uri;
import android.platform.test.annotations.AppModeFull;
-import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresDevice;
import android.util.Log;
import android.util.Pair;
import android.util.Range;
@@ -54,30 +52,43 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.After;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Consumer;
-import java.util.function.Function;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
@MediaHeavyPresubmitTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class VideoEncoderTest extends MediaTestBase {
private static final int MAX_SAMPLE_SIZE = 256 * 1024;
private static final String TAG = "VideoEncoderTest";
@@ -89,6 +100,11 @@
private static final String SOURCE_URL =
mInpPrefix + "video_480x360_mp4_h264_871kbps_30fps.mp4";
+ private static final String CODEC_PREFIX_KEY = "codec-prefix";
+ private static final String mCodecPrefix;
+
+ private final Encoder mEncHandle;
+
private final boolean DEBUG = false;
@Before
@@ -103,6 +119,11 @@
super.tearDown();
}
+ static {
+ android.os.Bundle args = InstrumentationRegistry.getArguments();
+ mCodecPrefix = args.getString(CODEC_PREFIX_KEY);
+ }
+
class VideoStorage {
private LinkedList<Pair<ByteBuffer, BufferInfo>> mStream;
private MediaFormat mFormat;
@@ -1226,1110 +1247,285 @@
return success;
}
}
-
- private Encoder[] googH265() { return goog(MediaFormat.MIMETYPE_VIDEO_HEVC); }
- private Encoder[] googH264() { return goog(MediaFormat.MIMETYPE_VIDEO_AVC); }
- private Encoder[] googH263() { return goog(MediaFormat.MIMETYPE_VIDEO_H263); }
- private Encoder[] googMpeg4() { return goog(MediaFormat.MIMETYPE_VIDEO_MPEG4); }
- private Encoder[] googVP8() { return goog(MediaFormat.MIMETYPE_VIDEO_VP8); }
- private Encoder[] googVP9() { return goog(MediaFormat.MIMETYPE_VIDEO_VP9); }
-
- private Encoder[] otherH265() { return other(MediaFormat.MIMETYPE_VIDEO_HEVC); }
- private Encoder[] otherH264() { return other(MediaFormat.MIMETYPE_VIDEO_AVC); }
- private Encoder[] otherH263() { return other(MediaFormat.MIMETYPE_VIDEO_H263); }
- private Encoder[] otherMpeg4() { return other(MediaFormat.MIMETYPE_VIDEO_MPEG4); }
- private Encoder[] otherVP8() { return other(MediaFormat.MIMETYPE_VIDEO_VP8); }
- private Encoder[] otherVP9() { return other(MediaFormat.MIMETYPE_VIDEO_VP9); }
-
- private Encoder[] goog(String mime) {
- return encoders(mime, true /* goog */);
- }
-
- private Encoder[] other(String mime) {
- return encoders(mime, false /* goog */);
- }
-
- private Encoder[] combineArray(Encoder[] a, Encoder[] b) {
- Encoder[] all = new Encoder[a.length + b.length];
- System.arraycopy(a, 0, all, 0, a.length);
- System.arraycopy(b, 0, all, a.length, b.length);
- return all;
- }
-
- private Encoder[] h264() {
- return combineArray(googH264(), otherH264());
- }
-
- private Encoder[] vp8() {
- return combineArray(googVP8(), otherVP8());
- }
-
- private Encoder[] encoders(String mime, boolean goog) {
+ private static CodecCapabilities getCodecCapabities(String encoderName, String mime,
+ boolean isEncoder) {
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
- ArrayList<Encoder> result = new ArrayList<Encoder>();
-
- for (MediaCodecInfo info : mcl.getCodecInfos()) {
- if (!info.isEncoder() || !info.isVendor() != goog || info.isAlias()) {
+ for (MediaCodecInfo codecInfo : mcl.getCodecInfos()) {
+ if (isEncoder != codecInfo.isEncoder()) {
continue;
}
- CodecCapabilities caps = null;
- try {
- caps = info.getCapabilitiesForType(mime);
- } catch (IllegalArgumentException e) { // mime is not supported
- continue;
+ if (encoderName.equals(codecInfo.getName())) {
+ return codecInfo.getCapabilitiesForType(mime);
}
- assertNotNull(info.getName() + " capabilties for " + mime + " returned null", caps);
- result.add(new Encoder(info.getName(), mime, caps));
}
- return result.toArray(new Encoder[result.size()]);
+ return null;
+ }
+ private Encoder getEncHandle(String encodername, String mime) {
+ CodecCapabilities caps = getCodecCapabities(encodername, mime, true);
+ assertNotNull(caps);
+ Encoder encoder = new Encoder(encodername, mime, caps);
+ return encoder;
+ }
+
+ static private List<Object[]> prepareParamList(List<Object[]> exhaustiveArgsList) {
+ final List<Object[]> argsList = new ArrayList<>();
+ int argLength = exhaustiveArgsList.get(0).length;
+ for (Object[] arg : exhaustiveArgsList) {
+ String[] encodersForMime = MediaUtils.getEncoderNamesForMime((String) arg[0]);
+ for (String encoder : encodersForMime) {
+ if (mCodecPrefix != null && !encoder.startsWith(mCodecPrefix)) {
+ continue;
+ }
+ Object[] testArgs = new Object[argLength + 1];
+ testArgs[0] = encoder;
+ System.arraycopy(arg, 0, testArgs, 1, argLength);
+ argsList.add(testArgs);
+ }
+ }
+ return argsList;
+ }
+
+ @Parameterized.Parameters(name = "{index}({0}_{1})")
+ public static Collection<Object[]> input() {
+ final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
+ {MediaFormat.MIMETYPE_VIDEO_AVC},
+ {MediaFormat.MIMETYPE_VIDEO_H263},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC},
+ {MediaFormat.MIMETYPE_VIDEO_MPEG4},
+ {MediaFormat.MIMETYPE_VIDEO_VP8},
+ {MediaFormat.MIMETYPE_VIDEO_VP9},
+ });
+ return prepareParamList(exhaustiveArgsList);
+ }
+
+ public VideoEncoderTest(String encoderName, String mime) {
+ mEncHandle = getEncHandle(encoderName, mime);
}
@Test
- public void testGoogH265FlexMinMin() { minmin(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfMinMin() { minmin(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexMinMin() { minmin(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfMinMin() { minmin(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexMinMin() { minmin(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfMinMin() { minmin(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexMinMin() { minmin(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfMinMin() { minmin(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexMinMin() { minmin(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfMinMin() { minmin(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexMinMin() { minmin(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfMinMin() { minmin(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexMinMin() { minmin(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfMinMin() { minmin(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexMinMin() { minmin(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfMinMin() { minmin(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexMinMin() { minmin(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfMinMin() { minmin(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexMinMin() { minmin(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfMinMin() { minmin(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexMinMin() { minmin(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfMinMin() { minmin(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexMinMin() { minmin(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfMinMin() { minmin(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexMinMax() { minmax(googH265(), true /* flex */); }
- @Test public void testGoogH265SurfMinMax() { minmax(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexMinMax() { minmax(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfMinMax() { minmax(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexMinMax() { minmax(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfMinMax() { minmax(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexMinMax() { minmax(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfMinMax() { minmax(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexMinMax() { minmax(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfMinMax() { minmax(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexMinMax() { minmax(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfMinMax() { minmax(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexMinMax() { minmax(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfMinMax() { minmax(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexMinMax() { minmax(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfMinMax() { minmax(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexMinMax() { minmax(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfMinMax() { minmax(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexMinMax() { minmax(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfMinMax() { minmax(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexMinMax() { minmax(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfMinMax() { minmax(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexMinMax() { minmax(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfMinMax() { minmax(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexMaxMin() { maxmin(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfMaxMin() { maxmin(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexMaxMin() { maxmin(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfMaxMin() { maxmin(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexMaxMin() { maxmin(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfMaxMin() { maxmin(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexMaxMin() { maxmin(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfMaxMin() { maxmin(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexMaxMin() { maxmin(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfMaxMin() { maxmin(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexMaxMin() { maxmin(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfMaxMin() { maxmin(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexMaxMin() { maxmin(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfMaxMin() { maxmin(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexMaxMin() { maxmin(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfMaxMin() { maxmin(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test public void testOtherH263FlexMaxMin() { maxmin(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfMaxMin() { maxmin(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexMaxMin() { maxmin(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfMaxMin() { maxmin(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexMaxMin() { maxmin(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfMaxMin() { maxmin(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexMaxMin() { maxmin(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfMaxMin() { maxmin(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexMaxMax() { maxmax(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfMaxMax() { maxmax(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexMaxMax() { maxmax(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfMaxMax() { maxmax(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexMaxMax() { maxmax(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfMaxMax() { maxmax(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexMaxMax() { maxmax(googMpeg4(), true /* flex */); }
- @Test public void testGoogMpeg4SurfMaxMax() { maxmax(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexMaxMax() { maxmax(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfMaxMax() { maxmax(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexMaxMax() { maxmax(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfMaxMax() { maxmax(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexMaxMax() { maxmax(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfMaxMax() { maxmax(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexMaxMax() { maxmax(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfMaxMax() { maxmax(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexMaxMax() { maxmax(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfMaxMax() { maxmax(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexMaxMax() { maxmax(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfMaxMax() { maxmax(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexMaxMax() { maxmax(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfMaxMax() { maxmax(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexMaxMax() { maxmax(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfMaxMax() { maxmax(otherVP9(), false /* flex */); }
-
- @Test public void testGoogH265FlexNearMinMin() { nearminmin(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfNearMinMin() { nearminmin(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexNearMinMin() { nearminmin(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfNearMinMin() { nearminmin(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexNearMinMin() { nearminmin(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfNearMinMin() { nearminmin(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexNearMinMin() { nearminmin(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfNearMinMin() { nearminmin(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexNearMinMin() { nearminmin(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfNearMinMin() { nearminmin(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexNearMinMin() { nearminmin(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfNearMinMin() { nearminmin(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexNearMinMin() { nearminmin(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfNearMinMin() { nearminmin(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexNearMinMin() { nearminmin(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfNearMinMin() { nearminmin(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexNearMinMin() { nearminmin(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfNearMinMin() { nearminmin(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexNearMinMin() { nearminmin(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfNearMinMin() { nearminmin(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexNearMinMin() { nearminmin(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfNearMinMin() { nearminmin(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexNearMinMin() { nearminmin(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfNearMinMin() { nearminmin(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexNearMinMax() { nearminmax(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfNearMinMax() { nearminmax(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexNearMinMax() { nearminmax(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfNearMinMax() { nearminmax(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexNearMinMax() { nearminmax(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfNearMinMax() { nearminmax(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexNearMinMax() { nearminmax(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfNearMinMax() { nearminmax(googMpeg4(), false /* flex */); }
- @Test public void testGoogVP8FlexNearMinMax() { nearminmax(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfNearMinMax() { nearminmax(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexNearMinMax() { nearminmax(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfNearMinMax() { nearminmax(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexNearMinMax() { nearminmax(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfNearMinMax() { nearminmax(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexNearMinMax() { nearminmax(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfNearMinMax() { nearminmax(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexNearMinMax() { nearminmax(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfNearMinMax() { nearminmax(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexNearMinMax() { nearminmax(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfNearMinMax() { nearminmax(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexNearMinMax() { nearminmax(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfNearMinMax() { nearminmax(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexNearMinMax() { nearminmax(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test public void testOtherVP9SurfNearMinMax() { nearminmax(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexNearMaxMin() { nearmaxmin(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfNearMaxMin() { nearmaxmin(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexNearMaxMin() { nearmaxmin(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfNearMaxMin() { nearmaxmin(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexNearMaxMin() { nearmaxmin(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfNearMaxMin() { nearmaxmin(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexNearMaxMin() { nearmaxmin(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfNearMaxMin() { nearmaxmin(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexNearMaxMin() { nearmaxmin(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfNearMaxMin() { nearmaxmin(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexNearMaxMin() { nearmaxmin(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfNearMaxMin() { nearmaxmin(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexNearMaxMin() { nearmaxmin(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfNearMaxMin() { nearmaxmin(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexNearMaxMin() { nearmaxmin(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfNearMaxMin() { nearmaxmin(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexNearMaxMin() { nearmaxmin(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfNearMaxMin() { nearmaxmin(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexNearMaxMin() { nearmaxmin(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfNearMaxMin() { nearmaxmin(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexNearMaxMin() { nearmaxmin(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfNearMaxMin() { nearmaxmin(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexNearMaxMin() { nearmaxmin(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfNearMaxMin() { nearmaxmin(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexNearMaxMax() { nearmaxmax(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfNearMaxMax() { nearmaxmax(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexNearMaxMax() { nearmaxmax(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfNearMaxMax() { nearmaxmax(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexNearMaxMax() { nearmaxmax(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfNearMaxMax() { nearmaxmax(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexNearMaxMax() { nearmaxmax(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfNearMaxMax() { nearmaxmax(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexNearMaxMax() { nearmaxmax(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfNearMaxMax() { nearmaxmax(googVP8(), false /* flex */); }
- @Test public void testGoogVP9FlexNearMaxMax() { nearmaxmax(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfNearMaxMax() { nearmaxmax(googVP9(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexNearMaxMax() { nearmaxmax(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfNearMaxMax() { nearmaxmax(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexNearMaxMax() { nearmaxmax(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfNearMaxMax() { nearmaxmax(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexNearMaxMax() { nearmaxmax(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfNearMaxMax() { nearmaxmax(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexNearMaxMax() { nearmaxmax(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfNearMaxMax() { nearmaxmax(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexNearMaxMax() { nearmaxmax(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfNearMaxMax() { nearmaxmax(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexNearMaxMax() { nearmaxmax(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfNearMaxMax() { nearmaxmax(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexArbitraryW() { arbitraryw(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfArbitraryW() { arbitraryw(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexArbitraryW() { arbitraryw(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfArbitraryW() { arbitraryw(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexArbitraryW() { arbitraryw(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfArbitraryW() { arbitraryw(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexArbitraryW() { arbitraryw(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfArbitraryW() { arbitraryw(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexArbitraryW() { arbitraryw(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfArbitraryW() { arbitraryw(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexArbitraryW() { arbitraryw(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfArbitraryW() { arbitraryw(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexArbitraryW() { arbitraryw(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfArbitraryW() { arbitraryw(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexArbitraryW() { arbitraryw(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfArbitraryW() { arbitraryw(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexArbitraryW() { arbitraryw(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfArbitraryW() { arbitraryw(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexArbitraryW() { arbitraryw(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfArbitraryW() { arbitraryw(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexArbitraryW() { arbitraryw(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfArbitraryW() { arbitraryw(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexArbitraryW() { arbitraryw(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfArbitraryW() { arbitraryw(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexArbitraryH() { arbitraryh(googH265(), true /* flex */); }
- @Test
- public void testGoogH265SurfArbitraryH() { arbitraryh(googH265(), false /* flex */); }
- @Test
- public void testGoogH264FlexArbitraryH() { arbitraryh(googH264(), true /* flex */); }
- @Test
- public void testGoogH264SurfArbitraryH() { arbitraryh(googH264(), false /* flex */); }
- @Test
- public void testGoogH263FlexArbitraryH() { arbitraryh(googH263(), true /* flex */); }
- @Test
- public void testGoogH263SurfArbitraryH() { arbitraryh(googH263(), false /* flex */); }
- @Test
- public void testGoogMpeg4FlexArbitraryH() { arbitraryh(googMpeg4(), true /* flex */); }
- @Test
- public void testGoogMpeg4SurfArbitraryH() { arbitraryh(googMpeg4(), false /* flex */); }
- @Test
- public void testGoogVP8FlexArbitraryH() { arbitraryh(googVP8(), true /* flex */); }
- @Test
- public void testGoogVP8SurfArbitraryH() { arbitraryh(googVP8(), false /* flex */); }
- @Test
- public void testGoogVP9FlexArbitraryH() { arbitraryh(googVP9(), true /* flex */); }
- @Test
- public void testGoogVP9SurfArbitraryH() { arbitraryh(googVP9(), false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexArbitraryH() { arbitraryh(otherH265(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfArbitraryH() { arbitraryh(otherH265(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264FlexArbitraryH() { arbitraryh(otherH264(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264SurfArbitraryH() { arbitraryh(otherH264(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexArbitraryH() { arbitraryh(otherH263(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfArbitraryH() { arbitraryh(otherH263(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexArbitraryH() { arbitraryh(otherMpeg4(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfArbitraryH() { arbitraryh(otherMpeg4(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexArbitraryH() { arbitraryh(otherVP8(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfArbitraryH() { arbitraryh(otherVP8(), false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexArbitraryH() { arbitraryh(otherVP9(), true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfArbitraryH() { arbitraryh(otherVP9(), false /* flex */); }
-
- @Test
- public void testGoogH265FlexQCIF() { specific(googH265(), 176, 144, true /* flex */); }
- @Test
- public void testGoogH265SurfQCIF() { specific(googH265(), 176, 144, false /* flex */); }
- @Presubmit
- @SmallTest
- @Test
- public void testGoogH264FlexQCIF() { specific(googH264(), 176, 144, true /* flex */); }
- @Presubmit
- @SmallTest
- @Test
- public void testGoogH264SurfQCIF() { specific(googH264(), 176, 144, false /* flex */); }
- @Test
- public void testGoogH263FlexQCIF() { specific(googH263(), 176, 144, true /* flex */); }
- @Test
- public void testGoogH263SurfQCIF() { specific(googH263(), 176, 144, false /* flex */); }
- @Test
- public void testGoogMpeg4FlexQCIF() { specific(googMpeg4(), 176, 144, true /* flex */); }
- @Test
- public void testGoogMpeg4SurfQCIF() { specific(googMpeg4(), 176, 144, false /* flex */); }
- @Test
- public void testGoogVP8FlexQCIF() { specific(googVP8(), 176, 144, true /* flex */); }
- @Test
- public void testGoogVP8SurfQCIF() { specific(googVP8(), 176, 144, false /* flex */); }
- @Test
- public void testGoogVP9FlexQCIF() { specific(googVP9(), 176, 144, true /* flex */); }
- @Test
- public void testGoogVP9SurfQCIF() { specific(googVP9(), 176, 144, false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265FlexQCIF() { specific(otherH265(), 176, 144, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265SurfQCIF() { specific(otherH265(), 176, 144, false /* flex */); }
- @NonMediaMainlineTest
- @RequiresDevice
- @Presubmit
- @SmallTest
- @Test
- public void testOtherH264FlexQCIF() { specific(otherH264(), 176, 144, true /* flex */); }
- @NonMediaMainlineTest
- @RequiresDevice
- @Presubmit
- @SmallTest
- @Test
- public void testOtherH264SurfQCIF() { specific(otherH264(), 176, 144, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263FlexQCIF() { specific(otherH263(), 176, 144, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263SurfQCIF() { specific(otherH263(), 176, 144, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4FlexQCIF() { specific(otherMpeg4(), 176, 144, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4SurfQCIF() { specific(otherMpeg4(), 176, 144, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8FlexQCIF() { specific(otherVP8(), 176, 144, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8SurfQCIF() { specific(otherVP8(), 176, 144, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9FlexQCIF() { specific(otherVP9(), 176, 144, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9SurfQCIF() { specific(otherVP9(), 176, 144, false /* flex */); }
-
- @Test
- public void testGoogH265Flex480p() { specific(googH265(), 720, 480, true /* flex */); }
- @Test
- public void testGoogH265Surf480p() { specific(googH265(), 720, 480, false /* flex */); }
- @Test
- public void testGoogH264Flex480p() { specific(googH264(), 720, 480, true /* flex */); }
- @Test
- public void testGoogH264Surf480p() { specific(googH264(), 720, 480, false /* flex */); }
- @Test
- public void testGoogH263Flex480p() { specific(googH263(), 720, 480, true /* flex */); }
- @Test
- public void testGoogH263Surf480p() { specific(googH263(), 720, 480, false /* flex */); }
- @Test
- public void testGoogMpeg4Flex480p() { specific(googMpeg4(), 720, 480, true /* flex */); }
- @Test
- public void testGoogMpeg4Surf480p() { specific(googMpeg4(), 720, 480, false /* flex */); }
- @Test
- public void testGoogVP8Flex480p() { specific(googVP8(), 720, 480, true /* flex */); }
- @Test
- public void testGoogVP8Surf480p() { specific(googVP8(), 720, 480, false /* flex */); }
- @Test public void testGoogVP9Flex480p() { specific(googVP9(), 720, 480, true /* flex */); }
- @Test public void testGoogVP9Surf480p() { specific(googVP9(), 720, 480, false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265Flex480p() { specific(otherH265(), 720, 480, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265Surf480p() { specific(otherH265(), 720, 480, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264Flex480p() { specific(otherH264(), 720, 480, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264Surf480p() { specific(otherH264(), 720, 480, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263Flex480p() { specific(otherH263(), 720, 480, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263Surf480p() { specific(otherH263(), 720, 480, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4Flex480p() { specific(otherMpeg4(), 720, 480, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4Surf480p() { specific(otherMpeg4(), 720, 480, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8Flex480p() { specific(otherVP8(), 720, 480, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8Surf480p() { specific(otherVP8(), 720, 480, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9Flex480p() { specific(otherVP9(), 720, 480, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9Surf480p() { specific(otherVP9(), 720, 480, false /* flex */); }
-
- // even though H.263 and MPEG-4 are not defined for 720p or 1080p
- // test for it, in case device claims support for it.
-
- @Test
- public void testGoogH265Flex720p() { specific(googH265(), 1280, 720, true /* flex */); }
- @Test
- public void testGoogH265Surf720p() { specific(googH265(), 1280, 720, false /* flex */); }
- @Test
- public void testGoogH264Flex720p() { specific(googH264(), 1280, 720, true /* flex */); }
- @Test
- public void testGoogH264Surf720p() { specific(googH264(), 1280, 720, false /* flex */); }
- @Test
- public void testGoogH263Flex720p() { specific(googH263(), 1280, 720, true /* flex */); }
- @Test
- public void testGoogH263Surf720p() { specific(googH263(), 1280, 720, false /* flex */); }
- @Test
- public void testGoogMpeg4Flex720p() { specific(googMpeg4(), 1280, 720, true /* flex */); }
- @Test
- public void testGoogMpeg4Surf720p() { specific(googMpeg4(), 1280, 720, false /* flex */); }
- @Test
- public void testGoogVP8Flex720p() { specific(googVP8(), 1280, 720, true /* flex */); }
- @Test
- public void testGoogVP8Surf720p() { specific(googVP8(), 1280, 720, false /* flex */); }
- @Test
- public void testGoogVP9Flex720p() { specific(googVP9(), 1280, 720, true /* flex */); }
- @Test
- public void testGoogVP9Surf720p() { specific(googVP9(), 1280, 720, false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265Flex720p() { specific(otherH265(), 1280, 720, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265Surf720p() { specific(otherH265(), 1280, 720, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264Flex720p() { specific(otherH264(), 1280, 720, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264Surf720p() { specific(otherH264(), 1280, 720, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263Flex720p() { specific(otherH263(), 1280, 720, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263Surf720p() { specific(otherH263(), 1280, 720, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4Flex720p() { specific(otherMpeg4(), 1280, 720, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4Surf720p() { specific(otherMpeg4(), 1280, 720, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8Flex720p() { specific(otherVP8(), 1280, 720, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8Surf720p() { specific(otherVP8(), 1280, 720, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9Flex720p() { specific(otherVP9(), 1280, 720, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9Surf720p() { specific(otherVP9(), 1280, 720, false /* flex */); }
-
- @Test public void testGoogH265Flex1080p() { specific(googH265(), 1920, 1080, true /* flex */); }
- @Test
- public void testGoogH265Surf1080p() { specific(googH265(), 1920, 1080, false /* flex */); }
- @Test
- public void testGoogH264Flex1080p() { specific(googH264(), 1920, 1080, true /* flex */); }
- @Test
- public void testGoogH264Surf1080p() { specific(googH264(), 1920, 1080, false /* flex */); }
- @Test
- public void testGoogH263Flex1080p() { specific(googH263(), 1920, 1080, true /* flex */); }
- @Test
- public void testGoogH263Surf1080p() { specific(googH263(), 1920, 1080, false /* flex */); }
- @Test
- public void testGoogMpeg4Flex1080p() { specific(googMpeg4(), 1920, 1080, true /* flex */); }
- @Test
- public void testGoogMpeg4Surf1080p() { specific(googMpeg4(), 1920, 1080, false /* flex */); }
- @Test
- public void testGoogVP8Flex1080p() { specific(googVP8(), 1920, 1080, true /* flex */); }
- @Test
- public void testGoogVP8Surf1080p() { specific(googVP8(), 1920, 1080, false /* flex */); }
- @Test
- public void testGoogVP9Flex1080p() { specific(googVP9(), 1920, 1080, true /* flex */); }
- @Test
- public void testGoogVP9Surf1080p() { specific(googVP9(), 1920, 1080, false /* flex */); }
-
- @NonMediaMainlineTest
- @Test
- public void testOtherH265Flex1080p() { specific(otherH265(), 1920, 1080, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH265Surf1080p() { specific(otherH265(), 1920, 1080, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264Flex1080p() { specific(otherH264(), 1920, 1080, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH264Surf1080p() { specific(otherH264(), 1920, 1080, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263Flex1080p() { specific(otherH263(), 1920, 1080, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherH263Surf1080p() { specific(otherH263(), 1920, 1080, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4Flex1080p() { specific(otherMpeg4(), 1920, 1080, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherMpeg4Surf1080p() { specific(otherMpeg4(), 1920, 1080, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8Flex1080p() { specific(otherVP8(), 1920, 1080, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP8Surf1080p() { specific(otherVP8(), 1920, 1080, false /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9Flex1080p() { specific(otherVP9(), 1920, 1080, true /* flex */); }
- @NonMediaMainlineTest
- @Test
- public void testOtherVP9Surf1080p() { specific(otherVP9(), 1920, 1080, false /* flex */); }
-
- @Test
- public void testGoogH265Flex360pWithIntraRefresh() {
- intraRefresh(googH265(), 480, 360);
+ public void testFlexMinMin() {
+ minmin(new Encoder[]{mEncHandle}, true);
}
@Test
- public void testGoogH264Flex360pWithIntraRefresh() {
- intraRefresh(googH264(), 480, 360);
+ public void testSurfMinMin() {
+ minmin(new Encoder[]{mEncHandle}, false);
}
@Test
- public void testGoogH263Flex360pWithIntraRefresh() {
- intraRefresh(googH263(), 480, 360);
+ public void testFlexMinMax() {
+ minmax(new Encoder[]{mEncHandle}, true);
}
@Test
- public void testGoogMpeg4Flex360pWithIntraRefresh() {
- intraRefresh(googMpeg4(), 480, 360);
+ public void testSurfMinMax() {
+ minmax(new Encoder[]{mEncHandle}, false);
}
@Test
- public void testGoogVP8Flex360pWithIntraRefresh() {
- intraRefresh(googVP8(), 480, 360);
+ public void testFlexMaxMin() {
+ maxmin(new Encoder[]{mEncHandle}, true);
}
- @NonMediaMainlineTest
@Test
- public void testOtherH265Flex360pWithIntraRefresh() {
- intraRefresh(otherH265(), 480, 360);
+ public void testSurfMaxMin() {
+ maxmin(new Encoder[]{mEncHandle}, false);
}
- @NonMediaMainlineTest
@Test
- public void testOtherH264Flex360pWithIntraRefresh() {
- intraRefresh(otherH264(), 480, 360);
+ public void testFlexMaxMax() {
+ maxmax(new Encoder[]{mEncHandle}, true);
}
- @NonMediaMainlineTest
@Test
- public void testOtherH263FlexQCIFWithIntraRefresh() {
- intraRefresh(otherH263(), 176, 120);
+ public void testSurfMaxMax() {
+ maxmax(new Encoder[]{mEncHandle}, false);
}
- @NonMediaMainlineTest
@Test
- public void testOtherMpeg4Flex360pWithIntraRefresh() {
- intraRefresh(otherMpeg4(), 480, 360);
+ public void testFlexNearMinMin() {
+ nearminmin(new Encoder[]{mEncHandle}, true);
}
- @NonMediaMainlineTest
@Test
- public void testOtherVP8Flex360pWithIntraRefresh() {
- intraRefresh(otherVP8(), 480, 360);
+ public void testSurfNearMinMin() {
+ nearminmin(new Encoder[]{mEncHandle}, false);
+ }
+
+ @Test
+ public void testFlexNearMinMax() {
+ nearminmax(new Encoder[]{mEncHandle}, true);
+ }
+
+ @Test
+ public void testSurfNearMinMax() {
+ nearminmax(new Encoder[]{mEncHandle}, false);
+ }
+
+ @Test
+ public void testFlexNearMaxMin() {
+ nearmaxmin(new Encoder[]{mEncHandle}, true);
+ }
+
+ @Test
+ public void testSurfNearMaxMin() {
+ nearmaxmin(new Encoder[]{mEncHandle}, false);
+ }
+
+ @Test
+ public void testFlexNearMaxMax() {
+ nearmaxmax(new Encoder[]{mEncHandle}, true);
+ }
+
+ @Test
+ public void testSurfNearMaxMax() {
+ nearmaxmax(new Encoder[]{mEncHandle}, false);
+ }
+
+ @Test
+ public void testFlexArbitraryW() {
+ arbitraryw(new Encoder[]{mEncHandle}, true);
+ }
+
+ @Test
+ public void testSurfArbitraryW() {
+ arbitraryw(new Encoder[]{mEncHandle}, false);
+ }
+
+ @Test
+ public void testFlexArbitraryH() {
+ arbitraryh(new Encoder[]{mEncHandle}, true);
+ }
+
+ @Test
+ public void testSurfArbitraryH() {
+ arbitraryh(new Encoder[]{mEncHandle}, false);
+ }
+
+ @Test
+ public void testFlexQCIF() {
+ specific(new Encoder[]{mEncHandle}, 176, 144, true);
+ }
+
+ @Test
+ public void testSurfQCIF() {
+ specific(new Encoder[]{mEncHandle}, 176, 144, false);
+ }
+
+ @Test
+ public void testFlex480p() {
+ specific(new Encoder[]{mEncHandle}, 720, 480, true);
+ }
+
+ @Test
+ public void testSurf480p() {
+ specific(new Encoder[]{mEncHandle}, 720, 480, false);
+ }
+
+ @Test
+ public void testFlex720p() {
+ specific(new Encoder[]{mEncHandle}, 1280, 720, true);
+ }
+
+ @Test
+ public void testSurf720p() {
+ specific(new Encoder[]{mEncHandle}, 1280, 720, false);
+ }
+
+ @Test
+ public void testFlex1080p() {
+ specific(new Encoder[]{mEncHandle}, 1920, 1080, true);
+ }
+
+ @Test
+ public void testSurf1080p() {
+ specific(new Encoder[]{mEncHandle}, 1920, 1080, false);
+ }
+
+ @Test
+ public void testFlex360pWithIntraRefresh() {
+ intraRefresh(new Encoder[]{mEncHandle}, 480, 360);
}
// Tests encoder profiles required by CDD.
- // H264
- @NonMediaMainlineTest
@Test
- public void testH264LowQualitySDSupport() {
- support(h264(), 320, 240, 20, 384 * 1000);
+ public void testLowQualitySDSupport() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ support(new Encoder[]{mEncHandle}, 720, 480, 20, 384 * 1000);
}
- @NonMediaMainlineTest
@Test
- public void testH264HighQualitySDSupport() {
- support(h264(), 720, 480, 30, 2 * 1000000);
+ public void testHighQualitySDSupport() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ support(new Encoder[]{mEncHandle}, 720, 480, 30, 2 * 1000000);
}
- @NonMediaMainlineTest
@Test
- public void testH264FlexQVGA20fps384kbps() {
- detailed(h264(), 320, 240, 20, 384 * 1000, true /* flex */);
+ public void testFlexQVGA20fps384kbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 320, 240, 20, 384 * 1000, true);
}
- @NonMediaMainlineTest
@Test
- public void testH264SurfQVGA20fps384kbps() {
- detailed(h264(), 320, 240, 20, 384 * 1000, false /* flex */);
+ public void testSurfQVGA20fps384kbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 320, 240, 20, 384 * 1000, false /* flex */);
}
- @NonMediaMainlineTest
@Test
- public void testH264Flex480p30fps2Mbps() {
- detailed(h264(), 720, 480, 30, 2 * 1000000, true /* flex */);
+ public void testFlex480p30fps2Mbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 720, 480, 30, 2 * 1000000, true /* flex */);
}
- @NonMediaMainlineTest
@Test
- public void testH264Surf480p30fps2Mbps() {
- detailed(h264(), 720, 480, 30, 2 * 1000000, false /* flex */);
+ public void testSurf480p30fps2Mbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 720, 480, 30, 2 * 1000000, false /* flex */);
}
- @NonMediaMainlineTest
@Test
- public void testH264Flex720p30fps4Mbps() {
- detailed(h264(), 1280, 720, 30, 4 * 1000000, true /* flex */);
+ public void testFlex720p30fps4Mbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 1280, 720, 30, 4 * 1000000, true /* flex */);
}
- @NonMediaMainlineTest
@Test
- public void testH264Surf720p30fps4Mbps() {
- detailed(h264(), 1280, 720, 30, 4 * 1000000, false /* flex */);
+ public void testSurf720p30fps4Mbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 1280, 720, 30, 4 * 1000000, false /* flex */);
}
- @NonMediaMainlineTest
@Test
- public void testH264Flex1080p30fps10Mbps() {
- detailed(h264(), 1920, 1080, 30, 10 * 1000000, true /* flex */);
+ public void testFlex1080p30fps10Mbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 1920, 1080, 30, 10 * 1000000, true /* flex */);
}
- @NonMediaMainlineTest
@Test
- public void testH264Surf1080p30fps10Mbps() {
- detailed(h264(), 1920, 1080, 30, 10 * 1000000, false /* flex */);
- }
-
- // VP8
- @NonMediaMainlineTest
- @Test
- public void testVP8LowQualitySDSupport() {
- support(vp8(), 320, 180, 30, 800 * 1000);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8HighQualitySDSupport() {
- support(vp8(), 640, 360, 30, 2 * 1000000);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Flex180p30fps800kbps() {
- detailed(vp8(), 320, 180, 30, 800 * 1000, true /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Surf180p30fps800kbps() {
- detailed(vp8(), 320, 180, 30, 800 * 1000, false /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Flex360p30fps2Mbps() {
- detailed(vp8(), 640, 360, 30, 2 * 1000000, true /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Surf360p30fps2Mbps() {
- detailed(vp8(), 640, 360, 30, 2 * 1000000, false /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Flex720p30fps4Mbps() {
- detailed(vp8(), 1280, 720, 30, 4 * 1000000, true /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Surf720p30fps4Mbps() {
- detailed(vp8(), 1280, 720, 30, 4 * 1000000, false /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Flex1080p30fps10Mbps() {
- detailed(vp8(), 1920, 1080, 30, 10 * 1000000, true /* flex */);
- }
-
- @NonMediaMainlineTest
- @Test
- public void testVP8Surf1080p30fps10Mbps() {
- detailed(vp8(), 1920, 1080, 30, 10 * 1000000, false /* flex */);
+ public void testSurf1080p30fps10Mbps() {
+ Assume.assumeTrue("Test is currently enabled only for avc and vp8 encoders",
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_AVC) ||
+ mEncHandle.mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8));
+ detailed(new Encoder[]{mEncHandle}, 1920, 1080, 30, 10 * 1000000, false /* flex */);
}
private void minmin(Encoder[] encoders, boolean flexYUV) {
diff --git a/tests/tests/media/extractor/AndroidManifest.xml b/tests/tests/media/extractor/AndroidManifest.xml
index 6911d53..82f45b9 100644
--- a/tests/tests/media/extractor/AndroidManifest.xml
+++ b/tests/tests/media/extractor/AndroidManifest.xml
@@ -17,9 +17,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.media.extractor.cts"
android:targetSandboxVersion="2">
-
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
diff --git a/tests/tests/media/libimagereaderjni/Android.bp b/tests/tests/media/libimagereaderjni/Android.bp
deleted file mode 100644
index bb84594..0000000
--- a/tests/tests/media/libimagereaderjni/Android.bp
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2017 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.
-
-// Build the unit tests.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-cc_test_library {
- name: "libctsimagereader_jni",
- srcs: ["AImageReaderCts.cpp"],
- shared_libs: [
- "libandroid",
- "libcamera2ndk",
- "libmediandk",
- "libnativewindow",
- "liblog",
- ],
- cflags: [
- "-Werror",
- "-Wall",
- ],
- gtest: false,
- // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
- // (revisit if/when we add features to this library that require newer sdk.
- sdk_version: "29",
- stl: "libc++_static",
-}
diff --git a/tests/tests/media/libimagereaderjni/OWNERS b/tests/tests/media/libimagereaderjni/OWNERS
deleted file mode 100644
index f48a95c..0000000
--- a/tests/tests/media/libimagereaderjni/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-include platform/frameworks/av:/camera/OWNERS
diff --git a/tests/tests/media/libmediandkjni/Android.bp b/tests/tests/media/libmediandkjni/Android.bp
deleted file mode 100644
index 02dcc3c..0000000
--- a/tests/tests/media/libmediandkjni/Android.bp
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2012 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.
-//
-
-//------------------------------------------------------------------------------
-// Builds libctscodecutils_jni.so
-//
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "cts_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- // legacy_unencumbered
- default_applicable_licenses: [
- "Android-Apache-2.0",
- "cts_tests_tests_media_libmediaandkjni_license",
- ],
-}
-
-license_kind {
- name: "libmediaandkjni_public_domain",
- conditions: ["unencumbered"],
-}
-
-license {
- name: "cts_tests_tests_media_libmediaandkjni_license",
- license_kinds: ["libmediaandkjni_public_domain"],
-}
-
-//------------------------------------------------------------------------------
-// Builds libctsmediacodec_jni.so
-//
-cc_test_library {
- name: "libctsmediacodec_jni",
- srcs: [
- "native-media-jni.cpp",
- ],
- shared_libs: [
- "libandroid",
- "libnativehelper_compat_libc++",
- "liblog",
- "libmediandk",
- "libEGL",
- ],
- header_libs: ["liblog_headers"],
- stl: "libc++_static",
- cflags: [
- "-Werror",
- "-Wall",
- "-DEGL_EGLEXT_PROTOTYPES",
- ],
- gtest: false,
- // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
- // (revisit if/when we add features to this library that require newer sdk.
- sdk_version: "29",
-}
-
diff --git a/tests/tests/media/misc/Android.bp b/tests/tests/media/misc/Android.bp
new file mode 100644
index 0000000..feaabe4
--- /dev/null
+++ b/tests/tests/media/misc/Android.bp
@@ -0,0 +1,113 @@
+// Copyright (C) 2008 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 {
+ // See: http://go/android-license-faq
+ default_applicable_licenses: [
+ "Android-Apache-2.0",
+ "cts_tests_tests_media_license", // CC-BY
+ ],
+}
+
+cc_test_library {
+ name: "libctsmediamisc_jni",
+ srcs: [
+ "jni/AImageReaderCts.cpp",
+ "jni/native-media-jni.cpp",
+ ],
+ shared_libs: [
+ "libandroid",
+ "libcamera2ndk",
+ "libnativehelper_compat_libc++",
+ "liblog",
+ "libmediandk",
+ "libEGL",
+ ],
+ header_libs: ["liblog_headers"],
+ stl: "libc++_static",
+ cflags: [
+ "-Werror",
+ "-Wall",
+ "-DEGL_EGLEXT_PROTOTYPES",
+ ],
+ gtest: false,
+ // this test suite will run on sdk 29 as part of MTS, make sure it's compatible
+ // (revisit if/when we add features to this library that require newer sdk.
+ sdk_version: "29",
+}
+
+android_test {
+ name: "CtsMediaMiscTestCases",
+ defaults: ["cts_defaults"],
+ // include both the 32 and 64 bit versions
+ compile_multilib: "both",
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.ext.junit",
+ "compatibility-device-util-axt",
+ "ctsdeviceutillegacy-axt",
+ "ctsmediautil",
+ "ctstestrunner-axt",
+ "hamcrest-library",
+ "ctstestserver",
+ "cts-media-common",
+ "junit",
+ "junit-params",
+ "testng",
+ "truth-prebuilt",
+ "mockito-target-minus-junit4",
+ "androidx.heifwriter_heifwriter",
+ "CtsCameraUtils",
+ ],
+ jni_libs: [
+ "libctscodecutils_jni",
+ "libctsmediamisc_jni",
+ "libctsmediacommon_jni",
+ "libnativehelper_compat_libc++",
+ ],
+ asset_dirs: ["assets"],
+ resource_dirs: ["res"],
+ aaptflags: [
+ "--auto-add-overlay",
+
+ // Do not compress these files:
+ "-0 .vp9",
+ "-0 .ts",
+ "-0 .heic",
+ "-0 .trp",
+ "-0 .ota",
+ "-0 .mxmf",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "aidl/**/*.aidl",
+ ],
+ // This test uses private APIs
+ platform_apis: true,
+ jni_uses_sdk_apis: true,
+ libs: [
+ "org.apache.http.legacy",
+ "android.test.base",
+ "android.test.runner",
+ ],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-media",
+ ],
+ host_required: ["cts-dynamic-config"],
+ min_sdk_version: "29",
+ target_sdk_version: "31",
+}
diff --git a/tests/tests/media/AndroidManifest.xml b/tests/tests/media/misc/AndroidManifest.xml
similarity index 63%
rename from tests/tests/media/AndroidManifest.xml
rename to tests/tests/media/misc/AndroidManifest.xml
index 86f744f..9b02586 100644
--- a/tests/tests/media/AndroidManifest.xml
+++ b/tests/tests/media/misc/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.media.cts"
+ package="android.media.misc.cts"
android:targetSandboxVersion="2">
<uses-sdk android:minSdkVersion="29"
@@ -44,24 +44,14 @@
<uses-permission android:name="android.permission.VIBRATE"/>
- <permission android:name="android.media.cts"
- android:protectionLevel="normal"/>
-
- <application android:networkSecurityConfig="@xml/network_security_config"
+ <application
android:requestLegacyExternalStorage="true"
android:largeHeap="true">
<uses-library android:name="android.test.runner"/>
<uses-library android:name="org.apache.http.legacy"
android:required="false"/>
- <activity android:name="android.media.cts.MediaProjectionActivity"
- android:label="MediaProjectionActivity"
- android:screenOrientation="locked"/>
- <activity android:name="android.media.cts.AudioManagerStub"
- android:label="AudioManagerStub"/>
- <activity android:name="android.media.cts.AudioManagerStubHelper"
- android:label="AudioManagerStubHelper"/>
- <activity android:name="android.media.cts.MediaSessionTestActivity"
+ <activity android:name="android.media.misc.cts.MediaSessionTestActivity"
android:label="MediaSessionTestActivity"
android:screenOrientation="nosensor"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
@@ -71,29 +61,9 @@
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
</intent-filter>
</activity>
- <activity android:name="android.media.cts.MediaStubActivity"
- android:label="MediaStubActivity"
- android:screenOrientation="nosensor"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
- </intent-filter>
- </activity>
- <activity android:name="android.media.cts.MediaStubActivity2"
- android:label="MediaStubActivity2"
- android:screenOrientation="nosensor"
- android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
- </intent-filter>
- </activity>
- <activity android:name="android.media.cts.FaceDetectorStub"
+ <activity android:name="android.media.misc.cts.FaceDetectorStub"
android:label="FaceDetectorStub"/>
- <activity android:name="android.media.cts.ResourceManagerStubActivity"
+ <activity android:name="android.media.misc.cts.ResourceManagerStubActivity"
android:label="ResourceManagerStubActivity"
android:exported="true">
<intent-filter>
@@ -101,50 +71,46 @@
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
</intent-filter>
</activity>
- <activity android:name="android.media.cts.ResourceManagerTestActivity1"
+ <activity android:name="android.media.misc.cts.ResourceManagerTestActivity1"
android:label="ResourceManagerTestActivity1"
android:process=":mediaCodecTestProcess1">
</activity>
- <activity android:name="android.media.cts.ResourceManagerTestActivity2"
+ <activity android:name="android.media.misc.cts.ResourceManagerTestActivity2"
android:label="ResourceManagerTestActivity2"
android:process=":mediaCodecTestProcess2">
</activity>
- <activity android:name="android.media.cts.MockActivity"/>
- <activity android:name="android.media.cts.MediaRouter2TestActivity"/>
- <service android:name="android.media.cts.StubMediaBrowserService"
+ <activity android:name="android.media.misc.cts.MockActivity"/>
+ <activity android:name="android.media.misc.cts.MediaRouter2TestActivity"/>
+ <service android:name="android.media.misc.cts.StubMediaBrowserService"
android:exported="true">
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
- <service android:name="android.media.cts.StubMediaSession2Service"
- android:permission="android.media.cts"
+ <service android:name="android.media.misc.cts.StubMediaSession2Service"
+ android:permission="android.media.misc.cts"
android:exported="true">
<intent-filter>
<action android:name="android.media.MediaSession2Service"/>
</intent-filter>
</service>
- <service android:name="android.media.cts.LocalMediaProjectionService"
- android:foregroundServiceType="mediaProjection"
- android:enabled="true">
- </service>
<service android:name=".StubMediaRoute2ProviderService"
android:exported="true">
<intent-filter>
<action android:name="android.media.MediaRoute2ProviderService"/>
</intent-filter>
</service>
- <service android:name="android.media.cts.MediaButtonReceiverService"
+ <service android:name="android.media.misc.cts.MediaButtonReceiverService"
android:exported="true"/>
<service android:name=".MediaBrowserServiceTestService"
android:process=":mediaBrowserServiceTestService"/>
<service android:name=".MediaSessionTestService"
android:process=":mediaSessionTestService"/>
- <receiver android:name="android.media.cts.MediaButtonBroadcastReceiver"/>
+ <receiver android:name="android.media.misc.cts.MediaButtonBroadcastReceiver"/>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.media.cts"
+ android:targetPackage="android.media.misc.cts"
android:label="CTS tests of android.media">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener"/>
diff --git a/tests/tests/media/AndroidTest.xml b/tests/tests/media/misc/AndroidTest.xml
similarity index 83%
rename from tests/tests/media/AndroidTest.xml
rename to tests/tests/media/misc/AndroidTest.xml
index 8d20655..58cea2c 100644
--- a/tests/tests/media/AndroidTest.xml
+++ b/tests/tests/media/misc/AndroidTest.xml
@@ -29,26 +29,26 @@
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
<option name="target" value="host" />
- <option name="config-filename" value="CtsMediaTestCases" />
- <option name="dynamic-config-name" value="CtsMediaTestCases" />
+ <option name="config-filename" value="CtsMediaMiscTestCases" />
+ <option name="dynamic-config-name" value="CtsMediaMiscTestCases" />
<option name="version" value="9.0_r1"/>
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaTestCases-1.4" />
- <option name="dynamic-config-module" value="CtsMediaTestCases" />
+ <option name="media-folder-name" value="CtsMediaMiscTestCases-1.0" />
+ <option name="dynamic-config-module" value="CtsMediaMiscTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsMediaTestCases.apk" />
+ <option name="test-file-name" value="CtsMediaMiscTestCases.apk" />
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
<option name="target" value="device" />
- <option name="config-filename" value="CtsMediaTestCases" />
- <option name="version" value="7.0"/>
+ <option name="config-filename" value="CtsMediaMiscTestCases" />
+ <option name="version" value="1.0"/>
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.media.cts" />
+ <option name="package" value="android.media.misc.cts" />
<!-- setup can be expensive so limit the number of shards -->
<option name="ajur-max-shard" value="5" />
<!-- test-timeout unit is ms, value = 30 min -->
diff --git a/tests/tests/media/misc/DynamicConfig.xml b/tests/tests/media/misc/DynamicConfig.xml
new file mode 100644
index 0000000..09e5fba
--- /dev/null
+++ b/tests/tests/media/misc/DynamicConfig.xml
@@ -0,0 +1,20 @@
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<dynamicConfig>
+ <entry key="media_files_url">
+ <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/misc/CtsMediaMiscTestCases-1.0.zip</value>
+ </entry>
+</dynamicConfig>
diff --git a/tests/tests/media/aidl/android/media/cts/IRemoteService.aidl b/tests/tests/media/misc/aidl/android/media/misc/cts/IRemoteService.aidl
similarity index 95%
rename from tests/tests/media/aidl/android/media/cts/IRemoteService.aidl
rename to tests/tests/media/misc/aidl/android/media/misc/cts/IRemoteService.aidl
index 5aacc30..7a9a957 100644
--- a/tests/tests/media/aidl/android/media/cts/IRemoteService.aidl
+++ b/tests/tests/media/misc/aidl/android/media/misc/cts/IRemoteService.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.os.Bundle;
diff --git a/tests/tests/media/assets/noiseandchirps.mp3 b/tests/tests/media/misc/assets/noiseandchirps.mp3
similarity index 100%
rename from tests/tests/media/assets/noiseandchirps.mp3
rename to tests/tests/media/misc/assets/noiseandchirps.mp3
Binary files differ
diff --git a/tests/tests/media/libimagereaderjni/AImageReaderCts.cpp b/tests/tests/media/misc/jni/AImageReaderCts.cpp
similarity index 98%
rename from tests/tests/media/libimagereaderjni/AImageReaderCts.cpp
rename to tests/tests/media/misc/jni/AImageReaderCts.cpp
index ea35540..44b8a8f 100644
--- a/tests/tests/media/libimagereaderjni/AImageReaderCts.cpp
+++ b/tests/tests/media/misc/jni/AImageReaderCts.cpp
@@ -506,7 +506,7 @@
} // namespace
// Test that newWithUsage can create AImageReader correctly.
-extern "C" jboolean Java_android_media_cts_NativeImageReaderTest_\
+extern "C" jboolean Java_android_media_misc_cts_NativeImageReaderTest_\
testSucceedsWithSupportedUsageFormatNative(JNIEnv* /*env*/, jclass /*clazz*/) {
static constexpr int kTestImageCount = 8;
@@ -526,7 +526,7 @@
return true;
}
-extern "C" jboolean Java_android_media_cts_NativeImageReaderTest_\
+extern "C" jboolean Java_android_media_misc_cts_NativeImageReaderTest_\
testTakePicturesNative(JNIEnv* /*env*/, jclass /*clazz*/) {
for (auto& readerUsage :
{AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}) {
@@ -546,7 +546,7 @@
return true;
}
-extern "C" jobject Java_android_media_cts_NativeImageReaderTest_\
+extern "C" jobject Java_android_media_misc_cts_NativeImageReaderTest_\
testCreateSurfaceNative(JNIEnv* env, jclass /*clazz*/) {
static constexpr uint64_t kTestImageUsage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN;
static constexpr int kTestImageCount = 8;
diff --git a/tests/tests/media/libmediandkjni/native-media-jni.cpp b/tests/tests/media/misc/jni/native-media-jni.cpp
similarity index 88%
rename from tests/tests/media/libmediandkjni/native-media-jni.cpp
rename to tests/tests/media/misc/jni/native-media-jni.cpp
index a38ca17b..8dc8e18 100644
--- a/tests/tests/media/libmediandkjni/native-media-jni.cpp
+++ b/tests/tests/media/misc/jni/native-media-jni.cpp
@@ -31,7 +31,7 @@
#include "media/NdkMediaDataSource.h"
#include "media/NdkMediaFormat.h"
-extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testFormatNative(JNIEnv * /*env*/,
+extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testFormatNative(JNIEnv * /*env*/,
jclass /*clazz*/) {
AMediaFormat* format = AMediaFormat_new();
if (!format) {
@@ -85,7 +85,7 @@
}
-extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testPsshNative(JNIEnv * /*env*/,
+extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testPsshNative(JNIEnv * /*env*/,
jclass /*clazz*/, int fd, jlong offset, jlong size) {
AMediaExtractor *ex = AMediaExtractor_new();
@@ -126,7 +126,7 @@
return true;
}
-extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv * /*env*/,
+extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testCryptoInfoNative(JNIEnv * /*env*/,
jclass /*clazz*/) {
size_t numsubsamples = 4;
@@ -171,13 +171,13 @@
return true;
}
-extern "C" jlong Java_android_media_cts_NativeDecoderTest_createAMediaExtractor(JNIEnv * /*env*/,
+extern "C" jlong Java_android_media_misc_cts_NativeDecoderTest_createAMediaExtractor(JNIEnv * /*env*/,
jclass /*clazz*/) {
AMediaExtractor *ex = AMediaExtractor_new();
return reinterpret_cast<jlong>(ex);
}
-extern "C" jlong Java_android_media_cts_NativeDecoderTest_createAMediaDataSource(JNIEnv * env,
+extern "C" jlong Java_android_media_misc_cts_NativeDecoderTest_createAMediaDataSource(JNIEnv * env,
jclass /*clazz*/, jstring jurl) {
const char *url = env->GetStringUTFChars(jurl, NULL);
if (url == NULL) {
@@ -190,29 +190,29 @@
return reinterpret_cast<jlong>(ds);
}
-extern "C" jint Java_android_media_cts_NativeDecoderTest_setAMediaExtractorDataSource(JNIEnv * /*env*/,
+extern "C" jint Java_android_media_misc_cts_NativeDecoderTest_setAMediaExtractorDataSource(JNIEnv * /*env*/,
jclass /*clazz*/, jlong jex, jlong jds) {
AMediaExtractor *ex = reinterpret_cast<AMediaExtractor *>(jex);
AMediaDataSource *ds = reinterpret_cast<AMediaDataSource *>(jds);
return AMediaExtractor_setDataSourceCustom(ex, ds);
}
-extern "C" void Java_android_media_cts_NativeDecoderTest_closeAMediaDataSource(
+extern "C" void Java_android_media_misc_cts_NativeDecoderTest_closeAMediaDataSource(
JNIEnv * /*env*/, jclass /*clazz*/, jlong ds) {
AMediaDataSource_close(reinterpret_cast<AMediaDataSource *>(ds));
}
-extern "C" void Java_android_media_cts_NativeDecoderTest_deleteAMediaExtractor(
+extern "C" void Java_android_media_misc_cts_NativeDecoderTest_deleteAMediaExtractor(
JNIEnv * /*env*/, jclass /*clazz*/, jlong ex) {
AMediaExtractor_delete(reinterpret_cast<AMediaExtractor *>(ex));
}
-extern "C" void Java_android_media_cts_NativeDecoderTest_deleteAMediaDataSource(
+extern "C" void Java_android_media_misc_cts_NativeDecoderTest_deleteAMediaDataSource(
JNIEnv * /*env*/, jclass /*clazz*/, jlong ds) {
AMediaDataSource_delete(reinterpret_cast<AMediaDataSource *>(ds));
}
-extern "C" jboolean Java_android_media_cts_NativeDecoderTest_testMediaFormatNative(
+extern "C" jboolean Java_android_media_misc_cts_NativeDecoderTest_testMediaFormatNative(
JNIEnv * /*env*/, jclass /*clazz*/) {
AMediaFormat *original = AMediaFormat_new();
diff --git a/tests/tests/media/res/drawable/faces.jpg b/tests/tests/media/misc/res/drawable/faces.jpg
similarity index 100%
rename from tests/tests/media/res/drawable/faces.jpg
rename to tests/tests/media/misc/res/drawable/faces.jpg
Binary files differ
diff --git a/tests/tests/media/res/drawable/single_face.jpg b/tests/tests/media/misc/res/drawable/single_face.jpg
similarity index 100%
rename from tests/tests/media/res/drawable/single_face.jpg
rename to tests/tests/media/misc/res/drawable/single_face.jpg
Binary files differ
diff --git a/tests/tests/media/res/raw/a_4.ogg b/tests/tests/media/misc/res/raw/a_4.ogg
similarity index 100%
rename from tests/tests/media/res/raw/a_4.ogg
rename to tests/tests/media/misc/res/raw/a_4.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/a_4_aac.mp4 b/tests/tests/media/misc/res/raw/a_4_aac.mp4
similarity index 100%
rename from tests/tests/media/res/raw/a_4_aac.mp4
rename to tests/tests/media/misc/res/raw/a_4_aac.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/a_4_haptic.ogg b/tests/tests/media/misc/res/raw/a_4_haptic.ogg
similarity index 100%
rename from tests/tests/media/res/raw/a_4_haptic.ogg
rename to tests/tests/media/misc/res/raw/a_4_haptic.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/b_5.ogg b/tests/tests/media/misc/res/raw/b_5.ogg
similarity index 100%
rename from tests/tests/media/res/raw/b_5.ogg
rename to tests/tests/media/misc/res/raw/b_5.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/b_5_aac.mp4 b/tests/tests/media/misc/res/raw/b_5_aac.mp4
similarity index 100%
rename from tests/tests/media/res/raw/b_5_aac.mp4
rename to tests/tests/media/misc/res/raw/b_5_aac.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/b_5_haptic.ogg b/tests/tests/media/misc/res/raw/b_5_haptic.ogg
similarity index 100%
rename from tests/tests/media/res/raw/b_5_haptic.ogg
rename to tests/tests/media/misc/res/raw/b_5_haptic.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/c_sharp_5.ogg b/tests/tests/media/misc/res/raw/c_sharp_5.ogg
similarity index 100%
rename from tests/tests/media/res/raw/c_sharp_5.ogg
rename to tests/tests/media/misc/res/raw/c_sharp_5.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/c_sharp_5_aac.mp4 b/tests/tests/media/misc/res/raw/c_sharp_5_aac.mp4
similarity index 100%
rename from tests/tests/media/res/raw/c_sharp_5_aac.mp4
rename to tests/tests/media/misc/res/raw/c_sharp_5_aac.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/c_sharp_5_haptic.ogg b/tests/tests/media/misc/res/raw/c_sharp_5_haptic.ogg
similarity index 100%
rename from tests/tests/media/res/raw/c_sharp_5_haptic.ogg
rename to tests/tests/media/misc/res/raw/c_sharp_5_haptic.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/e_5.ogg b/tests/tests/media/misc/res/raw/e_5.ogg
similarity index 100%
rename from tests/tests/media/res/raw/e_5.ogg
rename to tests/tests/media/misc/res/raw/e_5.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/e_5_aac.mp4 b/tests/tests/media/misc/res/raw/e_5_aac.mp4
similarity index 100%
rename from tests/tests/media/res/raw/e_5_aac.mp4
rename to tests/tests/media/misc/res/raw/e_5_aac.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/e_5_haptic.ogg b/tests/tests/media/misc/res/raw/e_5_haptic.ogg
similarity index 100%
rename from tests/tests/media/res/raw/e_5_haptic.ogg
rename to tests/tests/media/misc/res/raw/e_5_haptic.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/g_sharp_5.ogg b/tests/tests/media/misc/res/raw/g_sharp_5.ogg
similarity index 100%
rename from tests/tests/media/res/raw/g_sharp_5.ogg
rename to tests/tests/media/misc/res/raw/g_sharp_5.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/g_sharp_5_aac.mp4 b/tests/tests/media/misc/res/raw/g_sharp_5_aac.mp4
similarity index 100%
rename from tests/tests/media/res/raw/g_sharp_5_aac.mp4
rename to tests/tests/media/misc/res/raw/g_sharp_5_aac.mp4
Binary files differ
diff --git a/tests/tests/media/res/raw/g_sharp_5_haptic.ogg b/tests/tests/media/misc/res/raw/g_sharp_5_haptic.ogg
similarity index 100%
rename from tests/tests/media/res/raw/g_sharp_5_haptic.ogg
rename to tests/tests/media/misc/res/raw/g_sharp_5_haptic.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/heifwriter_input.heic b/tests/tests/media/misc/res/raw/heifwriter_input.heic
similarity index 100%
rename from tests/tests/media/res/raw/heifwriter_input.heic
rename to tests/tests/media/misc/res/raw/heifwriter_input.heic
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_a.mid b/tests/tests/media/misc/res/raw/midi_a.mid
similarity index 100%
rename from tests/tests/media/res/raw/midi_a.mid
rename to tests/tests/media/misc/res/raw/midi_a.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_b.mid b/tests/tests/media/misc/res/raw/midi_b.mid
similarity index 100%
rename from tests/tests/media/res/raw/midi_b.mid
rename to tests/tests/media/misc/res/raw/midi_b.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_cs.mid b/tests/tests/media/misc/res/raw/midi_cs.mid
similarity index 100%
rename from tests/tests/media/res/raw/midi_cs.mid
rename to tests/tests/media/misc/res/raw/midi_cs.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_e.mid b/tests/tests/media/misc/res/raw/midi_e.mid
similarity index 100%
rename from tests/tests/media/res/raw/midi_e.mid
rename to tests/tests/media/misc/res/raw/midi_e.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/midi_gs.mid b/tests/tests/media/misc/res/raw/midi_gs.mid
similarity index 100%
rename from tests/tests/media/res/raw/midi_gs.mid
rename to tests/tests/media/misc/res/raw/midi_gs.mid
Binary files differ
diff --git a/tests/tests/media/res/raw/sine1khzm40db.wav b/tests/tests/media/misc/res/raw/sine1khzm40db.wav
similarity index 100%
rename from tests/tests/media/res/raw/sine1khzm40db.wav
rename to tests/tests/media/misc/res/raw/sine1khzm40db.wav
Binary files differ
diff --git a/tests/tests/media/res/raw/sine1khzs40dblong.mp3 b/tests/tests/media/misc/res/raw/sine1khzs40dblong.mp3
similarity index 100%
rename from tests/tests/media/res/raw/sine1khzs40dblong.mp3
rename to tests/tests/media/misc/res/raw/sine1khzs40dblong.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/test1m1s.mp3 b/tests/tests/media/misc/res/raw/test1m1s.mp3
similarity index 100%
rename from tests/tests/media/res/raw/test1m1s.mp3
rename to tests/tests/media/misc/res/raw/test1m1s.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/testcanonicalize_localizable_mp3.mp3 b/tests/tests/media/misc/res/raw/testcanonicalize_localizable_mp3.mp3
similarity index 100%
rename from tests/tests/media/res/raw/testcanonicalize_localizable_mp3.mp3
rename to tests/tests/media/misc/res/raw/testcanonicalize_localizable_mp3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/testcanonicalize_mp3.mp3 b/tests/tests/media/misc/res/raw/testcanonicalize_mp3.mp3
similarity index 100%
rename from tests/tests/media/res/raw/testcanonicalize_mp3.mp3
rename to tests/tests/media/misc/res/raw/testcanonicalize_mp3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/testmp3.mp3 b/tests/tests/media/misc/res/raw/testmp3.mp3
similarity index 100%
rename from tests/tests/media/res/raw/testmp3.mp3
rename to tests/tests/media/misc/res/raw/testmp3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/testopus.opus b/tests/tests/media/misc/res/raw/testopus.opus
similarity index 100%
rename from tests/tests/media/res/raw/testopus.opus
rename to tests/tests/media/misc/res/raw/testopus.opus
Binary files differ
diff --git a/tests/tests/media/res/raw/testwav_16bit_44100hz.wav b/tests/tests/media/misc/res/raw/testwav_16bit_44100hz.wav
similarity index 100%
rename from tests/tests/media/res/raw/testwav_16bit_44100hz.wav
rename to tests/tests/media/misc/res/raw/testwav_16bit_44100hz.wav
Binary files differ
diff --git a/tests/tests/media/res/values/exifinterface.xml b/tests/tests/media/misc/res/values/exifinterface.xml
similarity index 100%
rename from tests/tests/media/res/values/exifinterface.xml
rename to tests/tests/media/misc/res/values/exifinterface.xml
diff --git a/tests/tests/media/res/values/strings.xml b/tests/tests/media/misc/res/values/strings.xml
similarity index 100%
rename from tests/tests/media/res/values/strings.xml
rename to tests/tests/media/misc/res/values/strings.xml
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java
index 3eecb04..c00407d 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/CamcorderProfileTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.pm.PackageManager;
import android.hardware.Camera;
@@ -26,6 +26,7 @@
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaRecorder;
+import android.media.cts.NonMediaMainlineTest;
import android.test.AndroidTestCase;
import android.util.Log;
diff --git a/tests/tests/media/src/android/media/cts/CameraProfileTest.java b/tests/tests/media/misc/src/android/media/misc/cts/CameraProfileTest.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/CameraProfileTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/CameraProfileTest.java
index 9949c73..1de7a91 100644
--- a/tests/tests/media/src/android/media/cts/CameraProfileTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/CameraProfileTest.java
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.hardware.Camera;
import android.media.CameraProfile;
+import android.media.cts.NonMediaMainlineTest;
import android.test.AndroidTestCase;
import android.util.Log;
diff --git a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java b/tests/tests/media/misc/src/android/media/misc/cts/ExifInterfaceTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ExifInterfaceTest.java
index 75ba4b1..22c8bf1 100644
--- a/tests/tests/media/src/android/media/cts/ExifInterfaceTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ExifInterfaceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.ExifInterface.TAG_SUBJECT_AREA;
@@ -22,6 +22,8 @@
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ExifInterface;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.cts.Preconditions;
import android.os.FileUtils;
import android.os.StrictMode;
import android.platform.test.annotations.AppModeFull;
diff --git a/tests/tests/media/src/android/media/cts/FaceDetectorStub.java b/tests/tests/media/misc/src/android/media/misc/cts/FaceDetectorStub.java
similarity index 95%
rename from tests/tests/media/src/android/media/cts/FaceDetectorStub.java
rename to tests/tests/media/misc/src/android/media/misc/cts/FaceDetectorStub.java
index 6635fda..ef33f01 100644
--- a/tests/tests/media/src/android/media/cts/FaceDetectorStub.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/FaceDetectorStub.java
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package android.media.cts;
-
-import android.media.cts.R;
+package android.media.misc.cts;
import android.app.Activity;
import android.media.FaceDetector.Face;
+
import android.os.Bundle;
import java.util.List;
diff --git a/tests/tests/media/src/android/media/cts/FaceDetectorTest.java b/tests/tests/media/misc/src/android/media/misc/cts/FaceDetectorTest.java
similarity index 95%
rename from tests/tests/media/src/android/media/cts/FaceDetectorTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/FaceDetectorTest.java
index 94e4e37..f5f24d0 100644
--- a/tests/tests/media/src/android/media/cts/FaceDetectorTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/FaceDetectorTest.java
@@ -14,15 +14,13 @@
* limitations under the License.
*/
-package android.media.cts;
-
-import android.media.cts.R;
-
+package android.media.misc.cts;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.FaceDetector;
import android.media.FaceDetector.Face;
+import android.media.cts.NonMediaMainlineTest;
import android.test.InstrumentationTestCase;
@NonMediaMainlineTest
diff --git a/tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java b/tests/tests/media/misc/src/android/media/misc/cts/FaceDetector_FaceTest.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/FaceDetector_FaceTest.java
index 7b50040..e32860c 100644
--- a/tests/tests/media/src/android/media/cts/FaceDetector_FaceTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/FaceDetector_FaceTest.java
@@ -14,15 +14,13 @@
* limitations under the License.
*/
-package android.media.cts;
-
-import android.media.cts.R;
-
+package android.media.misc.cts;
import android.content.Intent;
import android.graphics.PointF;
import android.media.FaceDetector;
import android.media.FaceDetector.Face;
+import android.media.cts.NonMediaMainlineTest;
import android.test.InstrumentationTestCase;
import java.util.List;
diff --git a/tests/tests/media/src/android/media/cts/FaceView.java b/tests/tests/media/misc/src/android/media/misc/cts/FaceView.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/FaceView.java
rename to tests/tests/media/misc/src/android/media/misc/cts/FaceView.java
index 6d3d84b..d928f69a 100644
--- a/tests/tests/media/src/android/media/cts/FaceView.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/FaceView.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.Context;
import android.graphics.Bitmap;
diff --git a/tests/tests/media/src/android/media/cts/HandlerExecutor.java b/tests/tests/media/misc/src/android/media/misc/cts/HandlerExecutor.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/HandlerExecutor.java
rename to tests/tests/media/misc/src/android/media/misc/cts/HandlerExecutor.java
index afeef51e..9b6cf44 100644
--- a/tests/tests/media/src/android/media/cts/HandlerExecutor.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/HandlerExecutor.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.annotation.NonNull;
import android.os.Handler;
diff --git a/tests/tests/media/src/android/media/cts/HeifWriterTest.java b/tests/tests/media/misc/src/android/media/misc/cts/HeifWriterTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/HeifWriterTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/HeifWriterTest.java
index 40d6128..e855a76 100644
--- a/tests/tests/media/src/android/media/cts/HeifWriterTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/HeifWriterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static androidx.heifwriter.HeifWriter.INPUT_MODE_BITMAP;
import static androidx.heifwriter.HeifWriter.INPUT_MODE_BUFFER;
@@ -40,6 +40,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
+import android.media.cts.InputSurface;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresDevice;
diff --git a/tests/tests/media/src/android/media/cts/MediaActivityTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaActivityTest.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/MediaActivityTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaActivityTest.java
index a03d429..50365dd 100644
--- a/tests/tests/media/src/android/media/cts/MediaActivityTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaActivityTest.java
@@ -14,25 +14,24 @@
* limitations under the License
*/
-package android.media.cts;
+package android.media.misc.cts;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
+import static org.junit.Assert.fail;
import android.Manifest;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.hardware.hdmi.HdmiControlManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
+import android.media.cts.NonMediaMainlineTest;
import android.media.session.MediaSession;
import android.os.Handler;
import android.os.Looper;
@@ -101,9 +100,8 @@
Manifest.permission.HDMI_CEC);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
mContext = mInstrumentation.getContext();
- mUseFixedVolume = mContext.getResources().getBoolean(
- Resources.getSystem().getIdentifier("config_useFixedVolume", "bool", "android"));
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
+ mUseFixedVolume = mAudioManager.isVolumeFixed();
mHdmiControlManager = mContext.getSystemService(HdmiControlManager.class);
if (mHdmiControlManager != null) {
mHdmiEnableStatus = mHdmiControlManager.getHdmiCecEnabled();
@@ -174,6 +172,7 @@
@Test
public void testVolumeKey_whileSessionAlive() throws Exception {
if (mUseFixedVolume) {
+ Log.i(TAG, "testVolumeKey_whileSessionAlive skipped due to full volume device");
return;
}
@@ -202,6 +201,7 @@
@Test
public void testVolumeKey_afterSessionReleased() throws Exception {
if (mUseFixedVolume) {
+ Log.i(TAG, "testVolumeKey_afterSessionReleased skipped due to full volume device");
return;
}
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserServiceTest.java
similarity index 94%
rename from tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserServiceTest.java
index 7203df4..f8c8418 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserServiceTest.java
@@ -13,22 +13,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.browse.MediaBrowser.MediaItem.FLAG_PLAYABLE;
-import static android.media.cts.MediaBrowserServiceTestService.KEY_PARENT_MEDIA_ID;
-import static android.media.cts.MediaBrowserServiceTestService.KEY_SERVICE_COMPONENT_NAME;
-import static android.media.cts.MediaBrowserServiceTestService.TEST_SERIES_OF_NOTIFY_CHILDREN_CHANGED;
-import static android.media.cts.MediaSessionTestService.KEY_EXPECTED_TOTAL_NUMBER_OF_ITEMS;
-import static android.media.cts.MediaSessionTestService.STEP_CHECK;
-import static android.media.cts.MediaSessionTestService.STEP_CLEAN_UP;
-import static android.media.cts.MediaSessionTestService.STEP_SET_UP;
+import static android.media.misc.cts.MediaBrowserServiceTestService.KEY_PARENT_MEDIA_ID;
+import static android.media.misc.cts.MediaBrowserServiceTestService.KEY_SERVICE_COMPONENT_NAME;
+import static android.media.misc.cts.MediaBrowserServiceTestService.TEST_SERIES_OF_NOTIFY_CHILDREN_CHANGED;
+import static android.media.misc.cts.MediaSessionTestService.KEY_EXPECTED_TOTAL_NUMBER_OF_ITEMS;
+import static android.media.misc.cts.MediaSessionTestService.STEP_CHECK;
+import static android.media.misc.cts.MediaSessionTestService.STEP_CLEAN_UP;
+import static android.media.misc.cts.MediaSessionTestService.STEP_SET_UP;
import static android.media.cts.Utils.compareRemoteUserInfo;
import android.content.ComponentName;
import android.media.MediaDescription;
import android.media.browse.MediaBrowser;
import android.media.browse.MediaBrowser.MediaItem;
+import android.media.cts.NonMediaMainlineTest;
import android.media.session.MediaSessionManager.RemoteUserInfo;
import android.os.Bundle;
import android.os.Process;
@@ -52,7 +53,7 @@
private static final long TIME_OUT_MS = 3000L;
private static final long WAIT_TIME_FOR_NO_RESPONSE_MS = 500L;
private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
- "android.media.cts", "android.media.cts.StubMediaBrowserService");
+ "android.media.misc.cts", "android.media.misc.cts.StubMediaBrowserService");
private final TestCountDownLatch mOnChildrenLoadedLatch = new TestCountDownLatch();
private final TestCountDownLatch mOnChildrenLoadedWithOptionsLatch = new TestCountDownLatch();
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTestService.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserServiceTestService.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/MediaBrowserServiceTestService.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserServiceTestService.java
index 0db43d9..e1868823 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserServiceTestService.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserServiceTestService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertTrue;
diff --git a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaBrowserTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserTest.java
index 8f3d299..8ab1b2b 100644
--- a/tests/tests/media/src/android/media/cts/MediaBrowserTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaBrowserTest.java
@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.ComponentName;
import android.media.browse.MediaBrowser;
import android.media.browse.MediaBrowser.MediaItem;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Bundle;
import android.test.InstrumentationTestCase;
@@ -46,7 +47,7 @@
*/
private static final long SLEEP_MS = 100L;
private static final ComponentName TEST_BROWSER_SERVICE = new ComponentName(
- "android.media.cts", "android.media.cts.StubMediaBrowserService");
+ "android.media.misc.cts", "android.media.misc.cts.StubMediaBrowserService");
private static final ComponentName TEST_INVALID_BROWSER_SERVICE = new ComponentName(
"invalid.package", "invalid.ServiceClassName");
private final StubConnectionCallback mConnectionCallback = new StubConnectionCallback();
diff --git a/tests/tests/media/src/android/media/cts/MediaButtonBroadcastReceiver.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaButtonBroadcastReceiver.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaButtonBroadcastReceiver.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaButtonBroadcastReceiver.java
index 1d320d8..e07394f 100644
--- a/tests/tests/media/src/android/media/cts/MediaButtonBroadcastReceiver.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaButtonBroadcastReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
diff --git a/tests/tests/media/src/android/media/cts/MediaButtonReceiverService.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaButtonReceiverService.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaButtonReceiverService.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaButtonReceiverService.java
index def8cee..2e37e95 100644
--- a/tests/tests/media/src/android/media/cts/MediaButtonReceiverService.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaButtonReceiverService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
diff --git a/tests/tests/media/src/android/media/cts/MediaCasTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaCasTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaCasTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaCasTest.java
index a5ab09b..dc2a2e8 100644
--- a/tests/tests/media/src/android/media/cts/MediaCasTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaCasTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.MediaCas;
import android.media.MediaCas.PluginDescriptor;
@@ -24,7 +24,6 @@
import android.media.MediaCasStateException;
import android.media.MediaCodec;
import android.media.MediaDescrambler;
-import android.media.cts.R;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaCodecListTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaCodecListTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaCodecListTest.java
index 19621ec..4b36407 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecListTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaCodecListTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_SecurePlayback;
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_TunneledPlayback;
diff --git a/tests/tests/media/src/android/media/cts/MediaCommunicationManagerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaCommunicationManagerTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaCommunicationManagerTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaCommunicationManagerTest.java
index 9fde336..cc5c3c1 100644
--- a/tests/tests/media/src/android/media/cts/MediaCommunicationManagerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaCommunicationManagerTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
diff --git a/tests/tests/media/src/android/media/cts/MediaController2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaController2Test.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaController2Test.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaController2Test.java
index 36085d9..1025109 100644
--- a/tests/tests/media/src/android/media/cts/MediaController2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaController2Test.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
diff --git a/tests/tests/media/src/android/media/cts/MediaControllerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaControllerTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaControllerTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaControllerTest.java
index 0fc6a5f..a44cd2c 100644
--- a/tests/tests/media/src/android/media/cts/MediaControllerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaControllerTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.cts.Utils.compareRemoteUserInfo;
import static android.media.session.PlaybackState.STATE_PLAYING;
@@ -24,6 +24,7 @@
import android.media.AudioManager;
import android.media.Rating;
import android.media.VolumeProvider;
+import android.media.cts.NonMediaMainlineTest;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager.RemoteUserInfo;
diff --git a/tests/tests/media/src/android/media/cts/MediaFormatTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaFormatTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaFormatTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaFormatTest.java
index ff7259a..86000f6 100644
--- a/tests/tests/media/src/android/media/cts/MediaFormatTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaFormatTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.annotation.NonNull;
import android.media.MediaFormat;
diff --git a/tests/tests/media/src/android/media/cts/MediaItemTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaItemTest.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaItemTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaItemTest.java
index 75235c9..747954b 100644
--- a/tests/tests/media/src/android/media/cts/MediaItemTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaItemTest.java
@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.MediaDescription;
import android.media.browse.MediaBrowser.MediaItem;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Parcel;
import android.test.AndroidTestCase;
import android.text.TextUtils;
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
index 20d0f50..70bf2b4 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataRetrieverTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.MediaMetadataRetriever.OPTION_CLOSEST;
import static android.media.MediaMetadataRetriever.OPTION_CLOSEST_SYNC;
@@ -32,6 +32,10 @@
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
+import android.media.cts.CodecUtils;
+import android.media.cts.Preconditions;
+import android.media.cts.TestMediaDataSource;
+import android.media.cts.TestUtils;
import android.os.ParcelFileDescriptor;
import android.net.Uri;
import android.os.Build;
diff --git a/tests/tests/media/src/android/media/cts/MediaMetadataTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaMetadataTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataTest.java
index ed7e0a3..9c00be6 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetadataTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetadataTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -24,6 +24,7 @@
import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.Rating;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Parcel;
import android.text.TextUtils;
diff --git a/tests/tests/media/src/android/media/cts/MediaMetricsTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetricsTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/MediaMetricsTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaMetricsTest.java
index 7898b2d..5120922 100644
--- a/tests/tests/media/src/android/media/cts/MediaMetricsTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaMetricsTest.java
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import android.media.MediaMetrics;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Bundle;
import android.os.Process;
import androidx.test.runner.AndroidJUnit4;
diff --git a/tests/tests/media/src/android/media/cts/MediaProjectionTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaProjectionTest.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/MediaProjectionTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaProjectionTest.java
index 1b7e3d41..351338c 100644
--- a/tests/tests/media/src/android/media/cts/MediaProjectionTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaProjectionTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
@@ -22,6 +22,8 @@
import android.app.ActivityManager;
import android.content.Context;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.cts.MediaProjectionActivity;
import android.media.projection.MediaProjection;
import android.os.Handler;
import android.os.Looper;
diff --git a/tests/tests/media/src/android/media/cts/MediaRoute2InfoTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRoute2InfoTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaRoute2InfoTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaRoute2InfoTest.java
index bf75ec8..94d5883 100644
--- a/tests/tests/media/src/android/media/cts/MediaRoute2InfoTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRoute2InfoTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -25,6 +25,7 @@
import static org.testng.Assert.assertThrows;
import android.media.MediaRoute2Info;
+import android.media.cts.NonMediaMainlineTest;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRoute2ProviderServiceTest.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaRoute2ProviderServiceTest.java
index 0a75047..531a2f2 100644
--- a/tests/tests/media/src/android/media/cts/MediaRoute2ProviderServiceTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRoute2ProviderServiceTest.java
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
-import static android.media.cts.MediaRouter2Test.releaseControllers;
-import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
-import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SPECIAL;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
+import static android.media.misc.cts.MediaRouter2Test.releaseControllers;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURE_SPECIAL;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -40,7 +40,8 @@
import android.media.MediaRouter2.TransferCallback;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
-import android.media.cts.StubMediaRoute2ProviderService.Proxy;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.misc.cts.StubMediaRoute2ProviderService.Proxy;
import android.os.Bundle;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.LargeTest;
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaRouter2Test.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
index b20a294..05cedf3 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouter2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
@@ -14,19 +14,20 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.content.Context.AUDIO_SERVICE;
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
-import static android.media.cts.StubMediaRoute2ProviderService.FEATURES_SPECIAL;
-import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID3_SESSION_CREATION_FAILED;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID_SPECIAL_FEATURE;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURES_ALL;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURES_SPECIAL;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID3_SESSION_CREATION_FAILED;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID_SPECIAL_FEATURE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -49,6 +50,7 @@
import android.media.MediaRouter2.RoutingController;
import android.media.MediaRouter2.TransferCallback;
import android.media.RouteDiscoveryPreference;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Bundle;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.LargeTest;
diff --git a/tests/tests/media/src/android/media/cts/MediaRouter2TestActivity.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2TestActivity.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaRouter2TestActivity.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2TestActivity.java
index e0ba399..76eb1c9 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouter2TestActivity.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2TestActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.Activity;
import android.content.Context;
diff --git a/tests/tests/media/src/android/media/cts/MediaRouterTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouterTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaRouterTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaRouterTest.java
index 5d9908f..aa66932 100644
--- a/tests/tests/media/src/android/media/cts/MediaRouterTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouterTest.java
@@ -13,9 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
-
-import android.media.cts.R;
+package android.media.misc.cts;
import android.app.PendingIntent;
import android.content.Context;
@@ -30,6 +28,7 @@
import android.media.MediaRouter.RouteInfo;
import android.media.MediaRouter.UserRouteInfo;
import android.media.RemoteControlClient;
+import android.media.cts.NonMediaMainlineTest;
import android.platform.test.annotations.AppModeFull;
import android.test.InstrumentationTestCase;
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaScannerConnectionTest.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaScannerConnectionTest.java
index 574ef2e..f03ae97 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerConnectionTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaScannerConnectionTest.java
@@ -14,12 +14,13 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.ComponentName;
import android.content.Context;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
+import android.media.cts.NonMediaMainlineTest;
import android.net.Uri;
import android.os.IBinder;
import android.platform.test.annotations.AppModeFull;
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaScannerNotificationTest.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaScannerNotificationTest.java
index 77f3d58..96ec5e6 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerNotificationTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaScannerNotificationTest.java
@@ -14,10 +14,11 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.Intent;
import android.content.IntentFilter;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Environment;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
diff --git a/tests/tests/media/src/android/media/cts/MediaScannerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaScannerTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaScannerTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaScannerTest.java
index f984381..1794eba 100644
--- a/tests/tests/media/src/android/media/cts/MediaScannerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaScannerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.UiAutomation;
import android.content.ComponentName;
@@ -25,6 +25,8 @@
import android.media.MediaMetadataRetriever;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.cts.Preconditions;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2ServiceTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSession2ServiceTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaSession2ServiceTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSession2ServiceTest.java
index 579d0a2..d031b9e 100644
--- a/tests/tests/media/src/android/media/cts/MediaSession2ServiceTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSession2ServiceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -34,6 +34,7 @@
import android.media.MediaSession2Service;
import android.media.Session2CommandGroup;
import android.media.Session2Token;
+import android.media.cts.TestUtils;
import android.os.Bundle;
import android.os.HandlerThread;
import android.os.Process;
diff --git a/tests/tests/media/src/android/media/cts/MediaSession2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSession2Test.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaSession2Test.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSession2Test.java
index 6ee8bd4..85cfa46 100644
--- a/tests/tests/media/src/android/media/cts/MediaSession2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSession2Test.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -35,6 +35,7 @@
import android.media.Session2Command;
import android.media.Session2CommandGroup;
import android.media.Session2Token;
+import android.media.cts.TestUtils;
import android.media.session.MediaSessionManager;
import android.os.Bundle;
import android.os.Handler;
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionManagerTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSessionManagerTest.java
index 3349206..05306f5 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionManagerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionManagerTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.Manifest;
import android.content.ComponentName;
@@ -25,6 +25,8 @@
import android.media.MediaSession2;
import android.media.Session2CommandGroup;
import android.media.Session2Token;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.cts.Utils;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionManager;
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTest.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/MediaSessionTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTest.java
index 04f2662..6edadaa 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTest.java
@@ -13,17 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.AudioAttributes.USAGE_GAME;
-import static android.media.cts.MediaSessionTestService.KEY_EXPECTED_QUEUE_SIZE;
-import static android.media.cts.MediaSessionTestService.KEY_EXPECTED_TOTAL_NUMBER_OF_ITEMS;
-import static android.media.cts.MediaSessionTestService.KEY_SESSION_TOKEN;
-import static android.media.cts.MediaSessionTestService.STEP_CHECK;
-import static android.media.cts.MediaSessionTestService.STEP_CLEAN_UP;
-import static android.media.cts.MediaSessionTestService.STEP_SET_UP;
-import static android.media.cts.MediaSessionTestService.TEST_SERIES_OF_SET_QUEUE;
-import static android.media.cts.MediaSessionTestService.TEST_SET_QUEUE;
+import static android.media.misc.cts.MediaSessionTestService.KEY_EXPECTED_QUEUE_SIZE;
+import static android.media.misc.cts.MediaSessionTestService.KEY_EXPECTED_TOTAL_NUMBER_OF_ITEMS;
+import static android.media.misc.cts.MediaSessionTestService.KEY_SESSION_TOKEN;
+import static android.media.misc.cts.MediaSessionTestService.STEP_CHECK;
+import static android.media.misc.cts.MediaSessionTestService.STEP_CLEAN_UP;
+import static android.media.misc.cts.MediaSessionTestService.STEP_SET_UP;
+import static android.media.misc.cts.MediaSessionTestService.TEST_SERIES_OF_SET_QUEUE;
+import static android.media.misc.cts.MediaSessionTestService.TEST_SET_QUEUE;
import static android.media.cts.Utils.compareRemoteUserInfo;
import android.app.PendingIntent;
@@ -37,6 +37,8 @@
import android.media.MediaSession2;
import android.media.Rating;
import android.media.VolumeProvider;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.cts.Utils;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSession.QueueItem;
@@ -402,7 +404,7 @@
*/
public void testSetMediaButtonReceiver_implicitIntent() throws Exception {
// Note: No such broadcast receiver exists.
- Intent intent = new Intent("android.media.cts.ACTION_MEDIA_TEST");
+ Intent intent = new Intent("android.media.misc.cts.ACTION_MEDIA_TEST");
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent,
PendingIntent.FLAG_MUTABLE_UNAUDITED);
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTestActivity.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTestActivity.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/MediaSessionTestActivity.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTestActivity.java
index 90f7247..5967418 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTestActivity.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTestActivity.java
@@ -14,7 +14,7 @@
* limitations under the License
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.fail;
diff --git a/tests/tests/media/src/android/media/cts/MediaSessionTestService.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTestService.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaSessionTestService.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTestService.java
index 08476ba..88ae926 100644
--- a/tests/tests/media/src/android/media/cts/MediaSessionTestService.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSessionTestService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertTrue;
diff --git a/tests/tests/media/src/android/media/cts/MediaSyncTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaSyncTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/MediaSyncTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaSyncTest.java
index 0e2562a..94529bf 100644
--- a/tests/tests/media/src/android/media/cts/MediaSyncTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaSyncTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -27,6 +27,9 @@
import android.media.MediaTimestamp;
import android.media.PlaybackParams;
import android.media.SyncParams;
+import android.media.cts.NonMediaMainlineTest;
+import android.media.cts.MediaStubActivity;
+import android.media.cts.Preconditions;
import android.os.Handler;
import android.os.HandlerThread;
import android.platform.test.annotations.AppModeFull;
diff --git a/tests/tests/media/src/android/media/cts/MediaTimestampTest.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaTimestampTest.java
similarity index 93%
rename from tests/tests/media/src/android/media/cts/MediaTimestampTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MediaTimestampTest.java
index 78fd1375..82cad3b 100644
--- a/tests/tests/media/src/android/media/cts/MediaTimestampTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaTimestampTest.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.MediaTimestamp;
+import android.media.cts.NonMediaMainlineTest;
import android.test.AndroidTestCase;
/**
diff --git a/tests/tests/media/src/android/media/cts/MockActivity.java b/tests/tests/media/misc/src/android/media/misc/cts/MockActivity.java
similarity index 95%
rename from tests/tests/media/src/android/media/cts/MockActivity.java
rename to tests/tests/media/misc/src/android/media/misc/cts/MockActivity.java
index 028cfae..0b90cf0 100644
--- a/tests/tests/media/src/android/media/cts/MockActivity.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MockActivity.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.Activity;
diff --git a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java b/tests/tests/media/misc/src/android/media/misc/cts/NativeDecoderTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/NativeDecoderTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/NativeDecoderTest.java
index c0330cb..c79e9bd 100644
--- a/tests/tests/media/src/android/media/cts/NativeDecoderTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/NativeDecoderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -28,6 +28,8 @@
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaPlayer;
+import android.media.cts.MediaTestBase;
+import android.media.cts.Preconditions;
import android.media.cts.TestUtils.Monitor;
import android.net.Uri;
import android.os.Build;
@@ -88,7 +90,7 @@
static {
// Load jni on initialization.
Log.i("@@@", "before loadlibrary");
- System.loadLibrary("ctsmediacodec_jni");
+ System.loadLibrary("ctsmediamisc_jni");
Log.i("@@@", "after loadlibrary");
}
diff --git a/tests/tests/media/src/android/media/cts/NativeImageReaderTest.java b/tests/tests/media/misc/src/android/media/misc/cts/NativeImageReaderTest.java
similarity index 95%
rename from tests/tests/media/src/android/media/cts/NativeImageReaderTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/NativeImageReaderTest.java
index 5de309a..17be6e5 100644
--- a/tests/tests/media/src/android/media/cts/NativeImageReaderTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/NativeImageReaderTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
@@ -32,7 +32,7 @@
/** Load jni on initialization */
static {
Log.i("NativeImageReaderTest", "before loadlibrary");
- System.loadLibrary("ctsimagereader_jni");
+ System.loadLibrary("ctsmediamisc_jni");
Log.i("NativeImageReaderTest", "after loadlibrary");
}
diff --git a/tests/tests/media/src/android/media/cts/ParamsTest.java b/tests/tests/media/misc/src/android/media/misc/cts/ParamsTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/ParamsTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ParamsTest.java
index adbad8d..69b3032 100644
--- a/tests/tests/media/src/android/media/cts/ParamsTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ParamsTest.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
-
-import android.media.cts.R;
+package android.media.misc.cts;
import android.media.PlaybackParams;
import android.media.SyncParams;
diff --git a/tests/tests/media/src/android/media/cts/PlaybackStateTest.java b/tests/tests/media/misc/src/android/media/misc/cts/PlaybackStateTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/PlaybackStateTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/PlaybackStateTest.java
index d8b4aec..1b07854 100644
--- a/tests/tests/media/src/android/media/cts/PlaybackStateTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/PlaybackStateTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
diff --git a/tests/tests/media/src/android/media/cts/PresentationSyncTest.java b/tests/tests/media/misc/src/android/media/misc/cts/PresentationSyncTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/PresentationSyncTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/PresentationSyncTest.java
index 25d6adb..1d0bd0c 100644
--- a/tests/tests/media/src/android/media/cts/PresentationSyncTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/PresentationSyncTest.java
@@ -14,13 +14,16 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.opengl.GLES20;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Trace;
+import android.media.cts.InputSurface;
+import android.media.cts.MediaStubActivity;
+import android.media.cts.NonMediaMainlineTest;
import android.platform.test.annotations.AppModeFull;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.Suppress;
diff --git a/tests/tests/media/src/android/media/cts/RatingTest.java b/tests/tests/media/misc/src/android/media/misc/cts/RatingTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/RatingTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/RatingTest.java
index 4b8857a..9b6975a 100644
--- a/tests/tests/media/src/android/media/cts/RatingTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/RatingTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.Rating.RATING_3_STARS;
import static android.media.Rating.RATING_4_STARS;
@@ -32,6 +32,7 @@
import android.media.Rating;
import android.os.Parcel;
+import android.media.cts.NonMediaMainlineTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
diff --git a/tests/tests/media/src/android/media/cts/RemoteControllerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/RemoteControllerTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/RemoteControllerTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/RemoteControllerTest.java
index a7d9f72..4eaa04a 100644
--- a/tests/tests/media/src/android/media/cts/RemoteControllerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/RemoteControllerTest.java
@@ -14,11 +14,12 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.Context;
import android.media.RemoteController;
import android.media.RemoteController.OnClientUpdateListener;
+import android.media.cts.NonMediaMainlineTest;
import android.platform.test.annotations.AppModeFull;
import android.test.InstrumentationTestCase;
import android.test.UiThreadTest;
diff --git a/tests/tests/media/src/android/media/cts/RemoteService.java b/tests/tests/media/misc/src/android/media/misc/cts/RemoteService.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/RemoteService.java
rename to tests/tests/media/misc/src/android/media/misc/cts/RemoteService.java
index 0d98251..357d241 100644
--- a/tests/tests/media/src/android/media/cts/RemoteService.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/RemoteService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertTrue;
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerStubActivity.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/ResourceManagerStubActivity.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java
index 5595800..1503cd1 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerStubActivity.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerStubActivity.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.Activity;
import android.content.Context;
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
similarity index 92%
rename from tests/tests/media/src/android/media/cts/ResourceManagerTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
index 115701b..5a9575f 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.os.Bundle;
import android.platform.test.annotations.AppModeFull;
@@ -30,13 +30,13 @@
extends ActivityInstrumentationTestCase2<ResourceManagerStubActivity> {
public ResourceManagerTest() {
- super("android.media.cts", ResourceManagerStubActivity.class);
+ super("android.media.misc.cts", ResourceManagerStubActivity.class);
}
private void doTestReclaimResource(int type1, int type2) throws Exception {
Bundle extras = new Bundle();
ResourceManagerStubActivity activity = launchActivity(
- "android.media.cts", ResourceManagerStubActivity.class, extras);
+ "android.media.misc.cts", ResourceManagerStubActivity.class, extras);
activity.testReclaimResource(type1, type2);
activity.finish();
}
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity1.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivity1.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/ResourceManagerTestActivity1.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivity1.java
index a11d773..b1f1178 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity1.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivity1.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivity2.java
similarity index 96%
rename from tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivity2.java
index ea0567f..b725e62 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivity2.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivity2.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.Activity;
import android.os.Bundle;
diff --git a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivityBase.java b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/ResourceManagerTestActivityBase.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
index 76c7b0f..664fba4 100644
--- a/tests/tests/media/src/android/media/cts/ResourceManagerTestActivityBase.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ResourceManagerTestActivityBase.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.app.Activity;
import android.media.MediaCodec;
diff --git a/tests/tests/media/src/android/media/cts/RouteDiscoveryPreferenceTest.java b/tests/tests/media/misc/src/android/media/misc/cts/RouteDiscoveryPreferenceTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/RouteDiscoveryPreferenceTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/RouteDiscoveryPreferenceTest.java
index 2891d4a..68a5725 100644
--- a/tests/tests/media/src/android/media/cts/RouteDiscoveryPreferenceTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/RouteDiscoveryPreferenceTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -23,6 +23,7 @@
import static org.testng.Assert.assertThrows;
import android.media.RouteDiscoveryPreference;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Parcel;
import org.junit.Test;
diff --git a/tests/tests/media/src/android/media/cts/RoutingSessionInfoTest.java b/tests/tests/media/misc/src/android/media/misc/cts/RoutingSessionInfoTest.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/RoutingSessionInfoTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/RoutingSessionInfoTest.java
index 3ff5e24..17b0774 100644
--- a/tests/tests/media/src/android/media/cts/RoutingSessionInfoTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/RoutingSessionInfoTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
@@ -25,6 +25,7 @@
import static org.testng.Assert.assertThrows;
import android.media.RoutingSessionInfo;
+import android.media.cts.NonMediaMainlineTest;
import android.os.Bundle;
import android.os.Parcel;
diff --git a/tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java b/tests/tests/media/misc/src/android/media/misc/cts/ScannerNotificationReceiver.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ScannerNotificationReceiver.java
index 9d91671..bdc89b2 100644
--- a/tests/tests/media/src/android/media/cts/ScannerNotificationReceiver.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ScannerNotificationReceiver.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.BroadcastReceiver;
import android.content.Context;
diff --git a/tests/tests/media/src/android/media/cts/Session2CommandGroupTest.java b/tests/tests/media/misc/src/android/media/misc/cts/Session2CommandGroupTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/Session2CommandGroupTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/Session2CommandGroupTest.java
index 988ea87..c6239fb 100644
--- a/tests/tests/media/src/android/media/cts/Session2CommandGroupTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/Session2CommandGroupTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/tests/tests/media/src/android/media/cts/Session2CommandTest.java b/tests/tests/media/misc/src/android/media/misc/cts/Session2CommandTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/Session2CommandTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/Session2CommandTest.java
index 91de258..36a22bc 100644
--- a/tests/tests/media/src/android/media/cts/Session2CommandTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/Session2CommandTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
diff --git a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java b/tests/tests/media/misc/src/android/media/misc/cts/StubMediaBrowserService.java
similarity index 99%
rename from tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
rename to tests/tests/media/misc/src/android/media/misc/cts/StubMediaBrowserService.java
index f9ec34c..f96adfc 100644
--- a/tests/tests/media/src/android/media/cts/StubMediaBrowserService.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/StubMediaBrowserService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.annotation.NonNull;
import android.media.MediaDescription;
diff --git a/tests/tests/media/src/android/media/cts/StubMediaRoute2ProviderService.java b/tests/tests/media/misc/src/android/media/misc/cts/StubMediaRoute2ProviderService.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/StubMediaRoute2ProviderService.java
rename to tests/tests/media/misc/src/android/media/misc/cts/StubMediaRoute2ProviderService.java
index efe4859..b9d17e8 100644
--- a/tests/tests/media/src/android/media/cts/StubMediaRoute2ProviderService.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/StubMediaRoute2ProviderService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
@@ -69,8 +69,8 @@
public static final String ROUTE_ID_VARIABLE_VOLUME = "route_variable_volume";
public static final String ROUTE_NAME_VARIABLE_VOLUME = "Variable Volume Route";
- public static final String FEATURE_SAMPLE = "android.media.cts.FEATURE_SAMPLE";
- public static final String FEATURE_SPECIAL = "android.media.cts.FEATURE_SPECIAL";
+ public static final String FEATURE_SAMPLE = "android.media.misc.cts.FEATURE_SAMPLE";
+ public static final String FEATURE_SPECIAL = "android.media.misc.cts.FEATURE_SPECIAL";
public static final List<String> FEATURES_ALL = new ArrayList();
public static final List<String> FEATURES_SPECIAL = new ArrayList();
diff --git a/tests/tests/media/src/android/media/cts/StubMediaSession2Service.java b/tests/tests/media/misc/src/android/media/misc/cts/StubMediaSession2Service.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/StubMediaSession2Service.java
rename to tests/tests/media/misc/src/android/media/misc/cts/StubMediaSession2Service.java
index 687910c..852a0fe 100644
--- a/tests/tests/media/src/android/media/cts/StubMediaSession2Service.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/StubMediaSession2Service.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.MediaSession2;
import android.media.MediaSession2.ControllerInfo;
diff --git a/tests/tests/media/src/android/media/cts/SubtitleDataTest.java b/tests/tests/media/misc/src/android/media/misc/cts/SubtitleDataTest.java
similarity index 94%
rename from tests/tests/media/src/android/media/cts/SubtitleDataTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/SubtitleDataTest.java
index 9cd4144..d2b6686 100644
--- a/tests/tests/media/src/android/media/cts/SubtitleDataTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/SubtitleDataTest.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.SubtitleData;
+import android.media.cts.NonMediaMainlineTest;
import android.test.AndroidTestCase;
import java.nio.charset.StandardCharsets;
diff --git a/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/SystemMediaRouter2Test.java
similarity index 97%
rename from tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
rename to tests/tests/media/misc/src/android/media/misc/cts/SystemMediaRouter2Test.java
index 3623f15..4126daf 100644
--- a/tests/tests/media/src/android/media/cts/SystemMediaRouter2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/SystemMediaRouter2Test.java
@@ -14,20 +14,20 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static android.content.Context.AUDIO_SERVICE;
import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
-import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
-import static android.media.cts.StubMediaRoute2ProviderService.FEATURE_SPECIAL;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID3_SESSION_CREATION_FAILED;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_ID_VARIABLE_VOLUME;
-import static android.media.cts.StubMediaRoute2ProviderService.ROUTE_NAME2;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURE_SAMPLE;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.FEATURE_SPECIAL;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID1;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID2;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID3_SESSION_CREATION_FAILED;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID4_TO_SELECT_AND_DESELECT;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID5_TO_TRANSFER_TO;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_ID_VARIABLE_VOLUME;
+import static android.media.misc.cts.StubMediaRoute2ProviderService.ROUTE_NAME2;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -50,6 +50,7 @@
import android.media.MediaRouter2Manager;
import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
+import android.media.cts.NonMediaMainlineTest;
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.LargeTest;
import android.text.TextUtils;
diff --git a/tests/tests/media/src/android/media/cts/TestProxyFileDescriptorCallback.java b/tests/tests/media/misc/src/android/media/misc/cts/TestProxyFileDescriptorCallback.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/TestProxyFileDescriptorCallback.java
rename to tests/tests/media/misc/src/android/media/misc/cts/TestProxyFileDescriptorCallback.java
index 0bc0215..b0d1032 100644
--- a/tests/tests/media/src/android/media/cts/TestProxyFileDescriptorCallback.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/TestProxyFileDescriptorCallback.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.content.res.AssetFileDescriptor;
import android.os.ProxyFileDescriptorCallback;
diff --git a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java b/tests/tests/media/misc/src/android/media/misc/cts/ThumbnailUtilsTest.java
similarity index 98%
rename from tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/ThumbnailUtilsTest.java
index 6fdf955..afca910 100644
--- a/tests/tests/media/src/android/media/cts/ThumbnailUtilsTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/ThumbnailUtilsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -24,6 +24,7 @@
import android.graphics.Color;
import static android.media.MediaFormat.MIMETYPE_VIDEO_HEVC;
import android.media.ThumbnailUtils;
+import android.media.cts.Preconditions;
import android.os.Build;
import android.platform.test.annotations.AppModeFull;
import android.util.Size;
diff --git a/tests/tests/media/src/android/media/cts/TimedMetaDataTest.java b/tests/tests/media/misc/src/android/media/misc/cts/TimedMetaDataTest.java
similarity index 94%
rename from tests/tests/media/src/android/media/cts/TimedMetaDataTest.java
rename to tests/tests/media/misc/src/android/media/misc/cts/TimedMetaDataTest.java
index 1e4d035..a14f933 100644
--- a/tests/tests/media/src/android/media/cts/TimedMetaDataTest.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/TimedMetaDataTest.java
@@ -14,9 +14,10 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.TimedMetaData;
+import android.media.cts.NonMediaMainlineTest;
import android.test.AndroidTestCase;
import java.nio.charset.StandardCharsets;
diff --git a/tests/tests/media/src/android/media/cts/WorkDir.java b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
similarity index 88%
rename from tests/tests/media/src/android/media/cts/WorkDir.java
rename to tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
index d29b810..0c39229 100644
--- a/tests/tests/media/src/android/media/cts/WorkDir.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/WorkDir.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media.cts;
+package android.media.misc.cts;
import android.media.cts.WorkDirBase;
class WorkDir extends WorkDirBase {
public static final String getMediaDirString() {
- return getMediaDirString("CtsMediaTestCases-1.4");
+ return getMediaDirString("CtsMediaMiscTestCases-1.0");
}
}
diff --git a/tests/tests/media/muxer/src/android/media/muxer/cts/MediaMuxerTest.java b/tests/tests/media/muxer/src/android/media/muxer/cts/MediaMuxerTest.java
index 972685a..c9e12fb 100644
--- a/tests/tests/media/muxer/src/android/media/muxer/cts/MediaMuxerTest.java
+++ b/tests/tests/media/muxer/src/android/media/muxer/cts/MediaMuxerTest.java
@@ -49,7 +49,7 @@
public class MediaMuxerTest extends AndroidTestCase {
private static final String TAG = "MediaMuxerTest";
private static final boolean VERBOSE = false;
- private static final int MAX_SAMPLE_SIZE = 256 * 1024;
+ private static final int MAX_SAMPLE_SIZE = 1024 * 1024;
private static final float LATITUDE = 0.0000f;
private static final float LONGITUDE = -180.0f;
private static final float BAD_LATITUDE = 91.0f;
@@ -83,6 +83,44 @@
}
/**
+ * Test: make sure the muxer handles dovi profile 8.4 video track only file correctly.
+ */
+ // TODO(b/216824291) Enable once extractor issue is fixed
+ public void SKIP_testDolbyVisionVideoOnlyP8() throws Exception {
+ final String source = "video_dovi_1920x1080_60fps_dvhe_08_04.mp4";
+ String outputFilePath = File.createTempFile("MediaMuxerTest_dolbyvisionP8videoOnly", ".mp4")
+ .getAbsolutePath();
+ try {
+ cloneAndVerify(source, outputFilePath, 2 /* expectedTrackCount */, 180 /* degrees */,
+ MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
+ MediaMuxerTest::filterOutNonDolbyVisionFormat);
+ } finally {
+ new File(outputFilePath).delete();
+ }
+ }
+
+ /**
+ * Test: make sure the muxer handles dovi profile 9.2 video track only file correctly.
+ */
+ public void testDolbyVisionVideoOnlyP9() throws Exception {
+ final String source = "video_dovi_1920x1080_60fps_dvav_09_02.mp4";
+ String outputFilePath = File.createTempFile("MediaMuxerTest_dolbyvisionP9videoOnly", ".mp4")
+ .getAbsolutePath();
+ try {
+ cloneAndVerify(source, outputFilePath, 2 /* expectedTrackCount */, 180 /* degrees */,
+ MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4,
+ MediaMuxerTest::filterOutNonDolbyVisionFormat);
+ } finally {
+ new File(outputFilePath).delete();
+ }
+ }
+
+ private static MediaFormat filterOutNonDolbyVisionFormat(MediaFormat format) {
+ String mime = format.getString(MediaFormat.KEY_MIME);
+ return mime.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION) ? format : null;
+ }
+
+ /**
* Test: makes sure if audio and video muxing using MPEG4Writer works well when there are frame
* drops as in b/63590381 and b/64949961 while B Frames encoding is enabled.
*/
@@ -433,6 +471,19 @@
*/
private void cloneAndVerify(final String srcMedia, String outputMediaFile,
int expectedTrackCount, int degrees, int fmt) throws IOException {
+ cloneAndVerify(srcMedia, outputMediaFile, expectedTrackCount, degrees, fmt,
+ Function.identity());
+ }
+
+ /**
+ * Clones a given file using MediaMuxer and verifies the output matches the input.
+ *
+ * <p>See {@link #cloneMediaUsingMuxer} for information about the parameters.
+ */
+ private void cloneAndVerify(final String srcMedia, String outputMediaFile,
+ int expectedTrackCount, int degrees, int fmt,
+ Function<MediaFormat, MediaFormat> muxerInputTrackFormatTransformer)
+ throws IOException {
try {
cloneMediaUsingMuxer(
srcMedia,
@@ -440,7 +491,7 @@
expectedTrackCount,
degrees,
fmt,
- Function.identity());
+ muxerInputTrackFormatTransformer);
if (fmt == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4 ||
fmt == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
verifyAttributesMatch(srcMedia, outputMediaFile, degrees);
@@ -454,7 +505,21 @@
}
}
- /** Using the MediaMuxer to clone a media file. */
+
+ /**
+ * Clones a given file using MediaMuxer.
+ *
+ * @param srcMedia Input file path passed to extractor
+ * @param dstMediaPath Output file path passed to muxer
+ * @param expectedTrackCount Expected number of tracks in the input file
+ * @param degrees orientation hint in degrees
+ * @param fmt one of the values defined in {@link MediaMuxer.OutputFormat}.
+ * @param muxerInputTrackFormatTransformer Function applied on the MediaMuxer input formats.
+ * If the function returns null for a given MediaFormat,
+ * the corresponding track is discarded and not passed
+ * to MediaMuxer.
+ * @throws IOException if muxer failed to open output file for write.
+ */
private void cloneMediaUsingMuxer(
final String srcMedia,
String dstMediaPath,
@@ -479,10 +544,13 @@
// Set up the tracks.
HashMap<Integer, Integer> indexMap = new HashMap<Integer, Integer>(trackCount);
for (int i = 0; i < trackCount; i++) {
- extractor.selectTrack(i);
MediaFormat format = extractor.getTrackFormat(i);
- int dstIndex = muxer.addTrack(muxerInputTrackFormatTransformer.apply(format));
- indexMap.put(i, dstIndex);
+ MediaFormat muxedFormat = muxerInputTrackFormatTransformer.apply(format);
+ if (muxedFormat != null) {
+ extractor.selectTrack(i);
+ int dstIndex = muxer.addTrack(muxedFormat);
+ indexMap.put(i, dstIndex);
+ }
}
// Copy the samples from MediaExtractor to MediaMuxer.
diff --git a/tests/tests/media/player/AndroidManifest.xml b/tests/tests/media/player/AndroidManifest.xml
index 050868a..2896da2 100644
--- a/tests/tests/media/player/AndroidManifest.xml
+++ b/tests/tests/media/player/AndroidManifest.xml
@@ -19,10 +19,12 @@
android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.CAMERA"/>
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
diff --git a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerRandomTest.java b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerRandomTest.java
index abecaf8..9060bd46 100644
--- a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerRandomTest.java
+++ b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerRandomTest.java
@@ -42,9 +42,10 @@
@MediaHeavyPresubmitTest
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class MediaPlayerRandomTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+ private static final int MAX_PARAM = 1000000;
private static final String TAG = "MediaPlayerRandomTest";
- static final String mInpPrefix = WorkDir.getMediaDirString();
+ private static final String mInpPrefix = WorkDir.getMediaDirString();
private static final int NUMBER_OF_PLAYER_RANDOM_ACTIONS = 100000;
@@ -146,9 +147,10 @@
watchDog.start();
for (int i = 0; i < NUMBER_OF_PLAYER_RANDOM_ACTIONS; i++) {
- int action = r.nextInt() % 12;
- int param = r.nextInt() % 1000000;
- Log.d(TAG, "Action: " + action + " Param: " + param);
+ int action = r.nextInt(12);
+ int param1 = r.nextInt(MAX_PARAM);
+ int param2 = r.nextInt(MAX_PARAM);
+ Log.d(TAG, "Action: " + action + " Param1: " + param1 + " Param2: " + param2);
watchDog.reset();
assertTrue(!mMediaServerDied);
@@ -180,20 +182,20 @@
mPlayer.prepareAsync();
break;
case 7:
- mPlayer.seekTo((int) (param));
+ mPlayer.seekTo(param1);
break;
case 8:
- mPlayer.setLooping(param % 2 == 0);
+ mPlayer.setLooping(param1 % 2 == 0);
break;
case 9:
- mPlayer.setVolume((param % 1000) / 500.0f,
- (param / 1000) / 500.0f);
+ mPlayer.setVolume((param1 * 2.0f) / MAX_PARAM,
+ (param2 * 2.0f) / MAX_PARAM);
break;
case 10:
mPlayer.start();
break;
case 11:
- Thread.sleep(param % 20);
+ Thread.sleep(param1 % 20);
break;
}
} catch (Exception e) {
diff --git a/tests/tests/media/recorder/AndroidManifest.xml b/tests/tests/media/recorder/AndroidManifest.xml
index fdfb196..28ddf67 100644
--- a/tests/tests/media/recorder/AndroidManifest.xml
+++ b/tests/tests/media/recorder/AndroidManifest.xml
@@ -21,7 +21,8 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INSTANT_APP_FOREGROUND_SERVICE"/>
-
+ <uses-permission android:name="android.permission.CAMERA"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
diff --git a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderRandomTest.java b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderRandomTest.java
index d1376ed..06f3b8f 100644
--- a/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderRandomTest.java
+++ b/tests/tests/media/recorder/src/android/media/recorder/cts/MediaRecorderRandomTest.java
@@ -40,7 +40,7 @@
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class MediaRecorderRandomTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
private static final String TAG = "MediaRecorderRandomTest";
-
+ private static final int MAX_PARAM = 1000000;
private static final String OUTPUT_FILE =
Environment.getExternalStorageDirectory().toString() + "/record.3gp";
@@ -115,7 +115,7 @@
watchDog.start();
for (int i = 0; i < NUMBER_OF_RECORDER_RANDOM_ACTIONS; i++) {
int action = r.nextInt(14);
- int param = r.nextInt(1000000);
+ int param = r.nextInt(MAX_PARAM);
Log.d(TAG, "Action: " + action + " Param: " + param);
watchDog.reset();
@@ -132,9 +132,9 @@
break;
}
case 1:
- // XXX:
- // Fix gralloc source and change
- // mRecorder.setVideoSource(param % 3);
+ // Limiting the random test to test default and camera source
+ // and not include video surface as required setInputSurface isn't
+ // done in this test.
mRecorder.setVideoSource(param % 2);
break;
case 2:
@@ -154,7 +154,7 @@
mRecorder.setVideoSize(width[index], height[index]);
break;
case 7:
- mRecorder.setVideoFrameRate(param % 40 - 5);
+ mRecorder.setVideoFrameRate((param % 40) - 1);
break;
case 8:
mRecorder.setOutputFile(OUTPUT_FILE);
diff --git a/tests/tests/nativehardware/jni/Android.bp b/tests/tests/nativehardware/jni/Android.bp
index 8ad2b05..bf88b12 100644
--- a/tests/tests/nativehardware/jni/Android.bp
+++ b/tests/tests/nativehardware/jni/Android.bp
@@ -19,6 +19,9 @@
cc_library_shared {
name: "libahardwarebuffertest",
compile_multilib: "both",
+ tidy_timeout_srcs: [
+ "AHardwareBufferGLTest.cpp",
+ ],
srcs: [
"AHardwareBufferGLTest.cpp",
"AHardwareBufferTest.cpp",
diff --git a/tests/tests/net/native/src/TagSocketTest.cpp b/tests/tests/net/native/src/TagSocketTest.cpp
index 9826747..75d83d5 100644
--- a/tests/tests/net/native/src/TagSocketTest.cpp
+++ b/tests/tests/net/native/src/TagSocketTest.cpp
@@ -87,22 +87,17 @@
uint64_t cookie = getSocketCookie(sock);
EXPECT_NE(NONEXISTENT_COOKIE, cookie);
- // TODO(b/214338829): Uncomment lines that check tagging result from BPF map when the
- // connectivity service is in charge of dumping BPF maps. Currently, it
- // doesn't work because BPF maps are dumped by netd. The shell does not have
- // permission to find netd service in user build. So, it only verify API
- // return codes for now.
- // EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
+ EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
EXPECT_EQ(0, android_tag_socket(sock, TEST_TAG));
- // EXPECT_TRUE(socketIsTagged(mBinder, cookie, geteuid(), TEST_TAG));
+ EXPECT_TRUE(socketIsTagged(mBinder, cookie, geteuid(), TEST_TAG));
EXPECT_EQ(0, android_untag_socket(sock));
- // EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
+ EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
EXPECT_EQ(0, android_tag_socket_with_uid(sock, TEST_TAG, TEST_UID));
- // EXPECT_TRUE(socketIsTagged(mBinder, cookie, TEST_UID, TEST_TAG));
+ EXPECT_TRUE(socketIsTagged(mBinder, cookie, TEST_UID, TEST_TAG));
EXPECT_EQ(0, android_untag_socket(sock));
- // EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
+ EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
}
TEST_F(TagSocketTest, TagSocketErrors) {
@@ -113,7 +108,7 @@
// Untag an untagged socket.
EXPECT_EQ(-ENOENT, android_untag_socket(sock));
- // EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
+ EXPECT_TRUE(socketIsNotTagged(mBinder, cookie));
// Untag a closed socket.
close(sock);
diff --git a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
index e240809..a35ff16 100644
--- a/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
+++ b/tests/tests/os/UffdGc/jni/android_os_cts_uffdgc_UserfaultfdTest.cc
@@ -227,6 +227,7 @@
extern "C"
JNIEXPORT jint JNICALL Java_android_os_cts_uffdgc_UserfaultfdTest_performMinorUffd(JNIEnv*) {
+ uint64_t req_features;
int ret = 0;
int uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
if (uffd < 0) {
@@ -236,15 +237,15 @@
struct uffdio_api api;
std::memset(&api, '\0', sizeof api);
api.api = UFFD_API;
- // TODO: Remove the following define once its definition is available in
- // linux/userfaultfd.h header file.
-#ifndef UFFD_FEATURE_MINOR_SHMEM
-#define UFFD_FEATURE_MINOR_SHMEM (1 << 10)
-#endif
- api.features = UFFD_FEATURE_MINOR_SHMEM;
+ req_features = UFFD_FEATURE_MINOR_SHMEM;
+ api.features = req_features;
if (ioctl(uffd, UFFDIO_API, &api) < 0) {
ret = errno;
}
+ // Minor feature is not supported by this kernel.
+ if ((api.features & req_features) != req_features) {
+ ret = -EINVAL;
+ }
close(uffd);
out:
return ret;
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index b1688d2..69d020b 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -56,7 +56,7 @@
// Time to find a notification. Unlikely, but in cases with a lot of notifications, it may take
// time to find the notification we're looking for
const val NOTIF_FIND_TIMEOUT = 20000L
-const val VIEW_WAIT_TIMEOUT = 1000L
+const val VIEW_WAIT_TIMEOUT = 3000L
const val CMD_EXPAND_NOTIFICATIONS = "cmd statusbar expand-notifications"
const val CMD_COLLAPSE = "cmd statusbar collapse"
diff --git a/tests/tests/os/src/android/os/cts/BuildTest.java b/tests/tests/os/src/android/os/cts/BuildTest.java
index 94e4ee4..2aedad2 100644
--- a/tests/tests/os/src/android/os/cts/BuildTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildTest.java
@@ -35,6 +35,7 @@
import java.util.Scanner;
import java.util.Set;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public class BuildTest extends TestCase {
@@ -281,12 +282,21 @@
assertTrue(TYPE_PATTERN.matcher(Build.TYPE).matches());
assertNotEmpty(Build.USER);
+ }
+ /**
+ * Tests that check for valid values of codenames related constants.
+ */
+ public void testBuildCodenameConstants() {
// CUR_DEVELOPMENT must be larger than any released version.
Field[] fields = Build.VERSION_CODES.class.getDeclaredFields();
- List<String> codenames = Arrays.asList(ACTIVE_CODENAMES);
+ List<String> activeCodenames = Arrays.asList(ACTIVE_CODENAMES);
// Make the codenames uppercase to match the field names.
- codenames.replaceAll(String::toUpperCase);
+ activeCodenames.replaceAll(String::toUpperCase);
+ Set<String> knownCodenames = Build.VERSION.KNOWN_CODENAMES.stream()
+ .map(String::toUpperCase)
+ .collect(Collectors.toSet());
+ HashSet<String> declaredCodenames = new HashSet<>();
for (Field field : fields) {
if (field.getType().equals(int.class) && Modifier.isStatic(field.getModifiers())) {
String fieldName = field.getName();
@@ -296,22 +306,45 @@
} catch (IllegalAccessException e) {
throw new AssertionError(e.getMessage());
}
+ declaredCodenames.add(fieldName);
if (fieldName.equals("CUR_DEVELOPMENT")) {
// It should be okay to change the value of this constant in future, but it
// should at least be a conscious decision.
assertEquals(10000, fieldValue);
- } else if (codenames.contains(fieldName)) {
- // This is the current development version. Note that fieldName can
- // become < CUR_DEVELOPMENT before CODENAME becomes "REL", so we
- // can't assertEquals(CUR_DEVELOPMENT, fieldValue) here.
- assertTrue("Expected " + fieldName + " value to be <= " + CUR_DEVELOPMENT
- + ", got " + fieldValue, fieldValue <= CUR_DEVELOPMENT);
} else {
- assertTrue("Expected " + fieldName + " value to be < " + CUR_DEVELOPMENT
- + ", got " + fieldValue, fieldValue < CUR_DEVELOPMENT);
+ if (activeCodenames.contains(fieldName)) {
+ // This is the current development version. Note that fieldName can
+ // become < CUR_DEVELOPMENT before CODENAME becomes "REL", so we
+ // can't assertEquals(CUR_DEVELOPMENT, fieldValue) here.
+ assertTrue("Expected " + fieldName + " value to be <= " + CUR_DEVELOPMENT
+ + ", got " + fieldValue, fieldValue <= CUR_DEVELOPMENT);
+ } else {
+ assertTrue("Expected " + fieldName + " value to be < " + CUR_DEVELOPMENT
+ + ", got " + fieldValue, fieldValue < CUR_DEVELOPMENT);
+ }
+ // KNOWN_CODENAMES only tracks Q+ codenames
+ if (fieldValue >= Build.VERSION_CODES.Q) {
+ // Remove all underscores to match build level codenames, e.g. S_V2 is Sv2.
+ String name = fieldName.replaceAll("_", "");
+ declaredCodenames.add(name);
+ assertTrue("Expected " + name
+ + " to be declared in Build.VERSION.KNOWN_CODENAMES",
+ knownCodenames.contains(name));
+ }
}
}
}
+
+ HashSet<String> diff = new HashSet<>(knownCodenames);
+ diff.removeAll(declaredCodenames);
+ assertTrue(
+ "Expected all elements in Build.VERSION.KNOWN_CODENAMES to be declared in"
+ + " Build.VERSION_CODES, found " + diff, diff.isEmpty());
+
+ if (!Build.VERSION.CODENAME.equals("REL")) {
+ assertTrue("In-development CODENAME must be declared in Build.VERSION.KNOWN_CODENAMES",
+ Build.VERSION.KNOWN_CODENAMES.contains(Build.VERSION.CODENAME));
+ }
}
/**
diff --git a/tests/tests/os/src/android/os/cts/BundleTest.java b/tests/tests/os/src/android/os/cts/BundleTest.java
index 8c91216..27d5643 100644
--- a/tests/tests/os/src/android/os/cts/BundleTest.java
+++ b/tests/tests/os/src/android/os/cts/BundleTest.java
@@ -62,6 +62,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertFalse;
@@ -552,6 +553,30 @@
assertBundleEquals(bundle, (Bundle) mBundle.getParcelable(KEY1));
}
+ @Test
+ public void testGetParcelableTypeSafe_withMismatchingType_returnsNull() {
+ mBundle.putParcelable(KEY1, new CustomParcelable(42, "don't panic"));
+ roundtrip();
+ assertNull(mBundle.getParcelable(KEY1, Intent.class));
+ assertFalse(CustomParcelable.sDeserialized);
+ }
+
+ @Test
+ public void testGetParcelableTypeSafe_withMatchingType_returnsObject() {
+ final CustomParcelable original = new CustomParcelable(42, "don't panic");
+ mBundle.putParcelable(KEY1, original);
+ roundtrip();
+ assertEquals(original, mBundle.getParcelable(KEY1, CustomParcelable.class));
+ }
+
+ @Test
+ public void testGetParcelableTypeSafe_withBaseType_returnsObject() {
+ final CustomParcelable original = new CustomParcelable(42, "don't panic");
+ mBundle.putParcelable(KEY1, original);
+ roundtrip();
+ assertEquals(original, mBundle.getParcelable(KEY1, Parcelable.class));
+ }
+
// getParcelableArray should only return the ParcelableArray set by putParcelableArray
@Test
public void testGetParcelableArray() {
@@ -572,6 +597,38 @@
assertBundleEquals(bundle2, (Bundle) parcelableArray[1]);
}
+ @Test
+ public void testGetParcelableArrayTypeSafe_withMismatchingType_returnsNull() {
+ mBundle.putParcelableArray(KEY1, new CustomParcelable[] {
+ new CustomParcelable(42, "don't panic")
+ });
+ roundtrip();
+ assertNull(mBundle.getParcelableArray(KEY1, Intent.class));
+ assertFalse(CustomParcelable.sDeserialized);
+ }
+
+ @Test
+ public void testGetParcelableArrayTypeSafe_withMatchingType_returnsObject() {
+ final CustomParcelable[] original = new CustomParcelable[] {
+ new CustomParcelable(42, "don't panic"),
+ new CustomParcelable(1961, "off we go")
+ };
+ mBundle.putParcelableArray(KEY1, original);
+ roundtrip();
+ assertArrayEquals(original, mBundle.getParcelableArray(KEY1, CustomParcelable.class));
+ }
+
+ @Test
+ public void testGetParcelableArrayTypeSafe_withBaseType_returnsObject() {
+ final CustomParcelable[] original = new CustomParcelable[] {
+ new CustomParcelable(42, "don't panic"),
+ new CustomParcelable(1961, "off we go")
+ };
+ mBundle.putParcelableArray(KEY1, original);
+ roundtrip();
+ assertArrayEquals(original, mBundle.getParcelableArray(KEY1, Parcelable.class));
+ }
+
// getParcelableArrayList should only return the parcelableArrayList set by putParcelableArrayList
@Test
public void testGetParcelableArrayList() {
@@ -594,6 +651,60 @@
}
@Test
+ public void testGetParcelableArrayListTypeSafe_withMismatchingType_returnsNull() {
+ final ArrayList<CustomParcelable> originalObjects = new ArrayList<>();
+ originalObjects.add(new CustomParcelable(42, "don't panic"));
+ mBundle.putParcelableArrayList(KEY1, originalObjects);
+ roundtrip();
+ assertNull(mBundle.getParcelableArrayList(KEY1, Intent.class));
+ assertFalse(CustomParcelable.sDeserialized);
+ }
+
+ @Test
+ public void testGetParcelableArrayListTypeSafe_withMatchingType_returnsObject() {
+ final ArrayList<CustomParcelable> original = new ArrayList<>();
+ original.add(new CustomParcelable(42, "don't panic"));
+ original.add(new CustomParcelable(1961, "off we go"));
+ mBundle.putParcelableArrayList(KEY1, original);
+ roundtrip();
+ assertEquals(original, mBundle.getParcelableArrayList(KEY1, CustomParcelable.class));
+ }
+
+ @Test
+ public void testGetParcelableArrayListTypeSafe_withBaseType_returnsObject() {
+ final ArrayList<CustomParcelable> original = new ArrayList<>();
+ original.add(new CustomParcelable(42, "don't panic"));
+ original.add(new CustomParcelable(1961, "off we go"));
+ mBundle.putParcelableArrayList(KEY1, original);
+ roundtrip();
+ assertEquals(original, mBundle.getParcelableArrayList(KEY1, Parcelable.class));
+ }
+
+ @Test
+ public void testGetSerializableTypeSafe_withMismatchingType_returnsNull() {
+ mBundle.putSerializable(KEY1, new CustomSerializable());
+ roundtrip();
+ assertNull(mBundle.getSerializable(KEY1, AnotherSerializable.class));
+ assertFalse(CustomSerializable.sDeserialized);
+ }
+
+ @Test
+ public void testGetSerializableTypeSafe_withMatchingType_returnsObject() {
+ mBundle.putSerializable(KEY1, new CustomSerializable());
+ roundtrip();
+ assertNotNull(mBundle.getSerializable(KEY1, CustomSerializable.class));
+ assertTrue(CustomSerializable.sDeserialized);
+ }
+
+ @Test
+ public void testGetSerializableTypeSafe_withBaseType_returnsObject() {
+ mBundle.putSerializable(KEY1, new CustomSerializable());
+ roundtrip();
+ assertNotNull(mBundle.getSerializable(KEY1, Serializable.class));
+ assertTrue(CustomSerializable.sDeserialized);
+ }
+
+ @Test
public void testGetSerializableWithString() {
assertNull(mBundle.getSerializable(KEY1));
String s = "android";
@@ -695,6 +806,49 @@
}
@Test
+ public void testGetSparseParcelableArrayTypeSafe_withMismatchingType_returnsNull() {
+ final SparseArray<CustomParcelable> originalObjects = new SparseArray<>();
+ originalObjects.put(42, new CustomParcelable(42, "don't panic"));
+ mBundle.putSparseParcelableArray(KEY1, originalObjects);
+ roundtrip();
+ assertNull(mBundle.getSparseParcelableArray(KEY1, Intent.class));
+ assertFalse(CustomParcelable.sDeserialized);
+ }
+
+ @Test
+ public void testGetSparseParcelableArrayTypeSafe_withMatchingType_returnsObject() {
+ final SparseArray<CustomParcelable> original = new SparseArray<>();
+ original.put(42, new CustomParcelable(42, "don't panic"));
+ original.put(1961, new CustomParcelable(1961, "off we go"));
+ mBundle.putSparseParcelableArray(KEY1, original);
+ roundtrip();
+ assertTrue(original.contentEquals(mBundle.getSparseParcelableArray(KEY1, CustomParcelable.class)));
+ }
+
+ @Test
+ public void testGetSparseParcelableArrayTypeSafe_withBaseType_returnsObject() {
+ final SparseArray<CustomParcelable> original = new SparseArray<>();
+ original.put(42, new CustomParcelable(42, "don't panic"));
+ original.put(1961, new CustomParcelable(1961, "off we go"));
+ mBundle.putSparseParcelableArray(KEY1, original);
+ roundtrip();
+ assertTrue(original.contentEquals(mBundle.getSparseParcelableArray(KEY1, Parcelable.class)));
+ }
+
+ @Test
+ public void testGetSparseParcelableArrayTypeSafe_withMixedTypes_returnsObject() {
+ final SparseArray<Parcelable> original = new SparseArray<>();
+ original.put(42, new CustomParcelable(42, "don't panic"));
+ original.put(1961, new Intent("action"));
+ mBundle.putSparseParcelableArray(KEY1, original);
+ roundtrip();
+ final SparseArray<Parcelable> received = mBundle.getSparseParcelableArray(KEY1, Parcelable.class);
+ assertEquals(original.size(), received.size());
+ assertEquals(original.get(42), received.get(42));
+ assertIntentEquals((Intent) original.get(1961), (Intent) received.get(1961));
+ }
+
+ @Test
public void testGetString() {
assertNull(mBundle.getString(KEY1));
mBundle.putString(KEY1, "android");
@@ -1338,6 +1492,9 @@
}
}
+ private static class AnotherSerializable implements Serializable {
+ }
+
private static class CustomParcelable implements Parcelable {
public static boolean sDeserialized = false;
@@ -1540,4 +1697,4 @@
throw new AssertionError(e);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/os/src/android/os/cts/ParcelTest.java b/tests/tests/os/src/android/os/cts/ParcelTest.java
index a0ad68e..2261fbe 100644
--- a/tests/tests/os/src/android/os/cts/ParcelTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelTest.java
@@ -3614,6 +3614,10 @@
p.writeFixedArray(ints, 0, new int[]{2, 3});
p.setDataPosition(0);
assertArrayEquals(ints, p.createFixedArray(int[][].class, new int[]{2, 3}));
+ int[][] readInts = new int[2][3];
+ p.setDataPosition(0);
+ p.readFixedArray(readInts);
+ assertArrayEquals(ints, readInts);
// test Parcelable[2][3]
p.setDataPosition(0);
@@ -3623,6 +3627,10 @@
p.writeFixedArray(signatures, 0, new int[]{2, 3});
p.setDataPosition(0);
assertArrayEquals(signatures, p.createFixedArray(Signature[][].class, Signature.CREATOR, new int[]{2, 3}));
+ Signature[][] readSignatures = new Signature[2][3];
+ p.setDataPosition(0);
+ p.readFixedArray(readSignatures, Signature.CREATOR);
+ assertArrayEquals(signatures, readSignatures);
// test IInterface[2][3]
p.setDataPosition(0);
@@ -3635,6 +3643,10 @@
MockIInterface::asInterface, new int[]{2, 3});
assertEquals(2, interfacesRead.length);
assertEquals(3, interfacesRead[0].length);
+ MockIInterface[][] mockInterfaces = new MockIInterface[2][3];
+ p.setDataPosition(0);
+ p.readFixedArray(mockInterfaces, MockIInterface::asInterface);
+ assertArrayEquals(interfaces, mockInterfaces);
// test null
p.setDataPosition(0);
diff --git a/tests/tests/permission/OWNERS b/tests/tests/permission/OWNERS
index d401f0d..6b28459 100644
--- a/tests/tests/permission/OWNERS
+++ b/tests/tests/permission/OWNERS
@@ -8,4 +8,5 @@
per-file NoAudioPermissionTest.java = elaurent@google.com
per-file MainlineNetworkStackPermissionTest.java = file: platform/frameworks/base:/services/net/OWNERS
per-file Camera2PermissionTest.java = file: platform/frameworks/av:/camera/OWNERS
-per-file NoRollbackPermissionTest.java = mpgroover@google.com
\ No newline at end of file
+per-file NoRollbackPermissionTest.java = mpgroover@google.com
+per-file EthernetManagerPermissionTest.java = file: platform/frameworks/base:/services/net/OWNERS
\ No newline at end of file
diff --git a/tests/tests/permission/src/android/permission/cts/EthernetManagerPermissionTest.java b/tests/tests/permission/src/android/permission/cts/EthernetManagerPermissionTest.java
new file mode 100644
index 0000000..069162e
--- /dev/null
+++ b/tests/tests/permission/src/android/permission/cts/EthernetManagerPermissionTest.java
@@ -0,0 +1,157 @@
+/*
+ * 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.permission.cts;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.net.EthernetManager;
+import android.net.EthernetNetworkUpdateRequest;
+import android.net.IpConfiguration;
+import android.net.NetworkCapabilities;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+
+/**
+ * Test protected android.net.EthernetManager methods cannot be called without permissions.
+ */
+@RunWith(AndroidJUnit4.class)
+public class EthernetManagerPermissionTest {
+ private static final String TEST_IFACE = "test123abc789";
+ private EthernetManager mEthernetManager;
+ private Context mContext;
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mEthernetManager = mContext.getSystemService(EthernetManager.class);
+ // mEthernetManager may be null depending on the device's configuration.
+ assumeNotNull(mEthernetManager);
+ }
+
+ private void callUpdateConfiguration() {
+ final IpConfiguration ipConfig = new IpConfiguration.Builder().build();
+ final NetworkCapabilities networkCapabilities =
+ new NetworkCapabilities.Builder().build();
+ final EthernetNetworkUpdateRequest request =
+ new EthernetNetworkUpdateRequest.Builder()
+ .setIpConfiguration(ipConfig)
+ .setNetworkCapabilities(networkCapabilities)
+ .build();
+ mEthernetManager.updateConfiguration(TEST_IFACE, request, null, null);
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#updateConfiguration(String,
+ * EthernetNetworkUpdateRequest, Executor, BiConsumer)} requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#MANAGE_ETHERNET_NETWORKS}.
+ */
+ @Test
+ public void testUpdateConfiguration() {
+ assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call updateConfiguration without permission",
+ SecurityException.class, () -> callUpdateConfiguration());
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#connectNetwork(String, Executor, BiConsumer)}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#MANAGE_ETHERNET_NETWORKS}.
+ */
+ @Test
+ public void testConnectNetwork() {
+ assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call connectNetwork without permission",
+ SecurityException.class,
+ () -> mEthernetManager.connectNetwork(TEST_IFACE, null, null));
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#disconnectNetwork(String, Executor, BiConsumer)}
+ * requires permissions.
+ * <p>Tests Permission:
+ * {@link android.Manifest.permission#MANAGE_ETHERNET_NETWORKS}.
+ */
+ @Test
+ public void testDisconnectNetwork() {
+ assumeTrue(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call disconnectNetwork without permission",
+ SecurityException.class,
+ () -> mEthernetManager.disconnectNetwork(TEST_IFACE, null, null));
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#updateConfiguration(
+ * String, EthernetNetworkUpdateRequest, Executor, BiConsumer)} requires automotive feature.
+ * <p>Tests Feature:
+ * {@link PackageManager#FEATURE_AUTOMOTIVE}.
+ */
+ @Test
+ public void testUpdateConfigurationHasAutomotiveFeature() {
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call updateConfiguration without automotive feature",
+ UnsupportedOperationException.class, () -> callUpdateConfiguration());
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#connectNetwork(String, Executor, BiConsumer)}
+ * requires automotive feature.
+ * <p>Tests Feature:
+ * {@link PackageManager#FEATURE_AUTOMOTIVE}.
+ */
+ @Test
+ public void testConnectNetworkHasAutomotiveFeature() {
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call connectNetwork without automotive feature",
+ UnsupportedOperationException.class,
+ () -> mEthernetManager.connectNetwork(TEST_IFACE, null, null));
+ }
+
+ /**
+ * Verify that calling {@link EthernetManager#disconnectNetwork(String, Executor, BiConsumer)}
+ * requires automotive feature.
+ * <p>Tests Feature:
+ * {@link PackageManager#FEATURE_AUTOMOTIVE}.
+ */
+ @Test
+ public void testDisconnectNetworkHasAutomotiveFeature() {
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE));
+ assertThrows("Should not be able to call disconnectNetwork without automotive feature",
+ UnsupportedOperationException.class,
+ () -> mEthernetManager.disconnectNetwork(TEST_IFACE, null, null));
+ }
+}
diff --git a/tests/tests/selinux/selinuxTargetSdk30/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdk30/src/android/security/SELinuxTargetSdkTest.java
index 64e40ff..279f9e6 100644
--- a/tests/tests/selinux/selinuxTargetSdk30/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdk30/src/android/security/SELinuxTargetSdkTest.java
@@ -49,6 +49,10 @@
checkNetlinkRouteGetneigh(true);
}
+ public void testNoHardwareAddress() throws Exception {
+ checkNetworkInterfaceHardwareAddress_returnsNull();
+ }
+
public void testCanNotExecuteFromHomeDir() throws Exception {
assertFalse(canExecuteFromHomeDir());
}
diff --git a/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java b/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
index 93d92e5..3e01ec1 100644
--- a/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
+++ b/tests/tests/selinux/selinuxTargetSdkCurrent/src/android/security/SELinuxTargetSdkTest.java
@@ -45,6 +45,10 @@
checkNetlinkRouteGetneigh(false);
}
+ public void testNoHardwareAddress() throws Exception {
+ checkNetworkInterfaceHardwareAddress_returnsNull();
+ }
+
public void testCanNotExecuteFromHomeDir() throws Exception {
assertFalse(canExecuteFromHomeDir());
}
diff --git a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionTest.java b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionTest.java
index 29beb99..b7c05b7 100644
--- a/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/SelfManagedConnectionTest.java
@@ -195,7 +195,6 @@
control.checkBindStatus(true /* bindStatus */);
connection.waitOnInCallServiceTrackingChanged();
- assertTrue(connection.isTracked());
assertTrue(connection.isAlternativeUiShowing());
connection.disconnectAndDestroy();
diff --git a/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl b/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl
index 2529ada..71924a2 100644
--- a/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl
+++ b/tests/tests/telephony/current/TestExternalImsServiceApp/aidl/android/telephony/cts/externalimsservice/ITestExternalImsService.aidl
@@ -29,4 +29,5 @@
boolean isRcsFeatureCreated();
boolean isMmTelFeatureCreated();
void resetState();
+ boolean isTelephonyBound();
}
diff --git a/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java b/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java
index 9101ae51..eaeb6d1 100644
--- a/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java
+++ b/tests/tests/telephony/current/TestExternalImsServiceApp/src/android/telephony/cts/externalimsservice/TestExternalImsService.java
@@ -29,7 +29,7 @@
*/
public class TestExternalImsService extends TestImsService {
- private static final String TAG = "GtsImsTestDeviceImsService";
+ private static final String TAG = "CtsImsTestDeviceImsService";
// TODO: Use ImsService.SERVICE_INTERFACE definition when it becomes public.
private static final String ACTION_BIND_IMS_SERVICE = "android.telephony.ims.ImsService";
@@ -56,19 +56,26 @@
public void resetState() {
TestExternalImsService.this.resetState();
}
+
+ public boolean isTelephonyBound() {
+ return TestExternalImsService.this.isTelephonyBound();
+ }
}
@Override
public IBinder onBind(Intent intent) {
- if (ACTION_BIND_IMS_SERVICE.equals(intent.getAction())) {
- if (ImsUtils.VDBG) {
- Log.i(TAG, "onBind-Remote");
+ synchronized (mLock) {
+ if (ACTION_BIND_IMS_SERVICE.equals(intent.getAction())) {
+ if (ImsUtils.VDBG) {
+ Log.i(TAG, "onBind-Remote");
+ }
+ mIsTelephonyBound = true;
+ return super.onBind(intent);
}
- return super.onBind(intent);
+ if (ImsUtils.VDBG) {
+ Log.i(TAG, "onBind-Local");
+ }
+ return mBinder;
}
- if (ImsUtils.VDBG) {
- Log.i(TAG, "onBind-Local");
- }
- return mBinder;
}
}
diff --git a/tests/tests/telephony/current/assets/mock_sim_tw_cht.xml b/tests/tests/telephony/current/assets/mock_sim_tw_cht.xml
new file mode 100644
index 0000000..aaabe62
--- /dev/null
+++ b/tests/tests/telephony/current/assets/mock_sim_tw_cht.xml
@@ -0,0 +1,28 @@
+<MockSim numofapp="2" iccid="89886920042507847155">
+<MockSimProfile id="0" type="APPTYPE_USIM">
+ <PinProfile appstate="APPSTATE_READY">
+ <Pin1State>PINSTATE_DISABLED</Pin1State>
+ <Pin2State>PINSTATE_ENABLED_NOT_VERIFIED</Pin2State>
+ </PinProfile>
+
+ <FacilityLock>
+ <FD>LOCK_DISABLED</FD>
+ <SC>LOCK_DISABLED</SC>
+ </FacilityLock>
+
+ <MF name="MF" path="3F00">
+ <EFDIR name="ADF1" curr_active="true">A0000000871002F886FF9289050B00FE</EFDIR>
+ </MF>
+
+ <ADF aid="A0000000871002F886FF9289050B00FE">
+ <EF name="EF_IMSI" id="6F07">311740123456789</EF>
+ </ADF>
+</MockSimProfile>
+
+<MockSimProfile id="1" type="APPTYPE_ISIM">
+ <PinProfile appstate="APPSTATE_DETECTED">
+ <Pin1State>PINSTATE_DISABLED</Pin1State>
+ <Pin2State>PINSTATE_ENABLED_NOT_VERIFIED</Pin2State>
+ </PinProfile>
+</MockSimProfile>
+</MockSim>
\ No newline at end of file
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/CellLocationTest.java b/tests/tests/telephony/current/src/android/telephony/cts/CellLocationTest.java
index fc97d48..871e378 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/CellLocationTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/CellLocationTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.Looper;
import android.net.ConnectivityManager;
import android.telephony.CellLocation;
@@ -40,6 +41,7 @@
private boolean mOnCellLocationChangedCalled;
private final Object mLock = new Object();
private TelephonyManager mTelephonyManager;
+ private PackageManager mPackageManager;
private PhoneStateListener mListener;
private static ConnectivityManager mCm;
private static final String TAG = "android.telephony.cts.CellLocationTest";
@@ -49,6 +51,7 @@
mTelephonyManager =
(TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE);
mCm = (ConnectivityManager)getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ mPackageManager = getContext().getPackageManager();
}
@After
@@ -61,8 +64,8 @@
@Test
public void testCellLocation() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java b/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java
index 8a9f241..08980a3 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/IRadioSimImpl.java
@@ -27,8 +27,11 @@
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
+import android.telephony.cts.MockSimService.SimAppData;
import android.util.Log;
+import java.util.ArrayList;
+
public class IRadioSimImpl extends IRadioSim.Stub {
private static final String TAG = "MRSIM";
@@ -42,10 +45,12 @@
// ***** Events
static final int EVENT_SIM_CARD_STATUS_CHANGED = 1;
+ static final int EVENT_SIM_APP_DATA_CHANGED = 2;
// ***** Cache of modem attributes/status
private int mNumOfLogicalSim;
private CardStatus mCardStatus;
+ private ArrayList<SimAppData> mSimAppList;
public IRadioSimImpl(
MockModemService service, MockModemConfigInterface[] interfaces, int instanceId) {
@@ -62,6 +67,10 @@
// Register events
sMockModemConfigInterfaces[mSubId].registerForCardStatusChanged(
mHandler, EVENT_SIM_CARD_STATUS_CHANGED, null);
+
+ // Register events
+ sMockModemConfigInterfaces[mSubId].registerForSimAppDataChanged(
+ mHandler, EVENT_SIM_APP_DATA_CHANGED, null);
}
/** Handler class to handle callbacks */
@@ -82,6 +91,21 @@
Log.e(TAG, msg.what + " failure. Exception: " + ar.exception);
}
break;
+
+ case EVENT_SIM_APP_DATA_CHANGED:
+ Log.d(TAG, "Received EVENT_SIM_APP_DATA_CHANGED");
+ ar = (AsyncResult) msg.obj;
+ if (ar != null && ar.exception == null) {
+ mSimAppList = (ArrayList<SimAppData>) ar.result;
+ if (mSimAppList != null) {
+ Log.i(TAG, "number of SIM app data: " + mSimAppList.size());
+ } else {
+ Log.e(TAG, "mSimAppList = null");
+ }
+ } else {
+ Log.e(TAG, msg.what + " failure. Exception: " + ar.exception);
+ }
+ break;
}
}
}
@@ -213,13 +237,49 @@
public void getFacilityLockForApp(
int serial, String facility, String password, int serviceClass, String appId) {
Log.d(TAG, "getFacilityLockForApp");
+ int numOfSimApp = mSimAppList.size();
+ int responseError = RadioError.NONE;
+ int simAppIdx;
+ boolean isHandled = false;
+ boolean isFacilitySupport = true;
+ int responseData = -1;
- // TODO: cache value
- int response = 0;
+ // TODO: check service class
+ for (simAppIdx = 0;
+ simAppIdx < numOfSimApp && isFacilitySupport && !isHandled;
+ simAppIdx++) {
+ switch (facility) {
+ case "FD": // FDN status query
+ if (appId.equals(mSimAppList.get(simAppIdx).getAid())) {
+ responseData = mSimAppList.get(simAppIdx).getFdnStatus();
+ isHandled = true;
+ }
+ break;
+ case "SC": // PIN1 status query
+ if (appId.equals(mSimAppList.get(simAppIdx).getAid())) {
+ responseData = mSimAppList.get(simAppIdx).getPin1State();
+ isHandled = true;
+ }
+ break;
+ default:
+ isFacilitySupport = false;
+ break;
+ }
+ }
- RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
+ if (!isHandled) {
+ Log.e(TAG, "Not support sim application aid = " + appId);
+ responseError = RadioError.NO_SUCH_ELEMENT;
+ } else if (!isFacilitySupport) {
+ Log.e(TAG, "Not support facility = " + facility);
+ responseError = RadioError.REQUEST_NOT_SUPPORTED;
+ } else if (responseData == -1) {
+ responseError = RadioError.INTERNAL_ERR;
+ }
+
+ RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
try {
- mRadioSimResponse.getFacilityLockForAppResponse(rsp, response);
+ mRadioSimResponse.getFacilityLockForAppResponse(rsp, responseData);
} catch (RemoteException ex) {
Log.e(TAG, "Failed to getFacilityLockForApp from AIDL. Exception" + ex);
}
@@ -245,10 +305,25 @@
@Override
public void getImsiForApp(int serial, String aid) {
Log.d(TAG, "getImsiForApp");
- // TODO: cache value
String imsi = "";
+ int numOfSimApp = mSimAppList.size();
+ int responseError = RadioError.NONE;
+ int simAppIdx;
+ boolean isHandled;
- RadioResponseInfo rsp = mService.makeSolRsp(serial, RadioError.REQUEST_NOT_SUPPORTED);
+ for (simAppIdx = 0, isHandled = false; simAppIdx < numOfSimApp && !isHandled; simAppIdx++) {
+ if (aid.equals(mSimAppList.get(simAppIdx).getAid())) {
+ imsi = mSimAppList.get(simAppIdx).getImsi();
+ isHandled = true;
+ }
+ }
+
+ if (!isHandled) {
+ Log.e(TAG, "Not support sim application aid = " + aid);
+ responseError = RadioError.NO_SUCH_ELEMENT;
+ }
+
+ RadioResponseInfo rsp = mService.makeSolRsp(serial, responseError);
try {
mRadioSimResponse.getImsiForAppResponse(rsp, imsi);
} catch (RemoteException ex) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigBase.java b/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigBase.java
index 6a8731d..a77dd66 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigBase.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigBase.java
@@ -20,13 +20,17 @@
import android.hardware.radio.config.PhoneCapability;
import android.hardware.radio.config.SimPortInfo;
import android.hardware.radio.config.SimSlotStatus;
+import android.hardware.radio.config.SlotPortMapping;
import android.hardware.radio.sim.CardStatus;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.RegistrantList;
+import android.telephony.cts.MockSimService.SimAppData;
import android.util.Log;
+import java.util.ArrayList;
+
public class MockModemConfigBase implements MockModemConfigInterface {
// ***** Instance Variables
private static final int DEFAULT_SUB_ID = 0;
@@ -41,7 +45,7 @@
// ***** Events
static final int EVENT_SET_RADIO_POWER = 1;
- static final int EVENT_SET_SIM_PRESENT = 2;
+ static final int EVENT_CHANGE_SIM_PROFILE = 2;
// ***** Modem config values
private String mBasebandVersion = MockModemConfigInterface.DEFAULT_BASEBAND_VERSION;
@@ -53,8 +57,10 @@
private byte mNumOfLiveModem = MockModemConfigInterface.DEFAULT_NUM_OF_LIVE_MODEM;
private SimSlotStatus[] mSimSlotStatus;
private CardStatus mCardStatus;
- private MockSimCard[] mSIMCard;
+ private int mFdnStatus;
+ private MockSimService[] mSimService;
private PhoneCapability mPhoneCapability = new PhoneCapability();
+ private ArrayList<SimAppData> mSimAppList;
// ***** RegistrantLists
// ***** IRadioConfig RegistrantLists
@@ -69,6 +75,7 @@
// ***** IRadioSim RegistrantLists
private RegistrantList mCardStatusChangedRegistrants = new RegistrantList();
+ private RegistrantList mSimAppDataChangedRegistrants = new RegistrantList();
public MockModemConfigBase(Context context, int instanceId, int numOfSim, int numOfPhone) {
mContext = context;
@@ -86,7 +93,7 @@
mHandler = new MockModemConfigHandler();
mSimSlotStatus = new SimSlotStatus[mNumOfSim];
mCardStatus = new CardStatus();
- mSIMCard = new MockSimCard[mNumOfSim];
+ mSimService = new MockSimService[mNumOfSim];
mSimPhyicalId = mSubId; // for default mapping
createSIMCards();
setDefaultConfigValue();
@@ -118,21 +125,24 @@
mRadioStateChangedRegistrants.notifyRegistrants(null);
}
break;
- case EVENT_SET_SIM_PRESENT:
- boolean isPresent = msg.getData().getBoolean("isPresent", false);
- Log.d(mTAG, "EVENT_SET_SIM_PRESENT: " + (isPresent ? "Present" : "Absent"));
- int newCardState =
- isPresent ? CardStatus.STATE_PRESENT : CardStatus.STATE_ABSENT;
- if (mSubId == DEFAULT_SUB_ID
- && mSimSlotStatus[mSimPhyicalId].cardState != newCardState) {
- mSimSlotStatus[mSimPhyicalId].cardState = newCardState;
- mSimSlotStatusChangedRegistrants.notifyRegistrants(
- new AsyncResult(null, mSimSlotStatus, null));
- }
- if (mCardStatus.cardState != newCardState) {
- mCardStatus.cardState = newCardState;
+ case EVENT_CHANGE_SIM_PROFILE:
+ int simprofileid =
+ msg.getData()
+ .getInt(
+ "changeSimProfile",
+ MockSimService.MOCK_SIM_PROFILE_ID_DEFAULT);
+ Log.d(mTAG, "EVENT_CHANGE_SIM_PROFILE: sim profile(" + simprofileid + ")");
+ if (loadSIMCard(simprofileid)) {
+ if (mSubId == DEFAULT_SUB_ID) {
+ mSimSlotStatusChangedRegistrants.notifyRegistrants(
+ new AsyncResult(null, mSimSlotStatus, null));
+ }
mCardStatusChangedRegistrants.notifyRegistrants(
new AsyncResult(null, mCardStatus, null));
+ mSimAppDataChangedRegistrants.notifyRegistrants(
+ new AsyncResult(null, mSimAppList, null));
+ } else {
+ Log.e(mTAG, "Load Sim card failed.");
}
break;
}
@@ -151,9 +161,9 @@
mNumOfLiveModem = MockModemConfigInterface.DEFAULT_NUM_OF_LIVE_MODEM;
setDefaultPhoneCapability(mPhoneCapability);
if (mSubId == DEFAULT_SUB_ID) {
- setDefaultSimSlotStatus();
+ updateSimSlotStatus();
}
- setDefaultCardStatus();
+ updateCardStatus();
}
}
@@ -171,59 +181,84 @@
private void createSIMCards() {
for (int i = 0; i < mNumOfSim; i++) {
- mSIMCard[i] = new MockSimCard(i);
+ mSimService[i] = new MockSimService(mContext, i);
}
}
- private void setDefaultSimSlotStatus() {
+ private void updateSimSlotStatus() {
if (mSubId != DEFAULT_SUB_ID) {
// Only sub 0 needs to response SimSlotStatus
return;
}
+ if (mSimService == null) {
+ Log.e(mTAG, "SIM service didn't be created yet.");
+ }
+
for (int i = 0; i < mNumOfSim; i++) {
- int portInfoListLen = mSIMCard[i].getNumOfSimPortInfo();
+ if (mSimService[i] == null) {
+ Log.e(mTAG, "SIM service[" + i + "] didn't be created yet.");
+ continue;
+ }
+ int portInfoListLen = mSimService[i].getNumOfSimPortInfo();
mSimSlotStatus[i] = new SimSlotStatus();
mSimSlotStatus[i].cardState =
- mSIMCard[i].isCardPresent()
+ mSimService[i].isCardPresent()
? CardStatus.STATE_PRESENT
: CardStatus.STATE_ABSENT;
- mSimSlotStatus[i].atr = mSIMCard[i].getATR();
- mSimSlotStatus[i].eid = mSIMCard[i].getEID();
- // Current only support one Sim port in MockSimCard
+ mSimSlotStatus[i].atr = mSimService[i].getATR();
+ mSimSlotStatus[i].eid = mSimService[i].getEID();
+ // Current only support one Sim port in MockSimService
SimPortInfo[] portInfoList0 = new SimPortInfo[portInfoListLen];
portInfoList0[0] = new SimPortInfo();
- portInfoList0[0].portActive = mSIMCard[i].isSlotPortActive();
- portInfoList0[0].logicalSlotId = mSIMCard[i].getLogicalSlotId();
- portInfoList0[0].iccId = mSIMCard[i].getICCID();
+ portInfoList0[0].portActive = mSimService[i].isSlotPortActive();
+ portInfoList0[0].logicalSlotId = mSimService[i].getLogicalSlotId();
+ portInfoList0[0].iccId = mSimService[i].getICCID();
mSimSlotStatus[i].portInfo = portInfoList0;
}
}
- private void setDefaultCardStatus() {
- if (mSimPhyicalId != -1) {
- int numbOfSimApp = mSIMCard[mSimPhyicalId].getNumOfSimApp();
+ private void updateCardStatus() {
+ if (mSimPhyicalId != -1 && mSimService != null && mSimService[mSimPhyicalId] != null) {
+ int numOfSimApp = mSimService[mSimPhyicalId].getNumOfSimApp();
mCardStatus = new CardStatus();
mCardStatus.cardState =
- mSIMCard[mSimPhyicalId].isCardPresent()
+ mSimService[mSimPhyicalId].isCardPresent()
? CardStatus.STATE_PRESENT
: CardStatus.STATE_ABSENT;
- mCardStatus.universalPinState = mSIMCard[mSimPhyicalId].getUniversalPinState();
- mCardStatus.gsmUmtsSubscriptionAppIndex = mSIMCard[mSimPhyicalId].getGsmAppIndex();
- mCardStatus.cdmaSubscriptionAppIndex = mSIMCard[mSimPhyicalId].getCdmaAppIndex();
- mCardStatus.imsSubscriptionAppIndex = mSIMCard[mSimPhyicalId].getImsAppIndex();
- mCardStatus.applications = new android.hardware.radio.sim.AppStatus[numbOfSimApp];
- mCardStatus.atr = mSIMCard[mSimPhyicalId].getATR();
- mCardStatus.iccid = mSIMCard[mSimPhyicalId].getICCID();
- mCardStatus.eid = mSIMCard[mSimPhyicalId].getEID();
- mCardStatus.slotMap = new android.hardware.radio.config.SlotPortMapping();
- mCardStatus.slotMap.physicalSlotId = mSIMCard[mSimPhyicalId].getPhysicalSlotId();
- mCardStatus.slotMap.portId = mSIMCard[mSimPhyicalId].getSlotPortId();
+ mCardStatus.universalPinState = mSimService[mSimPhyicalId].getUniversalPinState();
+ mCardStatus.gsmUmtsSubscriptionAppIndex = mSimService[mSimPhyicalId].getGsmAppIndex();
+ mCardStatus.cdmaSubscriptionAppIndex = mSimService[mSimPhyicalId].getCdmaAppIndex();
+ mCardStatus.imsSubscriptionAppIndex = mSimService[mSimPhyicalId].getImsAppIndex();
+ mCardStatus.applications = mSimService[mSimPhyicalId].getSimApp();
+ mCardStatus.atr = mSimService[mSimPhyicalId].getATR();
+ mCardStatus.iccid = mSimService[mSimPhyicalId].getICCID();
+ mCardStatus.eid = mSimService[mSimPhyicalId].getEID();
+ mCardStatus.slotMap = new SlotPortMapping();
+ mCardStatus.slotMap.physicalSlotId = mSimService[mSimPhyicalId].getPhysicalSlotId();
+ mCardStatus.slotMap.portId = mSimService[mSimPhyicalId].getSlotPortId();
+ mSimAppList = mSimService[mSimPhyicalId].getSimAppList();
} else {
- Log.e(mTAG, "Invalid Sim physical id");
+ Log.e(
+ mTAG,
+ "Invalid Sim physical id("
+ + mSimPhyicalId
+ + ") or SIM card didn't be created.");
}
}
+ private boolean loadSIMCard(int simProfileId) {
+ boolean result = false;
+ if (mSimPhyicalId != -1 && mSimService != null && mSimService[mSimPhyicalId] != null) {
+ result = mSimService[mSimPhyicalId].loadSimCard(simProfileId);
+ if (mSubId == DEFAULT_SUB_ID) {
+ updateSimSlotStatus();
+ }
+ updateCardStatus();
+ }
+ return result;
+ }
+
private void notifyDeviceIdentityChangedRegistrants() {
String[] deviceIdentity = new String[4];
synchronized (mConfigAccess) {
@@ -259,6 +294,8 @@
// IRadioSim
mCardStatusChangedRegistrants.notifyRegistrants(
new AsyncResult(null, mCardStatus, null));
+ mSimAppDataChangedRegistrants.notifyRegistrants(
+ new AsyncResult(null, mSimAppList, null));
}
}
@@ -335,6 +372,16 @@
mCardStatusChangedRegistrants.remove(h);
}
+ @Override
+ public void registerForSimAppDataChanged(Handler h, int what, Object obj) {
+ mSimAppDataChangedRegistrants.addUnique(h, what, obj);
+ }
+
+ @Override
+ public void unregisterForSimAppDataChanged(Handler h) {
+ mSimAppDataChangedRegistrants.remove(h);
+ }
+
// ***** IRadioConfig set APIs implementation
// ***** IRadioModem set APIs implementation
@@ -359,11 +406,17 @@
// ***** Helper APIs implementation
@Override
- public void setSimPresent(boolean isPresent, String client) {
- Log.d(mTAG, "setSimPresent (" + (isPresent ? "Present" : "Absent") + ") from: " + client);
+ public boolean isSimCardPresent(String client) {
+ Log.d(mTAG, "isSimCardPresent from: " + client);
+ return (mCardStatus.cardState == CardStatus.STATE_PRESENT) ? true : false;
+ }
- Message msg = mHandler.obtainMessage(EVENT_SET_SIM_PRESENT);
- msg.getData().putBoolean("isPresent", isPresent);
+ @Override
+ public void changeSimProfile(int simprofileid, String client) {
+ Log.d(mTAG, "changeSimProfile: profile id(" + simprofileid + ") from: " + client);
+
+ Message msg = mHandler.obtainMessage(EVENT_CHANGE_SIM_PROFILE);
+ msg.getData().putInt("changeSimProfile", simprofileid);
mHandler.sendMessage(msg);
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigInterface.java b/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigInterface.java
index 5632255..32b2908 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigInterface.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MockModemConfigInterface.java
@@ -84,6 +84,11 @@
void unregisterForCardStatusChanged(Handler h);
+ /** Register/unregister notification handler for sim app data changed */
+ void registerForSimAppDataChanged(Handler h, int what, Object obj);
+
+ void unregisterForSimAppDataChanged(Handler h);
+
/**
* Sets the latest radio power state of modem
*
@@ -93,10 +98,18 @@
void setRadioState(int state, String client);
/**
- * Sets a specific logical SIM state to absent or present
+ * Query whether any SIM cards are present or not.
*
- * @param isPresent true means "present", false means "absent".
+ * @param client for tracking calling client
+ * @return boolean true if any sim card inserted, otherwise false.
+ */
+ boolean isSimCardPresent(String client);
+
+ /**
+ * Change SIM profile
+ *
+ * @param simProfileId The target profile to be switched.
* @param client for tracking calling client
*/
- void setSimPresent(boolean isPresent, String client);
+ void changeSimProfile(int simProfileId, String client);
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockModemManager.java b/tests/tests/telephony/current/src/android/telephony/cts/MockModemManager.java
index 24eaa7a..38e36dd 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/MockModemManager.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MockModemManager.java
@@ -48,6 +48,15 @@
* @return boolean true if the operation is successful, otherwise false.
*/
public boolean connectMockModemService() throws Exception {
+ return connectMockModemService(MockSimService.MOCK_SIM_PROFILE_ID_DEFAULT);
+ }
+ /**
+ * Bring up Mock Modem Service and connect to it.
+ *
+ * @pararm simprofile for initial Sim profile
+ * @return boolean true if the operation is successful, otherwise false.
+ */
+ public boolean connectMockModemService(int simprofile) throws Exception {
boolean result = false;
if (sServiceConnector == null) {
@@ -56,7 +65,8 @@
}
if (sServiceConnector != null) {
- result = sServiceConnector.connectMockModemService();
+ // TODO: support DSDS
+ result = sServiceConnector.connectMockModemService(simprofile);
if (result) {
mMockModemService = sServiceConnector.getMockModemService();
@@ -104,19 +114,62 @@
}
/**
- * Set SIM card status as present.
+ * Query whether an active SIM card is present on this sub or not.
*
- * @param subId which sub needs to be set.
- * @return boolean true if the operation is successful, otherwise false.
+ * @param subId which sub would be checked.
+ * @return boolean true if any sim card inserted, otherwise false.
*/
- public boolean setSimPresent(int subId) throws Exception {
- Log.d(TAG, "setSimPresent[" + subId + "]");
- boolean result = true;
+ public boolean isSimCardPresent(int subId) throws Exception {
+ Log.d(TAG, "isSimCardPresent[" + subId + "]");
MockModemConfigInterface[] configInterfaces =
mMockModemService.getMockModemConfigInterfaces();
- configInterfaces[subId].setSimPresent(true, TAG);
- waitForTelephonyFrameworkDone(1);
+ return configInterfaces[subId].isSimCardPresent(TAG);
+ }
+
+ /**
+ * Insert a SIM card.
+ *
+ * @param subId which sub would insert.
+ * @param simProfileId which carrier sim card is inserted.
+ * @return boolean true if the operation is successful, otherwise false.
+ */
+ public boolean insertSimCard(int subId, int simProfileId) throws Exception {
+ Log.d(TAG, "insertSimCard[" + subId + "] with profile Id(" + simProfileId + ")");
+ boolean result = true;
+
+ if (!isSimCardPresent(subId)) {
+ MockModemConfigInterface[] configInterfaces =
+ mMockModemService.getMockModemConfigInterfaces();
+ configInterfaces[subId].changeSimProfile(simProfileId, TAG);
+ waitForTelephonyFrameworkDone(1);
+ } else {
+ Log.d(TAG, "There is a SIM inserted. Need to remove first.");
+ result = false;
+ }
+ return result;
+ }
+
+ /**
+ * Remove a SIM card.
+ *
+ * @param subId which sub would remove the SIM.
+ * @return boolean true if the operation is successful, otherwise false.
+ */
+ public boolean removeSimCard(int subId) throws Exception {
+ Log.d(TAG, "removeSimCard[" + subId + "]");
+ boolean result = true;
+
+ if (isSimCardPresent(subId)) {
+ MockModemConfigInterface[] configInterfaces =
+ mMockModemService.getMockModemConfigInterfaces();
+ configInterfaces[subId].changeSimProfile(
+ MockSimService.MOCK_SIM_PROFILE_ID_DEFAULT, TAG);
+ waitForTelephonyFrameworkDone(1);
+ } else {
+ Log.d(TAG, "There is no SIM inserted.");
+ result = false;
+ }
return result;
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockModemService.java b/tests/tests/telephony/current/src/android/telephony/cts/MockModemService.java
index 38e7086..741b0e7 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/MockModemService.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MockModemService.java
@@ -233,6 +233,17 @@
int numPhysicalSlots =
sContext.getResources()
.getInteger(com.android.internal.R.integer.config_num_physical_slots);
+ if (numPhysicalSlots > MockSimService.MOCK_SIM_SLOT_MAX) {
+ Log.d(
+ TAG,
+ "Number of physical Slot ("
+ + numPhysicalSlots
+ + ") > mock sim slot support. Reset to max number supported ("
+ + MockSimService.MOCK_SIM_SLOT_MAX
+ + ").");
+ numPhysicalSlots = MockSimService.MOCK_SIM_SLOT_MAX;
+ }
+
return numPhysicalSlots;
}
@@ -254,12 +265,16 @@
return rspInfo;
}
- public boolean initialize() {
- Log.d(TAG, "initialize");
+ public boolean initialize(int simprofile) {
+ Log.d(TAG, "initialize simprofile = " + simprofile);
boolean result = true;
// Sync mock modem status between modules
for (int i = 0; i < mNumOfPhone; i++) {
+ // Set initial SIM profile
+ sMockModemConfigInterfaces[i].changeSimProfile(simprofile, TAG);
+
+ // Sync modem configurations to radio modules
sMockModemConfigInterfaces[i].notifyAllRegistrantNotifications();
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockModemServiceConnector.java b/tests/tests/telephony/current/src/android/telephony/cts/MockModemServiceConnector.java
index beeb720..039a1e1 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/MockModemServiceConnector.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MockModemServiceConnector.java
@@ -186,7 +186,7 @@
*
* @return true if this request succeeded, false otherwise.
*/
- boolean switchFrameworkConnectionToMockModemService() throws Exception {
+ boolean switchFrameworkConnectionToMockModemService(int simprofile) throws Exception {
boolean isComplete = false;
if (overrideModemService()) {
@@ -196,7 +196,8 @@
BIND_RADIO_INTERFACE_READY_TIMEOUT_MS);
if (isComplete) {
- isComplete = mMockModemService.initialize();
+ // TODO: support DSDS
+ isComplete = mMockModemService.initialize(simprofile);
}
}
@@ -211,13 +212,13 @@
return isServiceTheSame(mModemServiceName, serviceName);
}
- boolean connectMockModemService() throws Exception {
+ boolean connectMockModemService(int simprofile) throws Exception {
boolean result = false;
if (!connectMockModemServiceLocally()) return false;
result = checkModemServiceOverridden(getModemService());
if (result) mIsServiceOverridden = true;
- else result = switchFrameworkConnectionToMockModemService();
+ else result = switchFrameworkConnectionToMockModemService(simprofile);
return result;
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockSimCard.java b/tests/tests/telephony/current/src/android/telephony/cts/MockSimCard.java
deleted file mode 100644
index 280b8d5..0000000
--- a/tests/tests/telephony/current/src/android/telephony/cts/MockSimCard.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony.cts;
-
-import android.util.Log;
-
-public class MockSimCard {
- private static final String TAG = "MockSimCard";
-
- /* Support SIM card identify */
- public static final int MOCK_SIM_PROFILE_ID_DEFAULT = 0; // SIM Absent
- public static final int MOCK_SIM_PROFILE_ID_MAX = 1;
-
- /* Support SIM slot */
- private static final int MOCK_SIM_SLOT_1 = 0;
- private static final int MOCK_SIM_SLOT_2 = 1;
- private static final int MOCK_SIM_SLOT_3 = 2;
- private static final int MOCK_SIM_SLOT_MAX = 3;
-
- /* Default value definition */
- private static final int MOCK_SIM_DEFAULT_SLOTID = MOCK_SIM_SLOT_1;
- private static final int DEFAULT_NUM_OF_SIM_PORT_INfO = 1;
- private static final int DEFAULT_NUM_OF_SIM_APP = 0;
- private static final int DEFAULT_GSM_APP_IDX = -1;
- private static final int DEFAULT_CDMA_APP_IDX = -1;
- private static final int DEFAULT_IMS_APP_IDX = -1;
- // SIM1 slot status
- private static final int DEFAULT_SIM1_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
- private static final boolean DEFAULT_SIM1_CARD_PRESENT = false;
- private static final String DEFAULT_SIM1_ATR = "";
- private static final String DEFAULT_SIM1_EID = "";
- private static final String DEFAULT_SIM1_ICCID = "";
- private static final boolean DEFAULT_SIM1_PORT_ACTIVE = true;
- private static final int DEFAULT_SIM1_PORT_ID = 0;
- private static final int DEFAULT_SIM1_LOGICAL_SLOT_ID = 0;
- private static final int DEFAULT_SIM1_PHYSICAL_SLOT_ID = 0;
- private static final int DEFAULT_SIM1_UNIVERSAL_PIN_STATE = 0;
- // SIM2 slot status
- private static final int DEFAULT_SIM2_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
- private static final boolean DEFAULT_SIM2_CARD_PRESENT = false;
- private static final String DEFAULT_SIM2_ATR =
- "3B9F97C00A3FC6828031E073FE211F65D002341512810F51";
- private static final String DEFAULT_SIM2_EID = "89033023426200000000005430099507";
- private static final String DEFAULT_SIM2_ICCID = "";
- private static final boolean DEFAULT_SIM2_PORT_ACTIVE = false;
- private static final int DEFAULT_SIM2_PORT_ID = 0;
- private static final int DEFAULT_SIM2_LOGICAL_SLOT_ID = -1;
- private static final int DEFAULT_SIM2_PHYSICAL_SLOT_ID = 0;
- private static final int DEFAULT_SIM2_UNIVERSAL_PIN_STATE = 0;
- // SIM3 slot status
- private static final int DEFAULT_SIM3_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
- private static final boolean DEFAULT_SIM3_CARD_PRESENT = false;
- private static final String DEFAULT_SIM3_ATR = "";
- private static final String DEFAULT_SIM3_EID = "";
- private static final String DEFAULT_SIM3_ICCID = "";
- private static final boolean DEFAULT_SIM3_PORT_ACTIVE = false;
- private static final int DEFAULT_SIM3_PORT_ID = 0;
- private static final int DEFAULT_SIM3_LOGICAL_SLOT_ID = -1;
- private static final int DEFAULT_SIM3_PHYSICAL_SLOT_ID = 0;
- private static final int DEFAULT_SIM3_UNIVERSAL_PIN_STATE = 0;
-
- // SIM Slot status
- private int mPhysicalSlotId;
- private int mLogicalSlotId;
- private int mSlotPortId;
- private boolean mIsSlotPortActive;
- private boolean mIsCardPresent;
-
- // SIM card data
- private int mSimProfileId;
- private String mICCID;
- private String mEID;
- private String mATR;
- private int mUniversalPinState;
- private int mGsmAppIndex;
- private int mCdmaAppIndex;
- private int mImsAppIndex;
- private int mNumOfSimApp;
-
- public MockSimCard(int slotId) {
- int simprofile = DEFAULT_SIM1_PROFILE_ID;
-
- if (slotId >= MOCK_SIM_SLOT_MAX) {
- Log.e(
- TAG,
- "Invalid slot id("
- + slotId
- + "). Using default slot id("
- + MOCK_SIM_DEFAULT_SLOTID
- + ").");
- slotId = MOCK_SIM_DEFAULT_SLOTID;
- }
-
- // Init default SIM profile id
- switch (slotId) {
- case MOCK_SIM_SLOT_1:
- simprofile = DEFAULT_SIM1_PROFILE_ID;
- break;
- case MOCK_SIM_SLOT_2:
- simprofile = DEFAULT_SIM2_PROFILE_ID;
- break;
- case MOCK_SIM_SLOT_3:
- simprofile = DEFAULT_SIM3_PROFILE_ID;
- break;
- }
-
- // Initiate SIM card with default profile
- initMockSimCard(slotId, simprofile);
- }
-
- private void initMockSimCard(int slotId, int simProfileId) {
- if (slotId > MockModemConfigInterface.MAX_NUM_OF_SIM_SLOT) {
- Log.e(
- TAG,
- "Physical slot id("
- + slotId
- + ") is invalid. Using default slot id("
- + MOCK_SIM_DEFAULT_SLOTID
- + ").");
- mPhysicalSlotId = MOCK_SIM_DEFAULT_SLOTID;
- } else {
- mPhysicalSlotId = slotId;
- }
- if (simProfileId >= 0 && simProfileId < MOCK_SIM_PROFILE_ID_MAX) {
- mSimProfileId = simProfileId;
- Log.i(
- TAG,
- "Load SIM profile ID: "
- + mSimProfileId
- + " into physical slot["
- + mPhysicalSlotId
- + "]");
- } else {
- mSimProfileId = MOCK_SIM_PROFILE_ID_DEFAULT;
- Log.e(
- TAG,
- "SIM Absent on physical slot["
- + mPhysicalSlotId
- + "]. Not support SIM card ID: "
- + mSimProfileId);
- }
-
- // Initiate slot status
- initMockSimSlot();
-
- // Load SIM profile data
- loadMockSimCard();
- }
-
- private void initMockSimSlot() {
- switch (mPhysicalSlotId) {
- case MOCK_SIM_SLOT_1:
- mLogicalSlotId = DEFAULT_SIM1_LOGICAL_SLOT_ID;
- mSlotPortId = DEFAULT_SIM1_PORT_ID;
- mIsSlotPortActive = DEFAULT_SIM1_PORT_ACTIVE;
- mIsCardPresent = DEFAULT_SIM1_CARD_PRESENT;
- break;
- case MOCK_SIM_SLOT_2:
- mLogicalSlotId = DEFAULT_SIM2_LOGICAL_SLOT_ID;
- mSlotPortId = DEFAULT_SIM2_PORT_ID;
- mIsSlotPortActive = DEFAULT_SIM2_PORT_ACTIVE;
- mIsCardPresent = DEFAULT_SIM2_CARD_PRESENT;
- break;
- case MOCK_SIM_SLOT_3:
- mLogicalSlotId = DEFAULT_SIM3_LOGICAL_SLOT_ID;
- mSlotPortId = DEFAULT_SIM3_PORT_ID;
- mIsSlotPortActive = DEFAULT_SIM3_PORT_ACTIVE;
- mIsCardPresent = DEFAULT_SIM3_CARD_PRESENT;
- break;
- }
- }
-
- private void loadMockSimCard() {
- // TODO: Read SIM card data from file
- switch (mSimProfileId) {
- default: // SIM absent
- switch (mPhysicalSlotId) {
- case MOCK_SIM_SLOT_1:
- mICCID = DEFAULT_SIM1_ICCID;
- mATR = DEFAULT_SIM1_ATR;
- mEID = DEFAULT_SIM1_EID;
- mUniversalPinState = DEFAULT_SIM1_UNIVERSAL_PIN_STATE;
- break;
- case MOCK_SIM_SLOT_2:
- mICCID = DEFAULT_SIM2_ICCID;
- mATR = DEFAULT_SIM2_ATR;
- mEID = DEFAULT_SIM2_EID;
- mUniversalPinState = DEFAULT_SIM2_UNIVERSAL_PIN_STATE;
- break;
- case MOCK_SIM_SLOT_3:
- mICCID = DEFAULT_SIM3_ICCID;
- mATR = DEFAULT_SIM3_ATR;
- mEID = DEFAULT_SIM3_EID;
- mUniversalPinState = DEFAULT_SIM3_UNIVERSAL_PIN_STATE;
- break;
- }
- mGsmAppIndex = DEFAULT_GSM_APP_IDX;
- mCdmaAppIndex = DEFAULT_CDMA_APP_IDX;
- mImsAppIndex = DEFAULT_IMS_APP_IDX;
- mNumOfSimApp = DEFAULT_NUM_OF_SIM_APP;
- break;
- }
- }
-
- public boolean isSlotPortActive() {
- return mIsSlotPortActive;
- }
-
- public boolean isCardPresent() {
- return mIsCardPresent;
- }
-
- public int getNumOfSimPortInfo() {
- return DEFAULT_NUM_OF_SIM_PORT_INfO;
- }
-
- public int getPhysicalSlotId() {
- return mPhysicalSlotId;
- }
-
- public int getLogicalSlotId() {
- return mLogicalSlotId;
- }
-
- public int getSlotPortId() {
- return mSlotPortId;
- }
-
- public String getEID() {
- return mEID;
- }
-
- public String getATR() {
- return mATR;
- }
-
- public String getICCID() {
- return mICCID;
- }
-
- public int getUniversalPinState() {
- return mUniversalPinState;
- }
-
- public int getGsmAppIndex() {
- return mGsmAppIndex;
- }
-
- public int getCdmaAppIndex() {
- return mCdmaAppIndex;
- }
-
- public int getImsAppIndex() {
- return mImsAppIndex;
- }
-
- public int getNumOfSimApp() {
- return mNumOfSimApp;
- }
-}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/MockSimService.java b/tests/tests/telephony/current/src/android/telephony/cts/MockSimService.java
new file mode 100644
index 0000000..2e43c54
--- /dev/null
+++ b/tests/tests/telephony/current/src/android/telephony/cts/MockSimService.java
@@ -0,0 +1,827 @@
+/*
+ * 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.telephony.cts;
+
+import android.content.Context;
+import android.hardware.radio.sim.AppStatus;
+import android.hardware.radio.sim.PinState;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+
+public class MockSimService {
+ private static final String TAG = "MockSimService";
+
+ /* Support SIM card identify */
+ public static final int MOCK_SIM_PROFILE_ID_DEFAULT = 0; // SIM Absent
+ public static final int MOCK_SIM_PROFILE_ID_TWN_CHT = 1;
+ public static final int MOCK_SIM_PROFILE_ID_MAX = 2;
+
+ /* SIM profile XML TAG definition */
+ private static final String MOCK_SIM_TAG = "MockSim";
+ private static final String MOCK_SIM_PROFILE_TAG = "MockSimProfile";
+ private static final String MOCK_PIN_PROFILE_TAG = "PinProfile";
+ private static final String MOCK_PIN1_STATE_TAG = "Pin1State";
+ private static final String MOCK_PIN2_STATE_TAG = "Pin2State";
+ private static final String MOCK_FACILITY_LOCK_TAG = "FacilityLock";
+ private static final String MOCK_FACILITY_LOCK_FD_TAG = "FD";
+ private static final String MOCK_FACILITY_LOCK_SC_TAG = "SC";
+ private static final String MOCK_MF_TAG = "MF";
+ private static final String MOCK_EF_TAG = "EF";
+ private static final String MOCK_EF_DIR_TAG = "EFDIR";
+ private static final String MOCK_ADF_TAG = "ADF";
+
+ /* Support SIM slot */
+ private static final int MOCK_SIM_SLOT_1 = 0;
+ private static final int MOCK_SIM_SLOT_2 = 1;
+ private static final int MOCK_SIM_SLOT_3 = 2;
+ public static final int MOCK_SIM_SLOT_MAX = 3;
+
+ /* Default value definition */
+ private static final int MOCK_SIM_DEFAULT_SLOTID = MOCK_SIM_SLOT_1;
+ private static final int DEFAULT_NUM_OF_SIM_PORT_INfO = 1;
+ private static final int DEFAULT_NUM_OF_SIM_APP = 0;
+ private static final int DEFAULT_GSM_APP_IDX = -1;
+ private static final int DEFAULT_CDMA_APP_IDX = -1;
+ private static final int DEFAULT_IMS_APP_IDX = -1;
+ // SIM1 slot status
+ private static final int DEFAULT_SIM1_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
+ private static final boolean DEFAULT_SIM1_CARD_PRESENT = false;
+ private static final String DEFAULT_SIM1_ATR = "";
+ private static final String DEFAULT_SIM1_EID = "";
+ private static final String DEFAULT_SIM1_ICCID = "";
+ private static final boolean DEFAULT_SIM1_PORT_ACTIVE = true;
+ private static final int DEFAULT_SIM1_PORT_ID = 0;
+ private static final int DEFAULT_SIM1_LOGICAL_SLOT_ID = 0;
+ private static final int DEFAULT_SIM1_PHYSICAL_SLOT_ID = 0;
+ private static final int DEFAULT_SIM1_UNIVERSAL_PIN_STATE = 0;
+ // SIM2 slot status
+ private static final int DEFAULT_SIM2_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
+ private static final boolean DEFAULT_SIM2_CARD_PRESENT = false;
+ private static final String DEFAULT_SIM2_ATR =
+ "3B9F97C00A3FC6828031E073FE211F65D002341512810F51";
+ private static final String DEFAULT_SIM2_EID = "89033023426200000000005430099507";
+ private static final String DEFAULT_SIM2_ICCID = "";
+ private static final boolean DEFAULT_SIM2_PORT_ACTIVE = false;
+ private static final int DEFAULT_SIM2_PORT_ID = 0;
+ private static final int DEFAULT_SIM2_LOGICAL_SLOT_ID = -1;
+ private static final int DEFAULT_SIM2_PHYSICAL_SLOT_ID = 0;
+ private static final int DEFAULT_SIM2_UNIVERSAL_PIN_STATE = 0;
+ // SIM3 slot status
+ private static final int DEFAULT_SIM3_PROFILE_ID = MOCK_SIM_PROFILE_ID_DEFAULT;
+ private static final boolean DEFAULT_SIM3_CARD_PRESENT = false;
+ private static final String DEFAULT_SIM3_ATR = "";
+ private static final String DEFAULT_SIM3_EID = "";
+ private static final String DEFAULT_SIM3_ICCID = "";
+ private static final boolean DEFAULT_SIM3_PORT_ACTIVE = false;
+ private static final int DEFAULT_SIM3_PORT_ID = 0;
+ private static final int DEFAULT_SIM3_LOGICAL_SLOT_ID = -1;
+ private static final int DEFAULT_SIM3_PHYSICAL_SLOT_ID = 0;
+ private static final int DEFAULT_SIM3_UNIVERSAL_PIN_STATE = 0;
+
+ private Context mContext;
+
+ // SIM Slot status
+ private int mPhysicalSlotId;
+ private int mLogicalSlotId;
+ private int mSlotPortId;
+ private boolean mIsSlotPortActive;
+ private boolean mIsCardPresent;
+
+ /* SIM profile info */
+ private SimProfileInfo[] mSimProfileInfoList;
+
+ // SIM card data
+ private int mSimProfileId;
+ private String mICCID;
+ private String mEID;
+ private String mATR;
+ private int mUniversalPinState;
+
+ private AppStatus[] mSimApp;
+ private ArrayList<SimAppData> mSimAppList;
+
+ public class SimAppData {
+ private int mSimAppId;
+ private String mAid;
+ private boolean mIsCurrentActive;
+ private String mPath;
+ private int mFdnStatus;
+ private int mPin1State;
+ private String mImsi;
+
+ public SimAppData(int simappid, String aid, String path) {
+ mSimAppId = simappid;
+ mAid = aid;
+ mIsCurrentActive = false;
+ mPath = path;
+ }
+
+ public int getSimAppId() {
+ return mSimAppId;
+ }
+
+ public String getAid() {
+ return mAid;
+ }
+
+ public boolean isCurrentActive() {
+ return mIsCurrentActive;
+ }
+
+ public String getPath() {
+ return mPath;
+ }
+
+ public int getFdnStatus() {
+ return mFdnStatus;
+ }
+
+ public void setFdnStatus(int status) {
+ mFdnStatus = status;
+ }
+
+ public int getPin1State() {
+ return mPin1State;
+ }
+
+ public void setPin1State(int state) {
+ mPin1State = state;
+ }
+
+ public String getImsi() {
+ return mImsi;
+ }
+
+ public void setImsi(String imsi) {
+ mImsi = imsi;
+ }
+ }
+
+ public class SimProfileInfo {
+ private int mSimProfileId;
+ private int mNumOfSimApp;
+ private int mGsmAppIndex;
+ private int mCdmaAppIndex;
+ private int mImsAppIndex;
+ private String mXmlFile;
+
+ public SimProfileInfo(int profileid) {
+ mSimProfileId = profileid;
+ mNumOfSimApp = DEFAULT_NUM_OF_SIM_APP;
+ mGsmAppIndex = DEFAULT_GSM_APP_IDX;
+ mCdmaAppIndex = DEFAULT_CDMA_APP_IDX;
+ mImsAppIndex = DEFAULT_IMS_APP_IDX;
+ mXmlFile = "";
+ }
+
+ public int getNumOfSimApp() {
+ return mNumOfSimApp;
+ }
+
+ public int getGsmAppIndex() {
+ return mGsmAppIndex;
+ }
+
+ public int getCdmaAppIndex() {
+ return mCdmaAppIndex;
+ }
+
+ public int getImsAppIndex() {
+ return mImsAppIndex;
+ }
+
+ public String getXmlFile() {
+ return mXmlFile;
+ }
+
+ public void setNumOfSimApp(int number) {
+ mNumOfSimApp = number;
+ }
+
+ public void setGsmAppIndex(int index) {
+ mGsmAppIndex = index;
+ }
+
+ public void setCdmaAppIndex(int index) {
+ mCdmaAppIndex = index;
+ }
+
+ public void setImsAppIndex(int index) {
+ mImsAppIndex = index;
+ }
+
+ public void setXmlFile(String file) {
+ mXmlFile = file;
+ }
+ }
+
+ public MockSimService(Context context, int slotId) {
+ mContext = context;
+ int simprofile = DEFAULT_SIM1_PROFILE_ID;
+
+ if (slotId >= MOCK_SIM_SLOT_MAX) {
+ Log.e(
+ TAG,
+ "Invalid slot id("
+ + slotId
+ + "). Using default slot id("
+ + MOCK_SIM_DEFAULT_SLOTID
+ + ").");
+ slotId = MOCK_SIM_DEFAULT_SLOTID;
+ }
+
+ // Init default SIM profile id
+ switch (slotId) {
+ case MOCK_SIM_SLOT_1:
+ simprofile = DEFAULT_SIM1_PROFILE_ID;
+ break;
+ case MOCK_SIM_SLOT_2:
+ simprofile = DEFAULT_SIM2_PROFILE_ID;
+ break;
+ case MOCK_SIM_SLOT_3:
+ simprofile = DEFAULT_SIM3_PROFILE_ID;
+ break;
+ }
+
+ // Initial support SIM profile list
+ mSimProfileInfoList = new SimProfileInfo[MOCK_SIM_PROFILE_ID_MAX];
+ for (int idx = 0; idx < MOCK_SIM_PROFILE_ID_MAX; idx++) {
+ Log.d(TAG, "Create sim profile id = " + idx);
+ mSimProfileInfoList[idx] = new SimProfileInfo(idx);
+ switch (idx) {
+ case MOCK_SIM_PROFILE_ID_TWN_CHT:
+ String filename = "mock_sim_tw_cht.xml";
+ mSimProfileInfoList[idx].setXmlFile(filename);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Initiate SIM card with default profile
+ initMockSimCard(slotId, simprofile);
+ }
+
+ private void initMockSimCard(int slotId, int simProfileId) {
+ if (slotId > MockModemConfigInterface.MAX_NUM_OF_SIM_SLOT) {
+ Log.e(
+ TAG,
+ "Physical slot id("
+ + slotId
+ + ") is invalid. Using default slot id("
+ + MOCK_SIM_DEFAULT_SLOTID
+ + ").");
+ mPhysicalSlotId = MOCK_SIM_DEFAULT_SLOTID;
+ } else {
+ mPhysicalSlotId = slotId;
+ }
+ if (simProfileId >= 0 && simProfileId < MOCK_SIM_PROFILE_ID_MAX) {
+ mSimProfileId = simProfileId;
+ Log.i(
+ TAG,
+ "Load SIM profile ID: "
+ + mSimProfileId
+ + " into physical slot["
+ + mPhysicalSlotId
+ + "]");
+ } else {
+ mSimProfileId = MOCK_SIM_PROFILE_ID_DEFAULT;
+ Log.e(
+ TAG,
+ "SIM Absent on physical slot["
+ + mPhysicalSlotId
+ + "]. Not support SIM card ID: "
+ + mSimProfileId);
+ }
+
+ // Initiate slot status
+ initMockSimSlot();
+
+ // Load SIM profile data
+ loadMockSimCard();
+ }
+
+ private void initMockSimSlot() {
+ switch (mPhysicalSlotId) {
+ case MOCK_SIM_SLOT_1:
+ mLogicalSlotId = DEFAULT_SIM1_LOGICAL_SLOT_ID;
+ mSlotPortId = DEFAULT_SIM1_PORT_ID;
+ mIsSlotPortActive = DEFAULT_SIM1_PORT_ACTIVE;
+ mIsCardPresent = DEFAULT_SIM1_CARD_PRESENT;
+ break;
+ case MOCK_SIM_SLOT_2:
+ mLogicalSlotId = DEFAULT_SIM2_LOGICAL_SLOT_ID;
+ mSlotPortId = DEFAULT_SIM2_PORT_ID;
+ mIsSlotPortActive = DEFAULT_SIM2_PORT_ACTIVE;
+ mIsCardPresent = DEFAULT_SIM2_CARD_PRESENT;
+ break;
+ case MOCK_SIM_SLOT_3:
+ mLogicalSlotId = DEFAULT_SIM3_LOGICAL_SLOT_ID;
+ mSlotPortId = DEFAULT_SIM3_PORT_ID;
+ mIsSlotPortActive = DEFAULT_SIM3_PORT_ACTIVE;
+ mIsCardPresent = DEFAULT_SIM3_CARD_PRESENT;
+ break;
+ }
+ }
+
+ private int convertMockSimPinState(String pinstate) {
+ int mocksim_pinstate = PinState.UNKNOWN;
+ switch (pinstate) {
+ case "PINSTATE_UNKNOWN":
+ mocksim_pinstate = PinState.UNKNOWN;
+ break;
+ case "PINSTATE_ENABLED_NOT_VERIFIED":
+ mocksim_pinstate = PinState.ENABLED_NOT_VERIFIED;
+ break;
+ case "PINSTATE_ENABLED_VERIFIED":
+ mocksim_pinstate = PinState.ENABLED_VERIFIED;
+ break;
+ case "PINSTATE_DISABLED":
+ mocksim_pinstate = PinState.DISABLED;
+ break;
+ case "PINSTATE_ENABLED_BLOCKED":
+ mocksim_pinstate = PinState.ENABLED_BLOCKED;
+ break;
+ case "PINSTATE_ENABLED_PERM_BLOCKED":
+ mocksim_pinstate = PinState.ENABLED_PERM_BLOCKED;
+ break;
+ }
+
+ return mocksim_pinstate;
+ }
+
+ private int convertMockSimAppType(String apptype) {
+ int mocksim_apptype = AppStatus.APP_TYPE_UNKNOWN;
+ switch (apptype) {
+ case "APPTYPE_UNKNOWN":
+ mocksim_apptype = AppStatus.APP_TYPE_UNKNOWN;
+ break;
+ case "APPTYPE_SIM":
+ mocksim_apptype = AppStatus.APP_TYPE_SIM;
+ break;
+ case "APPTYPE_USIM":
+ mocksim_apptype = AppStatus.APP_TYPE_USIM;
+ break;
+ case "APPTYPE_RUIM":
+ mocksim_apptype = AppStatus.APP_TYPE_RUIM;
+ break;
+ case "APPTYPE_CSIM":
+ mocksim_apptype = AppStatus.APP_TYPE_CSIM;
+ break;
+ case "APPTYPE_ISIM":
+ mocksim_apptype = AppStatus.APP_TYPE_ISIM;
+ break;
+ }
+
+ return mocksim_apptype;
+ }
+
+ private int convertMockSimAppState(String appstate) {
+ int mocksim_appstate = AppStatus.APP_STATE_UNKNOWN;
+ switch (appstate) {
+ case "APPSTATE_UNKNOWN":
+ mocksim_appstate = AppStatus.APP_STATE_UNKNOWN;
+ break;
+ case "APPSTATE_DETECTED":
+ mocksim_appstate = AppStatus.APP_STATE_DETECTED;
+ break;
+ case "APPSTATE_PIN":
+ mocksim_appstate = AppStatus.APP_STATE_PIN;
+ break;
+ case "APPSTATE_PUK":
+ mocksim_appstate = AppStatus.APP_STATE_PUK;
+ break;
+ case "APPSTATE_SUBSCRIPTION_PERSO":
+ mocksim_appstate = AppStatus.APP_STATE_SUBSCRIPTION_PERSO;
+ break;
+ case "APPSTATE_READY":
+ mocksim_appstate = AppStatus.APP_STATE_READY;
+ break;
+ }
+ return mocksim_appstate;
+ }
+
+ private int convertMockSimFacilityLock(String lock) {
+ int facilitylock = 0;
+ switch (lock) {
+ case "LOCK_ENABLED":
+ facilitylock = 1;
+ break;
+ case "LOCK_DISABLED":
+ facilitylock = 0;
+ break;
+ }
+ return facilitylock;
+ }
+
+ private int getSimAppDataIndexByAid(String aid) {
+ int idx;
+ for (idx = 0; idx < mSimAppList.size(); idx++) {
+ if (aid.equals(mSimAppList.get(idx).getAid())) {
+ break;
+ }
+ }
+ return idx;
+ }
+
+ private boolean storeEfData(String aid, String name, String id, String value) {
+ boolean result = true;
+ switch (name) {
+ case "EF_IMSI":
+ mSimAppList.get(getSimAppDataIndexByAid(aid)).setImsi(value);
+ break;
+ default:
+ result = false;
+ Log.w(TAG, "Not support EF field - " + name + "(" + id + ")");
+ break;
+ }
+ return result;
+ }
+
+ private boolean loadSimProfileFromXml() {
+ boolean result = true;
+
+ if (mSimProfileInfoList == null) {
+ Log.e(TAG, "No support SIM profile list.");
+ return false;
+ }
+
+ try {
+ String file = mSimProfileInfoList[mSimProfileId].getXmlFile();
+ int event;
+ XmlPullParser parser = Xml.newPullParser();
+ InputStream input;
+ boolean mocksim_validation = false;
+ boolean mocksim_mf_validation = false;
+ int appidx = 0;
+ int fd_lock = 0;
+ int sc_lock = 0;
+ String adf_aid = "";
+
+ input = mContext.getAssets().open(file);
+ parser.setInput(input, null);
+ while (result && (event = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ switch (event) {
+ case XmlPullParser.START_TAG:
+ if (MOCK_SIM_TAG.equals(parser.getName())) {
+ int numofapp = Integer.parseInt(parser.getAttributeValue(0));
+ String iccid = parser.getAttributeValue(1);
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_SIM_TAG
+ + ": numofapp = "
+ + numofapp
+ + " iccid = "
+ + iccid);
+ mICCID = iccid;
+ mSimApp = new AppStatus[numofapp];
+ if (mSimApp == null) {
+ Log.e(TAG, "Create SIM app failed!");
+ result = false;
+ break;
+ }
+ mocksim_validation = true;
+ } else if (mocksim_validation
+ && MOCK_SIM_PROFILE_TAG.equals(parser.getName())) {
+ int id = Integer.parseInt(parser.getAttributeValue(0));
+ int type = convertMockSimAppType(parser.getAttributeValue(1));
+ mSimApp[appidx] = new AppStatus();
+ mSimApp[appidx].appType = type;
+ switch (type) {
+ case AppStatus.APP_TYPE_SIM:
+ case AppStatus.APP_TYPE_USIM:
+ mSimProfileInfoList[mSimProfileId].setGsmAppIndex(id);
+ break;
+ case AppStatus.APP_TYPE_CSIM:
+ case AppStatus.APP_TYPE_RUIM:
+ mSimProfileInfoList[mSimProfileId].setCdmaAppIndex(id);
+ break;
+ case AppStatus.APP_TYPE_ISIM:
+ mSimProfileInfoList[mSimProfileId].setImsAppIndex(id);
+ break;
+ }
+ Log.d(
+ TAG,
+ "Found ["
+ + MOCK_SIM_PROFILE_TAG
+ + "]: id = "
+ + id
+ + " type = "
+ + parser.getAttributeValue(1)
+ + " ("
+ + type
+ + ")========");
+ } else if (mocksim_validation
+ && MOCK_PIN_PROFILE_TAG.equals(parser.getName())) {
+ int appstate = convertMockSimAppState(parser.getAttributeValue(0));
+ mSimApp[appidx].appState = appstate;
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_PIN_PROFILE_TAG
+ + ": appstate = "
+ + parser.getAttributeValue(0)
+ + " ("
+ + appstate
+ + ")");
+ } else if (mocksim_validation
+ && MOCK_PIN1_STATE_TAG.equals(parser.getName())) {
+ String state = parser.nextText();
+ int pin1state = convertMockSimPinState(state);
+ mSimApp[appidx].pin1 = pin1state;
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_PIN1_STATE_TAG
+ + " = "
+ + state
+ + " ("
+ + pin1state
+ + ")");
+ } else if (mocksim_validation
+ && MOCK_PIN2_STATE_TAG.equals(parser.getName())) {
+ String state = parser.nextText();
+ int pin2state = convertMockSimPinState(state);
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_PIN2_STATE_TAG
+ + " = "
+ + state
+ + " ("
+ + pin2state
+ + ")");
+ } else if (mocksim_validation
+ && MOCK_FACILITY_LOCK_FD_TAG.equals(parser.getName())) {
+ fd_lock = convertMockSimFacilityLock(parser.nextText());
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_FACILITY_LOCK_FD_TAG
+ + ": fd lock = "
+ + fd_lock);
+ } else if (mocksim_validation
+ && MOCK_FACILITY_LOCK_SC_TAG.equals(parser.getName())) {
+ sc_lock = convertMockSimFacilityLock(parser.nextText());
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_FACILITY_LOCK_SC_TAG
+ + ": sc lock = "
+ + sc_lock);
+ } else if (mocksim_validation && MOCK_MF_TAG.equals(parser.getName())) {
+ SimAppData simAppData;
+ String name = parser.getAttributeValue(0);
+ String path = parser.getAttributeValue(1);
+ simAppData = new SimAppData(appidx, name, path);
+ if (simAppData == null) {
+ Log.e(TAG, "Create SIM app data failed!");
+ result = false;
+ break;
+ }
+ mSimAppList.add(simAppData);
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_MF_TAG
+ + ": name = "
+ + name
+ + " path = "
+ + path);
+ } else if (mocksim_validation
+ && !mocksim_mf_validation
+ && MOCK_EF_DIR_TAG.equals(parser.getName())) {
+ SimAppData simAppData;
+ String name = parser.getAttributeValue(0);
+ boolean curr_active = Boolean.parseBoolean(parser.getAttributeValue(1));
+ String aid = parser.nextText();
+ simAppData = new SimAppData(appidx, aid, name);
+ if (simAppData == null) {
+ Log.e(TAG, "Create SIM app data failed!");
+ result = false;
+ break;
+ }
+ simAppData.setFdnStatus(fd_lock);
+ simAppData.setPin1State(sc_lock);
+ mSimAppList.add(simAppData);
+ if (curr_active) {
+ mSimApp[appidx].aidPtr = aid;
+ }
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_EF_DIR_TAG
+ + ": name = "
+ + name
+ + ": curr_active = "
+ + curr_active
+ + " aid = "
+ + aid);
+ mocksim_mf_validation = true;
+ } else if (mocksim_validation
+ && mocksim_mf_validation
+ && MOCK_ADF_TAG.equals(parser.getName())) {
+ String aid = parser.getAttributeValue(0);
+ Log.d(TAG, "Found " + MOCK_ADF_TAG + ": aid = " + aid);
+ adf_aid = aid;
+ } else if (mocksim_validation
+ && mocksim_mf_validation
+ && (adf_aid.length() > 0)
+ && MOCK_EF_TAG.equals(parser.getName())) {
+ String name = parser.getAttributeValue(0);
+ String id = parser.getAttributeValue(1);
+ String value = parser.nextText();
+ if (storeEfData(adf_aid, name, id, value)) {
+ Log.d(
+ TAG,
+ "Found "
+ + MOCK_EF_TAG
+ + ": name = "
+ + name
+ + " id = "
+ + id);
+ }
+ }
+ break;
+ case XmlPullParser.END_TAG:
+ if (mocksim_validation && MOCK_SIM_PROFILE_TAG.equals(parser.getName())) {
+ appidx++;
+ mocksim_mf_validation = false;
+ } else if (mocksim_validation && MOCK_ADF_TAG.equals(parser.getName())) {
+ adf_aid = "";
+ }
+ break;
+ }
+ }
+ Log.d(TAG, "Totally create " + appidx + " SIM profiles");
+ mSimProfileInfoList[mSimProfileId].setNumOfSimApp(appidx);
+ input.close();
+ } catch (Exception e) {
+ Log.e(TAG, "Exception error: " + e);
+ result = false;
+ }
+
+ return result;
+ }
+
+ private boolean loadSimApp() {
+ boolean result = true;
+
+ if (mSimAppList == null) {
+ mSimAppList = new ArrayList<SimAppData>();
+ } else {
+ mSimAppList.clear();
+ }
+
+ if (mSimProfileId == MOCK_SIM_PROFILE_ID_DEFAULT
+ || mSimProfileInfoList[mSimProfileId].getXmlFile().length() == 0) {
+ Log.d(TAG, "SIM absent case");
+ mSimApp = new AppStatus[0];
+ if (mSimApp == null) {
+ Log.e(TAG, "Create SIM app failed!");
+ result = false;
+ }
+ } else {
+ result = loadSimProfileFromXml();
+ }
+
+ return result;
+ }
+
+ private boolean loadMockSimCard() {
+ if (mSimProfileId != MOCK_SIM_PROFILE_ID_DEFAULT) {
+ switch (mPhysicalSlotId) {
+ case MOCK_SIM_SLOT_1:
+ mATR = "3B9F96801FC78031E073FE2111634082918307900099";
+ mEID = DEFAULT_SIM1_EID;
+ break;
+ case MOCK_SIM_SLOT_2:
+ mATR = DEFAULT_SIM2_ATR;
+ mEID = DEFAULT_SIM2_EID;
+ break;
+ case MOCK_SIM_SLOT_3:
+ mATR = DEFAULT_SIM3_ATR;
+ mEID = DEFAULT_SIM3_EID;
+ break;
+ }
+ mUniversalPinState = PinState.DISABLED;
+ mIsCardPresent = true;
+ } else {
+ switch (mPhysicalSlotId) {
+ case MOCK_SIM_SLOT_1:
+ mATR = DEFAULT_SIM1_ATR;
+ mEID = DEFAULT_SIM1_EID;
+ mICCID = DEFAULT_SIM1_ICCID;
+ mUniversalPinState = DEFAULT_SIM1_UNIVERSAL_PIN_STATE;
+ break;
+ case MOCK_SIM_SLOT_2:
+ mATR = DEFAULT_SIM2_ATR;
+ mEID = DEFAULT_SIM2_EID;
+ mICCID = DEFAULT_SIM2_ICCID;
+ mUniversalPinState = DEFAULT_SIM2_UNIVERSAL_PIN_STATE;
+ break;
+ case MOCK_SIM_SLOT_3:
+ mATR = DEFAULT_SIM3_ATR;
+ mEID = DEFAULT_SIM3_EID;
+ mICCID = DEFAULT_SIM3_ICCID;
+ mUniversalPinState = DEFAULT_SIM3_UNIVERSAL_PIN_STATE;
+ break;
+ }
+ mIsCardPresent = false;
+ }
+ return loadSimApp();
+ }
+
+ public boolean loadSimCard(int simprofileid) {
+ boolean result = true;
+ mSimProfileId = simprofileid;
+ if (result) {
+ result = loadMockSimCard();
+ }
+ return result;
+ }
+
+ public boolean isSlotPortActive() {
+ return mIsSlotPortActive;
+ }
+
+ public boolean isCardPresent() {
+ return mIsCardPresent;
+ }
+
+ public int getNumOfSimPortInfo() {
+ return DEFAULT_NUM_OF_SIM_PORT_INfO;
+ }
+
+ public int getPhysicalSlotId() {
+ return mPhysicalSlotId;
+ }
+
+ public int getLogicalSlotId() {
+ return mLogicalSlotId;
+ }
+
+ public int getSlotPortId() {
+ return mSlotPortId;
+ }
+
+ public String getEID() {
+ return mEID;
+ }
+
+ public String getATR() {
+ return mATR;
+ }
+
+ public String getICCID() {
+ return mICCID;
+ }
+
+ public int getUniversalPinState() {
+ return mUniversalPinState;
+ }
+
+ public int getGsmAppIndex() {
+ return mSimProfileInfoList[mSimProfileId].getGsmAppIndex();
+ }
+
+ public int getCdmaAppIndex() {
+ return mSimProfileInfoList[mSimProfileId].getCdmaAppIndex();
+ }
+
+ public int getImsAppIndex() {
+ return mSimProfileInfoList[mSimProfileId].getImsAppIndex();
+ }
+
+ public int getNumOfSimApp() {
+ return mSimProfileInfoList[mSimProfileId].getNumOfSimApp();
+ }
+
+ public AppStatus[] getSimApp() {
+ return mSimApp;
+ }
+
+ public ArrayList<SimAppData> getSimAppList() {
+ return mSimAppList;
+ }
+}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
index dfe41cf..0fbfc5a 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/PhoneStateListenerTest.java
@@ -26,6 +26,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.HandlerThread;
@@ -107,6 +108,7 @@
private static ConnectivityManager mCm;
private HandlerThread mHandlerThread;
private Handler mHandler;
+ private PackageManager mPackageManager;
private static final List<Integer> DATA_CONNECTION_STATE = Arrays.asList(
TelephonyManager.DATA_CONNECTED,
TelephonyManager.DATA_DISCONNECTED,
@@ -142,6 +144,7 @@
mHandlerThread = new HandlerThread("PhoneStateListenerTest");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
+ mPackageManager = getContext().getPackageManager();
}
@After
@@ -398,8 +401,8 @@
@Test
public void testOnPreciseCallStateChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnPreciseCallStateChangedCalled).isFalse();
@@ -433,8 +436,8 @@
@Test
public void testOnCallDisconnectCauseChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
@@ -465,8 +468,8 @@
@Test
public void testOnImsCallDisconnectCauseChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnImsCallDisconnectCauseChangedCalled).isFalse();
@@ -496,8 +499,8 @@
@Test
public void testOnPhoneStateListenerExecutorWithSrvccChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mSrvccStateChangedCalled).isFalse();
@@ -528,8 +531,8 @@
@Test
public void testOnRadioPowerStateChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnRadioPowerStateChangedCalled).isFalse();
@@ -596,8 +599,8 @@
@Test
public void testOnPreciseDataConnectionStateChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
@@ -906,8 +909,8 @@
@Test
public void testOnOutgoingSmsEmergencyNumberChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
index 5335f96..074f2037 100755
--- a/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/SubscriptionManagerTest.java
@@ -49,7 +49,6 @@
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import android.telephony.TelephonyManager;
-import android.telephony.cts.util.CarrierPrivilegeUtils;
import android.telephony.ims.ImsException;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
@@ -59,6 +58,7 @@
import androidx.test.InstrumentationRegistry;
+import com.android.compatibility.common.util.CarrierPrivilegeUtils;
import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.TestThread;
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
index 97f44f4..482cd92 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyCallbackTest.java
@@ -28,6 +28,7 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.HandlerThread;
@@ -116,6 +117,7 @@
private static ConnectivityManager mCm;
private HandlerThread mHandlerThread;
private Handler mHandler;
+ private PackageManager mPackageManager;
private static final List<Integer> DATA_CONNECTION_STATE = Arrays.asList(
TelephonyManager.DATA_CONNECTED,
TelephonyManager.DATA_DISCONNECTED,
@@ -151,6 +153,7 @@
mHandlerThread = new HandlerThread("TelephonyCallbackTest");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
+ mPackageManager = getContext().getPackageManager();
}
@After
@@ -487,8 +490,8 @@
@Test
public void testOnPreciseCallStateChangedByRegisterTelephonyCallback() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnPreciseCallStateChangedCalled).isFalse();
@@ -531,8 +534,8 @@
@Test
public void testOnCallDisconnectCauseChangedByRegisterTelephonyCallback() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
@@ -570,8 +573,8 @@
@Test
public void testOnImsCallDisconnectCauseChangedByRegisterTelephonyCallback() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnImsCallDisconnectCauseChangedCalled).isFalse();
@@ -609,8 +612,8 @@
@Test
public void testOSrvccStateChangedByRegisterTelephonyCallback() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mSrvccStateChangedCalled).isFalse();
@@ -649,8 +652,8 @@
@Test
public void testOnRadioPowerStateChangedByRegisterTelephonyCallback() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnRadioPowerStateChangedCalled).isFalse();
@@ -757,8 +760,8 @@
@Test
public void testOnPreciseDataConnectionStateChangedByRegisterTelephonyCallback()
throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
assertThat(mOnCallDisconnectCauseChangedCalled).isFalse();
@@ -1365,8 +1368,8 @@
@Test
public void testOnPhysicalChannelConfigChanged() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
@@ -1404,8 +1407,8 @@
@Test
public void testOnDataEnabledChangedByRegisterTelephonyCallback() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
@@ -1445,8 +1448,8 @@
@Test
public void testOnAllowedNetworkTypesChangedByRegisterPhoneStateListener() throws Throwable {
- if (mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE) == null) {
- Log.d(TAG, "Skipping test that requires ConnectivityManager.TYPE_MOBILE");
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
return;
}
long originalAllowedNetworkTypeUser = ShellIdentityUtils.invokeMethodWithShellPermissions(
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
index 6f0e3f5..b4d4986 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
@@ -24,6 +24,7 @@
import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.telephony.TelephonyManager;
import android.util.Log;
@@ -42,14 +43,22 @@
public class TelephonyManagerTestOnMockModem {
private static final String TAG = "TelephonyManagerTestOnMockModem";
private static MockModemManager sMockModemManager;
- private TelephonyManager mTelephonyManager =
- (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ private static TelephonyManager sTelephonyManager;
@BeforeClass
public static void beforeAllTests() throws Exception {
Log.d(TAG, "TelephonyManagerTestOnMockModem#beforeAllTests()");
+ final PackageManager pm = getContext().getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+ return;
+ }
+
+ sTelephonyManager =
+ (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
+
sMockModemManager = new MockModemManager();
assertNotNull(sMockModemManager);
assertTrue(sMockModemManager.connectMockModemService());
@@ -73,32 +82,42 @@
public void testSimStateChange() throws Throwable {
Log.d(TAG, "TelephonyManagerTestOnMockModem#testSimStateChange");
- int simCardState = mTelephonyManager.getSimCardState();
+ int slotId = 0;
+ int simCardState = sTelephonyManager.getSimCardState();
Log.d(TAG, "Current SIM card state: " + simCardState);
assertTrue(
Arrays.asList(TelephonyManager.SIM_STATE_UNKNOWN, TelephonyManager.SIM_STATE_ABSENT)
.contains(simCardState));
- int slotId = 0;
- sMockModemManager.setSimPresent(slotId);
-
- simCardState = mTelephonyManager.getSimCardState();
- Log.d(TAG, "New SIM card state: " + simCardState);
+ // Insert a SIM
+ assertTrue(
+ sMockModemManager.insertSimCard(
+ slotId, MockSimService.MOCK_SIM_PROFILE_ID_TWN_CHT));
+ simCardState = sTelephonyManager.getSimCardState();
assertEquals(TelephonyManager.SIM_STATE_PRESENT, simCardState);
+
+ // Check SIM state ready
+ simCardState = sTelephonyManager.getSimState();
+ assertEquals(TelephonyManager.SIM_STATE_READY, simCardState);
+
+ // Remove the SIM
+ assertTrue(sMockModemManager.removeSimCard(slotId));
+ simCardState = sTelephonyManager.getSimCardState();
+ assertEquals(TelephonyManager.SIM_STATE_ABSENT, simCardState);
}
@Test
public void testRadioPowerToggle() throws Throwable {
Log.d(TAG, "TelephonyManagerTestOnMockModem#testRadioPowerToggle");
- int radioState = mTelephonyManager.getRadioPowerState();
+ int radioState = sTelephonyManager.getRadioPowerState();
Log.d(TAG, "Radio state: " + radioState);
// Toggle radio power
try {
ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
+ sTelephonyManager,
(tm) -> tm.toggleRadioOnOff(),
SecurityException.class,
"android.permission.MODIFY_PHONE_STATE");
@@ -112,12 +131,12 @@
radioState == TelephonyManager.RADIO_POWER_ON
? TelephonyManager.RADIO_POWER_OFF
: TelephonyManager.RADIO_POWER_ON;
- assertEquals(mTelephonyManager.getRadioPowerState(), toggleRadioState);
+ assertEquals(sTelephonyManager.getRadioPowerState(), toggleRadioState);
// Toggle radio power again back to original radio state
try {
ShellIdentityUtils.invokeThrowableMethodWithShellPermissionsNoReturn(
- mTelephonyManager,
+ sTelephonyManager,
(tm) -> tm.toggleRadioOnOff(),
SecurityException.class,
"android.permission.MODIFY_PHONE_STATE");
@@ -127,7 +146,7 @@
// Wait the radio state update in Framework
TimeUnit.SECONDS.sleep(1);
- assertEquals(mTelephonyManager.getRadioPowerState(), radioState);
+ assertEquals(sTelephonyManager.getRadioPowerState(), radioState);
Log.d(TAG, "Test Done ");
}
@@ -136,7 +155,7 @@
public void testRadioPowerWithFailureResults() throws Throwable {
Log.d(TAG, "TelephonyManagerTestOnMockModem#testRadioPowerWithFailureResults");
- int radioState = mTelephonyManager.getRadioPowerState();
+ int radioState = sTelephonyManager.getRadioPowerState();
Log.d(TAG, "Radio state: " + radioState);
int slotId = 0;
@@ -153,7 +172,7 @@
boolean state = (toggleRadioState == TelephonyManager.RADIO_POWER_ON) ? true : false;
result =
ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
- mTelephonyManager,
+ sTelephonyManager,
(tm) -> tm.setRadioPower(state),
SecurityException.class,
"android.permission.MODIFY_PHONE_STATE");
@@ -163,7 +182,7 @@
TimeUnit.SECONDS.sleep(1);
assertTrue(result);
- assertNotEquals(mTelephonyManager.getRadioPowerState(), toggleRadioState);
+ assertNotEquals(sTelephonyManager.getRadioPowerState(), toggleRadioState);
// Reset the modified error response of RIL_REQUEST_RADIO_POWER to the original behavior
// and -1 means to disable the modifed mechanism in mock modem
@@ -174,7 +193,7 @@
boolean state = (radioState == TelephonyManager.RADIO_POWER_ON) ? true : false;
result =
ShellIdentityUtils.invokeThrowableMethodWithShellPermissions(
- mTelephonyManager,
+ sTelephonyManager,
(tm) -> tm.setRadioPower(state),
SecurityException.class,
"android.permission.MODIFY_PHONE_STATE");
@@ -183,6 +202,6 @@
}
TimeUnit.SECONDS.sleep(1);
assertTrue(result);
- assertEquals(mTelephonyManager.getRadioPowerState(), radioState);
+ assertEquals(sTelephonyManager.getRadioPowerState(), radioState);
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
index 71ffeea..f63a47e 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsCallingTest.java
@@ -82,6 +82,8 @@
public static final int WAIT_FOR_CONDITION = 3000;
public static final int WAIT_FOR_CALL_STATE = 10000;
public static final int WAIT_FOR_CALL_DISCONNECT = 5000;
+ public static final int WAIT_FOR_CALL_STATE_HOLD = 3000;
+ public static final int WAIT_FOR_CALL_STATE_RESUME = 3000;
public static final int LATCH_WAIT = 0;
public static final int LATCH_INCALL_SERVICE_BOUND = 1;
public static final int LATCH_INCALL_SERVICE_UNBOUND = 2;
@@ -92,7 +94,8 @@
public static final int LATCH_IS_CALL_DISCONNECTING = 7;
public static final int LATCH_IS_CALL_DISCONNECTED = 8;
public static final int LATCH_IS_CALL_RINGING = 9;
- public static final int LATCH_MAX = 10;
+ public static final int LATCH_IS_CALL_HOLDING = 10;
+ public static final int LATCH_MAX = 11;
private static boolean sIsBound = false;
private static int sCounter = 5553639;
@@ -318,6 +321,9 @@
fail("Invalid state found: the test subscription in slot " + sTestSlot + " changed "
+ "during this test.");
}
+ }
+
+ public void bindImsService() throws Exception {
// Connect to the ImsService with the MmTel feature.
assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
.addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL)
@@ -336,8 +342,8 @@
MmTelFeature.MmTelCapabilities capabilities = new MmTelFeature.MmTelCapabilities(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
// Set Registered and VoLTE capable
- sServiceConnector.getCarrierService().getImsService().getRegistration(0).onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ sServiceConnector.getCarrierService().getImsService().getRegistrationForSubscription(
+ sTestSlot, sTestSub).onRegistered(ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
sServiceConnector.getCarrierService().getMmTelFeature().setCapabilities(capabilities);
sServiceConnector.getCarrierService().getMmTelFeature()
.notifyCapabilitiesStatusChanged(capabilities);
@@ -371,6 +377,8 @@
if (!ImsUtils.shouldTestImsService()) {
return;
}
+
+ bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
@@ -407,6 +415,7 @@
return;
}
+ bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
@@ -449,11 +458,11 @@
}
@Test
- public void testIncomingCall() {
+ public void testIncomingCall() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
return;
}
-
+ bindImsService();
mServiceCallBack = new ServiceCallBack();
InCallServiceStateValidator.setCallbacks(mServiceCallBack);
@@ -480,6 +489,185 @@
waitForUnboundService();
}
+ @Test
+ public void testOutGoingCallForExecutor() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ sServiceConnector.setExecutorTestType(true);
+ bindImsService();
+
+ mServiceCallBack = new ServiceCallBack();
+ InCallServiceStateValidator.setCallbacks(mServiceCallBack);
+
+ TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
+ .getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
+
+ final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
+ Bundle extras = new Bundle();
+
+ // Place outgoing call
+ telecomManager.placeCall(imsUri, extras);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
+
+ Call call = getCall(mCurrentCallId);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
+
+ TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
+ .getImsCallsession();
+
+ isCallActive(call, callSession);
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_DISCONNECT);
+ call.disconnect();
+
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
+ isCallDisconnected(call, callSession);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
+ waitForUnboundService();
+ }
+
+ @Test
+ public void testOutGoingCallHoldResume() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ bindImsService();
+ mServiceCallBack = new ServiceCallBack();
+ InCallServiceStateValidator.setCallbacks(mServiceCallBack);
+
+ TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
+ .getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
+
+ final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
+ Bundle extras = new Bundle();
+
+ // Place outgoing call
+ telecomManager.placeCall(imsUri, extras);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
+
+ Call call = getCall(mCurrentCallId);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
+
+ TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
+ .getImsCallsession();
+
+ isCallActive(call, callSession);
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_STATE_HOLD);
+ // Put on hold
+ call.hold();
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_STATE_RESUME);
+ // Put on resume
+ call.unhold();
+ isCallActive(call, callSession);
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_DISCONNECT);
+ call.disconnect();
+
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
+ isCallDisconnected(call, callSession);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
+ waitForUnboundService();
+ }
+
+ @Test
+ public void testOutGoingCallHoldFailure() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ bindImsService();
+ mServiceCallBack = new ServiceCallBack();
+ InCallServiceStateValidator.setCallbacks(mServiceCallBack);
+
+ TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
+ .getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
+
+ final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
+ Bundle extras = new Bundle();
+
+ // Place outgoing call
+ telecomManager.placeCall(imsUri, extras);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
+
+ Call call = getCall(mCurrentCallId);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
+
+ TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
+ .getImsCallsession();
+
+ isCallActive(call, callSession);
+ callSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_HOLD_FAILED);
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_STATE_HOLD);
+ call.hold();
+ assertTrue("call is not in Active State", (call.getDetails().getState()
+ == call.STATE_ACTIVE));
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_DISCONNECT);
+ call.disconnect();
+
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
+ isCallDisconnected(call, callSession);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
+ waitForUnboundService();
+ }
+
+
+ @Test
+ public void testOutGoingCallResumeFailure() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ bindImsService();
+ mServiceCallBack = new ServiceCallBack();
+ InCallServiceStateValidator.setCallbacks(mServiceCallBack);
+
+ TelecomManager telecomManager = (TelecomManager) InstrumentationRegistry
+ .getInstrumentation().getContext().getSystemService(Context.TELECOM_SERVICE);
+
+ final Uri imsUri = Uri.fromParts(PhoneAccount.SCHEME_TEL, String.valueOf(++sCounter), null);
+ Bundle extras = new Bundle();
+
+ // Place outgoing call
+ telecomManager.placeCall(imsUri, extras);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_ADDED, WAIT_FOR_CALL_STATE));
+
+ Call call = getCall(mCurrentCallId);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DIALING, WAIT_FOR_CALL_STATE));
+
+ TestImsCallSessionImpl callSession = sServiceConnector.getCarrierService().getMmTelFeature()
+ .getImsCallsession();
+
+ isCallActive(call, callSession);
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_STATE_HOLD);
+ // Put on hold
+ call.hold();
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_HOLDING, WAIT_FOR_CALL_STATE));
+
+ callSession.addTestType(TestImsCallSessionImpl.TEST_TYPE_RESUME_FAILED);
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_STATE_RESUME);
+ call.unhold();
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_STATE);
+ assertTrue("Call is not in Hold State", (call.getDetails().getState()
+ == call.STATE_HOLDING));
+
+
+ callingTestLatchCountdown(LATCH_WAIT, WAIT_FOR_CALL_DISCONNECT);
+ call.disconnect();
+
+ assertTrue(callingTestLatchCountdown(LATCH_IS_CALL_DISCONNECTING, WAIT_FOR_CALL_STATE));
+ isCallDisconnected(call, callSession);
+ assertTrue(callingTestLatchCountdown(LATCH_IS_ON_CALL_REMOVED, WAIT_FOR_CALL_STATE));
+ waitForUnboundService();
+ }
+
public void waitForUnboundService() {
waitUntilConditionIsTrueOrTimeout(
new Condition() {
@@ -624,6 +812,11 @@
}
case Call.STATE_RINGING : {
countDownLatch(LATCH_IS_CALL_RINGING);
+ break;
+ }
+ case Call.STATE_HOLDING : {
+ countDownLatch(LATCH_IS_CALL_HOLDING);
+ break;
}
default:
break;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
index ae6306a..a994d988 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceConnector.java
@@ -81,6 +81,12 @@
private static final String COMMAND_SET_TEST_MODE_ENABLED = "src set-test-enabled ";
private static final String COMMAND_SET_D2D_ENABLED = "d2d set-device-support ";
+ private boolean mIsTestTypeExecutor = false;
+
+ public void setExecutorTestType(boolean type) {
+ mIsTestTypeExecutor = type;
+ }
+
private class TestCarrierServiceConnection implements ServiceConnection {
private final CountDownLatch mLatch;
@@ -117,7 +123,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- mCarrierService = null;
+ mExternalService = null;
}
}
@@ -143,11 +149,13 @@
mIsServiceOverridden = true;
switch (mConnectionType) {
case CONNECTION_TYPE_IMS_SERVICE_CARRIER: {
- setCarrierImsService("none");
+ boolean unbindSent = setCarrierImsService("none");
+ if (unbindSent) waitForCarrierPackageUnbind();
break;
}
case CONNECTION_TYPE_IMS_SERVICE_DEVICE: {
- setDeviceImsService("");
+ boolean unbindSent = setDeviceImsService("");
+ if (unbindSent) waitForDevicePackageUnbind();
break;
}
case CONNECTION_TYPE_DEFAULT_SMS_APP: {
@@ -157,6 +165,35 @@
}
}
+ void waitForCarrierPackageUnbind() {
+ TestImsService carrierService = getCarrierService();
+ if (carrierService == null) return;
+ // First unbind the local services
+ removeLocalCarrierServiceConnection();
+ // Then wait for AOSP to unbind if there is still an active binding.
+ boolean isBound = carrierService.isTelephonyBound();
+ if (ImsUtils.VDBG) Log.i(TAG, "waitForCarrierPackageUnbind: isBound=" + isBound);
+ if (isBound) {
+ // Wait for telephony to unbind to local ImsService
+ carrierService.waitForLatchCountdown(TestImsService.LATCH_ON_UNBIND);
+ }
+ }
+
+ void waitForDevicePackageUnbind() throws Exception {
+ // Wait until the ImsService unbinds
+ ITestExternalImsService externalService = getExternalService();
+ if (externalService == null) return;
+ // First unbind the local services
+ removeLocalExternalServiceConnection();
+ // Then wait for AOSP to unbind if there is still an active binding.
+ boolean isBound = externalService.isTelephonyBound();
+ if (ImsUtils.VDBG) Log.i(TAG, "waitForDevicePackageUnbind: isBound=" + isBound);
+ if (isBound) {
+ // Wait for telephony to unbind to external ImsService
+ externalService.waitForLatchCountdown(TestImsService.LATCH_ON_UNBIND);
+ }
+ }
+
boolean overrideService(ImsFeatureConfiguration config) throws Exception {
mIsServiceOverridden = true;
switch (mConnectionType) {
@@ -480,6 +517,11 @@
return false;
}
mCarrierService.resetState();
+ if (mIsTestTypeExecutor) {
+ mCarrierService.setExecutorTestType(mIsTestTypeExecutor);
+ // reset the mIsTestTypeExecutor value
+ mIsTestTypeExecutor = false;
+ }
return true;
}
@@ -559,17 +601,27 @@
}
}
- // Detect and disconnect all active services.
- void disconnectServices() throws Exception {
- // Remove local connection
+ void removeLocalCarrierServiceConnection() {
if (mCarrierServiceConn != null) {
mInstrumentation.getContext().unbindService(mCarrierServiceConn);
+ mCarrierServiceConn = null;
mCarrierService = null;
}
+ }
+
+ void removeLocalExternalServiceConnection() {
if (mExternalServiceConn != null) {
mInstrumentation.getContext().unbindService(mExternalServiceConn);
+ mExternalServiceConn = null;
mExternalService = null;
}
+ }
+
+ // Detect and disconnect all active services.
+ void disconnectServices() throws Exception {
+ // Remove local connections
+ removeLocalCarrierServiceConnection();
+ removeLocalExternalServiceConnection();
mDeviceServiceConnection.restoreOriginalPackage();
mCarrierServiceConnection.restoreOriginalPackage();
mDefaultSmsAppConnection.restoreOriginalPackage();
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
index 57dbeed..01361ff 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/ImsServiceTest.java
@@ -60,6 +60,7 @@
import android.telephony.ims.SipDelegateManager;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
+import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.CapabilityExchangeEventListener;
import android.telephony.ims.stub.ImsConfigImplBase;
@@ -87,6 +88,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -101,10 +103,36 @@
private static ImsServiceConnector sServiceConnector;
+ private static final int KEY_VOLTE_PROVISIONING_STATUS =
+ ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS;
+ private static final int KEY_VT_PROVISIONING_STATUS =
+ ProvisioningManager.KEY_VT_PROVISIONING_STATUS;
+ private static final int KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE =
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE;
+ private static final int KEY_EAB_PROVISIONING_STATUS =
+ ProvisioningManager.KEY_EAB_PROVISIONING_STATUS;
+
+ private static final int MMTEL_CAP_VOICE = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
+ private static final int MMTEL_CAP_VIDEO = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VIDEO;
+ private static final int MMTEL_CAP_UT = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT;
+ private static final int MMTEL_CAP_SMS = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_SMS;
+ private static final int MMTEL_CAP_COMPOSER =
+ MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_CALL_COMPOSER;
+
private static final int RCS_CAP_NONE = RcsImsCapabilities.CAPABILITY_TYPE_NONE;
private static final int RCS_CAP_OPTIONS = RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE;
private static final int RCS_CAP_PRESENCE = RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
+ private static final int IMS_REGI_TECH_NONE = ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
+ private static final int IMS_REGI_TECH_LTE = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
+ private static final int IMS_REGI_TECH_IWLAN = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
+ private static final int IMS_REGI_TECH_CROSS_SIM =
+ ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
+ private static final int IMS_REGI_TECH_NR = ImsRegistrationImplBase.REGISTRATION_TECH_NR;
+
+ private static final String SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING =
+ "SUPPORT_PROVISION_STATUS_FOR_CAPABILITY";
+
private static final String MSG_CONTENTS = "hi";
private static final String EXPECTED_RECEIVED_MESSAGE = "foo5";
private static final String DEST_NUMBER = "5555554567";
@@ -359,12 +387,14 @@
@After
public void afterTest() throws Exception {
TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
- TelephonyUtils.CTS_APP_PACKAGE,
- SUPPORT_PUBLISHING_STATE_STRING);
+ TelephonyUtils.CTS_APP_PACKAGE, SUPPORT_PUBLISHING_STATE_STRING);
+ TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE, SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
if (!ImsUtils.shouldTestImsService()) {
return;
}
- // Unbind the GTS ImsService after the test completes.
+ // Unbind the ImsService after the test completes.
if (sServiceConnector != null) {
sServiceConnector.setSingleRegistrationTestModeEnabled(false);
sServiceConnector.disconnectCarrierImsService();
@@ -387,6 +417,26 @@
TestImsService.LATCH_CREATE_RCS);
assertNotNull("ImsService created, but ImsService#createRcsFeature was not called!",
sServiceConnector.getCarrierService().getRcsFeature());
+ assertTrue("Not expected subId received!",
+ isExpectedSubId(sServiceConnector.getCarrierService().getSubIDs()));
+ }
+
+ @Test
+ public void testCarrierImsServiceBindRcsFeatureForExecutor() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+ sServiceConnector.setExecutorTestType(true);
+ // Connect to the ImsService with the RCS feature.
+ assertTrue(sServiceConnector.connectCarrierImsService(new ImsFeatureConfiguration.Builder()
+ .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
+ .build()));
+ // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
+ // Framework did not call it.
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_CREATE_RCS);
+ assertNotNull("ImsService created, but ImsService#createRcsFeature was not called!",
+ sServiceConnector.getCarrierService().getRcsFeature());
}
@Test
@@ -407,6 +457,8 @@
// Wait for the framework to set the capabilities on the ImsService
sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_MMTEL_CAP_SET);
+ assertTrue("Not expected subId received!",
+ isExpectedSubId(sServiceConnector.getCarrierService().getSubIDs()));
}
@Test
@@ -436,6 +488,8 @@
assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_DISABLE_IMS));
assertFalse(sServiceConnector.getCarrierService().isEnabled());
+ assertTrue("Not expected subId received!",
+ isExpectedSubId(sServiceConnector.getCarrierService().getSubIDs()));
}
@Test
@@ -464,6 +518,41 @@
// Wait for the framework to set the capabilities on the ImsService
sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_MMTEL_CAP_SET);
+ assertTrue("Not expected subId received!",
+ isExpectedSubId(sServiceConnector.getCarrierService().getSubIDs()));
+ }
+
+ @Test
+ public void testCarrierImsServiceBindRcsChangeToMmtelCompat() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+ // Connect to the ImsService with the RCS feature.
+ ImsFeatureConfiguration config = new ImsFeatureConfiguration.Builder()
+ .addFeature(sTestSlot, ImsFeature.FEATURE_RCS)
+ .build();
+ assertTrue(sServiceConnector.connectCarrierImsServiceLocally());
+ sServiceConnector.getCarrierService().resetState();
+ // Set the flag for ImsService compatibility test.
+ sServiceConnector.getCarrierService().setImsServiceCompat();
+ assertTrue(sServiceConnector.triggerFrameworkConnectionToCarrierImsService(config));
+ // The RcsFeature is created when the ImsService is bound. If it wasn't created, then the
+ // Framework did not call it.
+ assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_CREATE_RCS));
+
+ // Change the supported feature to MMTEl
+ sServiceConnector.getCarrierService().getImsServiceCompat().onUpdateSupportedImsFeatures(
+ new ImsFeatureConfiguration.Builder()
+ .addFeature(sTestSlot, ImsFeature.FEATURE_MMTEL).build());
+
+ // createMmTelFeature should be called.
+ assertTrue(sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_CREATE_MMTEL));
+
+ // Wait for the framework to set the capabilities on the ImsService
+ sServiceConnector.getCarrierService().waitForLatchCountdown(
+ TestImsService.LATCH_MMTEL_CAP_SET);
}
@Test
@@ -501,6 +590,8 @@
// Wait for the framework to set the capabilities on the ImsService
sServiceConnector.getCarrierService().waitForLatchCountdown(
TestImsService.LATCH_MMTEL_CAP_SET);
+ assertTrue("Not expected subId received!",
+ isExpectedSubId(sServiceConnector.getCarrierService().getSubIDs()));
}
@Test
@@ -944,28 +1035,28 @@
assertEquals(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, deregResult.getCode());
// Start registration
- verifyRegistering(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, featureTags, mRegQueue,
+ verifyRegistering(IMS_REGI_TECH_LTE, featureTags, mRegQueue,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 0 /*expected flags*/);
// move to NR
- verifyRegistering(ImsRegistrationImplBase.REGISTRATION_TECH_NR, featureTags, mRegQueue,
+ verifyRegistering(IMS_REGI_TECH_NR, featureTags, mRegQueue,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 0 /*expected flags*/);
// move to cross sim
- verifyRegistering(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM, featureTags,
+ verifyRegistering(IMS_REGI_TECH_CROSS_SIM, featureTags,
mRegQueue, AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
ImsRegistrationAttributes.ATTR_EPDG_OVER_CELL_INTERNET);
// Complete registration
- verifyRegistered(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, featureTags, mRegQueue,
+ verifyRegistered(IMS_REGI_TECH_LTE, featureTags, mRegQueue,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 0 /*expected flags*/);
// move to NR
- verifyRegistered(ImsRegistrationImplBase.REGISTRATION_TECH_NR, featureTags, mRegQueue,
+ verifyRegistered(IMS_REGI_TECH_NR, featureTags, mRegQueue,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, 0 /*expected flags*/);
// move to cross sim
- verifyRegistered(ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM, featureTags,
+ verifyRegistered(IMS_REGI_TECH_CROSS_SIM, featureTags,
mRegQueue, AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
ImsRegistrationAttributes.ATTR_EPDG_OVER_CELL_INTERNET);
@@ -1053,17 +1144,17 @@
// Start registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
// Complete registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
// Fail handover to IWLAN
sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ IMS_REGI_TECH_IWLAN,
new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
ImsReasonInfo.CODE_UNSPECIFIED, ""));
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
@@ -1071,7 +1162,7 @@
// Ensure null ImsReasonInfo still results in non-null callback value.
sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, null);
+ IMS_REGI_TECH_IWLAN, null);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
assertEquals(ImsReasonInfo.CODE_UNSPECIFIED, waitForIntResult(mQueue));
@@ -1193,7 +1284,7 @@
// IMS registers
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
// Framework should not trigger the device capabilities publish when the framework doesn't
// receive that the RcsUceAdapter.CAPABILITY_TYPE_PRESENCE_UCE is enabled.
@@ -1386,7 +1477,7 @@
featureTags.add(CHAT_FEATURE_TAG);
featureTags.add(FILE_TRANSFER_FEATURE_TAG);
ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(featureTags).build();
+ IMS_REGI_TECH_LTE).setFeatureTags(featureTags).build();
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(attr);
waitForParam(mQueue, attr);
@@ -1500,7 +1591,7 @@
// IMS registers
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
// Notify framework that the RCS capability status is changed and PRESENCE UCE is enabled.
RcsImsCapabilities capabilities =
@@ -1610,7 +1701,7 @@
// IMS registers
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
// Notify framework that the RCS capability status is changed and PRESENCE UCE is enabled.
RcsImsCapabilities capabilities =
@@ -1735,7 +1826,7 @@
// IMS registers
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
// Verify the PUBLISH request should not be triggered and the publish state is still
// NOT_PUBLISHED even the IMS is registered.
@@ -1863,7 +1954,7 @@
// IMS registers
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
// Verify the PUBLISH request should not be triggered and the publish state is still
// OK even the IMS is registered.
@@ -2002,7 +2093,7 @@
// IMS registers
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
// Notify framework that the RCS capability status is changed and PRESENCE UCE is enabled.
RcsImsCapabilities capabilities =
@@ -2421,17 +2512,17 @@
// Start registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
// Complete registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
// Fail handover to IWLAN
sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ IMS_REGI_TECH_IWLAN,
new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
ImsReasonInfo.CODE_UNSPECIFIED, ""));
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
@@ -2505,14 +2596,14 @@
// Start registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
verifyRegistrationState(regManager, RegistrationManager.REGISTRATION_STATE_REGISTERING);
verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Complete registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
verifyRegistrationState(regManager, RegistrationManager.REGISTRATION_STATE_REGISTERED);
verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
@@ -2520,7 +2611,7 @@
// Fail handover to IWLAN
sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ IMS_REGI_TECH_IWLAN,
new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
ImsReasonInfo.CODE_UNSPECIFIED, ""));
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
@@ -2529,7 +2620,7 @@
// handover to IWLAN
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
+ IMS_REGI_TECH_IWLAN);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
verifyRegistrationTransportType(regManager, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
@@ -2620,35 +2711,35 @@
// Start registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
verifyRegistrationState(imsRcsManager, RegistrationManager.REGISTRATION_STATE_REGISTERING);
verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Complete registration
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
verifyRegistrationState(imsRcsManager, RegistrationManager.REGISTRATION_STATE_REGISTERED);
verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Start registration over NR
sServiceConnector.getCarrierService().getImsRegistration().onRegistering(
- ImsRegistrationImplBase.REGISTRATION_TECH_NR);
+ IMS_REGI_TECH_NR);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
verifyRegistrationState(imsRcsManager, RegistrationManager.REGISTRATION_STATE_REGISTERING);
verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Complete registration over NR
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_NR);
+ IMS_REGI_TECH_NR);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, waitForIntResult(mQueue));
verifyRegistrationState(imsRcsManager, RegistrationManager.REGISTRATION_STATE_REGISTERED);
verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
// Fail handover to IWLAN
sServiceConnector.getCarrierService().getImsRegistration().onTechnologyChangeFailed(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+ IMS_REGI_TECH_IWLAN,
new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_HO_NOT_FEASIBLE,
ImsReasonInfo.CODE_UNSPECIFIED, ""));
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
@@ -2657,7 +2748,7 @@
// handover to IWLAN
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
+ IMS_REGI_TECH_IWLAN);
assertEquals(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, waitForIntResult(mQueue));
verifyRegistrationTransportType(imsRcsManager, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(imsRcsManager,
@@ -2684,7 +2775,7 @@
.getMmTelFeature().getCapabilities();
// Make sure we start off with every capability unavailable
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
sServiceConnector.getCarrierService().getMmTelFeature()
.notifyCapabilitiesStatusChanged(new MmTelFeature.MmTelCapabilities());
@@ -2696,7 +2787,7 @@
// Make sure we are tracking voice capability over LTE properly.
assertEquals(fwCaps.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE),
mmTelManager.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE));
+ IMS_REGI_TECH_LTE));
} finally {
automan.dropShellPermissionIdentity();
}
@@ -2745,7 +2836,7 @@
automan.adoptShellPermissionIdentity();
assertTrue(ImsUtils.retryUntilTrue(() -> mmTelManager.isAvailable(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE)));
+ IMS_REGI_TECH_LTE)));
mmTelManager.unregisterMmTelCapabilityCallback(callback);
} finally {
@@ -2778,7 +2869,7 @@
.getMmTelFeature().getCapabilities();
// Make sure we start off with every capability unavailable
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
sServiceConnector.getCarrierService().getMmTelFeature()
.notifyCapabilitiesStatusChanged(new MmTelFeature.MmTelCapabilities());
@@ -2790,7 +2881,7 @@
// Make sure we are tracking voice capability over LTE properly.
assertEquals(fwCaps.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE),
mmTelManager.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE));
+ IMS_REGI_TECH_LTE));
} finally {
automan.dropShellPermissionIdentity();
}
@@ -2835,7 +2926,7 @@
automan.adoptShellPermissionIdentity();
assertTrue(ImsUtils.retryUntilTrue(() -> mmTelManager.isAvailable(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_CALL_COMPOSER,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE)));
+ IMS_REGI_TECH_LTE)));
mmTelManager.unregisterMmTelCapabilityCallback(callback);
} finally {
@@ -2872,7 +2963,7 @@
// Make sure we start off with every capability unavailable
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
MmTelFeature.MmTelCapabilities stdCapabilities = new MmTelFeature.MmTelCapabilities();
sServiceConnector.getCarrierService().getMmTelFeature()
.notifyCapabilitiesStatusChanged(stdCapabilities);
@@ -2890,7 +2981,7 @@
automan.adoptShellPermissionIdentity();
boolean isAvailableBeforeStatusChange = mmTelManager.isAvailable(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
assertFalse(isAvailableBeforeStatusChange);
} finally {
automan.dropShellPermissionIdentity();
@@ -2907,7 +2998,7 @@
automan.adoptShellPermissionIdentity();
boolean isVoiceAvailable = mmTelManager
.isAvailable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
voiceIsAvailable.offer(isVoiceAvailable);
} finally {
@@ -2963,12 +3054,12 @@
// Connect to device ImsService with RcsFeature
triggerFrameworkConnectToLocalImsServiceBindRcsFeature();
- int registrationTech = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
+ int registrationTech = IMS_REGI_TECH_LTE;
ImsRcsManager imsRcsManager = imsManager.getImsRcsManager(sTestSub);
// Make sure we start off with none-capability
sServiceConnector.getCarrierService().getImsRegistration().onRegistered(
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
RcsImsCapabilities noCapabilities = new RcsImsCapabilities(RCS_CAP_NONE);
sServiceConnector.getCarrierService().getRcsFeature()
.notifyCapabilitiesStatusChanged(noCapabilities);
@@ -3030,7 +3121,7 @@
// Verify the callback and the api isAvailable that the capabilities is NONE in the
// beginning.
- int radioTechLTE = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
+ int radioTechLTE = IMS_REGI_TECH_LTE;
int capCb = waitForResult(availabilityChanged);
assertEquals(capCb, RCS_CAP_NONE);
availabilityChanged.clear();
@@ -3145,6 +3236,537 @@
}
}
+ @Test
+ public void testProvisioningManagerWhenMmtelProvisionIsRequired() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ // test in case provision for mmtel is required
+ PersistableBundle bundle = new PersistableBundle();
+
+ PersistableBundle innerBundle = new PersistableBundle();
+ innerBundle.putIntArray(
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+ new int[]{IMS_REGI_TECH_LTE, IMS_REGI_TECH_IWLAN}
+ );
+ innerBundle.putIntArray(
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+ new int[]{IMS_REGI_TECH_LTE}
+ );
+
+ bundle.putPersistableBundle(
+ CarrierConfigManager.Ims.KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE,
+ innerBundle);
+
+ overrideCarrierConfig(bundle);
+
+ triggerFrameworkConnectToCarrierImsService();
+ ProvisioningManager provisioningManager =
+ ProvisioningManager.createForSubscriptionId(sTestSub);
+
+ LinkedBlockingQueue<Pair<Integer, Integer>> mIntQueue = new LinkedBlockingQueue<>();
+ LinkedBlockingQueue<Pair<Integer, Pair<Integer, Boolean>>> mOnFeatureChangedQueue =
+ new LinkedBlockingQueue<>();
+
+ ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {
+ @Override
+ public void onProvisioningIntChanged(int item, int value) {
+ mIntQueue.offer(new Pair<>(item, value));
+ }
+ };
+
+ ProvisioningManager.FeatureProvisioningCallback featureProvisioningCallback =
+ new ProvisioningManager.FeatureProvisioningCallback() {
+ @Override
+ public void onFeatureProvisioningChanged(
+ @MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+ boolean isProvisioned) {
+ mOnFeatureChangedQueue.offer(new Pair<>(capability,
+ new Pair<>(tech, isProvisioned)));
+ }
+ };
+
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
+ callback);
+ provisioningManager.registerFeatureProvisioningChangedCallback(
+ getContext().getMainExecutor(), featureProvisioningCallback);
+
+ TelephonyUtils.enableCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
+ // test get/setProvisioningStatusForCapability for VoLTE
+ assertTrue(provisioningManager.isProvisioningRequiredForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+ boolean isProvisioned = provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE);
+ provisioningManager.setProvisioningStatusForCapability(MMTEL_CAP_VOICE,
+ IMS_REGI_TECH_LTE, !isProvisioned);
+ assertTrue(waitForParam(mOnFeatureChangedQueue,
+ new Pair<>(MMTEL_CAP_VOICE, new Pair<>(IMS_REGI_TECH_LTE, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VOLTE_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+ assertEquals(!isProvisioned, provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(MMTEL_CAP_VOICE,
+ IMS_REGI_TECH_LTE, isProvisioned);
+ assertTrue(waitForParam(mOnFeatureChangedQueue,
+ new Pair<>(MMTEL_CAP_VOICE, new Pair<>(IMS_REGI_TECH_LTE, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VOLTE_PROVISIONING_STATUS, isProvisioned ? 1 : 0)));
+ assertEquals(isProvisioned, provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+
+ // test get/setProvisioningStatusForCapability for VoWIFI
+ assertTrue(provisioningManager.isProvisioningRequiredForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+ isProvisioned = provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN);
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(MMTEL_CAP_VOICE,
+ IMS_REGI_TECH_IWLAN, !isProvisioned);
+ assertTrue(waitForParam(mOnFeatureChangedQueue,
+ new Pair<>(MMTEL_CAP_VOICE, new Pair<>(IMS_REGI_TECH_IWLAN, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, !isProvisioned ? 1 : 0)));
+ assertEquals(!isProvisioned, provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(MMTEL_CAP_VOICE,
+ IMS_REGI_TECH_IWLAN, isProvisioned);
+ assertTrue(waitForParam(mOnFeatureChangedQueue,
+ new Pair<>(MMTEL_CAP_VOICE, new Pair<>(IMS_REGI_TECH_IWLAN, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, isProvisioned ? 1 : 0)));
+ assertEquals(isProvisioned, provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+
+ // test get/setProvisioningStatusForCapability for VT
+ assertTrue(provisioningManager.isProvisioningRequiredForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+ isProvisioned = provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE);
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(MMTEL_CAP_VIDEO,
+ IMS_REGI_TECH_LTE, !isProvisioned);
+ assertTrue(waitForParam(mOnFeatureChangedQueue,
+ new Pair<>(MMTEL_CAP_VIDEO, new Pair<>(IMS_REGI_TECH_LTE, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VT_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+ assertEquals(!isProvisioned, provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(MMTEL_CAP_VIDEO,
+ IMS_REGI_TECH_LTE, isProvisioned);
+ assertTrue(waitForParam(mOnFeatureChangedQueue,
+ new Pair<>(MMTEL_CAP_VIDEO, new Pair<>(IMS_REGI_TECH_LTE, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VT_PROVISIONING_STATUS, isProvisioned ? 1 : 0)));
+ assertEquals(isProvisioned, provisioningManager
+ .getProvisioningStatusForCapability(MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+
+ TelephonyUtils.disableCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
+ // test get/setProvisioningStatusForCapability with lower bounding parameters
+ // when callback is not supported
+
+ isProvisioned = provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE);
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE, !isProvisioned);
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VOLTE_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+ assertEquals(!isProvisioned,
+ provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+ isProvisioned = provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN);
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN, !isProvisioned);
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE, !isProvisioned ? 1 : 0)));
+ assertEquals(!isProvisioned,
+ provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+
+ isProvisioned = provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE);
+ mIntQueue.clear();
+ mOnFeatureChangedQueue.clear();
+ provisioningManager.setProvisioningStatusForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE, !isProvisioned);
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_VT_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+ assertEquals(!isProvisioned,
+ provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.unregisterProvisioningChangedCallback(callback);
+ provisioningManager.unregisterFeatureProvisioningChangedCallback(
+ featureProvisioningCallback);
+ } finally {
+ TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ public void testProvisioningManagerWhenMmtelProvisionIsNotRequired() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+
+ // test in case provision for mmtel is required
+ PersistableBundle bundle = new PersistableBundle();
+ PersistableBundle innerBundle = new PersistableBundle();
+
+ bundle.putPersistableBundle(
+ CarrierConfigManager.Ims.KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE,
+ innerBundle);
+ overrideCarrierConfig(bundle);
+
+ triggerFrameworkConnectToCarrierImsService();
+ ProvisioningManager provisioningManager =
+ ProvisioningManager.createForSubscriptionId(sTestSub);
+
+ LinkedBlockingQueue<Pair<Integer, Integer>> mIntQueue = new LinkedBlockingQueue<>();
+ LinkedBlockingQueue<Pair<Integer, Pair<Integer, Boolean>>> mOnFeatureChangedQueue =
+ new LinkedBlockingQueue<>();
+
+
+ ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {};
+
+ ProvisioningManager.FeatureProvisioningCallback featureProvisioningCallback =
+ new ProvisioningManager.FeatureProvisioningCallback() {};
+
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
+ callback);
+ provisioningManager.registerFeatureProvisioningChangedCallback(
+ getContext().getMainExecutor(), featureProvisioningCallback);
+
+ // In case provisioning is not required
+ // true will be returned regardless of stored value
+ // ignore set value whatever value is set by app
+ // therefore set different value from current then check if the value has changed
+ // test get/setProvisioningStatusForCapability for VoLTE
+
+ // isProvisioningRequiredForCapability should return false because provision is not
+ // required
+ assertTrue(!provisioningManager.isProvisioningRequiredForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+ // However, getProvisioningStatusForCapability() should return true because it does not
+ // require provision
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+ // put opposite value to check if the key is changed or not
+ provisioningManager.setProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE, false);
+ // key value should not be changed whatever value is set
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_LTE));
+
+ // test case for VoWIFI
+ assertTrue(!provisioningManager.isProvisioningRequiredForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+ provisioningManager.setProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN, false);
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VOICE, IMS_REGI_TECH_IWLAN));
+
+ // test case for VT
+ assertTrue(!provisioningManager.isProvisioningRequiredForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+ provisioningManager.setProvisioningStatusForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE, false);
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ MMTEL_CAP_VIDEO, IMS_REGI_TECH_LTE));
+
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.unregisterProvisioningChangedCallback(callback);
+ provisioningManager.unregisterFeatureProvisioningChangedCallback(
+ featureProvisioningCallback);
+ } finally {
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ public void testProvisioningManagerWhenRcsProvisionIsRequired() throws Exception {
+ if (!ImsUtils.shouldTestImsSingleRegistration()) {
+ return;
+ }
+
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ true);
+
+ PersistableBundle innerBundle = new PersistableBundle();
+ innerBundle.putIntArray(
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY,
+ new int[]{IMS_REGI_TECH_LTE, IMS_REGI_TECH_IWLAN, IMS_REGI_TECH_CROSS_SIM,
+ IMS_REGI_TECH_NR}
+ );
+ bundle.putPersistableBundle(
+ CarrierConfigManager.Ims.KEY_RCS_REQUIRES_PROVISIONING_BUNDLE,
+ innerBundle);
+
+ overrideCarrierConfig(bundle);
+
+ triggerFrameworkConnectToImsServiceBindMmTelAndRcsFeature();
+
+ ProvisioningManager provisioningManager =
+ ProvisioningManager.createForSubscriptionId(sTestSub);
+
+ LinkedBlockingQueue<Pair<Integer, Integer>> mIntQueue = new LinkedBlockingQueue<>();
+ LinkedBlockingQueue<Pair<Integer, Pair<Integer, Boolean>>> mOnRcsFeatureChangedQueue =
+ new LinkedBlockingQueue<>();
+
+ ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {
+ @Override
+ public void onProvisioningIntChanged(int item, int value) {
+ mIntQueue.offer(new Pair<>(item, value));
+ }
+
+ };
+
+ ProvisioningManager.FeatureProvisioningCallback featureProvisioningCallback =
+ new ProvisioningManager.FeatureProvisioningCallback() {
+ @Override
+ public void onRcsFeatureProvisioningChanged(
+ @RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int tech,
+ boolean isProvisioned) {
+ mOnRcsFeatureChangedQueue.offer(new Pair<>(capability,
+ new Pair<>(tech, isProvisioned)));
+ }
+ };
+
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
+ callback);
+ provisioningManager.registerFeatureProvisioningChangedCallback(
+ getContext().getMainExecutor(), featureProvisioningCallback);
+
+ TelephonyUtils.enableCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
+ assertTrue(provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_LTE));
+ assertTrue(provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_IWLAN));
+ assertTrue(provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_CROSS_SIM));
+ assertTrue(provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_NR));
+
+ // test get/setRcsProvisioningStatusForCapability for PRESENCE over LTE
+ boolean isProvisioned = provisioningManager.getRcsProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_LTE);
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_LTE, !isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE, new Pair<>(IMS_REGI_TECH_LTE, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_LTE, isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE, new Pair<>(IMS_REGI_TECH_LTE, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, isProvisioned ? 1 : 0)));
+
+ // test get/setRcsProvisioningStatusForCapability for PRESENCE over IWLAN
+ isProvisioned = provisioningManager.getRcsProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_IWLAN);
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_IWLAN, !isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE, new Pair<>(IMS_REGI_TECH_IWLAN, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_IWLAN, isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE, new Pair<>(IMS_REGI_TECH_IWLAN, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, isProvisioned ? 1 : 0)));
+
+ // test get/setRcsProvisioningStatusForCapability for PRESENCE over CROSS SIM
+ isProvisioned = provisioningManager.getRcsProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_CROSS_SIM);
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_CROSS_SIM, !isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE,
+ new Pair<>(IMS_REGI_TECH_CROSS_SIM, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_CROSS_SIM, isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE,
+ new Pair<>(IMS_REGI_TECH_CROSS_SIM, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, isProvisioned ? 1 : 0)));
+
+ // test get/setRcsProvisioningStatusForCapability for PRESENCE over NR
+ isProvisioned = provisioningManager.getRcsProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_NR);
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_NR, !isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE, new Pair<>(IMS_REGI_TECH_NR, !isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, !isProvisioned ? 1 : 0)));
+
+ provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
+ IMS_REGI_TECH_NR, isProvisioned);
+ assertTrue(waitForParam(mOnRcsFeatureChangedQueue,
+ new Pair<>(RCS_CAP_PRESENCE, new Pair<>(IMS_REGI_TECH_NR, isProvisioned))));
+ assertTrue(waitForParam(mIntQueue,
+ new Pair<>(KEY_EAB_PROVISIONING_STATUS, isProvisioned ? 1 : 0)));
+
+ // TODO : work for OPTIONS case
+
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.unregisterProvisioningChangedCallback(callback);
+ provisioningManager.unregisterFeatureProvisioningChangedCallback(
+ featureProvisioningCallback);
+ } finally {
+ TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ public void testProvisioningManagerWhenRcsProvisionIsNotRequired() throws Exception {
+ if (!ImsUtils.shouldTestImsSingleRegistration()) {
+ return;
+ }
+
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ true);
+
+ PersistableBundle innerBundle = new PersistableBundle();
+ bundle.putPersistableBundle(
+ CarrierConfigManager.Ims.KEY_RCS_REQUIRES_PROVISIONING_BUNDLE,
+ innerBundle);
+
+ overrideCarrierConfig(bundle);
+
+ triggerFrameworkConnectToImsServiceBindMmTelAndRcsFeature();
+
+ ProvisioningManager provisioningManager =
+ ProvisioningManager.createForSubscriptionId(sTestSub);
+ ProvisioningManager.Callback callback = new ProvisioningManager.Callback() {};
+ ProvisioningManager.FeatureProvisioningCallback featureProvisioningCallback =
+ new ProvisioningManager.FeatureProvisioningCallback() {};
+
+ final UiAutomation automan = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ try {
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.registerProvisioningChangedCallback(getContext().getMainExecutor(),
+ callback);
+ provisioningManager.registerFeatureProvisioningChangedCallback(
+ getContext().getMainExecutor(), featureProvisioningCallback);
+
+ TelephonyUtils.enableCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
+ assertTrue(!provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_LTE));
+ assertTrue(!provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_IWLAN));
+ assertTrue(!provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_CROSS_SIM));
+ assertTrue(!provisioningManager.isRcsProvisioningRequiredForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_NR));
+
+ // However, getProvisioningStatusForCapability() should return true because it does not
+ // require provision
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_LTE));
+ // put opposite value to check if the key is changed or not
+ provisioningManager.setProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_LTE, false);
+ // key value should not be changed whatever value is set
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_LTE));
+
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_IWLAN));
+ provisioningManager.setProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_IWLAN, false);
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_IWLAN));
+
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_CROSS_SIM));
+ provisioningManager.setProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_CROSS_SIM, false);
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_CROSS_SIM));
+
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_NR));
+ provisioningManager.setProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_NR, false);
+ assertTrue(provisioningManager.getProvisioningStatusForCapability(
+ RCS_CAP_PRESENCE, IMS_REGI_TECH_NR));
+
+ // TODO : work for OPTIONS case
+
+ automan.adoptShellPermissionIdentity();
+ provisioningManager.unregisterProvisioningChangedCallback(callback);
+ provisioningManager.unregisterFeatureProvisioningChangedCallback(
+ featureProvisioningCallback);
+ } finally {
+ TelephonyUtils.resetCompatCommand(InstrumentationRegistry.getInstrumentation(),
+ TelephonyUtils.CTS_APP_PACKAGE,
+ SUPPORT_PROVISION_STATUS_FOR_CAPABILITY_STRING);
+
+ automan.dropShellPermissionIdentity();
+ }
+ }
+
@Ignore("The ProvisioningManager constants were moved back to @hide for now, don't want to "
+ "completely remove test.")
@Test
@@ -3342,7 +3964,15 @@
PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_SUPPORTS_SS_OVER_UT_BOOL, true);
- bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_UT_PROVISIONING_REQUIRED_BOOL, true);
+
+ PersistableBundle innerBundle = new PersistableBundle();
+ innerBundle.putIntArray(
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_UT_INT_ARRAY,
+ new int[]{IMS_REGI_TECH_LTE}); // UT/LTE
+ bundle.putPersistableBundle(
+ CarrierConfigManager.Ims.KEY_MMTEL_REQUIRES_PROVISIONING_BUNDLE,
+ innerBundle);
+
overrideCarrierConfig(bundle);
ProvisioningManager provisioningManager =
@@ -3353,22 +3983,22 @@
automan.adoptShellPermissionIdentity();
boolean provisioningStatus = provisioningManager.getProvisioningStatusForCapability(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
+ IMS_REGI_TECH_LTE);
provisioningManager.setProvisioningStatusForCapability(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE, !provisioningStatus);
+ IMS_REGI_TECH_LTE, !provisioningStatus);
// Make sure the change in provisioning status is correctly returned.
assertEquals(!provisioningStatus,
provisioningManager.getProvisioningStatusForCapability(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE));
+ IMS_REGI_TECH_LTE));
// TODO: Enhance test to make sure the provisioning change is also sent to the
// ImsService
// set back to current status
provisioningManager.setProvisioningStatusForCapability(
MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT,
- ImsRegistrationImplBase.REGISTRATION_TECH_LTE, provisioningStatus);
+ IMS_REGI_TECH_LTE, provisioningStatus);
} finally {
automan.dropShellPermissionIdentity();
}
@@ -3378,7 +4008,7 @@
@Test
public void testProvisioningManagerRcsProvisioningCaps() throws Exception {
- if (!ImsUtils.shouldTestImsService()) {
+ if (!ImsUtils.shouldTestImsSingleRegistration()) {
return;
}
@@ -3390,8 +4020,20 @@
true);
bundle.putBoolean(CarrierConfigManager.Ims.KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, true);
bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_RCS_PROVISIONING_REQUIRED_BOOL, true);
+ bundle.putBoolean(CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ true);
+ PersistableBundle innerBundle = new PersistableBundle();
+ innerBundle.putIntArray(
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY,
+ new int[]{IMS_REGI_TECH_LTE, IMS_REGI_TECH_IWLAN, IMS_REGI_TECH_CROSS_SIM,
+ IMS_REGI_TECH_NR}
+ );
+ bundle.putPersistableBundle(
+ CarrierConfigManager.Ims.KEY_RCS_REQUIRES_PROVISIONING_BUNDLE,
+ innerBundle);
overrideCarrierConfig(bundle);
+
ProvisioningManager provisioningManager =
ProvisioningManager.createForSubscriptionId(sTestSub);
@@ -3406,7 +4048,7 @@
assertEquals(!provisioningStatus,
provisioningManager.getRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE));
// TODO: Enhance test to make sure the provisioning change is also sent to the
- // ImsService
+ // ImsService
// set back to current status
provisioningManager.setRcsProvisioningStatusForCapability(RCS_CAP_PRESENCE,
@@ -4393,4 +5035,8 @@
throw new RuntimeException("Invalid hex char '" + c + "'");
}
+
+ private boolean isExpectedSubId(HashSet<Integer> subIDs) {
+ return (subIDs.size() == 1) && subIDs.contains(sTestSub);
+ }
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java
index cf1b2fe..34abd36 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsContactUceCapabilityTest.java
@@ -73,6 +73,7 @@
RcsContactUceCapability.REQUEST_RESULT_FOUND);
presenceBuilder.addCapabilityTuple(mmtelTuple);
presenceBuilder.addCapabilityTuples(Collections.singletonList(ftTuple));
+ presenceBuilder.setEntityUri(TEST_CONTACT);
final RcsContactUceCapability testCapability = presenceBuilder.build();
@@ -87,6 +88,7 @@
assertEquals(unparceledCapability.getContactUri(), testCapability.getContactUri());
assertEquals(unparceledCapability.getSourceType(), testCapability.getSourceType());
assertEquals(unparceledCapability.getRequestResult(), testCapability.getRequestResult());
+ assertEquals(unparceledCapability.getEntityUri(), testCapability.getEntityUri());
assertEquals(unparceledCapability.getCapabilityMechanism(),
testCapability.getCapabilityMechanism());
@@ -224,6 +226,7 @@
assertEquals(expectedCap.getContactUri(), unparceledCapability.getContactUri());
assertEquals(expectedCap.getSourceType(), unparceledCapability.getSourceType());
assertEquals(expectedCap.getRequestResult(), unparceledCapability.getRequestResult());
+ assertEquals(expectedCap.getEntityUri(), unparceledCapability.getEntityUri());
assertEquals(expectedCap.getCapabilityMechanism(),
unparceledCapability.getCapabilityMechanism());
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
index 91a4bd9..6491b67 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/RcsUceAdapterTest.java
@@ -1069,6 +1069,149 @@
overrideCarrierConfig(null);
}
+ /**
+ * Tests the case when contact1 has had a successful network query, but a query for contact2
+ * has resulted in the carrier network not responding with a NOTIFY. If contact1 caps are
+ * queried again, the query to the cache for contact1 should not be blocked in a queue behind
+ * the pending network query. Eventually, request for contact2 will timeout with onTimeout
+ * response from vendor, which will result in ERROR_REQUEST_TIMEOUT result back to app.
+ */
+ @Test
+ public void testCacheQuerySuccessWhenNetworkBlocked() throws Exception {
+ if (!ImsUtils.shouldTestImsService()) {
+ return;
+ }
+ ImsManager imsManager = getContext().getSystemService(ImsManager.class);
+ RcsUceAdapter uceAdapter = imsManager.getImsRcsManager(sTestSub).getUceAdapter();
+ assertNotNull("UCE adapter should not be null!", uceAdapter);
+
+ // Remove the test contact capabilities
+ removeTestContactFromEab();
+
+ // Connect to the ImsService
+ setupTestImsService(uceAdapter, true, true /* presence cap */, false /* OPTIONS */);
+
+ TestRcsCapabilityExchangeImpl capabilityExchangeImpl = sServiceConnector
+ .getCarrierService().getRcsFeature().getRcsCapabilityExchangeImpl();
+
+ BlockingQueue<Boolean> completeQueue = new LinkedBlockingQueue<>();
+ BlockingQueue<RcsContactUceCapability> capabilityQueue = new LinkedBlockingQueue<>();
+ BlockingQueue<Integer> errorQueue = new LinkedBlockingQueue<>();
+ RcsUceAdapter.CapabilitiesCallback callback = new RcsUceAdapter.CapabilitiesCallback() {
+ @Override
+ public void onCapabilitiesReceived(List<RcsContactUceCapability> capabilities) {
+ capabilities.forEach(capabilityQueue::offer);
+ }
+ @Override
+ public void onComplete() {
+ completeQueue.offer(true);
+ }
+ @Override
+ public void onError(int errorCode, long retryAfterMilliseconds) {
+ errorQueue.offer(errorCode);
+ }
+ };
+
+ // Prepare two contacts
+ final Uri contact1 = sTestNumberUri;
+ final Uri contact2 = sTestContact2Uri;
+
+ Collection<Uri> contacts = new ArrayList<>(1);
+ contacts.add(contact1);
+
+ ArrayList<String> pidfXmlList = new ArrayList<>(1);
+ pidfXmlList.add(getPidfXmlData(contact1, true, true));
+
+ // Setup the network response is 200 OK and notify capabilities update
+ int networkRespCode = 200;
+ String networkRespReason = "OK";
+ capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
+ cb.onNetworkResponse(networkRespCode, networkRespReason);
+ cb.onNotifyCapabilitiesUpdate(pidfXmlList);
+ cb.onTerminated("", 0L);
+ });
+
+ requestCapabilities(uceAdapter, contacts, callback);
+
+ List<RcsContactUceCapability> resultCapList = new ArrayList<>();
+
+ // Verify that the first contact is updated
+ RcsContactUceCapability capability = waitForResult(capabilityQueue);
+ assertNotNull("Cannot receive the first capabilities result.", capability);
+ resultCapList.add(capability);
+
+ // Verify contact1's capabilities from the received capabilities list
+ RcsContactUceCapability resultCapability = getContactCapability(resultCapList, contact1);
+ assertNotNull("Cannot find the contact: " + contact1, resultCapability);
+ verifyCapabilityResult(resultCapability, contact1, SOURCE_TYPE_NETWORK,
+ REQUEST_RESULT_FOUND, true, true);
+
+ // Verify the onCompleted is called
+ waitForResult(completeQueue);
+
+ completeQueue.clear();
+ capabilityQueue.clear();
+ resultCapList.clear();
+
+ // Now hold the second contact and do not return a response until after contact1 is queried
+ //again
+ CountDownLatch latch = new CountDownLatch(1);
+ capabilityExchangeImpl.setSubscribeOperation((uris, cb) -> {
+ try {
+ cb.onNetworkResponse(networkRespCode, networkRespReason);
+ assertTrue("Timed out waiting for latch", latch.await(10, TimeUnit.SECONDS));
+ // We didn't receive any NOTIFY
+ cb.onTerminated("timeout", 0L);
+ } catch (InterruptedException e) {
+ fail("Waiting for cap response resulted in unexpected exception: " + e);
+ }
+ });
+
+ contacts.clear();
+ contacts.add(contact2);
+
+ pidfXmlList.clear();
+ pidfXmlList.add(getPidfXmlData(contact2, true, true));
+
+ requestCapabilities(uceAdapter, contacts, callback);
+
+ // Send another request for contact1's caps. Although the request queue is blocked due to
+ // pending network request, contact1 has valid caps, so system should return those.
+ contacts.clear();
+ contacts.add(contact1);
+
+ pidfXmlList.clear();
+ pidfXmlList.add(getPidfXmlData(contact1, true, true));
+
+ requestCapabilities(uceAdapter, contacts, callback);
+
+ capability = waitForResult(capabilityQueue);
+ assertNotNull("Cannot receive the cached capabilities result.", capability);
+ resultCapList.add(capability);
+
+ // Verify contact1's capabilities from the received capabilities list
+ resultCapability = getContactCapability(resultCapList, contact1);
+ assertNotNull("Cannot find the contact: " + contact1, resultCapability);
+ verifyCapabilityResult(resultCapability, contact1, SOURCE_TYPE_CACHED, REQUEST_RESULT_FOUND,
+ true, true);
+
+ // Now contact2's query finishes and it timed out without a NOTIFY
+ latch.countDown();
+
+ Integer error = waitForResult(errorQueue);
+ assertNotNull("Cannot receive the expected error result.", capability);
+ assertEquals("Timeout without NOTIFY should result in ERROR_REQUEST_TIMEOUT",
+ RcsUceAdapter.ERROR_REQUEST_TIMEOUT, error.intValue());
+
+ errorQueue.clear();
+ completeQueue.clear();
+ capabilityQueue.clear();
+ resultCapList.clear();
+ removeTestContactFromEab();
+
+ overrideCarrierConfig(null);
+ }
+
@Test
public void testRequestCapabilitiesFromCacheWithPresenceMechanism() throws Exception {
if (!ImsUtils.shouldTestImsService()) {
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsCallSessionImpl.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsCallSessionImpl.java
index 3ded179..1dba231 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsCallSessionImpl.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsCallSessionImpl.java
@@ -63,6 +63,8 @@
public static final int TEST_TYPE_NONE = 0x00000000;
public static final int TEST_TYPE_MO_ANSWER = 0x00000001;
public static final int TEST_TYPE_MO_FAILED = 0x00000002;
+ public static final int TEST_TYPE_HOLD_FAILED = 0x00000004;
+ public static final int TEST_TYPE_RESUME_FAILED = 0x00000008;
private int mTestType = TEST_TYPE_NONE;
@@ -324,6 +326,132 @@
}
}
+ @Override
+ public void hold(ImsStreamMediaProfile profile) {
+ if (isTestType(TEST_TYPE_HOLD_FAILED)) {
+ holdFailed(profile);
+ } else {
+ int audioDirection = profile.getAudioDirection();
+ if (audioDirection == ImsStreamMediaProfile.DIRECTION_SEND) {
+ ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
+ ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
+ ImsStreamMediaProfile.DIRECTION_RECEIVE,
+ ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
+ ImsStreamMediaProfile.DIRECTION_INVALID,
+ ImsStreamMediaProfile.RTT_MODE_DISABLED);
+ ImsCallProfile mprofile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL,
+ ImsCallProfile.CALL_TYPE_VOICE, new Bundle(), mediaProfile);
+ mCallProfile.updateMediaProfile(mprofile);
+ }
+ setState(ImsCallSessionImplBase.State.RENEGOTIATING);
+
+ postAndRunTask(() -> {
+ imsCallSessionLatchCountdown(LATCH_WAIT, WAIT_FOR_ESTABLISHING);
+ try {
+ if (mListener == null) {
+ return;
+ }
+ Log.d(LOG_TAG, "invokeHeld mCallId = " + mCallId);
+ mListener.callSessionHeld(mCallProfile);
+ } catch (Throwable t) {
+ Throwable cause = t.getCause();
+ if (t instanceof DeadObjectException
+ || (cause != null && cause instanceof DeadObjectException)) {
+ fail("starting cause Throwable to be thrown: " + t);
+ }
+ }
+ });
+ setState(ImsCallSessionImplBase.State.ESTABLISHED);
+ }
+ }
+
+ @Override
+ public void resume(ImsStreamMediaProfile profile) {
+ if (isTestType(TEST_TYPE_RESUME_FAILED)) {
+ resumeFailed(profile);
+ } else {
+ int audioDirection = profile.getAudioDirection();
+ if (audioDirection == ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE) {
+ ImsStreamMediaProfile mediaProfile = new ImsStreamMediaProfile(
+ ImsStreamMediaProfile.AUDIO_QUALITY_AMR,
+ ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE,
+ ImsStreamMediaProfile.VIDEO_QUALITY_NONE,
+ ImsStreamMediaProfile.DIRECTION_INVALID,
+ ImsStreamMediaProfile.RTT_MODE_DISABLED);
+ ImsCallProfile mprofile = new ImsCallProfile(ImsCallProfile.SERVICE_TYPE_NORMAL,
+ ImsCallProfile.CALL_TYPE_VOICE, new Bundle(), mediaProfile);
+ mCallProfile.updateMediaProfile(mprofile);
+ }
+ setState(ImsCallSessionImplBase.State.RENEGOTIATING);
+
+ postAndRunTask(() -> {
+ imsCallSessionLatchCountdown(LATCH_WAIT, WAIT_FOR_ESTABLISHING);
+ try {
+ if (mListener == null) {
+ return;
+ }
+ Log.d(LOG_TAG, "invokeResume mCallId = " + mCallId);
+ mListener.callSessionResumed(mCallProfile);
+ } catch (Throwable t) {
+ Throwable cause = t.getCause();
+ if (t instanceof DeadObjectException
+ || (cause != null && cause instanceof DeadObjectException)) {
+ fail("starting cause Throwable to be thrown: " + t);
+ }
+ }
+ });
+ setState(ImsCallSessionImplBase.State.ESTABLISHED);
+ }
+ }
+
+ private void holdFailed(ImsStreamMediaProfile profile) {
+ int audioDirection = profile.getAudioDirection();
+ if (audioDirection == ImsStreamMediaProfile.DIRECTION_SEND) {
+ postAndRunTask(() -> {
+ imsCallSessionLatchCountdown(LATCH_WAIT, WAIT_FOR_ESTABLISHING);
+ try {
+ if (mListener == null) {
+ return;
+ }
+ Log.d(LOG_TAG, "invokeHoldFailed mCallId = " + mCallId);
+ mListener.callSessionHoldFailed(getReasonInfo(ImsReasonInfo
+ .CODE_SESSION_MODIFICATION_FAILED, ImsReasonInfo.CODE_UNSPECIFIED));
+ } catch (Throwable t) {
+ Throwable cause = t.getCause();
+ if (t instanceof DeadObjectException
+ || (cause != null && cause instanceof DeadObjectException)) {
+ fail("starting cause Throwable to be thrown: " + t);
+ }
+ }
+ });
+ setState(ImsCallSessionImplBase.State.ESTABLISHED);
+ }
+ }
+
+ private void resumeFailed(ImsStreamMediaProfile profile) {
+ int audioDirection = profile.getAudioDirection();
+ if (audioDirection == ImsStreamMediaProfile.DIRECTION_SEND_RECEIVE) {
+ postAndRunTask(() -> {
+ imsCallSessionLatchCountdown(LATCH_WAIT, WAIT_FOR_ESTABLISHING);
+ try {
+ if (mListener == null) {
+ return;
+ }
+ Log.d(LOG_TAG, "invokeResumeFailed mCallId = " + mCallId);
+ mListener.callSessionResumeFailed(getReasonInfo(ImsReasonInfo
+ .CODE_SESSION_MODIFICATION_FAILED, ImsReasonInfo.CODE_UNSPECIFIED));
+ } catch (Throwable t) {
+ Throwable cause = t.getCause();
+ if (t instanceof DeadObjectException
+ || (cause != null && cause instanceof DeadObjectException)) {
+ fail("starting cause Throwable to be thrown: " + t);
+ }
+ }
+ });
+ setState(ImsCallSessionImplBase.State.ESTABLISHED);
+ }
+ }
+
private void setState(int state) {
if (mState != state) {
Log.d(LOG_TAG, "ImsCallSession :: " + mState + " >> " + state);
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsConfig.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsConfig.java
index 10a39d3..3e3b331 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsConfig.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsConfig.java
@@ -18,15 +18,25 @@
import android.telephony.ims.RcsClientConfiguration;
import android.telephony.ims.stub.ImsConfigImplBase;
+import android.util.Log;
import java.util.HashMap;
+import java.util.concurrent.Executor;
public class TestImsConfig extends ImsConfigImplBase {
+ private static final String TAG = "TestImsConfig";
private HashMap<Integer, Integer> mIntHashMap = new HashMap<>();
private HashMap<Integer, String> mStringHashMap = new HashMap<>();
TestImsConfig() {
+ Log.d(TAG, "TestImsConfig with default constructor");
+ TestAcsClient.getInstance().setImsConfigImpl(this);
+ }
+
+ TestImsConfig(Executor executor) {
+ super(executor);
+ Log.d(TAG, "TestImsConfig with Executor constructor");
TestAcsClient.getInstance().setImsConfigImpl(this);
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsRegistration.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsRegistration.java
index afdd3d1..cb3a4d9 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsRegistration.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsRegistration.java
@@ -17,13 +17,26 @@
package android.telephony.ims.cts;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.util.Log;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class TestImsRegistration extends ImsRegistrationImplBase {
+ private static final String TAG = "TestImsRegistration";
+
+ public TestImsRegistration() {
+ Log.d(TAG, "TestImsRegistration with default constructor");
+ }
+
+ public TestImsRegistration(Executor executor) {
+ super(executor);
+ Log.d(TAG, "TestImsRegistration with Executor constructor");
+ }
+
public static class NetworkRegistrationInfo {
public final int sipCode;
public final String sipReason;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java
index a012513..97fa8f2 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestImsService.java
@@ -20,7 +20,11 @@
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.telephony.ims.ImsService;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
@@ -30,10 +34,12 @@
import android.telephony.ims.stub.SipTransportImplBase;
import android.util.Log;
-
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import java.util.HashSet;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
/**
@@ -41,22 +47,27 @@
*/
public class TestImsService extends Service {
- private static final String TAG = "GtsImsTestImsService";
+ private static final String TAG = "CtsImsTestImsService";
+ private static MessageExecutor sMessageExecutor = null;
- private static final TestImsRegistration sImsRegistrationImplBase =
- new TestImsRegistration();
-
+ private TestImsRegistration mImsRegistrationImplBase;
private TestRcsFeature mTestRcsFeature;
private TestMmTelFeature mTestMmTelFeature;
private TestImsConfig mTestImsConfig;
private TestSipTransport mTestSipTransport;
private ImsService mTestImsService;
+ private ImsService mTestImsServiceCompat;
+ private Executor mExecutor = Runnable::run;
private boolean mIsEnabled = false;
private boolean mSetNullRcsBinding = false;
private boolean mIsSipTransportImplemented = false;
+ private boolean mIsTestTypeExecutor = false;
+ private boolean mIsImsServiceCompat = false;
private long mCapabilities = 0;
private ImsFeatureConfiguration mFeatureConfig;
- private final Object mLock = new Object();
+ protected boolean mIsTelephonyBound = false;
+ private HashSet<Integer> mSubIDs = new HashSet<Integer>();
+ protected final Object mLock = new Object();
public static final int LATCH_FEATURES_READY = 0;
public static final int LATCH_ENABLE_IMS = 1;
@@ -71,7 +82,8 @@
public static final int LATCH_RCS_CAP_SET = 10;
public static final int LATCH_UCE_LISTENER_SET = 11;
public static final int LATCH_UCE_REQUEST_PUBLISH = 12;
- private static final int LATCH_MAX = 13;
+ public static final int LATCH_ON_UNBIND = 13;
+ private static final int LATCH_MAX = 14;
protected static final CountDownLatch[] sLatches = new CountDownLatch[LATCH_MAX];
static {
for (int i = 0; i < LATCH_MAX; i++) {
@@ -106,9 +118,193 @@
if (getBaseContext() == null) {
attachBaseContext(context);
}
- mTestImsConfig = new TestImsConfig();
- // For testing, just run on binder thread until required otherwise.
- mTestSipTransport = new TestSipTransport(Runnable::run);
+
+ if (mIsTestTypeExecutor) {
+ mImsRegistrationImplBase = new TestImsRegistration(mExecutor);
+ mTestSipTransport = new TestSipTransport(mExecutor);
+ mTestImsConfig = new TestImsConfig(mExecutor);
+ } else {
+ mImsRegistrationImplBase = new TestImsRegistration();
+ mTestImsConfig = new TestImsConfig();
+ mTestSipTransport = new TestSipTransport();
+ }
+ }
+
+ @Override
+ public ImsFeatureConfiguration querySupportedImsFeatures() {
+ return getFeatureConfig();
+ }
+
+ @Override
+ public long getImsServiceCapabilities() {
+ return mCapabilities;
+ }
+
+ @Override
+ public void readyForFeatureCreation() {
+ synchronized (mLock) {
+ countDownLatch(LATCH_FEATURES_READY);
+ }
+ }
+
+ @Override
+ public void enableImsForSubscription(int slotId, int subId) {
+ synchronized (mLock) {
+ countDownLatch(LATCH_ENABLE_IMS);
+ mSubIDs.add(subId);
+ setIsEnabled(true);
+ }
+ }
+
+ @Override
+ public void disableImsForSubscription(int slotId, int subId) {
+ synchronized (mLock) {
+ countDownLatch(LATCH_DISABLE_IMS);
+ mSubIDs.add(subId);
+ setIsEnabled(false);
+ }
+ }
+
+ @Override
+ public RcsFeature createRcsFeatureForSubscription(int slotId, int subId) {
+ TestImsService.ReadyListener readyListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_RCS_READY);
+ }
+ };
+
+ TestImsService.RemovedListener removedListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_REMOVE_RCS);
+ mTestRcsFeature = null;
+ }
+ };
+
+ TestImsService.CapabilitiesSetListener setListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_RCS_CAP_SET);
+ }
+ };
+
+ TestImsService.RcsCapabilityExchangeEventListener capExchangeEventListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_UCE_LISTENER_SET);
+ }
+ };
+
+ synchronized (mLock) {
+ countDownLatch(LATCH_CREATE_RCS);
+ mSubIDs.add(subId);
+
+ if (mIsTestTypeExecutor) {
+ mTestRcsFeature = new TestRcsFeature(readyListener, removedListener,
+ setListener, capExchangeEventListener, mExecutor);
+ } else {
+ mTestRcsFeature = new TestRcsFeature(readyListener, removedListener,
+ setListener, capExchangeEventListener);
+ }
+
+ // Setup UCE request listener
+ mTestRcsFeature.setDeviceCapPublishListener(() -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_UCE_REQUEST_PUBLISH);
+ }
+ });
+
+ if (mSetNullRcsBinding) {
+ return null;
+ }
+ return mTestRcsFeature;
+ }
+ }
+
+ @Override
+ public ImsConfigImplBase getConfigForSubscription(int slotId, int subId) {
+ mSubIDs.add(subId);
+ return mTestImsConfig;
+ }
+
+ @Override
+ public MmTelFeature createMmTelFeatureForSubscription(int slotId, int subId) {
+ TestImsService.ReadyListener readyListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_MMTEL_READY);
+ }
+ };
+
+ TestImsService.RemovedListener removedListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_REMOVE_MMTEL);
+ mTestMmTelFeature = null;
+ }
+ };
+
+ TestImsService.CapabilitiesSetListener capSetListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_MMTEL_CAP_SET);
+ }
+ };
+
+ synchronized (mLock) {
+ countDownLatch(LATCH_CREATE_MMTEL);
+ mSubIDs.add(subId);
+ if (mIsTestTypeExecutor) {
+ mTestMmTelFeature = new TestMmTelFeature(readyListener, removedListener,
+ capSetListener, mExecutor);
+ } else {
+ mTestMmTelFeature = new TestMmTelFeature(readyListener, removedListener,
+ capSetListener);
+ }
+
+ return mTestMmTelFeature;
+ }
+ }
+
+ @Override
+ public ImsRegistrationImplBase getRegistrationForSubscription(int slotId, int subId) {
+ mSubIDs.add(subId);
+ return mImsRegistrationImplBase;
+ }
+
+ @Nullable
+ @Override
+ public SipTransportImplBase getSipTransport(int slotId) {
+ if (mIsSipTransportImplemented) {
+ return mTestSipTransport;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public @NonNull Executor getExecutor() {
+ if (mIsTestTypeExecutor) {
+ return mExecutor;
+ } else {
+ mExecutor = Runnable::run;
+ return mExecutor;
+ }
+ }
+ }
+
+ private class ImsServiceUT_compat extends ImsService {
+
+ ImsServiceUT_compat(Context context) {
+ // As explained above, ImsServiceUT is created in order to get around classloader
+ // restrictions. Attach the base context from the wrapper ImsService.
+ if (getBaseContext() == null) {
+ attachBaseContext(context);
+ }
+
+ if (mIsTestTypeExecutor) {
+ mImsRegistrationImplBase = new TestImsRegistration(mExecutor);
+ mTestSipTransport = new TestSipTransport(mExecutor);
+ mTestImsConfig = new TestImsConfig(mExecutor);
+ } else {
+ mImsRegistrationImplBase = new TestImsRegistration();
+ mTestImsConfig = new TestImsConfig();
+ mTestSipTransport = new TestSipTransport();
+ }
}
@Override
@@ -146,33 +342,42 @@
@Override
public RcsFeature createRcsFeature(int slotId) {
+
+ TestImsService.ReadyListener readyListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_RCS_READY);
+ }
+ };
+
+ TestImsService.RemovedListener removedListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_REMOVE_RCS);
+ mTestRcsFeature = null;
+ }
+ };
+
+ TestImsService.CapabilitiesSetListener setListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_RCS_CAP_SET);
+ }
+ };
+
+ TestImsService.RcsCapabilityExchangeEventListener capExchangeEventListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_UCE_LISTENER_SET);
+ }
+ };
+
synchronized (mLock) {
countDownLatch(LATCH_CREATE_RCS);
- mTestRcsFeature = new TestRcsFeature(getBaseContext(),
- //onReady
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_RCS_READY);
- }
- },
- //onRemoved
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_REMOVE_RCS);
- mTestRcsFeature = null;
- }
- },
- //onCapabilitiesSet
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_RCS_CAP_SET);
- }
- },
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_UCE_LISTENER_SET);
- }
- });
+
+ if (mIsTestTypeExecutor) {
+ mTestRcsFeature = new TestRcsFeature(readyListener, removedListener,
+ setListener, capExchangeEventListener, mExecutor);
+ } else {
+ mTestRcsFeature = new TestRcsFeature(readyListener, removedListener,
+ setListener, capExchangeEventListener);
+ }
// Setup UCE request listener
mTestRcsFeature.setDeviceCapPublishListener(() -> {
@@ -195,36 +400,42 @@
@Override
public MmTelFeature createMmTelFeature(int slotId) {
+ TestImsService.ReadyListener readyListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_MMTEL_READY);
+ }
+ };
+
+ TestImsService.RemovedListener removedListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_REMOVE_MMTEL);
+ mTestMmTelFeature = null;
+ }
+ };
+
+ TestImsService.CapabilitiesSetListener capSetListener = () -> {
+ synchronized (mLock) {
+ countDownLatch(LATCH_MMTEL_CAP_SET);
+ }
+ };
+
synchronized (mLock) {
countDownLatch(LATCH_CREATE_MMTEL);
- mTestMmTelFeature = new TestMmTelFeature(
- //onReady
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_MMTEL_READY);
- }
- },
- //onRemoved
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_REMOVE_MMTEL);
- mTestMmTelFeature = null;
- }
- },
- //onCapabilitiesSet
- () -> {
- synchronized (mLock) {
- countDownLatch(LATCH_MMTEL_CAP_SET);
- }
- }
- );
+ if (mIsTestTypeExecutor) {
+ mTestMmTelFeature = new TestMmTelFeature(readyListener, removedListener,
+ capSetListener, mExecutor);
+ } else {
+ mTestMmTelFeature = new TestMmTelFeature(readyListener, removedListener,
+ capSetListener);
+ }
+
return mTestMmTelFeature;
}
}
@Override
public ImsRegistrationImplBase getRegistration(int slotId) {
- return sImsRegistrationImplBase;
+ return mImsRegistrationImplBase;
}
@Nullable
@@ -236,6 +447,62 @@
return null;
}
}
+
+ @Override
+ public @NonNull Executor getExecutor() {
+ if (mIsTestTypeExecutor) {
+ return mExecutor;
+ } else {
+ mExecutor = Runnable::run;
+ return mExecutor;
+ }
+ }
+ }
+
+ private static Looper createLooper(String name) {
+ HandlerThread thread = new HandlerThread(name);
+ thread.start();
+
+ Looper looper = thread.getLooper();
+
+ if (looper == null) {
+ return Looper.getMainLooper();
+ }
+ return looper;
+ }
+
+ /**
+ * Executes the tasks in the other thread rather than the calling thread.
+ */
+ public class MessageExecutor extends Handler implements Executor {
+ public MessageExecutor(String name) {
+ super(createLooper(name));
+ }
+
+ @Override
+ public void execute(Runnable r) {
+ Message m = Message.obtain(this, 0, r);
+ m.sendToTarget();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.obj instanceof Runnable) {
+ executeInternal((Runnable) msg.obj);
+ } else {
+ Log.d(TAG, "[MessageExecutor] handleMessage :: "
+ + "Not runnable object; ignore the msg=" + msg);
+ }
+ }
+
+ private void executeInternal(Runnable r) {
+ try {
+ r.run();
+ } catch (Throwable t) {
+ Log.d(TAG, "[MessageExecutor] executeInternal :: run task=" + r);
+ t.printStackTrace();
+ }
+ }
}
private final LocalBinder mBinder = new LocalBinder();
@@ -256,18 +523,53 @@
}
}
+ protected ImsService getImsServiceCompat() {
+ synchronized (mLock) {
+ if (mTestImsServiceCompat != null) {
+ return mTestImsServiceCompat;
+ }
+ mTestImsServiceCompat = new ImsServiceUT_compat(this);
+ return mTestImsServiceCompat;
+ }
+ }
+
@Override
public IBinder onBind(Intent intent) {
- if ("android.telephony.ims.ImsService".equals(intent.getAction())) {
- if (ImsUtils.VDBG) {
- Log.d(TAG, "onBind-Remote");
+ synchronized (mLock) {
+ if ("android.telephony.ims.ImsService".equals(intent.getAction())) {
+ mIsTelephonyBound = true;
+ if (mIsImsServiceCompat) {
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "onBind-Remote-Compat");
+ }
+ return getImsServiceCompat().onBind(intent);
+ } else {
+ if (ImsUtils.VDBG) {
+ Log.d(TAG, "onBind-Remote");
+ }
+ return getImsService().onBind(intent);
+ }
}
- return getImsService().onBind(intent);
+ if (ImsUtils.VDBG) {
+ Log.i(TAG, "onBind-Local");
+ }
+ return mBinder;
}
- if (ImsUtils.VDBG) {
- Log.i(TAG, "onBind-Local");
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ synchronized (mLock) {
+ if ("android.telephony.ims.ImsService".equals(intent.getAction())) {
+ if (ImsUtils.VDBG) Log.i(TAG, "onUnbind-Remote");
+ mIsTelephonyBound = false;
+ countDownLatch(LATCH_ON_UNBIND);
+ } else {
+ if (ImsUtils.VDBG) Log.i(TAG, "onUnbind-Local");
+ }
+ // return false so that onBind is called next time.
+ return false;
}
- return mBinder;
}
public void resetState() {
@@ -277,10 +579,38 @@
mIsEnabled = false;
mSetNullRcsBinding = false;
mIsSipTransportImplemented = false;
+ mIsTestTypeExecutor = false;
+ mIsImsServiceCompat = false;
mCapabilities = 0;
for (int i = 0; i < LATCH_MAX; i++) {
sLatches[i] = new CountDownLatch(1);
}
+
+ if (sMessageExecutor != null) {
+ sMessageExecutor.getLooper().quit();
+ sMessageExecutor = null;
+ }
+ mSubIDs.clear();
+ }
+ }
+
+ public boolean isTelephonyBound() {
+ return mIsTelephonyBound;
+ }
+
+ public void setExecutorTestType(boolean type) {
+ mIsTestTypeExecutor = type;
+ if (mIsTestTypeExecutor) {
+ if (sMessageExecutor == null) {
+ sMessageExecutor = new MessageExecutor("TestImsService");
+ }
+ mExecutor = sMessageExecutor;
+ }
+ }
+
+ public void setImsServiceCompat() {
+ synchronized (mLock) {
+ mIsImsServiceCompat = true;
}
}
@@ -329,20 +659,7 @@
}
public boolean waitForLatchCountdown(int latchIndex) {
- boolean complete = false;
- try {
- CountDownLatch latch;
- synchronized (mLock) {
- latch = sLatches[latchIndex];
- }
- complete = latch.await(ImsUtils.TEST_TIMEOUT_MS, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- // complete == false
- }
- synchronized (mLock) {
- sLatches[latchIndex] = new CountDownLatch(1);
- }
- return complete;
+ return waitForLatchCountdown(latchIndex, ImsUtils.TEST_TIMEOUT_MS);
}
public boolean waitForLatchCountdown(int latchIndex, long waitMs) {
@@ -352,7 +669,12 @@
synchronized (mLock) {
latch = sLatches[latchIndex];
}
+ long startTime = System.currentTimeMillis();
complete = latch.await(waitMs, TimeUnit.MILLISECONDS);
+ if (ImsUtils.VDBG) {
+ Log.i(TAG, "Latch " + latchIndex + " took "
+ + (System.currentTimeMillis() - startTime) + " ms to count down.");
+ }
} catch (InterruptedException e) {
// complete == false
}
@@ -388,11 +710,15 @@
public TestImsRegistration getImsRegistration() {
synchronized (mLock) {
- return sImsRegistrationImplBase;
+ return mImsRegistrationImplBase;
}
}
public ImsConfigImplBase getConfig() {
return mTestImsConfig;
}
+
+ public HashSet<Integer> getSubIDs() {
+ return mSubIDs;
+ }
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestMmTelFeature.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestMmTelFeature.java
index d38a63a..d300b71 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestMmTelFeature.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestMmTelFeature.java
@@ -16,7 +16,6 @@
package android.telephony.ims.cts;
-import android.app.UiAutomation;
import android.os.Bundle;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsStreamMediaProfile;
@@ -27,8 +26,6 @@
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
-import androidx.test.platform.app.InstrumentationRegistry;
-
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@@ -52,6 +49,21 @@
TestMmTelFeature(TestImsService.ReadyListener readyListener,
TestImsService.RemovedListener removedListener,
TestImsService.CapabilitiesSetListener setListener) {
+ Log.d(TAG, "TestMmTelFeature with default constructor");
+ mReadyListener = readyListener;
+ mRemovedListener = removedListener;
+ mCapSetListener = setListener;
+ mSmsImpl = new TestImsSmsImpl();
+ // Must set the state to READY in the constructor - onFeatureReady depends on the state
+ // being ready.
+ setFeatureState(STATE_READY);
+ }
+
+ TestMmTelFeature(TestImsService.ReadyListener readyListener,
+ TestImsService.RemovedListener removedListener,
+ TestImsService.CapabilitiesSetListener setListener, Executor executor) {
+ super(executor);
+ Log.d(TAG, "TestMmTelFeature with Executor constructor");
mReadyListener = readyListener;
mRemovedListener = removedListener;
mCapSetListener = setListener;
@@ -154,7 +166,7 @@
}
public boolean isCallSessionCreated() {
- return (mCallSession != null) ? true : false;
+ return (mCallSession != null);
}
public void onIncomingCallReceived(Bundle extras) {
@@ -175,13 +187,7 @@
Executor executor = incomingSession.getExecutor();
executor.execute(() -> {
- UiAutomation ui = InstrumentationRegistry.getInstrumentation().getUiAutomation();
- try {
- ui.adoptShellPermissionIdentity();
- notifyIncomingCall(incomingSession, extras);
- } finally {
- ui.dropShellPermissionIdentity();
- }
+ notifyIncomingCall(incomingSession, extras);
});
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java
index 08eaa85..3915fc5 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestRcsFeature.java
@@ -16,7 +16,6 @@
package android.telephony.ims.cts;
-import android.content.Context;
import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.CapabilityExchangeEventListener;
@@ -43,13 +42,30 @@
private CapabilityExchangeEventListener mCapEventListener;
private TestImsService.DeviceCapPublishListener mDeviceCapPublishListener;
- TestRcsFeature(Context context,
- TestImsService.ReadyListener readyListener,
+ TestRcsFeature(TestImsService.ReadyListener readyListener,
TestImsService.RemovedListener removedListener,
TestImsService.CapabilitiesSetListener setListener,
TestImsService.RcsCapabilityExchangeEventListener capExchangeEventListener) {
- super(context.getMainExecutor());
+ super();
+ Log.d(TAG, "TestRcsFeature with default constructor");
+ mReadyListener = readyListener;
+ mRemovedListener = removedListener;
+ mCapExchangeEventListener = capExchangeEventListener;
+ mRcsCapabilityChangedListener = setListener;
+ mRcsCapabilitiesLte = new RcsImsCapabilities(RcsImsCapabilities.CAPABILITY_TYPE_NONE);
+ mRcsCapabilitiesIWan = new RcsImsCapabilities(RcsImsCapabilities.CAPABILITY_TYPE_NONE);
+
+ setFeatureState(STATE_READY);
+ }
+
+ TestRcsFeature(TestImsService.ReadyListener readyListener,
+ TestImsService.RemovedListener removedListener,
+ TestImsService.CapabilitiesSetListener setListener,
+ TestImsService.RcsCapabilityExchangeEventListener capExchangeEventListener,
+ Executor executor) {
+ super(executor);
+ Log.d(TAG, "TestRcsFeature with Executor constructor");
mReadyListener = readyListener;
mRemovedListener = removedListener;
mCapExchangeEventListener = capExchangeEventListener;
diff --git a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipTransport.java b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipTransport.java
index 0ea195c..88dcc2a 100644
--- a/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipTransport.java
+++ b/tests/tests/telephony/current/src/android/telephony/ims/cts/TestSipTransport.java
@@ -23,6 +23,7 @@
import android.telephony.ims.DelegateStateCallback;
import android.telephony.ims.stub.SipDelegate;
import android.telephony.ims.stub.SipTransportImplBase;
+import android.util.Log;
import androidx.annotation.NonNull;
@@ -34,6 +35,7 @@
public class TestSipTransport extends SipTransportImplBase {
+ private static final String TAG = "TestSipTransport";
public static final String ONE_TO_ONE_CHAT_TAG =
"+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gppservice.ims.icsi.oma.cpm.msg\"";
public static final String GROUP_CHAT_TAG =
@@ -54,8 +56,13 @@
private final ArrayList<TestSipDelegate> mDelegates = new ArrayList<>();
private final Object mLock = new Object();
+ public TestSipTransport() {
+ Log.d(TAG, "TestSipTransport with default constructor");
+ }
+
public TestSipTransport(Executor executor) {
super(executor);
+ Log.d(TAG, "TestSipTransport with Executor constructor");
}
@Override
diff --git a/tests/tests/textclassifier/OWNERS b/tests/tests/textclassifier/OWNERS
index 3e84e0b..3da8126 100644
--- a/tests/tests/textclassifier/OWNERS
+++ b/tests/tests/textclassifier/OWNERS
@@ -1,2 +1,3 @@
# Bug component: 709498
+
include platform/frameworks/base:/core/java/android/view/textclassifier/OWNERS
diff --git a/tests/tests/vcn/AndroidTest.xml b/tests/tests/vcn/AndroidTest.xml
index 519b88a..4b431b3 100644
--- a/tests/tests/vcn/AndroidTest.xml
+++ b/tests/tests/vcn/AndroidTest.xml
@@ -19,6 +19,7 @@
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
index f3703d9..028c6b7 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -59,12 +59,13 @@
import android.os.SystemClock;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-import android.telephony.cts.util.CarrierPrivilegeUtils;
import android.telephony.cts.util.SubscriptionGroupUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.compatibility.common.util.CarrierPrivilegeUtils;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/tests/voiceRecognition/OWNERS b/tests/tests/voiceRecognition/OWNERS
index 88d73a9..fac43c0 100644
--- a/tests/tests/voiceRecognition/OWNERS
+++ b/tests/tests/voiceRecognition/OWNERS
@@ -1,7 +1,8 @@
# Bug component: 533220
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+volnov@google.com
+andreaambu@google.com
+eugeniom@google.com
+schfan@google.com
+
+# Framework team as backup
+include platform/frameworks/base:/core/java/android/service/voice/OWNERS
diff --git a/tests/tests/voiceinteraction/OWNERS b/tests/tests/voiceinteraction/OWNERS
index 88d73a9..8352b6f 100644
--- a/tests/tests/voiceinteraction/OWNERS
+++ b/tests/tests/voiceinteraction/OWNERS
@@ -1,7 +1,3 @@
# Bug component: 533220
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+
+include platform/frameworks/base:/core/java/android/service/voice/OWNERS
diff --git a/tests/tests/voicesettings/OWNERS b/tests/tests/voicesettings/OWNERS
index 88d73a9..8352b6f 100644
--- a/tests/tests/voicesettings/OWNERS
+++ b/tests/tests/voicesettings/OWNERS
@@ -1,7 +1,3 @@
# Bug component: 533220
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+
+include platform/frameworks/base:/core/java/android/service/voice/OWNERS
diff --git a/tests/translation/OWNERS b/tests/translation/OWNERS
index a1e663a..6344b5e 100644
--- a/tests/translation/OWNERS
+++ b/tests/translation/OWNERS
@@ -1,8 +1,3 @@
# Bug component: 994311
-adamhe@google.com
-augale@google.com
-joannechung@google.com
-lpeter@google.com
-svetoslavganov@google.com
-tymtsai@google.com
+include platform/frameworks/base:/core/java/android/view/translation/OWNERS
diff --git a/tools/cts-tradefed/res/config/cts-developer.xml b/tools/cts-tradefed/res/config/cts-developer.xml
index a74c1a8..62c39d8 100644
--- a/tools/cts-tradefed/res/config/cts-developer.xml
+++ b/tools/cts-tradefed/res/config/cts-developer.xml
@@ -16,7 +16,7 @@
-->
<configuration description="Runs the CTS developer added tests">
- <include name="cts" />
+ <include name="cts-common" />
<option name="plan" value="cts-developer" />
diff --git a/tools/release-parser/tests/resources/platform.xml b/tools/release-parser/tests/resources/platform.xml
index 5895f77..878cf1a 100644
--- a/tools/release-parser/tests/resources/platform.xml
+++ b/tools/release-parser/tests/resources/platform.xml
@@ -192,11 +192,11 @@
<library name="org.apache.http.legacy"
file="/system/framework/org.apache.http.legacy.boot.jar" />
- <!-- These are the standard packages that are white-listed to always have internet
+ <!-- These are the standard packages that are allow-listed to always have internet
access while in power save mode, even if they aren't in the foreground. -->
<allow-in-power-save package="com.android.providers.downloads" />
- <!-- These are the standard packages that are white-listed to always have internet
+ <!-- These are the standard packages that are allow-listed to always have internet
access while in data mode, even if they aren't in the foreground. -->
<allow-in-data-usage-save package="com.android.providers.downloads" />
@@ -204,7 +204,7 @@
<allow-in-power-save package="com.android.cellbroadcastreceiver" />
<allow-in-power-save package="com.android.shell" />
- <!-- Whitelist system providers -->
+ <!-- Allowlist system providers -->
<allow-in-power-save-except-idle package="com.android.providers.calendar" />
<allow-in-power-save-except-idle package="com.android.providers.contacts" />
</permissions>