Merge "Change MediaProjection CTS directory"
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 974fc24..7283f20 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -234,6 +234,8 @@
raw_avlb = camera_properties_utils.raw16(props)
debug = self.debug_mode
+ # Converge 3A.
+ cam.do_3a()
req = capture_request_utils.auto_capture_request()
# If raw available, use as ground truth.
diff --git a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
index de5bfd4..c0d9f39 100644
--- a/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
+++ b/apps/CameraITS/tests/scene4/test_preview_stabilization_fov.py
@@ -38,7 +38,7 @@
_MAX_CENTER_THRESHOLD_PERCENT = 0.075
_MAX_AREA = 1920 * 1440 # max mandatory preview stream resolution
-_MIN_CENTER_THRESHOLD_PERCENT = 0.02
+_MIN_CENTER_THRESHOLD_PERCENT = 0.03
_MIN_AREA = 176 * 144 # assume QCIF to be min preview size
diff --git a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
index 1f09669..844807b 100644
--- a/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_video_aspect_ratio_and_crop.py
@@ -162,12 +162,11 @@
if raw_avlb and (fls_physical == fls_logical):
logging.debug('RAW')
- raw_bool = True
else:
logging.debug('JPEG')
- raw_bool = False
+
ref_fov, cc_ct_gt, aspect_ratio_gt = image_fov_utils.find_fov_reference(
- cam, req, props, raw_bool, ref_img_name_stem)
+ cam, req, props, raw_avlb, ref_img_name_stem)
run_crop_test = full_or_better and raw_avlb
diff --git a/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py b/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
index 93e4f11..834fe9b 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_multi_camera_frame_sync.py
@@ -245,10 +245,21 @@
hidden_physical_id=self.hidden_physical_id) as cam:
props = cam.get_camera_properties()
props = cam.override_with_hidden_physical_camera_props(props)
+ unavailable_physical_cameras = cam.get_unavailable_physical_cameras(
+ self.camera_id)
+ unavailable_physical_ids = unavailable_physical_cameras['unavailablePhysicalCamerasArray']
+ # find available physical camera IDs
+ all_physical_ids = camera_properties_utils.logical_multi_camera_physical_ids(
+ props)
+ for i in unavailable_physical_ids:
+ if i in all_physical_ids:
+ all_physical_ids.remove(i)
+ logging.debug('available physical ids: %s', all_physical_ids)
# Check SKIP conditions.
camera_properties_utils.skip_unless(
- camera_properties_utils.multi_camera_frame_sync_capable(props))
+ camera_properties_utils.multi_camera_frame_sync_capable(props) and
+ len(all_physical_ids) >= 2)
# Get first API level & multi camera sync type
first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 480fca3..4e01da0 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -453,6 +453,24 @@
self.sock.settimeout(self.SOCK_TIMEOUT)
return data['objValue']
+ def get_unavailable_physical_cameras(self, camera_id):
+ """Get the unavailable physical cameras ids.
+
+ Args:
+ camera_id: int; device id
+ Returns:
+ List of all physical camera ids which are unavailable.
+ """
+ cmd = {'cmdName': 'doGetUnavailablePhysicalCameras',
+ 'cameraId': camera_id}
+ self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
+ timeout = self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT
+ self.sock.settimeout(timeout)
+ data, _ = self.__read_response_from_socket()
+ if data['tag'] != 'unavailablePhysicalCameras':
+ raise error_util.CameraItsError('Invalid command response')
+ return data['objValue']
+
def is_hlg10_recording_supported(self, profile_id):
"""Query whether the camera device supports HLG10 video recording.
diff --git a/apps/CameraITS/utils/opencv_processing_utils.py b/apps/CameraITS/utils/opencv_processing_utils.py
index ae71504..ef0c8ac 100644
--- a/apps/CameraITS/utils/opencv_processing_utils.py
+++ b/apps/CameraITS/utils/opencv_processing_utils.py
@@ -42,7 +42,9 @@
CIRCLISH_LOW_RES_ATOL = 0.15 # loosen for low res images
CIRCLE_MIN_PTS = 20
CIRCLE_RADIUS_NUMPTS_THRESH = 2 # contour num_pts/radius: empirically ~3x
+CIRCLE_COLOR_ATOL = 0.01 # circle color fill tolerance
+CV2_CONTOUR_LINE_THICKNESS = 3 # for drawing contours if multiple circles found
CV2_RED = (255, 0, 0) # color in cv2 to draw lines
FOV_THRESH_TELE25 = 25
@@ -312,6 +314,28 @@
return shape
+def find_circle_fill_metric(shape, img_bw, color):
+ """Find the proportion of points matching a desired color on a shape's axes.
+
+ Args:
+ shape: dictionary returned by component_shape(...)
+ img_bw: binarized numpy image array
+ color: int of [0 or 255] 0 is black, 255 is white
+ Returns:
+ float: number of x, y axis points matching color / total x, y axis points
+ """
+ matching = 0
+ total = 0
+ for y in range(shape['top'], shape['bottom']):
+ total += 1
+ matching += 1 if img_bw[y][shape['ctx']] == color else 0
+ for x in range(shape['left'], shape['right']):
+ total += 1
+ matching += 1 if img_bw[shape['cty']][x] == color else 0
+ logging.debug('Found %d matching points out of %d', matching, total)
+ return matching / total
+
+
def find_circle(img, img_name, min_area, color):
"""Find the circle in the test image.
@@ -343,6 +367,7 @@
# Check each contour and find the circle bigger than min_area
num_circles = 0
+ circle_contours = []
logging.debug('Initial number of contours: %d', len(contours))
for contour in contours:
area = cv2.contourArea(contour)
@@ -354,13 +379,16 @@
colour = img_bw[shape['cty']][shape['ctx']]
circlish = (math.pi * radius**2) / area
aspect_ratio = shape['width'] / shape['height']
+ fill = find_circle_fill_metric(shape, img_bw, color)
logging.debug('Potential circle found. radius: %.2f, color: %d, '
- 'circlish: %.3f, ar: %.3f, pts: %d', radius, colour,
- circlish, aspect_ratio, num_pts)
+ 'circlish: %.3f, ar: %.3f, pts: %d, fill metric: %.3f',
+ radius, colour, circlish, aspect_ratio, num_pts, fill)
if (colour == color and
- numpy.isclose(1.0, circlish, atol=circlish_atol) and
- numpy.isclose(1.0, aspect_ratio, atol=CIRCLE_AR_ATOL) and
- num_pts/radius >= CIRCLE_RADIUS_NUMPTS_THRESH):
+ math.isclose(1.0, circlish, abs_tol=circlish_atol) and
+ math.isclose(1.0, aspect_ratio, abs_tol=CIRCLE_AR_ATOL) and
+ num_pts/radius >= CIRCLE_RADIUS_NUMPTS_THRESH and
+ math.isclose(1.0, fill, abs_tol=CIRCLE_COLOR_ATOL)):
+ circle_contours.append(contour)
# Populate circle dictionary
circle['x'] = shape['ctx']
@@ -389,6 +417,11 @@
if num_circles > 1:
image_processing_utils.write_image(img/255, img_name, True)
+ cv2.drawContours(img, circle_contours, -1, CV2_RED,
+ CV2_CONTOUR_LINE_THICKNESS)
+ img_name_parts = img_name.split('.')
+ image_processing_utils.write_image(
+ img/255, f'{img_name_parts[0]}_contours.{img_name_parts[1]}', True)
raise AssertionError('More than 1 black circle detected. '
'Background of scene may be too complex.')
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index b140e56..a6eb237 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cts.verifier"
android:versionCode="5"
- android:versionName="13_r3">
+ android:versionName="13_r4">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="33"/>
@@ -3049,7 +3049,7 @@
<meta-data android:name="test_excluded_features"
android:value="android.hardware.type.automotive"/>
<meta-data android:name="display_mode"
- android:value="single_display_mode" />
+ android:value="multi_display_mode" />
</activity>
<activity android:name=".camera.flashlight.CameraFlashlightActivity"
diff --git a/apps/CtsVerifier/jni/audio_loopback/OWNERS b/apps/CtsVerifier/jni/audio_loopback/OWNERS
new file mode 100644
index 0000000..0f50343
--- /dev/null
+++ b/apps/CtsVerifier/jni/audio_loopback/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48436
+elaurent@google.com
+pmclean@google.com
+philburk@google.com
diff --git a/apps/CtsVerifier/jni/midi/OWNERS b/apps/CtsVerifier/jni/midi/OWNERS
new file mode 100644
index 0000000..0f50343
--- /dev/null
+++ b/apps/CtsVerifier/jni/midi/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48436
+elaurent@google.com
+pmclean@google.com
+philburk@google.com
diff --git a/apps/CtsVerifier/jni/verifier/OWNERS b/apps/CtsVerifier/jni/verifier/OWNERS
new file mode 100644
index 0000000..0f50343
--- /dev/null
+++ b/apps/CtsVerifier/jni/verifier/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 48436
+elaurent@google.com
+pmclean@google.com
+philburk@google.com
diff --git a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
index 24767d2..716b18f 100644
--- a/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
+++ b/apps/CtsVerifier/res/layout/audio_headset_audio_activity.xml
@@ -123,7 +123,8 @@
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/analog_headset_keycodes_label"/>
+ android:text="@string/analog_headset_keycodes_label"
+ android:id="@+id/headset_keycodes"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/apps/CtsVerifier/res/layout/logcat_read_logs.xml b/apps/CtsVerifier/res/layout/logcat_read_logs.xml
index e7cf4ab..db48502 100644
--- a/apps/CtsVerifier/res/layout/logcat_read_logs.xml
+++ b/apps/CtsVerifier/res/layout/logcat_read_logs.xml
@@ -14,40 +14,43 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ style="@style/RootLayoutPadding"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:padding="10dip"
->
+ android:layout_height="match_parent">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:text="Test should be executed at least 2 minutes apart"
- android:id="@+id/run_read_logs_title"
- android:layout_margin="2dp"
- android:textSize="14sp"
- android:textStyle="bold"
- />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <Button android:id="@+id/run_read_logs_fg_allow_btn"
- android:text="@string/read_logs_fg_allow_text"
- android:layout_marginBottom="20dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:text="Test should be executed at least 2 minutes apart"
+ android:id="@+id/run_read_logs_title"
+ android:layout_margin="2dp"
+ android:textSize="14sp"
+ android:textStyle="bold"
+ />
- <Button android:id="@+id/run_read_logs_fg_deny_btn"
- android:text="@string/read_logs_fg_deny_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" />
+ <Button android:id="@+id/run_read_logs_fg_allow_btn"
+ android:text="@string/read_logs_fg_allow_text"
+ android:layout_marginBottom="20dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
- <include android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- layout="@layout/pass_fail_buttons"
- />
+ <Button android:id="@+id/run_read_logs_fg_deny_btn"
+ android:text="@string/read_logs_fg_deny_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"/>
-</LinearLayout>
+ <include android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ layout="@layout/pass_fail_buttons"
+ />
+ </LinearLayout>
+</ScrollView>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index b694e2f..704be2e 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -5419,6 +5419,16 @@
input jack and BT01 input plug to the USB interface output jack.
\nThe Virtual MIDI test does not require any MIDI interface hardware.
</string>
+ <string name="analog_headset_test_info_tv">This test tests the following functionality with respect to wired analog headsets.\n
+ 1. Correct audio playback.\n
+ 2. Plug intents.\n
+ \nTo execute test:\n
+ 1. Plug in an Android-compatible, analog headset. Verify connection/recognition.\n
+ 2. Play test tone and verify correct behavior.\n
+ \nTo run this test it is necessary to have an Android device with a 3.5mm analog headset jack and a compatible analog headset.\n
+ \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>
<string name="midiHasMIDILbl">Has MIDI Support</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 83b32de..307eb6f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Color;
import android.media.AudioDeviceCallback;
@@ -153,6 +154,14 @@
mHeadsetVolUpText = (TextView)findViewById(R.id.headset_keycode_volume_up);
mHeadsetVolDownText = (TextView)findViewById(R.id.headset_keycode_volume_down);
+ if (isTelevision()) {
+ mButtonsPromptTxt.setVisibility(View.GONE);
+ mHeadsetHookText.setVisibility(View.GONE);
+ mHeadsetVolUpText.setVisibility(View.GONE);
+ mHeadsetVolDownText.setVisibility(View.GONE);
+ ((TextView) findViewById(R.id.headset_keycodes)).setVisibility(View.GONE);
+ }
+
mResultsTxt = (TextView)findViewById(R.id.headset_results);
mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
@@ -168,7 +177,8 @@
showKeyMessagesState();
- setInfoResources(R.string.analog_headset_test, R.string.analog_headset_test_info, -1);
+ setInfoResources(R.string.analog_headset_test, isTelevision()
+ ? R.string.analog_headset_test_info_tv : R.string.analog_headset_test_info, -1);
setPassFailButtonClickListeners();
getPassButton().setEnabled(false);
@@ -182,11 +192,12 @@
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass_noheadset));
return true;
} else {
- boolean pass = isReportLogOkToPass()
- && mPlugIntentReceived
- && mHeadsetDeviceInfo != null
- && mPlaybackSuccess
- && (mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown;
+ boolean pass = isReportLogOkToPass() &&
+ mPlugIntentReceived &&
+ mHeadsetDeviceInfo != null &&
+ mPlaybackSuccess &&
+ (isTelevision()
+ || ((mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown));
if (pass) {
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
} else if (!isReportLogOkToPass()) {
@@ -488,4 +499,8 @@
}
return super.onKeyDown(keyCode, event);
}
+
+ private boolean isTelevision() {
+ return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ }
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index 8ff2358..cf09a74 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -16,6 +16,11 @@
package com.android.cts.verifier.audio;
+import static com.android.cts.verifier.TestListActivity.sCurrentDisplayMode;
+import static com.android.cts.verifier.TestListAdapter.setTestNameSuffix;
+
+import android.mediapc.cts.common.PerformanceClassEvaluator;
+
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
@@ -46,6 +51,7 @@
import org.hyphonate.megaaudio.recorder.AudioSinkProvider;
import org.hyphonate.megaaudio.recorder.sinks.AppCallback;
import org.hyphonate.megaaudio.recorder.sinks.AppCallbackAudioSinkProvider;
+import org.junit.rules.TestName;
/**
* CtsVerifier test to measure tap-to-tone latency.
@@ -144,6 +150,8 @@
private static final String KEY_LATENCY_AVE = "latency_max_";
private static final String KEY_LATENCY_NUM_MEASUREMENTS = "latency_num_measurements_";
+ public final TestName testName = new TestName();
+
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.audio_tap2tone_activity);
@@ -505,6 +513,54 @@
super.setTestResultAndFinish(passed);
}
+ private void reportTestResultForApi(int api) {
+ CtsVerifierReportLog reportLog = getReportLog();
+ reportLog.addValue(
+ KEY_LATENCY_MIN + api,
+ mLatencyMin[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ reportLog.addValue(
+ KEY_LATENCY_MAX + api,
+ mLatencyMax[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ reportLog.addValue(
+ KEY_LATENCY_AVE + api,
+ mLatencyAve[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ reportLog.addValue(
+ KEY_LATENCY_NUM_MEASUREMENTS + api,
+ mNumMeasurements[api],
+ ResultType.NEUTRAL,
+ ResultUnit.NONE);
+ }
+
+ /** Records perf class results and returns if mpc is met */
+ private void recordPerfClassResults() {
+ PerformanceClassEvaluator pce = new PerformanceClassEvaluator(testName);
+ PerformanceClassEvaluator.AudioTap2ToneLatencyRequirement r5_6__h_1_1 =
+ pce.addR5_6__H_1_1();
+
+ r5_6__h_1_1.setNativeLatency(mLatencyAve[TEST_API_NATIVE]);
+ r5_6__h_1_1.setJavaLatency(mLatencyAve[TEST_API_JAVA]);
+
+ pce.submitAndVerify();
+ }
+
+ @Override
+ public void recordTestResults() {
+ Log.i(TAG, "recordTestResults()");
+
+ reportTestResultForApi(TEST_API_NATIVE);
+ reportTestResultForApi(TEST_API_JAVA);
+
+ getReportLog().submit();
+
+ recordPerfClassResults();
+ }
+
//
// AppCallback overrides
//
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
index 4ef46fa..8d1d3a0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java
@@ -78,6 +78,7 @@
import android.os.SystemClock;
import android.os.Vibrator;
import android.util.Log;
+import android.util.Pair;
import android.util.Rational;
import android.util.Size;
import android.util.SparseArray;
@@ -123,6 +124,7 @@
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.HashSet;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
@@ -183,6 +185,8 @@
public static final String EVCOMP_KEY = "evComp";
public static final String AUTO_FLASH_KEY = "autoFlash";
public static final String AUDIO_RESTRICTION_MODE_KEY = "mode";
+ public static final int AVAILABILITY_TIMEOUT_MS = 10;
+
private CameraManager mCameraManager = null;
private HandlerThread mCameraThread = null;
@@ -252,6 +256,8 @@
private volatile boolean mNeedsLockedAWB = false;
private volatile boolean mDoAE = true;
private volatile boolean mDoAF = true;
+ private Set<Pair<String, String>> mUnavailablePhysicalCameras;
+
class MySensorEvent {
public Sensor sensor;
@@ -469,6 +475,7 @@
}
try {
+ mUnavailablePhysicalCameras = getUnavailablePhysicalCameras();
mCamera = mBlockingCameraManager.openCamera(cameraId, mCameraListener, mCameraHandler);
mCameraCharacteristics = mCameraManager.getCameraCharacteristics(cameraId);
@@ -826,6 +833,9 @@
doCheckHLG10Support(cameraId, profileId);
} else if ("doCaptureWithFlash".equals(cmdObj.getString("cmdName"))) {
doCaptureWithFlash(cmdObj);
+ } else if ("doGetUnavailablePhysicalCameras".equals(cmdObj.getString("cmdName"))) {
+ String cameraId = cmdObj.getString("cameraId");
+ doGetUnavailablePhysicalCameras(cameraId);
} else {
throw new ItsException("Unknown command: " + cmd);
}
@@ -1184,6 +1194,53 @@
hasPrivacySupport ? "true" : "false");
}
+ private void doGetUnavailablePhysicalCameras(String cameraId) throws ItsException {
+ try {
+ JSONArray cameras = new JSONArray();
+ JSONObject jsonObj = new JSONObject();
+ for (Pair<String, String> p : mUnavailablePhysicalCameras) {
+ if (cameraId.equals(p.first)) {
+ cameras.put(p.second);
+ }
+ }
+ jsonObj.put("unavailablePhysicalCamerasArray", cameras);
+ Log.i(TAG, "unavailablePhysicalCameras : " +
+ Arrays.asList(mUnavailablePhysicalCameras.toString()));
+ mSocketRunnableObj.sendResponse("unavailablePhysicalCameras", null, jsonObj, null);
+ } catch (org.json.JSONException e) {
+ throw new ItsException("JSON error: ", e);
+ }
+ }
+
+ private Set<Pair<String, String>> getUnavailablePhysicalCameras() throws ItsException {
+ final LinkedBlockingQueue<Pair<String, String>> unavailablePhysicalCamEventQueue =
+ new LinkedBlockingQueue<>();
+ try {
+ CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
+ @Override
+ public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
+ unavailablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
+ }
+ };
+ mCameraManager.registerAvailabilityCallback(ac, mCameraHandler);
+ Set<Pair<String, String>> unavailablePhysicalCameras =
+ new HashSet<Pair<String, String>>();
+ Pair<String, String> candidatePhysicalIds =
+ unavailablePhysicalCamEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
+ java.util.concurrent.TimeUnit.MILLISECONDS);
+ while (candidatePhysicalIds != null) {
+ unavailablePhysicalCameras.add(candidatePhysicalIds);
+ candidatePhysicalIds =
+ unavailablePhysicalCamEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
+ java.util.concurrent.TimeUnit.MILLISECONDS);
+ }
+ mCameraManager.unregisterAvailabilityCallback(ac);
+ return unavailablePhysicalCameras;
+ } catch (Exception e) {
+ throw new ItsException("Exception: ", e);
+ }
+ }
+
private void doCheckPrimaryCamera(String cameraId) throws ItsException {
if (mItsCameraIdList == null) {
mItsCameraIdList = ItsUtils.getItsCompatibleCameraIds(mCameraManager);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
index 33f8f2c..ee505fc 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsTestActivity.java
@@ -391,7 +391,7 @@
// Save MPC info once both front primary and rear primary data are collected.
if (mExecutedMpcTests.size() == 4) {
- mPce.submit();
+ mPce.submitAndVerify();
}
return true;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
index d23d43b..69580bc 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/ByodFlowTestActivity.java
@@ -116,9 +116,9 @@
private TestListItem mDisableLocationModeThroughMainSwitchTest;
private TestListItem mDisableLocationModeThroughWorkSwitchTest;
private TestListItem mPrimaryLocationWhenWorkDisabledTest;
- private DialogTestListItem mSelectWorkChallenge;
- private DialogTestListItem mConfirmWorkCredentials;
- private DialogTestListItem mPatternWorkChallenge;
+// private DialogTestListItem mSelectWorkChallenge;
+// private DialogTestListItem mConfirmWorkCredentials;
+// private DialogTestListItem mPatternWorkChallenge;
private DialogTestListItem mParentProfilePassword;
private DialogTestListItem mPersonalRingtonesTest;
private TestListItem mVpnTest;
@@ -291,19 +291,20 @@
R.string.provisioning_byod_workapps_visible_instruction,
new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),
R.drawable.badged_icon);
-
+ /* Disabling due to b/259890166
mConfirmWorkCredentials = new DialogTestListItem(this,
R.string.provisioning_byod_confirm_work_credentials,
"BYOD_ConfirmWorkCredentials",
R.string.provisioning_byod_confirm_work_credentials_description,
new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
-
+ */
+ /* Disable due to b/242477777
mPatternWorkChallenge = new DialogTestListItem(this,
R.string.provisioning_byod_pattern_work_challenge,
"BYOD_PatternWorkChallenge",
R.string.provisioning_byod_pattern_work_challenge_description,
new Intent(ByodHelperActivity.ACTION_TEST_PATTERN_WORK_CHALLENGE));
-
+ */
mWiFiDataUsageSettingsVisibleTest = new DialogTestListItem(this,
R.string.provisioning_byod_wifi_data_usage_settings,
"BYOD_WiFiDataUsageSettingsVisibleTest",
@@ -471,13 +472,13 @@
"BYOD_PermissionLockdownTest",
R.string.profile_owner_permission_lockdown_test_info,
permissionCheckIntent);
-
+ /* Disable due to b/241498104
mSelectWorkChallenge = new DialogTestListItem(this,
R.string.provisioning_byod_select_work_challenge,
"BYOD_SelectWorkChallenge",
R.string.provisioning_byod_select_work_challenge_description,
new Intent(ByodHelperActivity.ACTION_TEST_SELECT_WORK_CHALLENGE));
-
+ */
mRecentsTest = TestListItem.newTest(this,
R.string.provisioning_byod_recents,
RecentsRedactionActivity.class.getName(),
@@ -560,11 +561,11 @@
adapter.add(mVpnTest);
adapter.add(mAlwaysOnVpnSettingsTest);
adapter.add(mTurnOffWorkFeaturesTest);
- adapter.add(mSelectWorkChallenge);
- if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
- adapter.add(mConfirmWorkCredentials);
- adapter.add(mPatternWorkChallenge);
- }
+// adapter.add(mSelectWorkChallenge);
+// if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+// adapter.add(mConfirmWorkCredentials);
+// adapter.add(mPatternWorkChallenge);
+// }
adapter.add(mRecentsTest);
adapter.add(mOrganizationInfoTest);
adapter.add(mParentProfilePassword);
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/OWNERS
index ea76354..5a93fd0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/OWNERS
@@ -1,2 +1,6 @@
# Bug component: 48448
-alisher@google.com
\ No newline at end of file
+alisher@google.com
+jackcwyu@google.com
+georgekgchang@google.com
+sattiraju@google.com
+henrichataing@google.com
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
index b804b45..a0f5bd0 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/FingerprintBoundKeysTest.java
@@ -24,6 +24,8 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
+import android.hardware.biometrics.BiometricManager;
+import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.os.CancellationSignal;
@@ -70,6 +72,8 @@
protected boolean useStrongBox;
+ private BiometricManager mBiometricManager;
+
private FingerprintManager mFingerprintManager;
private KeyguardManager mKeyguardManager;
private FingerprintAuthDialogFragment mFingerprintDialog;
@@ -92,6 +96,10 @@
getPassButton().setEnabled(false);
requestPermissions(new String[]{Manifest.permission.USE_BIOMETRIC},
BIOMETRIC_REQUEST_PERMISSION_CODE);
+
+ mBiometricManager = getSystemService(BiometricManager.class);
+
+ checkBiometricStrength();
}
@Override
@@ -134,6 +142,28 @@
}
}
+ private void checkBiometricStrength()
+ {
+ if (!hasStrongBiometrics())
+ {
+ // Disable the start button
+ Button startTestButton = findViewById(R.id.sec_start_test_button);
+ startTestButton.setEnabled(false);
+
+ // Show a message that STRONG Biometrics is not supported and user can
+ // pass the test.
+ showToast("Device does not support STRONG Biometric level of authentication.");
+
+ // Allow to pass the test
+ getPassButton().setEnabled(true);
+ }
+ }
+
+ private boolean hasStrongBiometrics() {
+ return mBiometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG)
+ != BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE;
+ }
+
protected void startTest() {
createKey(false /* hasValidityDuration */);
prepareEncrypt();
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/BlockingIntentSender.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/BlockingIntentSender.java
index a3f5007..86e2d4f 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/BlockingIntentSender.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/utils/BlockingIntentSender.java
@@ -69,6 +69,7 @@
Intent intent = new Intent(mAction);
intent.setPackage(mTestApis.context().instrumentedContext().getPackageName());
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
mTestApis.context().instrumentedContext(),
/* requestCode= */ 0,
diff --git a/common/device-side/util-axt/Android.bp b/common/device-side/util-axt/Android.bp
index 11f851b..d07fe3d 100644
--- a/common/device-side/util-axt/Android.bp
+++ b/common/device-side/util-axt/Android.bp
@@ -16,8 +16,8 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-java_library_static {
- name: "compatibility-device-util-axt",
+java_defaults {
+ name: "compatibility-device-util-axt-default",
sdk_version: "test_current",
srcs: [
@@ -31,23 +31,39 @@
"androidx.test.rules",
"androidx.test.ext.junit",
"ub-uiautomator",
- "mockito-target-minus-junit4",
"androidx.annotation_annotation",
"truth-prebuilt",
"modules-utils-build_system",
],
libs: [
- "android.test.runner",
- "android.test.base",
+ "android.test.runner.stubs",
+ "android.test.base.stubs",
],
jarjar_rules: "protobuf-jarjar-rules.txt",
}
+java_library_static {
+ name: "compatibility-device-util-axt",
+ defaults: ["compatibility-device-util-axt-default"],
+ static_libs: [
+ "mockito-target-minus-junit4",
+ ],
+}
+
+// This target can be used with ExtendedMockito
+java_library {
+ name: "compatibility-device-util-axt-minus-dexmaker",
+ defaults: ["compatibility-device-util-axt-default"],
+ static_libs: [
+ "mockito",
+ ],
+}
+
filegroup {
name: "compatibility-device-util-nodeps",
srcs: [
- "src/com/android/compatibility/common/util/IBinderParcelable.java",
+ "src/com/android/compatibility/common/util/IBinderParcelable.java",
],
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java
index e53eb08..5cabd64 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/CtsMouseUtil.java
@@ -126,8 +126,8 @@
@Override
public boolean matches(MotionEvent actual) {
return super.matches(actual)
- && ((int) actual.getX()) == mX
- && ((int) actual.getY()) == mY;
+ && Math.round(actual.getX()) == mX
+ && Math.round(actual.getY()) == mY;
}
@Override
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java
index 06b8cc2..ad78975 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/MediaPerfUtils.java
@@ -16,6 +16,7 @@
package com.android.compatibility.common.util;
import android.media.MediaFormat;
+import android.util.Log;
import android.util.Range;
import com.android.compatibility.common.util.DeviceReportLog;
@@ -23,7 +24,6 @@
import com.android.compatibility.common.util.ResultUnit;
import java.util.Arrays;
-import android.util.Log;
public class MediaPerfUtils {
private static final String TAG = "MediaPerfUtils";
@@ -36,6 +36,8 @@
// a limit for the size of the published rates (e.g. upper-limit / lower-limit <= tolerance).
private static final double FRAMERATE_TOLERANCE = 2.0 * 1.1;
+ // Allow extra tolerance when B frames are enabled
+ private static final double EXTRA_TOLERANCE_BFRAMES = 1.25;
/*
* ------------------ HELPER METHODS FOR ACHIEVABLE FRAME RATES ------------------
*/
@@ -146,18 +148,31 @@
/** Verifies |measuredFps| against reported achievable rates. Returns null if at least
* one measurement falls within the margins of the reported range. Otherwise, returns
* an error message to display.*/
- public static String verifyAchievableFrameRates(
- String name, String mime, int w, int h, boolean fasterIsOk, double... measuredFps) {
+ public static String verifyAchievableFrameRates(String name, String mime, int w,
+ int h, boolean fasterIsOk, double... measuredFps) {
+ return verifyAchievableFrameRates(
+ name, mime, w, h, fasterIsOk, /* bFramesEnabled */ false, measuredFps);
+ }
+
+ /** Verifies |measuredFps| against reported achievable rates allowing extra tolerance when
+ * B frames are enabled. Returns null if at least one measurement falls within the margins
+ * of the reported range. Otherwise, returns an error message to display.*/
+ public static String verifyAchievableFrameRates(String name, String mime, int w, int h,
+ boolean fasterIsOk, boolean bFramesEnabled, double... measuredFps) {
Range<Double> reported =
MediaUtils.getVideoCapabilities(name, mime).getAchievableFrameRatesFor(w, h);
String kind = "achievable frame rates for " + name + " " + mime + " " + w + "x" + h;
if (reported == null) {
return "Failed to get " + kind;
}
- double lowerBoundary1 = reported.getLower() / FRAMERATE_TOLERANCE;
- double upperBoundary1 = reported.getUpper() * FRAMERATE_TOLERANCE;
- double lowerBoundary2 = reported.getUpper() / Math.pow(FRAMERATE_TOLERANCE, 2);
- double upperBoundary2 = reported.getLower() * Math.pow(FRAMERATE_TOLERANCE, 2);
+ double tolerance = FRAMERATE_TOLERANCE;
+ if (bFramesEnabled) {
+ tolerance *= EXTRA_TOLERANCE_BFRAMES;
+ }
+ double lowerBoundary1 = reported.getLower() / tolerance;
+ double upperBoundary1 = reported.getUpper() * tolerance;
+ double lowerBoundary2 = reported.getUpper() / Math.pow(tolerance, 2);
+ double upperBoundary2 = reported.getLower() * Math.pow(tolerance, 2);
Log.d(TAG, name + " " + mime + " " + w + "x" + h +
" lowerBoundary1 " + lowerBoundary1 + " upperBoundary1 " + upperBoundary1 +
" lowerBoundary2 " + lowerBoundary2 + " upperBoundary2 " + upperBoundary2 +
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
index b85bed9..56a053b 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
@@ -1,2 +1,3 @@
+per-file AnrMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
per-file BaseDefaultPermissionGrantPolicyTest.java = file:platform/frameworks/base:/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
per-file ReadElf.java = enh@google.com
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
index a9543c2..1611e13 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/UiAutomatorUtils.java
@@ -42,7 +42,13 @@
private static final String LOG_TAG = "UiAutomatorUtils";
/** Default swipe deadzone percentage. See {@link UiScrollable}. */
- private static final double DEFAULT_SWIPE_DEADZONE_PCT = 0.1;
+ private static final double DEFAULT_SWIPE_DEADZONE_PCT_TV = 0.1f;
+ private static final double DEFAULT_SWIPE_DEADZONE_PCT_ALL = 0.25f;
+ /**
+ * On Wear, some cts tests like CtsPermission3TestCases that run on
+ * low performance device. Keep 0.05 to have better matching.
+ */
+ private static final double DEFAULT_SWIPE_DEADZONE_PCT_WEAR = 0.05f;
/** Minimum view height accepted (before needing to scroll more). */
private static final float MIN_VIEW_HEIGHT_DP = 8;
@@ -78,6 +84,16 @@
ApplicationProvider.getApplicationContext().getResources().getDisplayMetrics()));
}
+ private static double getSwipeDeadZonePct() {
+ if (FeatureUtil.isTV()) {
+ return DEFAULT_SWIPE_DEADZONE_PCT_TV;
+ } else if (FeatureUtil.isWatch()) {
+ return DEFAULT_SWIPE_DEADZONE_PCT_WEAR;
+ } else {
+ return DEFAULT_SWIPE_DEADZONE_PCT_ALL;
+ }
+ }
+
public static UiObject2 waitFindObjectOrNull(BySelector selector, long timeoutMs)
throws UiObjectNotFoundException {
UiObject2 view = null;
@@ -101,8 +117,7 @@
}
if (view == null || view.getVisibleBounds().height() < minViewHeightPx) {
- final double deadZone = !(FeatureUtil.isWatch() || FeatureUtil.isTV())
- ? 0.25 : DEFAULT_SWIPE_DEADZONE_PCT;
+ final double deadZone = getSwipeDeadZonePct();
UiScrollable scrollable = new UiScrollable(new UiSelector().scrollable(true));
scrollable.setSwipeDeadZonePercentage(deadZone);
if (scrollable.exists()) {
diff --git a/hostsidetests/appsearch/Android.bp b/hostsidetests/appsearch/Android.bp
index cb2762ca..17e1022 100644
--- a/hostsidetests/appsearch/Android.bp
+++ b/hostsidetests/appsearch/Android.bp
@@ -64,6 +64,7 @@
manifest: "test-apps/AppSearchHostTestHelperA/AndroidManifest.xml",
certificate: ":cts-appsearch-hosttest-helper-cert-a",
sdk_version: "test_current",
+ min_sdk_version: "31",
}
android_test_helper_app {
@@ -87,4 +88,5 @@
manifest: "test-apps/AppSearchHostTestHelperB/AndroidManifest.xml",
certificate: ":cts-appsearch-hosttest-helper-cert-b",
sdk_version: "test_current",
+ min_sdk_version: "31",
}
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.bp b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.bp
index 134b231..2423476 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "CtsExternalStorageApp",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
target_sdk_version: "29",
sdk_version: "30",
static_libs: [
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/Android.bp b/hostsidetests/appsecurity/test-apps/MediaStorageApp/Android.bp
index a110ce0..e83bcd8e 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "CtsMediaStorageApp",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
sdk_version: "test_current",
static_libs: [
"compatibility-device-util-axt",
@@ -37,6 +38,7 @@
android_test_helper_app {
name: "CtsMediaStorageApp28",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "28",
sdk_version: "test_current",
static_libs: [
"compatibility-device-util-axt",
@@ -56,6 +58,7 @@
android_test_helper_app {
name: "CtsMediaStorageApp29",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
sdk_version: "test_current",
static_libs: [
"compatibility-device-util-axt",
diff --git a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.bp b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.bp
index 0ec98cb..da3f96e 100644
--- a/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/MultiUserStorageApp/Android.bp
@@ -20,6 +20,7 @@
name: "CtsMultiUserStorageApp",
defaults: ["cts_support_defaults"],
sdk_version: "current",
+ min_sdk_version: "29",
target_sdk_version: "29",
static_libs: [
"androidx.test.rules",
diff --git a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.bp b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.bp
index 4893590..f1eb155 100644
--- a/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/ReadExternalStorageApp/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "CtsReadExternalStorageApp",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
target_sdk_version: "29",
sdk_version: "30",
static_libs: [
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.bp b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.bp
index 2744c6f..27b2310 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "CtsWriteExternalStorageApp",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
sdk_version: "test_current",
static_libs: [
"CtsWriteExternalStorageWriteGiftLib",
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp2/Android.bp b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp2/Android.bp
index 94742eb..e28c0f0 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp2/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp2/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "CtsWriteExternalStorageApp2",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
sdk_version: "test_current",
static_libs: [
"CtsWriteExternalStorageWriteGiftLib",
diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
index 5a3e46f..17db439 100644
--- a/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
+++ b/hostsidetests/car/src/android/car/cts/powerpolicy/SilentModeInfo.java
@@ -71,11 +71,7 @@
boolean[] attrs = new boolean[ATTR_HEADERS.length];
String[] lines = cmdOutput.split("\n");
- if (lines.length != SilentModeInfo.ATTR_HEADERS.length) {
- throw new IllegalArgumentException(
- "SilentModeQueryResult.parse(): malformatted cmd output: " + cmdOutput);
- }
- for (int idx = 0; idx < ATTR_HEADERS.length; idx++) {
+ for (int idx = 0; idx < lines.length; idx++) {
String[] tokens = lines[idx].trim().split(":");
if (tokens.length != 2) {
throw new IllegalArgumentException(
@@ -90,8 +86,7 @@
}
}
if (hdrIdx == ATTR_HEADERS.length) {
- throw new IllegalArgumentException(
- "SilentModeQueryResult.parse(): unknown header: " + hdr);
+ continue;
}
attrs[hdrIdx] = Boolean.parseBoolean(val.trim());
}
diff --git a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java
index af0d156..6b79ac1 100644
--- a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java
+++ b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTest.java
@@ -134,20 +134,30 @@
if (!SurfaceFlingerProperties.enable_frame_rate_override().orElse(false)) {
return modesToTest;
}
+
+ List<Display.Mode> modesWithSameResolution = new ArrayList<>();
+ Display.Mode currentMode = mActivityRule.getActivity().getDisplay().getMode();
+ final long currentDisplayHeight = currentMode.getPhysicalHeight();
+ final long currentDisplayWidth = currentMode.getPhysicalWidth();
+
Display.Mode[] modes = mActivityRule.getActivity().getDisplay().getSupportedModes();
for (Display.Mode mode : modes) {
- for (Display.Mode otherMode : modes) {
+ if (mode.getPhysicalHeight() == currentDisplayHeight
+ && mode.getPhysicalWidth() == currentDisplayWidth) {
+ modesWithSameResolution.add(mode);
+ }
+ }
+
+ for (Display.Mode mode : modesWithSameResolution) {
+ for (Display.Mode otherMode : modesWithSameResolution) {
if (mode.getModeId() == otherMode.getModeId()) {
continue;
}
- if (mode.getPhysicalHeight() != otherMode.getPhysicalHeight()
- || mode.getPhysicalWidth() != otherMode.getPhysicalWidth()) {
- continue;
- }
-
+ // only add if this refresh rate is a multiple of the other
if (areEqual(mode.getRefreshRate(), 2 * otherMode.getRefreshRate())) {
modesToTest.add(mode);
+ continue;
}
}
}
diff --git a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java
index c54ae79..3c218b9 100644
--- a/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java
+++ b/hostsidetests/graphics/framerateoverride/app/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideTestActivity.java
@@ -429,7 +429,7 @@
@Override
public void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
float initialRefreshRate) throws InterruptedException {
- Log.i(TAG, "Staring testFrameRateOverride");
+ Log.i(TAG, "Starting testFrameRateOverride");
float halfFrameRate = initialRefreshRate / 2;
waitForRefreshRateChange(initialRefreshRate);
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
index ad8e506..5f445d4 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/HdmiCecClientWrapper.java
@@ -795,7 +795,7 @@
throw new CecClientWrapperException(ErrorCodes.CecMessageNotFound, expectedMessage.name());
}
- public void checkNoMessagesSentFromDevice(int timeoutMillis)
+ public void checkNoMessagesSentFromDevice(int timeoutMillis, List<CecOperand> excludeOperands)
throws CecClientWrapperException {
checkCecClient();
long startTime = System.currentTimeMillis();
@@ -810,6 +810,10 @@
if (mInputConsole.ready()) {
String line = mInputConsole.readLine();
if (pattern.matcher(line).matches()) {
+ CecOperand operand = CecMessage.getOperand(line);
+ if(excludeOperands.contains(operand)){
+ continue;
+ }
CLog.v("Found unexpected message in " + line);
throw new CecClientWrapperException(
ErrorCodes.CecMessageFound,
@@ -827,6 +831,12 @@
}
}
+ public void checkNoMessagesSentFromDevice(int timeoutMillis)
+ throws CecClientWrapperException {
+ List<CecOperand> excludeOperands = new ArrayList<>();
+ checkNoMessagesSentFromDevice(timeoutMillis, excludeOperands);
+ }
+
/**
* Looks for the CEC message incorrectMessage sent to CEC device toDevice on the cec-client
* communication channel and throws an CecClientWrapperException if it finds the line that
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
index c62ce8f..19d2c75 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/common/HdmiCecGeneralProtocolTest.java
@@ -33,6 +33,9 @@
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.List;
+
/** HDMI CEC 2.0 general protocol tests */
@RunWith(DeviceJUnit4ClassRunner.class)
public final class HdmiCecGeneralProtocolTest extends BaseHdmiCecCtsTest {
@@ -52,30 +55,34 @@
@Test
public void cect_4_2_2_ignoreMessagesFromAddressF() throws Exception {
setCec20();
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_TUNER_DEVICE_STATUS, "01");
+ // get cec reinit messages
+ hdmiCecClient.getAllMessages(mDutLogicalAddresses,
+ HdmiCecConstants.TIMEOUT_CEC_REINIT_SECONDS);
+
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_TUNER_DEVICE_STATUS, ":01");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.RECORD_ON);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.RECORD_OFF);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.RECORD_TV_SCREEN);
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_DECK_STATUS, "01");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_DECK_STATUS, ":01");
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.CLEAR_ANALOG_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
+ CecOperand.CLEAR_ANALOG_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.SET_ANALOG_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.PLAY, "05");
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.DECK_CONTROL, "01");
+ CecOperand.SET_ANALOG_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.PLAY, ":05");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.DECK_CONTROL, ":01");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_OSD_NAME);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_AUDIO_STATUS);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_SYSTEM_AUDIO_MODE_STATUS);
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.VENDOR_COMMAND, "00:01");
- sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.MENU_REQUEST, "00");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.VENDOR_COMMAND, ":00:01");
+ sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.MENU_REQUEST, ":00");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GIVE_POWER_STATUS);
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.SET_DIGITAL_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
+ CecOperand.SET_DIGITAL_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.CLEAR_DIGITAL_TIMER, "02:02:02:02:02:02:00:00:00:02:00");
+ CecOperand.CLEAR_DIGITAL_TIMER, ":02:02:02:02:02:02:00:00:00:02:00");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.GET_CEC_VERSION);
sendMessageAndVerifyNoMessageSentFromDevice(
- CecOperand.CLEAR_EXTERNAL_TIMER, "02:02:02:02:02:02:00:10:02");
+ CecOperand.CLEAR_EXTERNAL_TIMER, ":02:02:02:02:02:02:00:10:02");
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.REQUEST_SHORT_AUDIO_DESCRIPTOR);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.INITIATE_ARC);
sendMessageAndVerifyNoMessageSentFromDevice(CecOperand.REQUEST_ARC_INITIATION);
@@ -86,10 +93,17 @@
public void sendMessageAndVerifyNoMessageSentFromDevice(CecOperand message, String params)
throws Exception {
+ // DeviceDiscoveryAction will send GIVE_OSD_NAME and GIVE_DEVICE_VENDOR_ID
+ // HotplugDetectionAction will send GIVE_PHYSICAL_ADDRESS
+ List<CecOperand> excludeOperands = new ArrayList<>();
+ excludeOperands.add(CecOperand.GIVE_PHYSICAL_ADDRESS);
+ excludeOperands.add(CecOperand.GIVE_DEVICE_VENDOR_ID);
+ excludeOperands.add(CecOperand.GIVE_OSD_NAME);
+
hdmiCecClient.sendCecMessage(message, params);
// Default timeout for the incoming command to arrive in response to a request is 2 secs
// Thus test ensures no messages are sent from DUT for a spacing of 3 secs
- hdmiCecClient.checkNoMessagesSentFromDevice(3000);
+ hdmiCecClient.checkNoMessagesSentFromDevice(3000, excludeOperands);
}
public void sendMessageAndVerifyNoMessageSentFromDevice(CecOperand message) throws Exception {
diff --git a/hostsidetests/media/Android.bp b/hostsidetests/media/Android.bp
index 7f174a2..d6367d9 100644
--- a/hostsidetests/media/Android.bp
+++ b/hostsidetests/media/Android.bp
@@ -23,27 +23,25 @@
defaults: ["cts_defaults"],
srcs: [
"src/**/*.java",
- ":CtsMediaSessionTestCommon",
],
// tag this module as a cts test artifact
test_suites: [
"cts",
"general-tests",
],
-
libs: [
"cts-tradefed",
"tradefed",
"compatibility-host-util",
+ "CtsMediaHostTestCommon",
],
-
static_libs: [
"cts-host-utils",
"cts-statsd-atom-host-test-utils",
],
-}
-
-filegroup {
- name: "CtsMediaSessionTestCommon",
- srcs: ["common/**/*.java"],
+ data: [
+ ":CtsMediaMetricsHostTestApp",
+ ":CtsMediaSessionHostTestApp",
+ ":CtsMediaSessionTestHelper",
+ ],
}
diff --git a/hostsidetests/media/app/MediaMetricsTest/Android.bp b/hostsidetests/media/app/MediaMetricsTest/Android.bp
index ebab6b4..6278f36 100644
--- a/hostsidetests/media/app/MediaMetricsTest/Android.bp
+++ b/hostsidetests/media/app/MediaMetricsTest/Android.bp
@@ -50,6 +50,7 @@
],
static_libs: [
"androidx.test.rules",
+ "collector-device-lib",
"compatibility-device-util-axt",
"truth-prebuilt",
],
diff --git a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
index 8c91c5b..3d0edfc 100644
--- a/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
+++ b/hostsidetests/media/app/MediaMetricsTest/src/android/media/metrics/cts/MediaMetricsAtomHostSideTests.java
@@ -19,6 +19,7 @@
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.device.collectors.util.SendToInstrumentation;
import android.media.metrics.BundleSession;
import android.media.metrics.EditingSession;
import android.media.metrics.LogSessionId;
@@ -44,10 +45,6 @@
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-
@RunWith(AndroidJUnit4.class)
public class MediaMetricsAtomHostSideTests {
private static final String TAG = "MediaMetricsAtomHostSideTests";
@@ -300,7 +297,7 @@
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
- .setDrmSessionId(new byte[] {2, 3, 3, 10})
+ .setDrmSessionId(new byte[]{2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
@@ -443,7 +440,7 @@
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
- .setDrmSessionId(new byte[] {2, 3, 3, 10})
+ .setDrmSessionId(new byte[]{2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
@@ -507,7 +504,7 @@
.setNetworkBytesRead(102400)
.setLocalBytesRead(2000)
.setNetworkTransferDurationMillis(6000)
- .setDrmSessionId(new byte[] {2, 3, 3, 10})
+ .setDrmSessionId(new byte[]{2, 3, 3, 10})
.setMetricsBundle(new Bundle())
.addExperimentId(123)
.build();
@@ -540,16 +537,11 @@
@Test
public native void testAAudioLegacyInputStream();
- private void writeSessionIdToFile(String stringId) throws IOException {
- // TODO(b/259258249): Name session id after the test.
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ private void writeSessionIdToFile(String stringId) {
Log.i(TAG, "log_session_id=" + stringId);
- File logDir = context.getExternalFilesDir(null);
- File logFile = new File(logDir, "log_session_id.txt");
- logFile.createNewFile();
- FileWriter fw = new FileWriter(logFile.getAbsolutePath());
- fw.write(stringId);
- fw.close();
- Log.i(TAG, "Logged to " + logFile.getAbsolutePath());
+ Bundle b = new Bundle();
+ // TODO(b/265311058): use a common constant for metrics keys.
+ b.putString("log_session_id", stringId);
+ SendToInstrumentation.sendBundle(InstrumentationRegistry.getInstrumentation(), b);
}
}
diff --git a/hostsidetests/media/app/MediaSessionTest/Android.bp b/hostsidetests/media/app/MediaSessionTest/Android.bp
index 4dd94a0..71528a7 100644
--- a/hostsidetests/media/app/MediaSessionTest/Android.bp
+++ b/hostsidetests/media/app/MediaSessionTest/Android.bp
@@ -25,7 +25,9 @@
],
srcs: [
"src/**/*.java",
- ":CtsMediaSessionTestCommon",
+ ],
+ libs: [
+ "CtsMediaHostTestCommon",
],
static_libs: [
"androidx.test.rules",
diff --git a/hostsidetests/media/app/MediaSessionTestHelper/Android.bp b/hostsidetests/media/app/MediaSessionTestHelper/Android.bp
index 66340b2..54d98d1 100644
--- a/hostsidetests/media/app/MediaSessionTestHelper/Android.bp
+++ b/hostsidetests/media/app/MediaSessionTestHelper/Android.bp
@@ -21,7 +21,9 @@
defaults: ["cts_defaults"],
srcs: [
"src/**/*.java",
- ":CtsMediaSessionTestCommon",
+ ],
+ libs: [
+ "CtsMediaHostTestCommon",
],
// tag this module as a cts test artifact
test_suites: [
diff --git a/hostsidetests/media/common/Android.bp b/hostsidetests/media/common/Android.bp
new file mode 100644
index 0000000..40aa1b2
--- /dev/null
+++ b/hostsidetests/media/common/Android.bp
@@ -0,0 +1,28 @@
+// Copyright (C) 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 common library for use device-side
+//##############################################################################
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+ name: "CtsMediaHostTestCommon",
+ srcs: ["**/*.java"],
+ sdk_version: "current",
+ host_supported: true,
+}
diff --git a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
index fe2ac25..335bbc5 100644
--- a/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
+++ b/hostsidetests/media/src/android/media/metrics/cts/MediaMetricsAtomTests.java
@@ -24,60 +24,89 @@
import android.cts.statsdatom.lib.DeviceUtils;
import android.cts.statsdatom.lib.ReportUtils;
+import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
import com.android.os.AtomsProto;
import com.android.os.StatsLog;
-import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.testtype.DeviceTestCase;
-import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.invoker.TestInformation;
+import com.android.tradefed.log.LogUtil;
+import com.android.tradefed.metrics.proto.MetricMeasurement;
+import com.android.tradefed.result.CollectingTestListener;
+import com.android.tradefed.result.TestDescription;
+import com.android.tradefed.result.TestResult;
+import com.android.tradefed.result.TestRunResult;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.AfterClassWithInfo;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.testtype.junit4.BeforeClassWithInfo;
import com.google.common.truth.Correspondence;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.FileNotFoundException;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
-public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildReceiver {
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class MediaMetricsAtomTests extends BaseHostJUnit4Test {
+
+ private static final String TEST_RUNNER = "androidx.test.runner.AndroidJUnitRunner";
private static final String TAG = "MediaMetricsAtomTests";
public static final String TEST_APK = "CtsMediaMetricsHostTestApp.apk";
public static final String TEST_PKG = "android.media.metrics.cts";
private static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
private static final String FEATURE_MICROPHONE = "android.hardware.microphone";
private static final int MAX_BUFFER_CAPACITY = 30 * 1024 * 1024; // 30M
- private IBuildInfo mCtsBuild;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- assertThat(mCtsBuild).isNotNull();
- DeviceUtils.installTestApp(getDevice(), TEST_APK, TEST_PKG, mCtsBuild);
+
+ @BeforeClassWithInfo
+ public static void installApp(TestInformation testInfo)
+ throws DeviceNotAvailableException, FileNotFoundException {
+ assertThat(testInfo.getBuildInfo()).isNotNull();
+ DeviceUtils.installTestApp(testInfo.getDevice(), TEST_APK, TEST_PKG,
+ testInfo.getBuildInfo());
+ }
+
+ @Before
+ public void setUp() throws Exception {
ConfigUtils.removeConfig(getDevice());
ReportUtils.clearReports(getDevice());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
ConfigUtils.removeConfig(getDevice());
ReportUtils.clearReports(getDevice());
- DeviceUtils.uninstallTestApp(getDevice(), TEST_PKG);
- super.tearDown();
}
- @Override
- public void setBuild(IBuildInfo buildInfo) {
- mCtsBuild = buildInfo;
+ @AfterClassWithInfo
+ public static void uninstallApp(TestInformation testInfo) throws Exception {
+ DeviceUtils.uninstallTestApp(testInfo.getDevice(), TEST_PKG);
}
+
+ @Test
public void testPlaybackStateEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackStateEvent_default");
+ "testPlaybackStateEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -90,12 +119,13 @@
assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
}
+ @Test
public void testPlaybackStateEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackStateEvent");
+ "testPlaybackStateEvent", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -109,12 +139,13 @@
}
// same as testPlaybackStateEvent, but we use the BundleSession transport.
+ @Test
public void testBundleSessionPlaybackStateEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testBundleSessionPlaybackStateEvent");
+ "testBundleSessionPlaybackStateEvent", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -127,13 +158,13 @@
assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
}
-
+ @Test
public void testPlaybackErrorEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackErrorEvent_default");
+ "testPlaybackErrorEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -151,12 +182,13 @@
+ ".testPlaybackErrorEvent")).isTrue();
}
+ @Test
public void testPlaybackErrorEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackErrorEvent");
+ "testPlaybackErrorEvent", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -174,12 +206,13 @@
+ ".testPlaybackErrorEvent")).isTrue();
}
+ @Test
public void testTrackChangeEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_default");
+ "testTrackChangeEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -203,12 +236,13 @@
assertThat(result.getChannelCount()).isEqualTo(-1);
}
+ @Test
public void testTrackChangeEvent_text() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_text");
+ "testTrackChangeEvent_text", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -230,12 +264,13 @@
assertThat(result.getLanguageRegion()).isEqualTo("US");
}
+ @Test
public void testTrackChangeEvent_audio() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_audio");
+ "testTrackChangeEvent_audio", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -259,12 +294,13 @@
assertThat(result.getChannelCount()).isEqualTo(3);
}
+ @Test
public void testTrackChangeEvent_video() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTrackChangeEvent_video");
+ "testTrackChangeEvent_video", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -289,12 +325,13 @@
assertThat(result.getVideoFrameRate()).isEqualTo(60);
}
+ @Test
public void testNetworkEvent_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testNetworkEvent_default");
+ "testNetworkEvent_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -308,11 +345,13 @@
assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_UNKNOWN");
}
+ @Test
public void testNetworkEvent() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -326,12 +365,13 @@
assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_WIFI");
}
+ @Test
public void testPlaybackMetrics_default() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testPlaybackMetrics_default");
+ "testPlaybackMetrics_default", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -361,11 +401,13 @@
assertThat(result.getDrmSessionId().length()).isEqualTo(0);
}
+ @Test
public void testPlaybackMetrics() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
@@ -397,70 +439,83 @@
assertThat(result.getDrmSessionId()).isNotEqualTo(null);
}
+ @Test
public void testSessionId() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
assertThat(data).isEmpty();
}
+ @Test
public void testRecordingSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
assertThat(data).isEmpty();
}
+ @Test
public void testEditingSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
assertThat(data).isEmpty();
}
+ @Test
public void testTranscodingSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testTranscodingSession");
+ "testTranscodingSession", new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
assertThat(data).isEmpty();
}
+ @Test
public void testBundleSession() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession");
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession",
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
assertThat(data).isEmpty();
}
+ @Test
public void testAppBlocklist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist");
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(),
+ TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist",
+ listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
@@ -470,17 +525,18 @@
"getLogSessionId")).doesNotContain(logSessionId);
}
-
+ @Test
public void testAttributionBlocklist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testAttributionBlocklist");
+ "testAttributionBlocklist", listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
AtomsProto.Atom::getMediametricsPlaybackReported);
@@ -508,15 +564,18 @@
assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000);
}
+ @Test
public void testAppAllowlist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppAllowlist");
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
+ "testAppAllowlist", listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<AtomsProto.MediaPlaybackStateChanged> stateChangedList = toMyAtoms(data,
AtomsProto.Atom::getMediaPlaybackStateChanged);
@@ -530,16 +589,18 @@
assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
}
+ @Test
public void testAttributionAllowlist() throws Exception {
ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
+ LogSessionIdListener listener = new LogSessionIdListener();
+ runDeviceTests(getDevice(), TEST_PKG,
"android.media.metrics.cts.MediaMetricsAtomHostSideTests",
- "testAttributionAllowlist");
+ "testAttributionAllowlist", listener);
+ String logSessionId = listener.getLogSessionId();
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
- String logSessionId = getLogSessionId();
assertWithMessage("log session id").that(logSessionId).isNotEmpty();
List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data,
AtomsProto.Atom::getMediametricsPlaybackReported);
@@ -595,8 +656,9 @@
ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
AtomsProto.Atom.MEDIAMETRICS_AAUDIOSTREAM_REPORTED_FIELD_NUMBER);
- DeviceUtils.runDeviceTests(getDevice(), TEST_PKG,
- "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName);
+ runDeviceTests(getDevice(), TEST_PKG,
+ "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName,
+ new LogSessionIdListener());
Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
validateAAudioStreamAtom(direction);
@@ -608,6 +670,7 @@
* After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
* the data is collected correctly.
*/
+ @Test
public void testAAudioLowLatencyInputStream() throws Exception {
runAAudioTestAndValidate(FEATURE_MICROPHONE,
AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE,
@@ -620,6 +683,7 @@
* After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
* the data is collected correctly.
*/
+ @Test
public void testAAudioLowLatencyOutputStream() throws Exception {
runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT,
AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE,
@@ -632,6 +696,7 @@
* After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
* the data is collected correctly.
*/
+ @Test
public void testAAudioLegacyInputStream() throws Exception {
runAAudioTestAndValidate(FEATURE_MICROPHONE,
AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE,
@@ -644,23 +709,93 @@
* After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
* the data is collected correctly.
*/
+ @Test
public void testAAudioLegacyOutputStream() throws Exception {
runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT,
AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE,
"testAAudioLegacyOutputStream");
}
- private String getLogSessionId() throws DeviceNotAvailableException {
- // TODO(b/259258249): Name session id file after the test.
- String logSessionId = getDevice().pullFileContents(
- "/storage/emulated/0/Android/data/android.media.metrics"
- + ".cts/files/log_session_id" + ".txt");
- return logSessionId;
- }
-
private static <T> List<T> toMyAtoms(List<StatsLog.EventMetricData> data,
Function<AtomsProto.Atom, T> mapper) {
return data.stream().map(StatsLog.EventMetricData::getAtom).map(mapper).collect(
Collectors.toUnmodifiableList());
}
+
+ // TODO(b/265208340): update DeviceUtils to accept listeners.
+
+ /**
+ * Runs device side tests.
+ *
+ * @param device Can be retrieved by running getDevice() in a class that extends
+ * DeviceTestCase
+ * @param pkgName Test package name, such as "com.android.server.cts.statsdatom"
+ * @param testClassName Test class name which can either be a fully qualified name or "." + a
+ * class name; if null, all test in the package will be run
+ * @param testMethodName Test method name; if null, all tests in class or package will be run
+ * @return {@link TestRunResult} of this invocation
+ */
+ @Nonnull
+ private static TestRunResult runDeviceTests(ITestDevice device, String pkgName,
+ @Nullable String testClassName, @Nullable String testMethodName,
+ LogSessionIdListener listener)
+ throws DeviceNotAvailableException {
+ if (testClassName != null && testClassName.startsWith(".")) {
+ testClassName = pkgName + testClassName;
+ }
+
+ RemoteAndroidTestRunner testRunner = new RemoteAndroidTestRunner(
+ pkgName, TEST_RUNNER, device.getIDevice());
+ if (testClassName != null && testMethodName != null) {
+ testRunner.setMethodName(testClassName, testMethodName);
+ } else if (testClassName != null) {
+ testRunner.setClassName(testClassName);
+ }
+
+ assertThat(device.runInstrumentationTests(testRunner, listener)).isTrue();
+
+ final TestRunResult result = listener.getCurrentRunResults();
+ if (result.isRunFailure()) {
+ throw new Error("Failed to successfully run device tests for "
+ + result.getName() + ": " + result.getRunFailureMessage());
+ }
+ if (result.getNumTests() == 0) {
+ throw new Error("No tests were run on the device");
+ }
+ if (result.hasFailedTests()) {
+ StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
+ for (Map.Entry<TestDescription, TestResult> resultEntry :
+ result.getTestResults().entrySet()) {
+ if (!resultEntry.getValue().getStatus().equals(
+ com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ }
+ }
+ throw new AssertionError(errorBuilder.toString());
+ }
+
+ return result;
+ }
+
+ private static final class LogSessionIdListener extends CollectingTestListener {
+
+ @Nullable
+ private String mLogSessionId;
+
+ @Nullable
+ public String getLogSessionId() {
+ return mLogSessionId;
+ }
+
+ @Override
+ public void testEnded(TestDescription test, long endTime,
+ HashMap<String, MetricMeasurement.Metric> testMetrics) {
+ super.testEnded(test, endTime, testMetrics);
+ LogUtil.CLog.i("testEnded MetricMeasurement.Metric " + testMetrics);
+ // TODO(b/265311058): use a common constant for metrics keys.
+ mLogSessionId = testMetrics.get("log_session_id").getMeasurements().getSingleString();
+ }
+ }
}
diff --git a/hostsidetests/multidevices/bluetooth/Android.bp b/hostsidetests/multidevices/bluetooth/Android.bp
new file mode 100644
index 0000000..dc3efac
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/Android.bp
@@ -0,0 +1,42 @@
+// 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"],
+}
+
+python_test_host {
+ name: "CtsBluetoothMultiDevicesTestCases",
+ main: "bluetooth_multi_devices_test.py",
+ srcs: ["bluetooth_multi_devices_test.py"],
+ libs: [
+ "mobly",
+ ],
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+ test_options: {
+ unit_test: false,
+ },
+ data: [
+ // Package the snippet with the mobly test
+ ":bluetooth_multi_devices_snippet",
+ ],
+ version: {
+ py3: {
+ embedded_launcher: true,
+ },
+ },
+}
diff --git a/hostsidetests/multidevices/bluetooth/AndroidTest.xml b/hostsidetests/multidevices/bluetooth/AndroidTest.xml
new file mode 100644
index 0000000..2bc2216
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/AndroidTest.xml
@@ -0,0 +1,46 @@
+<?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.
+-->
+<configuration description="Config for CTS Bluetooth multi devices test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="bluetooth" />
+ <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="not_secondary_user" />
+
+ <device name="device1">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="bluetooth_multi_devices_snippet.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
+ </target_preparer>
+ </device>
+ <device name="device2">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="bluetooth_multi_devices_snippet.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="wm dismiss-keyguard" />
+ </target_preparer>
+ </device>
+
+ <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest">
+ <!-- The mobly-par-file-name should match the module name -->
+ <option name="mobly-par-file-name" value="CtsBluetoothMultiDevicesTestCases" />
+ <!-- Timeout limit in milliseconds for all test cases of the python binary -->
+ <option name="mobly-test-timeout" value="180000" />
+ </test>
+</configuration>
+
diff --git a/hostsidetests/multidevices/bluetooth/OWNERS b/hostsidetests/multidevices/bluetooth/OWNERS
new file mode 100644
index 0000000..21197f3
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/OWNERS
@@ -0,0 +1,10 @@
+# Bug component: 27441
+
+eruffieux@google.com
+girardier@google.com
+muhammadfalam@google.com
+rahulsabnis@google.com
+sattiraju@google.com
+siyuanh@google.com
+sungsoo@google.com
+wescande@google.com
diff --git a/hostsidetests/multidevices/bluetooth/bluetooth_multi_devices_test.py b/hostsidetests/multidevices/bluetooth/bluetooth_multi_devices_test.py
new file mode 100644
index 0000000..145d22e
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/bluetooth_multi_devices_test.py
@@ -0,0 +1,79 @@
+# Lint as: python3
+"""
+Bluetooth multi devices tests.
+"""
+import sys
+import os.path
+import time
+import re
+
+import logging
+logging.basicConfig(filename="/tmp/bluetooth_multi_devices_test_log.txt", level=logging.INFO)
+
+from mobly import asserts
+from mobly import base_test
+from mobly import test_runner
+from mobly import utils
+from mobly.controllers import android_device
+
+BLUETOOTH_MULTI_DEVICES_SNIPPET_PACKAGE = 'com.google.snippet.bluetooth'
+
+GATT_PRIORITY_BALANCED = 0
+GATT_PRIORITY_HIGH = 1
+GATT_PRIORITY_LOW = 2
+CONNECTION_PRIORITY_CCC = 3
+
+class BluetoothMultiDevicesTest(base_test.BaseTestClass):
+
+ def setup_class(self):
+ # Declare that two Android devices are needed.
+ self.client, self.server = self.register_controller(
+ android_device, min_number=2)
+
+ def setup_device(device):
+ device.load_snippet('bluetooth_multi_devices_snippet', BLUETOOTH_MULTI_DEVICES_SNIPPET_PACKAGE)
+
+ # Sets up devices in parallel to save time.
+ utils.concurrent_exec(
+ setup_device, ((self.client,), (self.server,)),
+ max_workers=2,
+ raise_on_exception=True)
+
+ def test_gatt_connection_interval_test_case(self):
+
+ if not self.server.bluetooth_multi_devices_snippet.isBluetoothOn() or\
+ not self.client.bluetooth_multi_devices_snippet.isBluetoothOn():
+ self.server.bluetooth_multi_devices_snippet.enableBluetooth()
+ self.client.bluetooth_multi_devices_snippet.enableBluetooth()
+
+ #TODO implement callback (b/266635827)
+ time.sleep(3)
+
+ asserts.assert_true(self.server.bluetooth_multi_devices_snippet.isBluetoothOn(), 'Server Bluetooth is OFF')
+ asserts.assert_true(self.client.bluetooth_multi_devices_snippet.isBluetoothOn(), 'Client Bluetooth is OFF')
+
+
+ # Start server, register callback, connect client, wait for connection
+ self.server_name = self.server.bluetooth_multi_devices_snippet.createServer()
+ asserts.assert_true(self.client.bluetooth_multi_devices_snippet.discoverServer(self.server_name), "Server not discovered");
+ self.client.bluetooth_multi_devices_snippet.connectGatt(CONNECTION_PRIORITY_CCC)
+ asserts.assert_true(self.server.bluetooth_multi_devices_snippet.waitConnection(), "Device not connected before timeout")
+
+ used_interval = self.server.bluetooth_multi_devices_snippet.receivePriority()
+ asserts.assert_true(used_interval is CONNECTION_PRIORITY_CCC, "Connection priority is not equal")
+
+ self.client.bluetooth_multi_devices_snippet.updatePriority(GATT_PRIORITY_HIGH)
+ used_interval = self.server.bluetooth_multi_devices_snippet.receivePriority()
+ asserts.assert_true(used_interval is GATT_PRIORITY_HIGH, "Connection priority is not equal, expected: " + str(GATT_PRIORITY_HIGH) + " received: " + str(used_interval))
+
+ self.client.bluetooth_multi_devices_snippet.disconnectGatt()
+ self.client.bluetooth_multi_devices_snippet.clearClient()
+
+ self.server.bluetooth_multi_devices_snippet.destroyServer()
+
+
+if __name__ == '__main__':
+ # Take test args
+ index = sys.argv.index('--')
+ sys.argv = sys.argv[:1] + sys.argv[index + 1:]
+ test_runner.main()
diff --git a/hostsidetests/multidevices/bluetooth/snippet/Android.bp b/hostsidetests/multidevices/bluetooth/snippet/Android.bp
new file mode 100644
index 0000000..c9cd2ec
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/snippet/Android.bp
@@ -0,0 +1,33 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test {
+ name: "bluetooth_multi_devices_snippet",
+ sdk_version: "current",
+ srcs: [
+ "BluetoothGattMultiDevicesClient.java",
+ "BluetoothGattMultiDevicesServer.java",
+ "BluetoothGattMultiDevicesSnippet.java",
+ ],
+ manifest: "AndroidManifest.xml",
+ static_libs: [
+ "androidx.test.runner",
+ "guava",
+ "mobly-snippet-lib",
+ ],
+}
diff --git a/hostsidetests/multidevices/bluetooth/snippet/AndroidManifest.xml b/hostsidetests/multidevices/bluetooth/snippet/AndroidManifest.xml
new file mode 100644
index 0000000..75724bf
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/snippet/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 The Android Open Source Project
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+ http://www.apache.org/licenses/LICENSE-2.0
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.snippet.bluetooth">
+ <!-- Declare the minimum Android SDK version and internet permission,
+ which are required by Mobly Snippet Lib since it uses network socket. -->
+ <uses-sdk android:minSdkVersion="Tiramisu" />
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
+ <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <application>
+ <!-- Add any classes that implement the Snippet interface as meta-data, whose
+ value is a comma-separated string, each section being the package path
+ of a snippet class -->
+ <meta-data
+ android:name="mobly-snippets"
+ android:value="com.google.snippet.bluetooth.BluetoothGattMultiDevicesSnippet" />
+ </application>
+ <!-- Add an instrumentation tag so that the app can be launched through an
+ instrument command. The runner `com.google.android.mobly.snippet.SnippetRunner`
+ is derived from `AndroidJUnitRunner`, and is required to use the
+ Mobly Snippet Lib. -->
+ <instrumentation
+ android:name="com.google.android.mobly.snippet.SnippetRunner"
+ android:targetPackage="com.google.snippet.bluetooth" />
+</manifest>
diff --git a/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesClient.java b/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesClient.java
new file mode 100644
index 0000000..c6e9d552
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesClient.java
@@ -0,0 +1,123 @@
+/*
+ * 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 com.google.snippet.bluetooth;
+
+import static android.bluetooth.BluetoothDevice.PHY_LE_1M_MASK;
+import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCallback;
+import android.bluetooth.BluetoothManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import java.util.concurrent.CountDownLatch;
+
+public final class BluetoothGattMultiDevicesClient {
+
+ private static final String TAG = "BluetoothGattMultiDevicesClient";
+
+ private Context mContext;
+ private BluetoothAdapter mBluetoothAdapter;
+ private BluetoothGatt mBluetoothGatt;
+
+ private CountDownLatch mServerFoundBlocker = null;
+
+ private UiAutomation mUiAutomation;
+
+ private static final int CALLBACK_TIMEOUT_SEC = 60;
+
+ private String mServerName;
+ private BluetoothDevice mServer;
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
+ BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ Log.i(TAG, "Device discovered: " + device.getName()
+ + " Server name: " + mServerName);
+ if (mServerName.equals(device.getName())) {
+ Log.i(TAG, "Server discovered");
+ mServer = device;
+ mServerFoundBlocker.countDown();
+ }
+ }
+ }
+ };
+
+ public BluetoothGattMultiDevicesClient(Context context, BluetoothManager manager) {
+ mContext = context;
+ mBluetoothAdapter = manager.getAdapter();
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity();
+
+ IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+ mContext.registerReceiver(mReceiver, filter);
+
+ }
+
+ public void clear() {
+ mContext.unregisterReceiver(mReceiver);
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+
+ private boolean startDiscovery() throws InterruptedException {
+ mServerFoundBlocker = new CountDownLatch(1);
+ mBluetoothAdapter.startDiscovery();
+ boolean timeout = !mServerFoundBlocker.await(CALLBACK_TIMEOUT_SEC, SECONDS);
+ mBluetoothAdapter.cancelDiscovery();
+ if (timeout) {
+ Log.e(TAG, "Did not discover server");
+ return false;
+ }
+ return true;
+ }
+
+ public boolean discoverServer(String deviceName) {
+ try {
+ mServerName = deviceName;
+ return startDiscovery();
+ } catch (Exception e) {
+ Log.e(TAG, "", e);
+ }
+ return false;
+ }
+
+ public void connect(int priority) {
+ mBluetoothGatt = mServer.connectGatt(mContext, false,
+ TRANSPORT_LE, PHY_LE_1M_MASK, priority, null, new BluetoothGattCallback(){});
+ }
+
+ public void disconnect() {
+ mBluetoothGatt.disconnect();
+ }
+
+ public void updatePriority(int priority) {
+ mBluetoothGatt.requestConnectionPriority(priority);
+ }
+}
diff --git a/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesServer.java b/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesServer.java
new file mode 100644
index 0000000..fa196da
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesServer.java
@@ -0,0 +1,166 @@
+/*
+ * 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 com.google.snippet.bluetooth;
+
+import static android.bluetooth.BluetoothGattService.SERVICE_TYPE_PRIMARY;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattServer;
+import android.bluetooth.BluetoothGattServerCallback;
+import android.bluetooth.BluetoothGattService;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.le.AdvertiseCallback;
+import android.bluetooth.le.AdvertiseData;
+import android.bluetooth.le.AdvertiseSettings;
+import android.bluetooth.le.BluetoothLeAdvertiser;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+
+public final class BluetoothGattMultiDevicesServer {
+
+ private static final String TAG = "BluetoothGattMultiDevicesServer";
+
+ private Context mContext;
+ private BluetoothManager mBluetoothManager;
+ private BluetoothAdapter mBluetoothAdapter;
+ private BluetoothGattServer mBluetoothGattServer;
+ private BluetoothLeAdvertiser mBluetoothLeAdvertiser;
+
+ private int mConnectionPriority = -1;
+ private CountDownLatch mPriorityBlocker = null;
+ private CountDownLatch mConnectionBlocker = null;
+
+ private static final int CALLBACK_TIMEOUT_SEC = 60;
+
+ private BluetoothGattServerCallback mServerCallback = new BluetoothGattServerCallback() {
+
+ @Override
+ public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
+ Log.i(TAG, "onConnectionStateChange: newState=" + newState);
+ if (newState == BluetoothProfile.STATE_CONNECTED && mConnectionBlocker != null) {
+ mConnectionBlocker.countDown();
+ }
+ }
+
+ @Override
+ public void onPriorityChanged(BluetoothDevice device, int priority) {
+ Log.i(TAG, "onPriorityChanged: priority=" + priority);
+ if (priority == 0) {
+ return;
+ }
+ mConnectionPriority = priority;
+ if (mPriorityBlocker != null) {
+ mPriorityBlocker.countDown();
+ }
+ }
+
+ };
+
+ private AdvertiseCallback mAdvertiseCallback = new AdvertiseCallback() {
+ @Override
+ public void onStartSuccess(AdvertiseSettings settingsInEffect) {
+ }
+
+ @Override
+ public void onStartFailure(int errorCode) {
+ }
+ };
+
+ public BluetoothGattMultiDevicesServer(Context context, BluetoothManager manager) {
+ mContext = context;
+ mBluetoothManager = manager;
+ mBluetoothAdapter = manager.getAdapter();
+ }
+
+ public String createServer() {
+ mBluetoothLeAdvertiser = mBluetoothAdapter.getBluetoothLeAdvertiser();
+ AdvertiseSettings settings = new AdvertiseSettings.Builder()
+ .setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED)
+ .setConnectable(true)
+ .setTimeout(0)
+ .setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
+ .build();
+
+ AdvertiseData data = new AdvertiseData.Builder()
+ .setIncludeDeviceName(true)
+ .setIncludeTxPowerLevel(false)
+ .addServiceUuid(new ParcelUuid(UUID.fromString(
+ "0000fffa-0000-1000-8000-00805f9b34fb")))
+ .build();
+
+ mBluetoothLeAdvertiser
+ .startAdvertising(settings, data, mAdvertiseCallback);
+
+ mBluetoothGattServer = mBluetoothManager.openGattServer(mContext, mServerCallback);
+
+ BluetoothGattService service = new BluetoothGattService(UUID.fromString(
+ "0000fffa-0000-1000-8000-00805f9b34fb"), SERVICE_TYPE_PRIMARY);
+ service.addCharacteristic(new BluetoothGattCharacteristic(UUID.fromString(
+ "0000fffb-0000-1000-8000-00805f9b34fb"), 0x02, 0x01));
+ mBluetoothGattServer.addService(service);
+ return mBluetoothAdapter.getName();
+ }
+
+ private boolean waitConnectCallback() throws InterruptedException {
+ mConnectionBlocker = new CountDownLatch(1);
+ return mConnectionBlocker.await(CALLBACK_TIMEOUT_SEC, SECONDS);
+ }
+
+ public boolean waitConnection() {
+ if (mBluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER).size() > 0) {
+ return true;
+ }
+ try {
+ return waitConnectCallback();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "", e);
+ }
+ return false;
+ }
+
+ public void destroyServer() {
+ mBluetoothGattServer.close();
+ }
+
+ private int waitForPriority() throws InterruptedException {
+ mConnectionPriority = -1;
+ mPriorityBlocker = new CountDownLatch(1);
+ boolean timeout = !mPriorityBlocker.await(CALLBACK_TIMEOUT_SEC, SECONDS);
+ if (timeout) {
+ Log.e(TAG, "Did not receive priority update");
+ }
+ return mConnectionPriority;
+ }
+
+ public int receivePriority() {
+ try {
+ return waitForPriority();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "", e);
+ }
+ return -1;
+ }
+}
diff --git a/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesSnippet.java b/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesSnippet.java
new file mode 100644
index 0000000..7b78d84
--- /dev/null
+++ b/hostsidetests/multidevices/bluetooth/snippet/BluetoothGattMultiDevicesSnippet.java
@@ -0,0 +1,93 @@
+/*
+ * 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 com.google.snippet.bluetooth;
+
+import android.bluetooth.BluetoothManager;
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.google.android.mobly.snippet.Snippet;
+import com.google.android.mobly.snippet.rpc.Rpc;
+
+public class BluetoothGattMultiDevicesSnippet implements Snippet {
+
+ private static final String TAG = "BluetoothGattMultiDevicesSnippet";
+
+ private BluetoothGattMultiDevicesServer mGattServer;
+ private BluetoothGattMultiDevicesClient mGattClient;
+
+ private Context mContext;
+ private BluetoothManager mBluetoothManager;
+
+ public BluetoothGattMultiDevicesSnippet() {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mBluetoothManager = mContext.getSystemService(BluetoothManager.class);
+ mGattServer = new BluetoothGattMultiDevicesServer(mContext, mBluetoothManager);
+ mGattClient = new BluetoothGattMultiDevicesClient(mContext, mBluetoothManager);
+ }
+
+ @Rpc(description = "Creates Bluetooth GATT server and returns device address.")
+ public String createServer() {
+ return mGattServer.createServer();
+ }
+
+ @Rpc(description = "Waits for a connection to be made btween client and server")
+ public boolean waitConnection() {
+ return mGattServer.waitConnection();
+ }
+
+ @Rpc(description = "Destroys Bluetooth GATT server.")
+ public void destroyServer() {
+ mGattServer.destroyServer();
+ }
+
+ @Rpc(description = "Destroys Bluetooth GATT server.")
+ public int receivePriority() {
+ return mGattServer.receivePriority();
+ }
+
+ @Rpc(description = "Try to discover Bluetooth GATT server")
+ public boolean discoverServer(String name) {
+ return mGattClient.discoverServer(name);
+ }
+
+ @Rpc(description = "Creates Bluetooth GATT server and returns device address")
+ public void connectGatt(int priority) {
+ mGattClient.connect(priority);
+ }
+
+ @Rpc(description = "Creates Bluetooth GATT server and returns device address")
+ public void disconnectGatt() {
+ mGattClient.disconnect();
+ }
+
+ @Rpc(description = "Creates Bluetooth GATT server and returns device address")
+ public void updatePriority(int priority) {
+ mGattClient.updatePriority(priority);
+ }
+
+ @Rpc(description = "Checks Bluetooth state")
+ public boolean isBluetoothOn() {
+ return mBluetoothManager.getAdapter().isEnabled();
+ }
+
+ @Rpc(description = "Clears the receivers and permissions")
+ public void clearClient() {
+ mGattClient.clear();
+ }
+}
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 7f83dce..7c87e54 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -142,6 +142,7 @@
import androidx.annotation.Nullable;
import androidx.test.filters.SdkSuppress;
+import com.android.compatibility.common.util.FeatureUtil;
import com.android.cts.install.lib.TestApp;
import com.android.modules.utils.build.SdkLevel;
@@ -3042,6 +3043,10 @@
@Test
@SdkSuppress(minSdkVersion = 31, codeName = "S")
public void testExternalStorageProviderAndDownloadsProvider() throws Exception {
+ // External Storage Provider and Downloads Provider are not supported on Wear OS
+ if (FeatureUtil.isWatch()) {
+ return;
+ }
assertWritableMountModeForProvider(DocumentsContract.EXTERNAL_STORAGE_PROVIDER_AUTHORITY);
assertWritableMountModeForProvider(DocumentsContract.DOWNLOADS_PROVIDER_AUTHORITY);
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c
index b5386e1..306f0f34 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5862/poc.c
@@ -36,7 +36,7 @@
unsigned int id = 0;
struct snd_ctl_elem_list lst;
memset(&lst, 0, sizeof(lst));
- lst.pids = calloc(NUM_BLOCKS, sizeof(struct snd_ctl_elem_list));
+ lst.pids = calloc(NUM_BLOCKS, sizeof(struct snd_ctl_elem_id));
lst.space = NUM_BLOCKS;
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &lst);
if (ret < 0) {
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c
index 3b8771f..669101d 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2016-5867/poc.c
@@ -38,7 +38,7 @@
unsigned int id = 0;
struct snd_ctl_elem_list lst;
memset(&lst, 0, sizeof(lst));
- lst.pids = calloc(NUM_BLOCKS, sizeof(struct snd_ctl_elem_list));
+ lst.pids = calloc(NUM_BLOCKS, sizeof(struct snd_ctl_elem_id));
lst.space = NUM_BLOCKS;
ret = ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &lst);
if (ret < 0) {
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
index 8b6f991..aa748e5 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/HostAtomTests.java
@@ -339,6 +339,7 @@
public void testBatterySaverModeStateChangedAtom() throws Exception {
if (DeviceUtils.hasFeature(getDevice(), FEATURE_TWM)) return;
if (DeviceUtils.hasFeature(getDevice(), FEATURE_AUTOMOTIVE)) return;
+ if (DeviceUtils.hasFeature(getDevice(), FEATURE_WATCH)) return;
// Setup, turn off battery saver.
turnBatterySaverOff();
DeviceUtils.flushBatteryStatsHandlers(getDevice());
diff --git a/hostsidetests/usage/app/Android.bp b/hostsidetests/usage/app/Android.bp
index 2093cdf..9f96ebd 100644
--- a/hostsidetests/usage/app/Android.bp
+++ b/hostsidetests/usage/app/Android.bp
@@ -20,6 +20,7 @@
name: "CtsAppUsageTestApp",
defaults: ["cts_support_defaults"],
srcs: ["src/**/*.java"],
+ min_sdk_version: "29",
sdk_version: "current",
// tag this module as a cts test artifact
test_suites: [
@@ -35,6 +36,7 @@
name: "CtsAppUsageTestAppToo",
defaults: ["cts_support_defaults"],
srcs: ["src/**/*.java"],
+ min_sdk_version: "29",
sdk_version: "current",
// tag this module as a cts test artifact
test_suites: [
diff --git a/libs/helpers/interfaces/Android.bp b/libs/helpers/interfaces/Android.bp
index 3cdb264..dcb38f5 100644
--- a/libs/helpers/interfaces/Android.bp
+++ b/libs/helpers/interfaces/Android.bp
@@ -23,7 +23,6 @@
static_libs: [
"cts-helpers-core",
- "ub-uiautomator",
],
sdk_version: "test_current",
diff --git a/tests/AlarmManager/Android.bp b/tests/AlarmManager/Android.bp
index 60eefcc..e62687a 100644
--- a/tests/AlarmManager/Android.bp
+++ b/tests/AlarmManager/Android.bp
@@ -43,4 +43,5 @@
":AlarmTestAppWithUserPermissionSdk32",
],
per_testcase_directory: true,
+ min_sdk_version: "29",
}
diff --git a/tests/AlarmManager/app/Android.bp b/tests/AlarmManager/app/Android.bp
index 31bb43c..2e2d642 100644
--- a/tests/AlarmManager/app/Android.bp
+++ b/tests/AlarmManager/app/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "AlarmTestApp",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "29",
sdk_version: "current",
test_suites: [
"cts",
diff --git a/tests/AlarmManager/app30/Android.bp b/tests/AlarmManager/app30/Android.bp
index e6e2f17..6d54031 100644
--- a/tests/AlarmManager/app30/Android.bp
+++ b/tests/AlarmManager/app30/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "AlarmTestApp30",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "30",
sdk_version: "current",
test_suites: [
"cts",
diff --git a/tests/AlarmManager/app_policy_permission32/Android.bp b/tests/AlarmManager/app_policy_permission32/Android.bp
index 420c5db..5e16581 100644
--- a/tests/AlarmManager/app_policy_permission32/Android.bp
+++ b/tests/AlarmManager/app_policy_permission32/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "AlarmTestAppWithPolicyPermissionSdk32",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "32",
sdk_version: "current",
test_suites: [
"cts",
diff --git a/tests/AlarmManager/app_user_permission32/Android.bp b/tests/AlarmManager/app_user_permission32/Android.bp
index 3c5fc0f1..793e565 100644
--- a/tests/AlarmManager/app_user_permission32/Android.bp
+++ b/tests/AlarmManager/app_user_permission32/Android.bp
@@ -19,6 +19,7 @@
android_test_helper_app {
name: "AlarmTestAppWithUserPermissionSdk32",
defaults: ["cts_support_defaults"],
+ min_sdk_version: "32",
sdk_version: "current",
test_suites: [
"cts",
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
index f6ff23f..e26f8b4 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/BatteryConstraintTest.java
@@ -24,6 +24,7 @@
import android.os.BatteryManager;
import android.provider.Settings;
import android.util.Log;
+import android.content.res.Resources;
import com.android.compatibility.common.util.SystemUtil;
@@ -41,6 +42,7 @@
public static final int BATTERY_JOB_ID = BatteryConstraintTest.class.hashCode();
private JobInfo.Builder mBuilder;
+ private int mLowBatteryWarningLevel = 15;
/**
* Record of the previous state of power save mode trigger level to reset it after the test
* finishes.
@@ -51,6 +53,9 @@
public void setUp() throws Exception {
super.setUp();
+ mLowBatteryWarningLevel = Resources.getSystem().getInteger(
+ Resources.getSystem().getIdentifier(
+ "config_lowBatteryWarningLevel", "integer", "android"));
// Disable power save mode as some devices may turn off Android when power save mode is
// enabled, causing the test to fail.
mPreviousLowPowerTriggerLevel = Settings.Global.getInt(getContext().getContentResolver(),
@@ -253,7 +258,7 @@
return;
}
- setBatteryState(false, 5);
+ setBatteryState(false, mLowBatteryWarningLevel);
// setBatteryState() waited for the charging/not-charging state to formally settle,
// but battery level reporting lags behind that. wait a moment to let that happen
// before proceeding.
@@ -288,8 +293,8 @@
kTestEnvironment.awaitExecution());
// And check that the job is stopped if battery goes low again.
- setBatteryState(false, 5);
- setBatteryState(false, 4);
+ setBatteryState(false, mLowBatteryWarningLevel);
+ setBatteryState(false, mLowBatteryWarningLevel - 1);
Thread.sleep(2_000);
verifyChargingState(false);
verifyBatteryNotLowState(false);
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
index 00d7517..7b0d261 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/ConnectivityConstraintTest.java
@@ -18,48 +18,25 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
-import static com.android.compatibility.common.util.TestUtils.waitUntil;
-
-import android.Manifest;
import android.annotation.TargetApi;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
-import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
-import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
import android.platform.test.annotations.RequiresDevice;
import android.provider.Settings;
import android.util.Log;
import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
-import com.android.compatibility.common.util.CallbackAsserter;
-import com.android.compatibility.common.util.ShellIdentityUtils;
import com.android.compatibility.common.util.SystemUtil;
-import junit.framework.AssertionFailedError;
-
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* Schedules jobs with the {@link android.app.job.JobScheduler} that have network connectivity
* constraints.
@@ -70,18 +47,13 @@
@RequiresDevice // Emulators don't always have access to wifi/network
public class ConnectivityConstraintTest extends BaseJobSchedulerTest {
private static final String TAG = "ConnectivityConstraintTest";
- private static final String RESTRICT_BACKGROUND_GET_CMD =
- "cmd netpolicy get restrict-background";
- private static final String RESTRICT_BACKGROUND_ON_CMD =
- "cmd netpolicy set restrict-background true";
- private static final String RESTRICT_BACKGROUND_OFF_CMD =
- "cmd netpolicy set restrict-background false";
/** Unique identifier for the job scheduled by this suite of tests. */
public static final int CONNECTIVITY_JOB_ID = ConnectivityConstraintTest.class.hashCode();
/** Wait this long before timing out the test. */
private static final long DEFAULT_TIMEOUT_MILLIS = 30000L; // 30 seconds.
+ private NetworkingHelper mNetworkingHelper;
private WifiManager mWifiManager;
private ConnectivityManager mCm;
@@ -89,21 +61,8 @@
private boolean mHasWifi;
/** Whether the device running these tests supports telephony. */
private boolean mHasTelephony;
- /** Whether the device running these tests supports ethernet. */
- private boolean mHasEthernet;
- /** Track whether WiFi was enabled in case we turn it off. */
- private boolean mInitialWiFiState;
- /** Track initial WiFi metered state. */
- private String mInitialWiFiMeteredState;
- private String mInitialWiFiSSID;
- /** Track whether restrict background policy was enabled in case we turn it off. */
- private boolean mInitialRestrictBackground;
- /** Track whether airplane mode was enabled in case we toggle it. */
- private boolean mInitialAirplaneMode;
/** Track whether the restricted bucket was enabled in case we toggle it. */
private String mInitialRestrictedBucketEnabled;
- /** Track the location mode in case we change it. */
- private String mInitialLocationMode;
private JobInfo.Builder mBuilder;
@@ -115,30 +74,20 @@
mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+ mNetworkingHelper = new NetworkingHelper(getInstrumentation(), getContext());
PackageManager packageManager = mContext.getPackageManager();
mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
- mHasEthernet = packageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
mBuilder = new JobInfo.Builder(CONNECTIVITY_JOB_ID, kJobServiceComponent);
- mInitialLocationMode = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE);
if (mHasWifi) {
- mInitialWiFiState = mWifiManager.isWifiEnabled();
- ensureSavedWifiNetwork(mWifiManager);
- setWifiState(true, mCm, mWifiManager);
- mInitialWiFiSSID = getWifiSSID();
- mInitialWiFiMeteredState = getWifiMeteredStatus(mInitialWiFiSSID);
+ mNetworkingHelper.ensureSavedWifiNetwork();
}
- mInitialRestrictBackground = SystemUtil
- .runShellCommand(getInstrumentation(), RESTRICT_BACKGROUND_GET_CMD)
- .contains("enabled");
mInitialRestrictedBucketEnabled = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET);
setDataSaverEnabled(false);
- mInitialAirplaneMode = isAirplaneModeOn();
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
// Force the test app out of the never bucket.
SystemUtil.runShellCommand("am set-standby-bucket "
+ TestAppInterface.TEST_APP_PACKAGE + " rare");
@@ -153,31 +102,12 @@
BatteryUtils.runDumpsysBatteryReset();
- // Restore initial restrict background data usage policy
- setDataSaverEnabled(mInitialRestrictBackground);
-
// Restore initial restricted bucket setting.
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET, mInitialRestrictedBucketEnabled);
// Ensure that we leave WiFi in its previous state.
- if (mHasWifi) {
- setWifiMeteredState(mInitialWiFiSSID, mInitialWiFiMeteredState);
- if (mWifiManager.isWifiEnabled() != mInitialWiFiState) {
- try {
- setWifiState(mInitialWiFiState, mCm, mWifiManager);
- } catch (AssertionFailedError e) {
- // Don't fail the test just because wifi state wasn't set in tearDown.
- Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
- }
- }
- }
-
- // Restore initial airplane mode status. Do it after setting wifi in case wifi was
- // originally metered.
- setAirplaneMode(mInitialAirplaneMode);
-
- setLocationMode(mInitialLocationMode);
+ mNetworkingHelper.tearDown();
super.tearDown();
}
@@ -585,7 +515,7 @@
}
public void testJobParametersNetwork() throws Exception {
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
// Everything good.
final NetworkRequest nr = new NetworkRequest.Builder()
@@ -608,7 +538,7 @@
if (!hasEthernetConnection()) {
// Deadline passed with no network satisfied.
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
ji = mBuilder
.setRequiredNetwork(nr)
.setOverrideDeadline(0)
@@ -624,7 +554,7 @@
}
// No network requested
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
ji = mBuilder.setRequiredNetwork(null).build();
kTestEnvironment.setExpectedExecutions(1);
mJobScheduler.schedule(ji);
@@ -875,149 +805,25 @@
}
private boolean hasEthernetConnection() {
- if (!mHasEthernet) return false;
- Network[] networks = mCm.getAllNetworks();
- for (Network network : networks) {
- if (mCm.getNetworkCapabilities(network).hasTransport(TRANSPORT_ETHERNET)) {
- return true;
- }
- }
- return false;
- }
-
- private String unquoteSSID(String ssid) {
- // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
- // Otherwise it's guaranteed not to start with a quote.
- if (ssid.charAt(0) == '"') {
- return ssid.substring(1, ssid.length() - 1);
- } else {
- return ssid;
- }
- }
-
- private String getWifiSSID() throws Exception {
- // Location needs to be enabled to get the WiFi information.
- setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
- final AtomicReference<String> ssid = new AtomicReference<>();
- SystemUtil.runWithShellPermissionIdentity(() -> {
- ssid.set(mWifiManager.getConnectionInfo().getSSID());
- }, Manifest.permission.ACCESS_FINE_LOCATION);
- return unquoteSSID(ssid.get());
- }
-
- private void setLocationMode(String mode) throws Exception {
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE, mode);
- final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
- final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
- waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
- () -> wantEnabled == locationManager.isLocationEnabled());
- }
-
- // Returns "true", "false" or "none"
- private String getWifiMeteredStatus(String ssid) {
- // Interestingly giving the SSID as an argument to list wifi-networks
- // only works iff the network in question has the "false" policy.
- // Also unfortunately runShellCommand does not pass the command to the interpreter
- // so it's not possible to | grep the ssid.
- final String command = "cmd netpolicy list wifi-networks";
- final String policyString = SystemUtil.runShellCommand(command);
-
- final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
- Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
- if (!m.find()) {
- fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
- + policyString);
- }
- return m.group(1);
+ return mNetworkingHelper.hasEthernetConnection();
}
private void setWifiMeteredState(boolean metered) throws Exception {
- if (metered) {
- // Make sure unmetered cellular networks don't interfere.
- setAirplaneMode(true);
- setWifiState(true, mCm, mWifiManager);
- }
- final String ssid = getWifiSSID();
- setWifiMeteredState(ssid, metered ? "true" : "false");
- }
-
- // metered should be "true", "false" or "none"
- private void setWifiMeteredState(String ssid, String metered) throws Exception {
- if (metered.equals(getWifiMeteredStatus(ssid))) {
- return;
- }
- SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
- assertEquals(getWifiMeteredStatus(ssid), metered);
+ mNetworkingHelper.setWifiMeteredState(metered);
}
/**
* Ensure WiFi is enabled, and block until we've verified that we are in fact connected.
*/
private void connectToWifi() throws Exception {
- setWifiState(true, mCm, mWifiManager);
+ mNetworkingHelper.setWifiState(true);
}
/**
* Ensure WiFi is disabled, and block until we've verified that we are in fact disconnected.
*/
private void disconnectFromWifi() throws Exception {
- setWifiState(false, mCm, mWifiManager);
- }
-
- /** Ensures that the device has a wifi network saved. */
- static void ensureSavedWifiNetwork(WifiManager wifiManager) {
- final List<WifiConfiguration> savedNetworks =
- ShellIdentityUtils.invokeMethodWithShellPermissions(
- wifiManager, WifiManager::getConfiguredNetworks);
- assertFalse("Need at least one saved wifi network", savedNetworks.isEmpty());
- }
-
- /**
- * Set Wifi connection to specific state, and block until we've verified
- * that we are in the state.
- * Taken from {@link android.net.http.cts.ApacheHttpClientTest}.
- */
- static void setWifiState(final boolean enable,
- final ConnectivityManager cm, final WifiManager wm) throws Exception {
- if (enable != isWiFiConnected(cm, wm)) {
- NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
- NetworkCapabilities nc = new NetworkCapabilities.Builder()
- .addTransportType(TRANSPORT_WIFI)
- .build();
- NetworkTracker tracker = new NetworkTracker(nc, enable, cm);
- cm.registerNetworkCallback(nr, tracker);
-
- if (enable) {
- SystemUtil.runShellCommand("svc wifi enable");
- waitUntil("Failed to enable Wifi", 30 /* seconds */, () -> wm.isWifiEnabled());
- //noinspection deprecation
- SystemUtil.runWithShellPermissionIdentity(wm::reconnect,
- android.Manifest.permission.NETWORK_SETTINGS);
- } else {
- SystemUtil.runShellCommand("svc wifi disable");
- }
-
- tracker.waitForStateChange();
-
- assertTrue("Wifi must be " + (enable ? "connected to" : "disconnected from")
- + " an access point for this test.",
- enable == isWiFiConnected(cm, wm));
-
- cm.unregisterNetworkCallback(tracker);
- }
- }
-
- static boolean isWiFiConnected(final ConnectivityManager cm, final WifiManager wm) {
- if (!wm.isWifiEnabled()) {
- return false;
- }
- final Network network = cm.getActiveNetwork();
- if (network == null) {
- return false;
- }
- final NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(network);
- return networkCapabilities != null && networkCapabilities.hasTransport(TRANSPORT_WIFI);
+ mNetworkingHelper.setWifiState(false);
}
/**
@@ -1029,13 +835,14 @@
* @see #checkDeviceSupportsMobileData()
*/
private void disconnectWifiToConnectToMobile() throws Exception {
- setAirplaneMode(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
if (mHasWifi && mWifiManager.isWifiEnabled()) {
NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
NetworkCapabilities nc = new NetworkCapabilities.Builder()
.addTransportType(TRANSPORT_CELLULAR)
.build();
- NetworkTracker tracker = new NetworkTracker(nc, true, mCm);
+ NetworkingHelper.NetworkTracker tracker =
+ new NetworkingHelper.NetworkTracker(nc, true, mCm);
mCm.registerNetworkCallback(nr, tracker);
disconnectFromWifi();
@@ -1052,107 +859,6 @@
* If the policy is on, it interferes with tests that relies on metered connection.
*/
private void setDataSaverEnabled(boolean enabled) throws Exception {
- SystemUtil.runShellCommand(getInstrumentation(),
- enabled ? RESTRICT_BACKGROUND_ON_CMD : RESTRICT_BACKGROUND_OFF_CMD);
- }
-
- private boolean isAirplaneModeOn() throws Exception {
- final String output = SystemUtil.runShellCommand(getInstrumentation(),
- "cmd connectivity airplane-mode").trim();
- return "enabled".equals(output);
- }
-
- private void setAirplaneMode(boolean on) throws Exception {
- if (isAirplaneModeOn() == on) {
- return;
- }
- final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
- new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
- SystemUtil.runShellCommand(getInstrumentation(),
- "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
- airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
- 15 /* 15 seconds */);
- waitUntil("Networks didn't change to " + (!on ? " on" : " off"), 60 /* seconds */,
- () -> {
- if (on) {
- return mCm.getActiveNetwork() == null
- && (!mHasWifi || !isWiFiConnected(mCm, mWifiManager));
- } else {
- return mCm.getActiveNetwork() != null;
- }
- });
- // Wait some time for the network changes to propagate. Can't use
- // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
- // airplane mode status even though the network changes haven't propagated all the way to
- // JobScheduler.
- Thread.sleep(5000);
- }
-
- private static class NetworkTracker extends ConnectivityManager.NetworkCallback {
- private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
- private final ConnectivityManager mCm;
-
- private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
-
- private final NetworkCapabilities mExpectedCapabilities;
-
- private final boolean mExpectedConnected;
-
- private final Handler mHandler = new Handler(Looper.getMainLooper()) {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
- checkActiveNetwork();
- }
- }
- };
-
- private NetworkTracker(NetworkCapabilities expectedCapabilities, boolean expectedConnected,
- ConnectivityManager cm) {
- mExpectedCapabilities = expectedCapabilities;
- mExpectedConnected = expectedConnected;
- mCm = cm;
- }
-
- @Override
- public void onAvailable(Network network) {
- // Available doesn't mean it's the active network. We need to check that separately.
- checkActiveNetwork();
- }
-
- @Override
- public void onLost(Network network) {
- checkActiveNetwork();
- }
-
- boolean waitForStateChange() throws InterruptedException {
- checkActiveNetwork();
- return mReceiveLatch.await(60, TimeUnit.SECONDS);
- }
-
- private void checkActiveNetwork() {
- mHandler.removeMessages(MSG_CHECK_ACTIVE_NETWORK);
- if (mReceiveLatch.getCount() == 0) {
- return;
- }
-
- Network activeNetwork = mCm.getActiveNetwork();
- if (mExpectedConnected) {
- if (activeNetwork != null && mExpectedCapabilities.satisfiedByNetworkCapabilities(
- mCm.getNetworkCapabilities(activeNetwork))) {
- mReceiveLatch.countDown();
- } else {
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
- }
- } else {
- if (activeNetwork == null
- || !mExpectedCapabilities.satisfiedByNetworkCapabilities(
- mCm.getNetworkCapabilities(activeNetwork))) {
- mReceiveLatch.countDown();
- } else {
- mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
- }
- }
- }
+ mNetworkingHelper.setDataSaverEnabled(enabled);
}
}
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
index e4cb16c..5789a60 100644
--- a/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/JobThrottlingTest.java
@@ -18,24 +18,17 @@
import static android.app.job.JobInfo.NETWORK_TYPE_ANY;
import static android.app.job.JobInfo.NETWORK_TYPE_NONE;
-import static android.jobscheduler.cts.ConnectivityConstraintTest.ensureSavedWifiNetwork;
-import static android.jobscheduler.cts.ConnectivityConstraintTest.isWiFiConnected;
-import static android.jobscheduler.cts.ConnectivityConstraintTest.setWifiState;
import static android.jobscheduler.cts.TestAppInterface.TEST_APP_PACKAGE;
-import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
import static android.os.PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED;
import static com.android.compatibility.common.util.TestUtils.waitUntil;
-import static junit.framework.Assert.fail;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
-import android.Manifest;
import android.app.AppOpsManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
@@ -45,10 +38,6 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver;
-import android.location.LocationManager;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.wifi.WifiManager;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Temperature;
@@ -66,23 +55,14 @@
import com.android.compatibility.common.util.AppOpsUtils;
import com.android.compatibility.common.util.AppStandbyUtils;
import com.android.compatibility.common.util.BatteryUtils;
-import com.android.compatibility.common.util.CallbackAsserter;
import com.android.compatibility.common.util.DeviceConfigStateHelper;
-import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThermalUtils;
-import junit.framework.AssertionFailedError;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* Tests related to job throttling -- device idle, app standby and battery saver.
*/
@@ -108,24 +88,15 @@
private Context mContext;
private UiDevice mUiDevice;
+ private NetworkingHelper mNetworkingHelper;
private PowerManager mPowerManager;
private int mTestJobId;
private int mTestPackageUid;
private boolean mDeviceInDoze;
private boolean mDeviceIdleEnabled;
private boolean mAppStandbyEnabled;
- private WifiManager mWifiManager;
- private ConnectivityManager mCm;
- /** Whether the device running these tests supports WiFi. */
- private boolean mHasWifi;
- /** Track whether WiFi was enabled in case we turn it off. */
- private boolean mInitialWiFiState;
- /** Whether the device running these tests supports ethernet. */
- private boolean mHasEthernet;
- private boolean mInitialAirplaneModeState;
private String mInitialDisplayTimeout;
private String mInitialRestrictedBucketEnabled;
- private String mInitialLocationMode;
private String mInitialBatteryStatsConstants;
private boolean mAutomotiveDevice;
private boolean mLeanbackOnly;
@@ -158,6 +129,8 @@
public void setUp() throws Exception {
mContext = InstrumentationRegistry.getTargetContext();
mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ mNetworkingHelper =
+ new NetworkingHelper(InstrumentationRegistry.getInstrumentation(), mContext);
mPowerManager = mContext.getSystemService(PowerManager.class);
mDeviceInDoze = mPowerManager.isDeviceIdleMode();
mTestPackageUid = mContext.getPackageManager().getPackageUid(TEST_APP_PACKAGE, 0);
@@ -175,13 +148,6 @@
} else {
Log.w(TAG, "App standby not enabled on test device");
}
- mWifiManager = mContext.getSystemService(WifiManager.class);
- mCm = mContext.getSystemService(ConnectivityManager.class);
- mHasWifi = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WIFI);
- mInitialWiFiState = mWifiManager.isWifiEnabled();
- mHasEthernet = mContext.getPackageManager()
- .hasSystemFeature(PackageManager.FEATURE_ETHERNET);
- mInitialAirplaneModeState = isAirplaneModeOn();
mInitialRestrictedBucketEnabled = Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET);
mInitialBatteryStatsConstants = Settings.Global.getString(mContext.getContentResolver(),
@@ -189,8 +155,6 @@
// Make sure ACTION_CHARGING is sent immediately.
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.BATTERY_STATS_CONSTANTS, "battery_charged_delay_ms=0");
- mInitialLocationMode = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE);
// Make sure test jobs can run regardless of bucket.
mDeviceConfigStateHelper =
new DeviceConfigStateHelper(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
@@ -610,7 +574,7 @@
mDeviceConfigStateHelper.set("qc_timing_session_coalescing_duration_ms", "0");
mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
setScreenState(true);
setChargingState(false);
@@ -642,9 +606,8 @@
assumeFalse("not testable in automotive device", mAutomotiveDevice);
assumeFalse("not testable in leanback device", mLeanbackOnly);
assumeFalse("not testable, since ethernet is connected", hasEthernetConnection());
-
- assumeTrue(mHasWifi);
- ensureSavedWifiNetwork(mWifiManager);
+ assumeTrue(mNetworkingHelper.hasWifiFeature());
+ mNetworkingHelper.ensureSavedWifiNetwork();
setRestrictedBucketEnabled(true);
@@ -652,7 +615,7 @@
mDeviceConfigStateHelper.set("qc_timing_session_coalescing_duration_ms", "0");
mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
setScreenState(true);
setChargingState(false);
@@ -681,9 +644,8 @@
assertFalse("New job started in RESTRICTED bucket", mTestAppInterface.awaitJobStart(3_000));
// Add network
- setAirplaneMode(false);
- setWifiState(true, mCm, mWifiManager);
- setWifiMeteredState(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
+ mNetworkingHelper.setWifiMeteredState(false);
runJob();
assertTrue("New job didn't start in RESTRICTED bucket",
mTestAppInterface.awaitJobStart(5_000));
@@ -987,8 +949,8 @@
assumeFalse("not testable in leanback device", mLeanbackOnly);
assumeFalse("not testable, since ethernet is connected", hasEthernetConnection());
- assumeTrue(mHasWifi);
- ensureSavedWifiNetwork(mWifiManager);
+ assumeTrue(mNetworkingHelper.hasWifiFeature());
+ mNetworkingHelper.ensureSavedWifiNetwork();
setRestrictedBucketEnabled(true);
setTestPackageStandbyBucket(Bucket.RESTRICTED);
@@ -998,9 +960,8 @@
mDeviceConfigStateHelper.set("qc_max_session_count_restricted", "0");
// Satisfy all additional constraints.
- setAirplaneMode(false);
- setWifiState(true, mCm, mWifiManager);
- setWifiMeteredState(false);
+ mNetworkingHelper.setAllNetworksEnabled(true);
+ mNetworkingHelper.setWifiMeteredState(false);
setChargingState(true);
BatteryUtils.runDumpsysBatterySetLevel(100);
setScreenState(false);
@@ -1013,13 +974,12 @@
runJob();
assertTrue("New job didn't start in RESTRICTED bucket",
mTestAppInterface.awaitJobStart(DEFAULT_WAIT_TIMEOUT));
- setAirplaneMode(true);
+ mNetworkingHelper.setAllNetworksEnabled(false);
assertTrue("New job didn't stop when connectivity dropped",
mTestAppInterface.awaitJobStop(DEFAULT_WAIT_TIMEOUT));
assertEquals(JobParameters.STOP_REASON_CONSTRAINT_CONNECTIVITY,
mTestAppInterface.getLastParams().getStopReason());
- setAirplaneMode(false);
- setWifiState(true, mCm, mWifiManager);
+ mNetworkingHelper.setAllNetworksEnabled(true);
// Idle
mTestAppInterface.scheduleJob(false, NETWORK_TYPE_ANY, false);
@@ -1204,23 +1164,12 @@
Settings.Global.BATTERY_STATS_CONSTANTS, mInitialBatteryStatsConstants);
removeTestAppFromTempWhitelist();
- // Ensure that we leave WiFi in its previous state.
- if (mHasWifi && mWifiManager.isWifiEnabled() != mInitialWiFiState) {
- try {
- setWifiState(mInitialWiFiState, mCm, mWifiManager);
- } catch (AssertionFailedError e) {
- // Don't fail the test just because wifi state wasn't set in tearDown.
- Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
- }
- }
+ mNetworkingHelper.tearDown();
mDeviceConfigStateHelper.restoreOriginalValues();
mActivityManagerDeviceConfigStateHelper.restoreOriginalValues();
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.ENABLE_RESTRICTED_BUCKET, mInitialRestrictedBucketEnabled);
- if (isAirplaneModeOn() != mInitialAirplaneModeState) {
- setAirplaneMode(mInitialAirplaneModeState);
- }
- setLocationMode(mInitialLocationMode);
+
mUiDevice.executeShellCommand(
"cmd jobscheduler reset-execution-quota -u " + UserHandle.myUserId()
+ " " + TEST_APP_PACKAGE);
@@ -1377,120 +1326,7 @@
}
private boolean hasEthernetConnection() {
- if (!mHasEthernet) return false;
- Network[] networks = mCm.getAllNetworks();
- for (Network network : networks) {
- if (mCm.getNetworkCapabilities(network).hasTransport(TRANSPORT_ETHERNET)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isAirplaneModeOn() throws IOException {
- final String output =
- mUiDevice.executeShellCommand("cmd connectivity airplane-mode").trim();
- return "enabled".equals(output);
- }
-
- private void setAirplaneMode(boolean on) throws Exception {
- final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
- new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
- mUiDevice.executeShellCommand(
- "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
- airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
- 15 /* 15 seconds */);
- if (!on && mHasWifi) {
- // Force wifi to connect ASAP.
- mUiDevice.executeShellCommand("svc wifi enable");
- waitUntil("Failed to enable Wifi", 30 /* seconds */,
- () -> {
- return mWifiManager.isWifiEnabled();
- });
- //noinspection deprecation
- SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect,
- android.Manifest.permission.NETWORK_SETTINGS);
- }
- waitUntil("Networks didn't change to " + (!on ? "on" : "off"), 60 /* seconds */,
- () -> {
- if (on) {
- return mCm.getActiveNetwork() == null
- && (!mHasWifi || !isWiFiConnected(mCm, mWifiManager));
- } else {
- return mCm.getActiveNetwork() != null;
- }
- });
- // Wait some time for the network changes to propagate. Can't use
- // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
- // airplane mode status even though the network changes haven't propagated all the way to
- // JobScheduler.
- Thread.sleep(5000);
- }
-
- private static String unquoteSSID(String ssid) {
- // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
- // Otherwise it's guaranteed not to start with a quote.
- if (ssid.charAt(0) == '"') {
- return ssid.substring(1, ssid.length() - 1);
- } else {
- return ssid;
- }
- }
-
- private String getWifiSSID() throws Exception {
- // Location needs to be enabled to get the WiFi information.
- setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
- final AtomicReference<String> ssid = new AtomicReference<>();
- SystemUtil.runWithShellPermissionIdentity(() -> {
- ssid.set(mWifiManager.getConnectionInfo().getSSID());
- }, Manifest.permission.ACCESS_FINE_LOCATION);
- return unquoteSSID(ssid.get());
- }
-
- private void setLocationMode(String mode) throws Exception {
- Settings.Secure.putString(mContext.getContentResolver(),
- Settings.Secure.LOCATION_MODE, mode);
- final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
- final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
- waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
- () -> wantEnabled == locationManager.isLocationEnabled());
- }
-
- // Returns "true", "false" or "none"
- private String getWifiMeteredStatus(String ssid) {
- // Interestingly giving the SSID as an argument to list wifi-networks
- // only works iff the network in question has the "false" policy.
- // Also unfortunately runShellCommand does not pass the command to the interpreter
- // so it's not possible to | grep the ssid.
- final String command = "cmd netpolicy list wifi-networks";
- final String policyString = SystemUtil.runShellCommand(command);
-
- final Matcher m = Pattern.compile("^" + ssid + ";(true|false|none)$",
- Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
- if (!m.find()) {
- fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
- + policyString);
- }
- return m.group(1);
- }
-
- private void setWifiMeteredState(boolean metered) throws Exception {
- if (metered) {
- // Make sure unmetered cellular networks don't interfere.
- setAirplaneMode(true);
- setWifiState(true, mCm, mWifiManager);
- }
- final String ssid = getWifiSSID();
- setWifiMeteredState(ssid, metered ? "true" : "false");
- }
-
- // metered should be "true", "false" or "none"
- private void setWifiMeteredState(String ssid, String metered) {
- if (metered.equals(getWifiMeteredStatus(ssid))) {
- return;
- }
- SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
- assertEquals(getWifiMeteredStatus(ssid), metered);
+ return mNetworkingHelper.hasEthernetConnection();
}
private String getJobState() throws Exception {
diff --git a/tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java b/tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java
new file mode 100644
index 0000000..1402975
--- /dev/null
+++ b/tests/JobScheduler/src/android/jobscheduler/cts/NetworkingHelper.java
@@ -0,0 +1,432 @@
+/*
+ * 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.jobscheduler.cts;
+
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static com.android.compatibility.common.util.TestUtils.waitUntil;
+
+import static junit.framework.Assert.fail;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.location.LocationManager;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+
+import com.android.compatibility.common.util.CallbackAsserter;
+import com.android.compatibility.common.util.ShellIdentityUtils;
+import com.android.compatibility.common.util.SystemUtil;
+
+import junit.framework.AssertionFailedError;
+
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class NetworkingHelper {
+ private static final String TAG = "JsNetworkingUtils";
+
+ private static final String RESTRICT_BACKGROUND_GET_CMD =
+ "cmd netpolicy get restrict-background";
+ private static final String RESTRICT_BACKGROUND_ON_CMD =
+ "cmd netpolicy set restrict-background true";
+ private static final String RESTRICT_BACKGROUND_OFF_CMD =
+ "cmd netpolicy set restrict-background false";
+
+ private final Context mContext;
+ private final Instrumentation mInstrumentation;
+
+ private final ConnectivityManager mConnectivityManager;
+ private final WifiManager mWifiManager;
+
+ /** Whether the device running these tests supports WiFi. */
+ private final boolean mHasWifi;
+ /** Whether the device running these tests supports ethernet. */
+ private final boolean mHasEthernet;
+ /** Whether the device running these tests supports telephony. */
+ private final boolean mHasTelephony;
+
+ private final boolean mInitialAirplaneModeState;
+ private final boolean mInitialDataSaverState;
+ private final String mInitialLocationMode;
+ private final boolean mInitialWiFiState;
+ private String mInitialWiFiMeteredState;
+ private String mInitialWiFiSSID;
+
+ NetworkingHelper(@NonNull Instrumentation instrumentation, @NonNull Context context)
+ throws Exception {
+ mContext = context;
+ mInstrumentation = instrumentation;
+
+ mConnectivityManager = context.getSystemService(ConnectivityManager.class);
+ mWifiManager = context.getSystemService(WifiManager.class);
+
+ PackageManager packageManager = mContext.getPackageManager();
+ mHasWifi = packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
+ mHasEthernet = packageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET);
+ mHasTelephony = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+
+ mInitialAirplaneModeState = isAirplaneModeOn();
+ mInitialDataSaverState = isDataSaverEnabled();
+ mInitialLocationMode = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.LOCATION_MODE);
+ mInitialWiFiState = mHasWifi && isWifiEnabled();
+ }
+
+ /** Ensures that the device has a wifi network saved. */
+ void ensureSavedWifiNetwork() throws Exception {
+ if (!mHasWifi) {
+ return;
+ }
+ final List<WifiConfiguration> savedNetworks =
+ ShellIdentityUtils.invokeMethodWithShellPermissions(
+ mWifiManager, WifiManager::getConfiguredNetworks);
+ assertFalse("Need at least one saved wifi network", savedNetworks.isEmpty());
+
+ setWifiState(true);
+ if (mInitialWiFiSSID == null) {
+ mInitialWiFiSSID = getWifiSSID();
+ mInitialWiFiMeteredState = getWifiMeteredStatus(mInitialWiFiSSID);
+ }
+ }
+
+ // Returns "true", "false", or "none".
+ private String getWifiMeteredStatus(String ssid) {
+ // Interestingly giving the SSID as an argument to list wifi-networks
+ // only works iff the network in question has the "false" policy.
+ // Also unfortunately runShellCommand does not pass the command to the interpreter
+ // so it's not possible to | grep the ssid.
+ final String command = "cmd netpolicy list wifi-networks";
+ final String policyString = SystemUtil.runShellCommand(command);
+
+ final Matcher m = Pattern.compile(ssid + ";(true|false|none)",
+ Pattern.MULTILINE | Pattern.UNIX_LINES).matcher(policyString);
+ if (!m.find()) {
+ fail("Unexpected format from cmd netpolicy (when looking for " + ssid + "): "
+ + policyString);
+ }
+ return m.group(1);
+ }
+
+ @NonNull
+ private String getWifiSSID() throws Exception {
+ // Location needs to be enabled to get the WiFi information.
+ setLocationMode(String.valueOf(Settings.Secure.LOCATION_MODE_ON));
+ final AtomicReference<String> ssid = new AtomicReference<>();
+ SystemUtil.runWithShellPermissionIdentity(
+ () -> ssid.set(mWifiManager.getConnectionInfo().getSSID()),
+ Manifest.permission.ACCESS_FINE_LOCATION);
+ return unquoteSSID(ssid.get());
+ }
+
+ boolean hasEthernetConnection() {
+ if (!mHasEthernet) return false;
+ Network[] networks = mConnectivityManager.getAllNetworks();
+ for (Network network : networks) {
+ if (mConnectivityManager.getNetworkCapabilities(network)
+ .hasTransport(TRANSPORT_ETHERNET)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean hasWifiFeature() {
+ return mHasWifi;
+ }
+
+ boolean isAirplaneModeOn() throws Exception {
+ final String output = SystemUtil.runShellCommand(mInstrumentation,
+ "cmd connectivity airplane-mode").trim();
+ return "enabled".equals(output);
+ }
+
+ boolean isDataSaverEnabled() throws Exception {
+ return SystemUtil
+ .runShellCommand(mInstrumentation, RESTRICT_BACKGROUND_GET_CMD)
+ .contains("enabled");
+ }
+
+ boolean isWiFiConnected() {
+ if (!mWifiManager.isWifiEnabled()) {
+ return false;
+ }
+ final Network network = mConnectivityManager.getActiveNetwork();
+ if (network == null) {
+ return false;
+ }
+ final NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(network);
+ return networkCapabilities != null && networkCapabilities.hasTransport(TRANSPORT_WIFI);
+ }
+
+ boolean isWifiEnabled() {
+ return mWifiManager.isWifiEnabled();
+ }
+
+ /**
+ * Tries to set all network statuses to {@code enabled}.
+ * However, this does not support ethernet connections.
+ * Confirm that {@link #hasEthernetConnection()} returns false before relying on this.
+ */
+ void setAllNetworksEnabled(boolean enabled) throws Exception {
+ if (mHasWifi) {
+ setWifiState(enabled);
+ }
+ setAirplaneMode(!enabled);
+ }
+
+ void setAirplaneMode(boolean on) throws Exception {
+ if (isAirplaneModeOn() == on) {
+ return;
+ }
+ final CallbackAsserter airplaneModeBroadcastAsserter = CallbackAsserter.forBroadcast(
+ new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+ SystemUtil.runShellCommand(mInstrumentation,
+ "cmd connectivity airplane-mode " + (on ? "enable" : "disable"));
+ airplaneModeBroadcastAsserter.assertCalled("Didn't get airplane mode changed broadcast",
+ 15 /* 15 seconds */);
+ if (!on && mHasWifi) {
+ // Try to trigger some network connection.
+ setWifiState(true);
+ }
+ waitUntil("Airplane mode didn't change to " + (on ? " on" : " off"), 60 /* seconds */,
+ () -> {
+ // Airplane mode only affects the cellular network. If the device doesn't
+ // support cellular, then we can only check that the airplane mode toggle is on.
+ if (!mHasTelephony) {
+ return on == isAirplaneModeOn();
+ }
+ if (on) {
+ Network[] networks = mConnectivityManager.getAllNetworks();
+ for (Network network : networks) {
+ if (mConnectivityManager.getNetworkCapabilities(network)
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return mConnectivityManager.getActiveNetwork() != null;
+ }
+ });
+ // Wait some time for the network changes to propagate. Can't use
+ // waitUntil(isAirplaneModeOn() == on) because the response quickly gives the new
+ // airplane mode status even though the network changes haven't propagated all the way to
+ // JobScheduler.
+ Thread.sleep(5000);
+ }
+
+ /**
+ * Ensures that restrict background data usage policy is turned off.
+ * If the policy is on, it interferes with tests that relies on metered connection.
+ */
+ void setDataSaverEnabled(boolean enabled) throws Exception {
+ SystemUtil.runShellCommand(mInstrumentation,
+ enabled ? RESTRICT_BACKGROUND_ON_CMD : RESTRICT_BACKGROUND_OFF_CMD);
+ }
+
+ private void setLocationMode(String mode) throws Exception {
+ Settings.Secure.putString(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_MODE, mode);
+ final LocationManager locationManager = mContext.getSystemService(LocationManager.class);
+ final boolean wantEnabled = !String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(mode);
+ waitUntil("Location " + (wantEnabled ? "not enabled" : "still enabled"),
+ () -> wantEnabled == locationManager.isLocationEnabled());
+ }
+
+ void setWifiMeteredState(boolean metered) throws Exception {
+ if (metered) {
+ // Make sure unmetered cellular networks don't interfere.
+ setAirplaneMode(true);
+ setWifiState(true);
+ }
+ final String ssid = getWifiSSID();
+ setWifiMeteredState(ssid, metered ? "true" : "false");
+ }
+
+ // metered should be "true", "false" or "none"
+ private void setWifiMeteredState(String ssid, String metered) {
+ if (metered.equals(getWifiMeteredStatus(ssid))) {
+ return;
+ }
+ SystemUtil.runShellCommand("cmd netpolicy set metered-network " + ssid + " " + metered);
+ assertEquals(getWifiMeteredStatus(ssid), metered);
+ }
+
+ /**
+ * Set Wifi connection to specific state, and block until we've verified
+ * that we are in the state.
+ * Taken from {@link android.net.http.cts.ApacheHttpClientTest}.
+ */
+ void setWifiState(final boolean enable) throws Exception {
+ if (enable != isWiFiConnected()) {
+ NetworkRequest nr = new NetworkRequest.Builder().clearCapabilities().build();
+ NetworkCapabilities nc = new NetworkCapabilities.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build();
+ NetworkTracker tracker = new NetworkTracker(nc, enable, mConnectivityManager);
+ mConnectivityManager.registerNetworkCallback(nr, tracker);
+
+ if (enable) {
+ SystemUtil.runShellCommand("svc wifi enable");
+ waitUntil("Failed to enable Wifi", 30 /* seconds */,
+ this::isWifiEnabled);
+ //noinspection deprecation
+ SystemUtil.runWithShellPermissionIdentity(mWifiManager::reconnect,
+ android.Manifest.permission.NETWORK_SETTINGS);
+ } else {
+ SystemUtil.runShellCommand("svc wifi disable");
+ }
+
+ tracker.waitForStateChange();
+
+ assertEquals("Wifi must be " + (enable ? "connected to" : "disconnected from")
+ + " an access point for this test.", enable, isWiFiConnected());
+
+ mConnectivityManager.unregisterNetworkCallback(tracker);
+ }
+ }
+
+ void tearDown() throws Exception {
+ // Restore initial restrict background data usage policy
+ setDataSaverEnabled(mInitialDataSaverState);
+
+ // Ensure that we leave WiFi in its previous state.
+ if (mHasWifi) {
+ if (mInitialWiFiSSID != null) {
+ setWifiMeteredState(mInitialWiFiSSID, mInitialWiFiMeteredState);
+ }
+ if (mWifiManager.isWifiEnabled() != mInitialWiFiState) {
+ try {
+ setWifiState(mInitialWiFiState);
+ } catch (AssertionFailedError e) {
+ // Don't fail the test just because wifi state wasn't set in tearDown.
+ Log.e(TAG, "Failed to return wifi state to " + mInitialWiFiState, e);
+ }
+ }
+ }
+
+ // Restore initial airplane mode status. Do it after setting wifi in case wifi was
+ // originally metered.
+ if (isAirplaneModeOn() != mInitialAirplaneModeState) {
+ setAirplaneMode(mInitialAirplaneModeState);
+ }
+
+ setLocationMode(mInitialLocationMode);
+ }
+
+ private String unquoteSSID(String ssid) {
+ // SSID is returned surrounded by quotes if it can be decoded as UTF-8.
+ // Otherwise it's guaranteed not to start with a quote.
+ if (ssid.charAt(0) == '"') {
+ return ssid.substring(1, ssid.length() - 1);
+ } else {
+ return ssid;
+ }
+ }
+
+ static class NetworkTracker extends ConnectivityManager.NetworkCallback {
+ private static final int MSG_CHECK_ACTIVE_NETWORK = 1;
+ private final ConnectivityManager mConnectivityManager;
+
+ private final CountDownLatch mReceiveLatch = new CountDownLatch(1);
+
+ private final NetworkCapabilities mExpectedCapabilities;
+
+ private final boolean mExpectedConnected;
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_CHECK_ACTIVE_NETWORK) {
+ checkActiveNetwork();
+ }
+ }
+ };
+
+ NetworkTracker(NetworkCapabilities expectedCapabilities, boolean expectedConnected,
+ ConnectivityManager cm) {
+ mExpectedCapabilities = expectedCapabilities;
+ mExpectedConnected = expectedConnected;
+ mConnectivityManager = cm;
+ }
+
+ @Override
+ public void onAvailable(Network network) {
+ // Available doesn't mean it's the active network. We need to check that separately.
+ checkActiveNetwork();
+ }
+
+ @Override
+ public void onLost(Network network) {
+ checkActiveNetwork();
+ }
+
+ boolean waitForStateChange() throws InterruptedException {
+ checkActiveNetwork();
+ return mReceiveLatch.await(60, TimeUnit.SECONDS);
+ }
+
+ private void checkActiveNetwork() {
+ mHandler.removeMessages(MSG_CHECK_ACTIVE_NETWORK);
+ if (mReceiveLatch.getCount() == 0) {
+ return;
+ }
+
+ Network activeNetwork = mConnectivityManager.getActiveNetwork();
+ if (mExpectedConnected) {
+ if (activeNetwork != null && mExpectedCapabilities.satisfiedByNetworkCapabilities(
+ mConnectivityManager.getNetworkCapabilities(activeNetwork))) {
+ mReceiveLatch.countDown();
+ } else {
+ mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
+ }
+ } else {
+ if (activeNetwork == null
+ || !mExpectedCapabilities.satisfiedByNetworkCapabilities(
+ mConnectivityManager.getNetworkCapabilities(activeNetwork))) {
+ mReceiveLatch.countDown();
+ } else {
+ mHandler.sendEmptyMessageDelayed(MSG_CHECK_ACTIVE_NETWORK, 5000);
+ }
+ }
+ }
+ }
+}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
index f0e3b67..d23e211 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDispatchTest.java
@@ -25,7 +25,6 @@
import static android.accessibilityservice.cts.utils.GestureUtils.IS_ACTION_POINTER_UP;
import static android.accessibilityservice.cts.utils.GestureUtils.IS_ACTION_UP;
import static android.accessibilityservice.cts.utils.GestureUtils.add;
-import static android.accessibilityservice.cts.utils.GestureUtils.ceil;
import static android.accessibilityservice.cts.utils.GestureUtils.click;
import static android.accessibilityservice.cts.utils.GestureUtils.diff;
import static android.accessibilityservice.cts.utils.GestureUtils.dispatchGesture;
@@ -56,11 +55,11 @@
import android.accessibilityservice.cts.activities.AccessibilityTestActivity;
import android.app.Instrumentation;
import android.app.UiAutomation;
-import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Matrix;
import android.graphics.Path;
import android.graphics.PointF;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
@@ -69,7 +68,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
-import android.view.WindowManager;
import android.widget.TextView;
import androidx.test.rule.ActivityTestRule;
@@ -88,8 +86,6 @@
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
-import android.graphics.Rect;
-
/**
* Verify that gestures dispatched from an accessibility service show up in the current UI
*/
@@ -196,7 +192,8 @@
// Verify other MotionEvent fields in this test to make sure they get initialized.
assertEquals(0, clickDown.getActionIndex());
assertEquals(VIRTUAL_KEYBOARD, clickDown.getDeviceId());
- assertEquals(MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT, clickDown.getFlags());
+ assertEquals(MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT,
+ clickDown.getFlags() & MotionEvent.FLAG_IS_ACCESSIBILITY_EVENT);
assertEquals(0, clickDown.getEdgeFlags());
assertEquals(1F, clickDown.getXPrecision(), 0F);
assertEquals(1F, clickDown.getYPrecision(), 0F);
diff --git a/tests/app/src/android/app/cts/DisplayTest.java b/tests/app/src/android/app/cts/DisplayTest.java
index f0669b9..a79a6b3 100644
--- a/tests/app/src/android/app/cts/DisplayTest.java
+++ b/tests/app/src/android/app/cts/DisplayTest.java
@@ -20,12 +20,17 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import android.app.ActivityOptions;
import android.app.stubs.DisplayTestActivity;
import android.app.stubs.OrientationTestUtils;
+import android.content.Intent;
import android.graphics.Point;
import android.server.wm.SetRequestedOrientationRule;
+import android.util.Pair;
import android.view.Display;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import com.android.compatibility.common.util.ApiTest;
import org.junit.Rule;
@@ -52,55 +57,62 @@
return;
}
- final DisplayTestActivity activity =
- mSetRequestedOrientationRule.launchActivityInFullscreen(DisplayTestActivity.class);
+ final Pair<Intent, ActivityOptions> launchArgs =
+ SetRequestedOrientationRule.buildFullScreenLaunchArgs(DisplayTestActivity.class);
- // Get a {@link Display} instance before rotation.
- final Display origDisplay = activity.getDisplay();
+ final DisplayTestActivity activity = (DisplayTestActivity) InstrumentationRegistry
+ .getInstrumentation()
+ .startActivitySync(launchArgs.first, launchArgs.second.toBundle());
+ try {
+ // Get a {@link Display} instance before rotation.
+ final Display origDisplay = activity.getDisplay();
- // Capture the originally reported width and heights
- final Point origSize = new Point();
- origDisplay.getRealSize(origSize);
+ // Capture the originally reported width and heights
+ final Point origSize = new Point();
+ origDisplay.getRealSize(origSize);
- // Change orientation
- activity.configurationChangeObserver.startObserving();
- OrientationTestUtils.switchOrientation(activity);
+ // Change orientation
+ activity.configurationChangeObserver.startObserving();
+ OrientationTestUtils.switchOrientation(activity);
- final boolean closeToSquareBounds =
- OrientationTestUtils.isCloseToSquareBounds(activity);
+ final boolean closeToSquareBounds =
+ OrientationTestUtils.isCloseToSquareBounds(activity);
- // Don't wait for the configuration to change if
- // the display is square. In many cases it won't.
- if (!closeToSquareBounds) {
- activity.configurationChangeObserver.await();
- }
+ // Don't wait for the configuration to change if
+ // the display is square. In many cases it won't.
+ if (!closeToSquareBounds) {
+ activity.configurationChangeObserver.await();
+ }
- final Point newOrigSize = new Point();
- origDisplay.getRealSize(newOrigSize);
+ final Point newOrigSize = new Point();
+ origDisplay.getRealSize(newOrigSize);
- // Get a {@link Display} instance after rotation.
- final Display updatedDisplay = activity.getDisplay();
- final Point updatedSize = new Point();
- updatedDisplay.getRealSize(updatedSize);
+ // Get a {@link Display} instance after rotation.
+ final Display updatedDisplay = activity.getDisplay();
+ final Point updatedSize = new Point();
+ updatedDisplay.getRealSize(updatedSize);
- // For square screens the following assertions do not make sense and will always
- // fail.
- if (!closeToSquareBounds) {
- // Ensure that the width and height of the original instance no longer are the
- // same.
- // Note that this will be false if the device width and height are identical.
- // Note there are cases where width and height may not all be updated, such as
- // on docked devices where the app is letterboxed. However, at least one
- // dimension needs to be updated.
+ // For square screens the following assertions do not make sense and will always
+ // fail.
+ if (!closeToSquareBounds) {
+ // Ensure that the width and height of the original instance no longer are the
+ // same.
+ // Note that this will be false if the device width and height are identical.
+ // Note there are cases where width and height may not all be updated, such as
+ // on docked devices where the app is letterboxed. However, at least one
+ // dimension needs to be updated.
+ assertWithMessage(
+ "size from original display instance should have changed")
+ .that(origSize).isNotEqualTo(newOrigSize);
+ }
+
+ // Ensure that the width and height of the original instance have been updated to
+ // match the values that would be found in a new instance.
assertWithMessage(
- "size from original display instance should have changed")
- .that(origSize).isNotEqualTo(newOrigSize);
+ "size from original display instance should match current")
+ .that(newOrigSize).isEqualTo(updatedSize);
+ } finally {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(activity::finish);
}
-
- // Ensure that the width and height of the original instance have been updated to
- // match the values that would be found in a new instance.
- assertWithMessage(
- "size from original display instance should match current")
- .that(newOrigSize).isEqualTo(updatedSize);
}
}
diff --git a/tests/app/src/android/app/cts/NotificationTemplateTest.kt b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
index ff8bf56..cd1de26 100644
--- a/tests/app/src/android/app/cts/NotificationTemplateTest.kt
+++ b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
@@ -16,7 +16,6 @@
package android.app.cts
import android.R
-import android.app.ActivityManager
import android.app.Notification
import android.app.PendingIntent
import android.app.Person
@@ -36,7 +35,6 @@
import androidx.test.filters.SmallTest
import com.android.compatibility.common.util.CddTest
import com.google.common.truth.Truth.assertThat
-import kotlin.math.min
import kotlin.test.assertFailsWith
class NotificationTemplateTest : NotificationTemplateTestBase() {
@@ -144,11 +142,10 @@
}
fun testWideIcon_inBigPicture_cappedTo16By9() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testWideIcon_inBigPicture_cappedTo16By9" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val icon = createBitmap(200, 100)
val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -166,11 +163,10 @@
}
fun testWideIcon_inBigPicture_canShowExact4By3() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testWideIcon_inBigPicture_canShowExact4By3" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val icon = createBitmap(400, 300)
val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -188,11 +184,10 @@
}
fun testWideIcon_inBigPicture_neverNarrowerThanSquare() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testWideIcon_inBigPicture_neverNarrowerThanSquare" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val icon = createBitmap(200, 300)
val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -254,11 +249,10 @@
}
fun testBigPictureStyle_populatesExtrasCompatibly() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testBigPictureStyle_populatesExtrasCompatibly" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val bitmap = createBitmap(40, 30)
val uri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
val iconWithUri = Icon.createWithContentUri(uri)
@@ -272,7 +266,7 @@
style.bigPicture(bitmap)
builder.build().let {
assertThat(it.extras.getParcelable<Bitmap>(Notification.EXTRA_PICTURE)
- !!.sameAs(bitmap)).isTrue()
+ !!.sameAs(bitmap)).isTrue()
assertThat(it.extras.get(Notification.EXTRA_PICTURE_ICON)).isNull()
}
@@ -286,18 +280,17 @@
style.bigPicture(iconWithBitmap)
builder.build().let {
assertThat(it.extras.getParcelable<Bitmap>(Notification.EXTRA_PICTURE)
- !!.sameAs(bitmap)).isTrue()
+ !!.sameAs(bitmap)).isTrue()
assertThat(it.extras.get(Notification.EXTRA_PICTURE_ICON)).isNull()
}
}
@CddTest(requirement = "3.8.3.1/C-2-1")
fun testBigPictureStyle_bigPictureUriIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testBigPictureStyle_bigPictureUriIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_400_by_300.png")
val pictureIcon = Icon.createWithContentUri(pictureUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -307,28 +300,19 @@
checkViews(builder.createBigContentView()) {
val pictureView = requireViewByIdName<ImageView>("big_picture")
assertThat(pictureView.visibility).isEqualTo(View.VISIBLE)
-
- var expectedWidth = min(400, bigPictureWidth())
- var expectedHeight = min(300, bigPictureWidth() * 3 / 4)
- // It's possible that big picture width is configured smaller than we expect here.
- // In that situation, we need to flip the expected size.
- if (bigPictureHeight() < expectedHeight) {
- expectedHeight = bigPictureHeight()
- expectedWidth = bigPictureHeight() * 4 / 3
- }
-
- assertThat(pictureView.drawable.intrinsicWidth).isEqualTo(expectedWidth)
- assertThat(pictureView.drawable.intrinsicHeight).isEqualTo(expectedHeight)
+ assertThat(pictureView.width.toFloat())
+ .isWithin(1f)
+ .of((pictureView.height * 4 / 3).toFloat())
+ assertThat(pictureView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
@CddTest(requirement = "3.8.3.1/C-2-1")
fun testPromoteBigPicture_withBigPictureUriIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withBigPictureUriIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val pictureUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
val pictureIcon = Icon.createWithContentUri(pictureUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -343,17 +327,15 @@
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(rightIconSize())
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(rightIconSize() * 3 / 4)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
fun testPromoteBigPicture_withoutLargeIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withoutLargeIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_media_play)
@@ -367,8 +349,7 @@
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(40)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(30)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
checkIconView(builder.createBigContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.GONE)
@@ -376,11 +357,10 @@
}
fun testPromoteBigPicture_withLargeIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withLargeIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val icon = createBitmap(80, 65)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -392,37 +372,28 @@
.showBigPictureWhenCollapsed(true)
)
- // At really high densities the size of rendered icon can dip below the
- // tested size - we allow rendering of smaller icon with the same
- // aspect ratio then.
- val expectedIconWidth = minOf(rightIconSize(), 80)
- val expectedIconHeight = minOf(rightIconSize() * 65 / 80, 65)
-
checkIconView(builder.createContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(40)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(30)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
checkIconView(builder.createBigContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 80 / 65).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(expectedIconWidth)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(expectedIconHeight)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
@CddTest(requirement = "3.8.3.1/C-2-1")
fun testPromoteBigPicture_withBigLargeIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withBigLargeIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val inputWidth = 400
val inputHeight = 300
@@ -436,36 +407,30 @@
.showBigPictureWhenCollapsed(true)
)
- val expectedIconWidth = minOf(rightIconSize(), inputWidth)
- val expectedIconHeight = minOf(rightIconSize() * inputHeight / inputWidth, inputHeight)
-
checkIconView(builder.createContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(40)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(30)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
checkIconView(builder.createBigContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(expectedIconWidth)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(expectedIconHeight)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
assertThat(builder.build().extras.getParcelable<Bitmap>(Notification.EXTRA_PICTURE)
- !!.sameAs(picture)).isTrue()
+ !!.sameAs(picture)).isTrue()
}
@CddTest(requirement = "3.8.3.1/C-2-1")
fun testBigPicture_withBigLargeIcon_withContentUri() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testBigPicture_withBigLargeIcon_withContentUri" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val iconUri = Uri.parse("content://android.app.stubs.assets/picture_800_by_600.png")
val icon = Icon.createWithContentUri(iconUri)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -477,9 +442,7 @@
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
-
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(rightIconSize())
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(rightIconSize() * 3 / 4)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
@@ -864,39 +827,14 @@
PendingIntent.getBroadcast(mContext, 0, Intent("test"), PendingIntent.FLAG_IMMUTABLE)
}
- private fun rightIconSize(): Int {
- return mContext.resources.getDimensionPixelSize(getAndroidRDimen(
- if (isLowRamDevice()) {
- "notification_right_icon_size_low_ram"
- } else {
- "notification_right_icon_size"
- }))
- }
-
- private fun bigPictureWidth(): Int {
- return mContext.resources.getDimensionPixelSize(getAndroidRDimen(
- if (isLowRamDevice()) {
- "notification_big_picture_max_width_low_ram"
- } else {
- "notification_big_picture_max_width"
- }))
- }
-
- private fun bigPictureHeight(): Int {
- return mContext.resources.getDimensionPixelSize(getAndroidRDimen(
- if (isLowRamDevice()) {
- "notification_big_picture_max_width_low_ram"
- } else {
- "notification_big_picture_max_width"
- }))
- }
-
- private fun isLowRamDevice(): Boolean {
- return mContext.getSystemService(ActivityManager::class.java).isLowRamDevice()
- }
-
- private fun isPlatformAutomotive(): Boolean {
- return mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ /**
+ * Assume that we're running on the platform that supports styled notifications.
+ *
+ * If the current platform does not support notification styles, skip this test without failure.
+ */
+ private fun skipIfPlatformDoesNotSupportNotificationStyles(): Boolean {
+ return mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
+ mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
}
companion object {
diff --git a/tests/appsearch/Android.bp b/tests/appsearch/Android.bp
index c8219c9..f858b17 100644
--- a/tests/appsearch/Android.bp
+++ b/tests/appsearch/Android.bp
@@ -40,6 +40,7 @@
":CtsAppSearchTestHelperB",
],
per_testcase_directory: true,
+ min_sdk_version: "31",
}
android_test_helper_app {
@@ -67,6 +68,7 @@
],
certificate: ":cts-appsearch-helper-cert-a",
sdk_version: "test_current",
+ min_sdk_version: "31",
}
android_test_helper_app {
@@ -94,6 +96,7 @@
],
certificate: ":cts-appsearch-helper-cert-b",
sdk_version: "test_current",
+ min_sdk_version: "31",
}
filegroup {
diff --git a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
index 18d4904..533ece4 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CameraManagerTest.java
@@ -33,6 +33,7 @@
import android.hardware.camera2.cts.CameraTestUtils.HandlerExecutor;
import android.hardware.camera2.cts.CameraTestUtils.MockStateCallback;
import android.hardware.camera2.cts.helpers.CameraErrorCollector;
+import android.hardware.camera2.cts.helpers.StaticMetadata;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -669,18 +670,23 @@
}
private <T> void verifyAvailabilityCbsReceived(HashSet<T> expectedCameras,
- LinkedBlockingQueue<T> queue, LinkedBlockingQueue<T> otherQueue,
+ LinkedBlockingQueue<T> expectedEventQueue, LinkedBlockingQueue<T> unExpectedEventQueue,
boolean available) throws Exception {
while (expectedCameras.size() > 0) {
- T id = queue.poll(AVAILABILITY_TIMEOUT_MS,
+ T id = expectedEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
java.util.concurrent.TimeUnit.MILLISECONDS);
assertTrue("Did not receive initial " + (available ? "available" : "unavailable")
+ " notices for some cameras", id != null);
+ assertTrue("Received initial " + (available ? "available" : "unavailable")
+ + " notice for wrong camera " + id, expectedCameras.contains(id));
expectedCameras.remove(id);
}
- // Verify no unavailable/available cameras were reported
- assertTrue("Some camera devices are initially " + (available ? "unavailable" : "available"),
- otherQueue.size() == 0);
+ // Verify no unexpected unavailable/available cameras were reported
+ if (unExpectedEventQueue != null) {
+ assertTrue("Received unexpected initial "
+ + (available ? "unavailable" : "available"),
+ unExpectedEventQueue.size() == 0);
+ }
}
private void verifySingleAvailabilityCbsReceived(LinkedBlockingQueue<String> expectedEventQueue,
@@ -781,15 +787,15 @@
verifyAvailabilityCbsReceived(expectedAvailableCameras, availableEventQueue,
unavailableEventQueue, true /*available*/);
+ // Clear physical camera callback queue in case the initial state of certain physical
+ // cameras are unavailable.
+ unavailablePhysicalCamEventQueue.clear();
+
// Verify transitions for individual cameras
for (String id : cameras) {
MockStateCallback mockListener = MockStateCallback.mock();
mCameraListener = new BlockingStateCallback(mockListener);
- // Clear logical camera callback queue in case the initial state of certain physical
- // cameras are unavailable.
- unavailablePhysicalCamEventQueue.clear();
-
if (useExecutor) {
mCameraManager.openCamera(id, executor, mCameraListener);
} else {
@@ -843,8 +849,13 @@
expectedLogicalCameras = new HashSet<Pair<String, String>>(relatedLogicalCameras);
verifyAvailabilityCbsReceived(expectedLogicalCameras,
- availablePhysicalCamEventQueue, unavailablePhysicalCamEventQueue,
+ availablePhysicalCamEventQueue,
+ null /*unExpectedEventQueue*/,
true /*available*/);
+
+ // Clear physical camera callback queue in case the initial state of certain physical
+ // cameras are unavailable.
+ unavailablePhysicalCamEventQueue.clear();
}
// Verify that we can unregister the listener and see no more events
@@ -938,9 +949,142 @@
verifySingleAvailabilityCbsReceived(onCameraClosedEventQueue,
onCameraOpenedEventQueue, cameras[0], "onCameraClosed", "onCameraOpened");
+
+ mCameraManager.unregisterAvailabilityCallback(ac);
}
} // testCameraManagerListenerCallbacks
+ /**
+ * Test that the physical camera available/unavailable callback behavior is consistent
+ * between:
+ *
+ * - No camera is open, and
+ * - camera opens, close camera, expect callback
+ */
+ @Test
+ public void testPhysicalCameraAvailabilityConsistency() throws Throwable {
+ final LinkedBlockingQueue<String> availableEventQueue = new LinkedBlockingQueue<>();
+ final LinkedBlockingQueue<String> unavailableEventQueue = new LinkedBlockingQueue<>();
+ final LinkedBlockingQueue<Pair<String, String>> unavailablePhysicalCamEventQueue =
+ new LinkedBlockingQueue<>();
+ CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
+ @Override
+ public void onCameraAvailable(String cameraId) {
+ super.onCameraAvailable(cameraId);
+ availableEventQueue.offer(cameraId);
+ }
+
+ @Override
+ public void onCameraUnavailable(String cameraId) {
+ super.onCameraUnavailable(cameraId);
+ unavailableEventQueue.offer(cameraId);
+ }
+
+ @Override
+ public void onPhysicalCameraAvailable(String cameraId, String physicalCameraId) {
+ super.onPhysicalCameraAvailable(cameraId, physicalCameraId);
+ unavailablePhysicalCamEventQueue.remove(new Pair<>(cameraId, physicalCameraId));
+ }
+
+ @Override
+ public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
+ super.onPhysicalCameraUnavailable(cameraId, physicalCameraId);
+ unavailablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
+ }
+ };
+
+ String[] cameras = mCameraIdsUnderTest;
+ if (cameras.length == 0) {
+ Log.i(TAG, "Skipping testPhysicalCameraAvailabilityConsistency, no cameras");
+ return;
+ }
+
+ for (String cameraId : cameras) {
+ CameraCharacteristics ch = mCameraManager.getCameraCharacteristics(cameraId);
+ StaticMetadata staticInfo = new StaticMetadata(ch);
+ if (!staticInfo.isLogicalMultiCamera()) {
+ // Test is only applicable for logical multi-camera.
+ continue;
+ }
+
+ // Get initial physical unavailable callbacks without opening camera
+ mCameraManager.registerAvailabilityCallback(ac, mHandler);
+ Set<String> unavailablePhysicalCameras = getUnavailablePhysicalCamerasAndDrain(
+ unavailablePhysicalCamEventQueue, cameraId);
+
+ // Open camera
+ MockStateCallback mockListener = MockStateCallback.mock();
+ mCameraListener = new BlockingStateCallback(mockListener);
+ mCameraManager.openCamera(cameraId, mCameraListener, mHandler);
+ // Block until opened
+ mCameraListener.waitForState(BlockingStateCallback.STATE_OPENED,
+ CameraTestUtils.CAMERA_IDLE_TIMEOUT_MS);
+ // Then verify only open happened, and get the camera handle
+ CameraDevice camera = verifyCameraStateOpened(cameraId, mockListener);
+
+ // The camera should be in available->unavailable state.
+ String candidateUnavailableId = unavailableEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
+ java.util.concurrent.TimeUnit.MILLISECONDS);
+ assertNotNull("No unavailable notice for expected ID " + cameraId,
+ candidateUnavailableId);
+ assertTrue("Received unavailable notice for wrong ID, "
+ + "expected " + cameraId + ", got " + candidateUnavailableId,
+ cameraId.equals(candidateUnavailableId));
+ assertTrue("Received > 1 unavailable callback for id " + cameraId,
+ unavailableEventQueue.size() == 0);
+ availableEventQueue.clear();
+ unavailableEventQueue.clear();
+
+ // Close camera device
+ camera.close();
+ mCameraListener.waitForState(BlockingStateCallback.STATE_CLOSED,
+ CameraTestUtils.CAMERA_CLOSE_TIMEOUT_MS);
+ verifySingleAvailabilityCbsReceived(availableEventQueue, unavailableEventQueue,
+ cameraId, "availability", "Unavailability");
+
+ // Get physical unavailable callbacks after opening and closing camera
+ Set<String> unavailablePhysicalCamerasAfterClose =
+ getUnavailablePhysicalCamerasAndDrain(
+ unavailablePhysicalCamEventQueue, cameraId);
+
+ assertTrue("The unavailable physical cameras must be the same between before open "
+ + unavailablePhysicalCameras.toString() + " and after close "
+ + unavailablePhysicalCamerasAfterClose.toString(),
+ unavailablePhysicalCameras.equals(unavailablePhysicalCamerasAfterClose));
+
+ mCameraManager.unregisterAvailabilityCallback(ac);
+ }
+ }
+
+ /**
+ * This function polls on the event queue to get unavailable physical camera IDs belonging
+ * to a particular logical camera. The event queue is drained before the function returns.
+ *
+ * @param queue The event queue capturing unavailable physical cameras
+ * @param cameraId The logical camera ID
+ *
+ * @return The currently unavailable physical cameras
+ */
+ private Set<String> getUnavailablePhysicalCamerasAndDrain(
+ LinkedBlockingQueue<Pair<String, String>> queue, String cameraId) throws Exception {
+ Set<String> unavailablePhysicalCameras = new HashSet<String>();
+
+ while (true) {
+ Pair<String, String> unavailableIdCombo = queue.poll(
+ AVAILABILITY_TIMEOUT_MS, java.util.concurrent.TimeUnit.MILLISECONDS);
+ if (unavailableIdCombo == null) {
+ // No more entries in the queue. Break out of the loop and return.
+ break;
+ }
+
+ if (cameraId.equals(unavailableIdCombo.first)) {
+ unavailablePhysicalCameras.add(unavailableIdCombo.second);
+ }
+ };
+
+ return unavailablePhysicalCameras;
+ }
+
// Verify no LEGACY-level devices appear on devices first launched in the Q release or newer
@Test
@AppModeFull(reason = "Instant apps can't access Test API")
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java
index 52e1a7e..8d6d421 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/PreferentialNetworkServiceTest.java
@@ -37,6 +37,7 @@
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.Process;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.util.Range;
@@ -55,11 +56,18 @@
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
+import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
+import java.net.Socket;
import java.util.List;
import java.util.Objects;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
// TODO(b/190797743): Move this test to to net test folder.
@RunWith(BedsteadJUnit4.class)
@@ -102,6 +110,33 @@
}
/**
+ * Make sure both including and excluding UIDs from a policy is disallowed.
+ */
+ @Test
+ public void buildPreferentialNetworkServiceConfig_includedAndExcluded() {
+ // May not set both included and excluded UIDs
+ assertThrows(IllegalStateException.class, () ->
+ new PreferentialNetworkServiceConfig.Builder()
+ .setIncludedUids(new int[] { 1001, 1002 })
+ .setExcludedUids(new int[] { 1003, 1004 })
+ .build());
+ }
+
+ /**
+ * Make sure setting fallback allowed and blocking together is disallowed.
+ */
+ @Test
+ public void buildPreferentialNetworkServiceConfig_fallbackAndBlock() {
+ // May not set block non-matching networks and fallback to default connection at the same
+ // time, because this makes no sense when there is no preferential network service available
+ assertThrows(IllegalStateException.class, () ->
+ new PreferentialNetworkServiceConfig.Builder()
+ .setFallbackToDefaultConnectionAllowed(true)
+ .setShouldBlockNonMatchingNetworks(true)
+ .build());
+ }
+
+ /**
* Enable PreferentialNetworkService, verify the provider that provides enterprise slice can
* see the enterprise slice requests.
*/
@@ -174,6 +209,85 @@
}
}
+ /**
+ * Enable PreferentialNetworkService with blocking non-enterprise network feature enabled,
+ * verify the application cannot access non-enterprise network.
+ */
+ @EnsureHasPermission({ACCESS_NETWORK_STATE, NETWORK_SETTINGS})
+ @PolicyAppliesTest(policy = PreferentialNetworkService.class)
+ public void setPreferentialNetworkServiceEnabled_blockingNonEnterprise_noAccess()
+ throws Exception {
+ // Expect a regular default network.
+ final Network defaultNetwork = Objects.requireNonNull(sCm.getActiveNetwork(),
+ "Default network is required to perform the test.");
+ final TestableNetworkCallback defaultCallback = new TestableNetworkCallback();
+ sCm.registerDefaultNetworkCallback(defaultCallback);
+ defaultCallback.expectAvailableCallbacks(defaultNetwork, /* suspended= */ false,
+ /* validated= */ true, /* blocked= */ false, DEFAULT_TIMEOUT_MS);
+
+ // Verify the default network could be accessed.
+ assertBindSocketToNetwork(true /* expectSuccess */, defaultNetwork);
+
+ PreferentialNetworkServiceConfig blockConfig =
+ (new PreferentialNetworkServiceConfig.Builder())
+ .setEnabled(true)
+ .setNetworkId(PreferentialNetworkServiceConfig.PREFERENTIAL_NETWORK_ID_1)
+ .setFallbackToDefaultConnectionAllowed(false)
+ .setShouldBlockNonMatchingNetworks(true)
+ .build();
+ try {
+ // Enable PreferentialNetworkService, with blocking non-enterprise network feature
+ // enabled. The default network should be lost since the preference does not allow
+ // fallback.
+ sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceConfigs(
+ List.of(blockConfig));
+ defaultCallback.expect(TestableNetworkCallback.CallbackEntry.LOST, DEFAULT_TIMEOUT_MS);
+
+ // Verify the application cannot access default network since it is
+ // a non-enterprise network.
+ assertBindSocketToNetwork(false /* expectSuccess */, defaultNetwork);
+ } finally {
+ sCm.unregisterNetworkCallback(defaultCallback);
+ sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceConfigs(
+ List.of(PreferentialNetworkServiceConfig.DEFAULT));
+ }
+ }
+
+ // TODO: Copied and modified from android.net.cts.ConnectivityManager. Need to refactor them
+ // to a common place.
+ private void assertBindSocketToNetwork(boolean expectSuccess, final Network network)
+ throws Exception {
+ final CompletableFuture<Boolean> future = new CompletableFuture<>();
+ final ExecutorService executor = Executors.newSingleThreadExecutor();
+ try {
+ executor.execute(() -> {
+ for (int i = 0; i < 300; i++) {
+ SystemClock.sleep(10);
+
+ try (Socket socket = new Socket()) {
+ network.bindSocket(socket);
+ if (expectSuccess) {
+ future.complete(true);
+ return;
+ }
+ } catch (IOException e) {
+ if (!expectSuccess) {
+ future.complete(false);
+ return;
+ }
+ }
+ }
+ });
+ if (expectSuccess) {
+ assertThat(future.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)).isTrue();
+ } else {
+ assertThat(future.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS)).isFalse();
+ }
+ } finally {
+ executor.shutdown();
+ }
+ }
+
@CannotSetPolicyTest(policy = PreferentialNetworkService.class)
public void setPreferentialNetworkServiceEnabled_enableService_throwsSecurityException() {
assertThrows(SecurityException.class,
@@ -232,6 +346,33 @@
}
@CanSetPolicyTest(policy = PreferentialNetworkService.class)
+ public void setPreferentialNetworkServiceConfigs_block_isSet() {
+ PreferentialNetworkServiceConfig blockConfig =
+ (new PreferentialNetworkServiceConfig.Builder())
+ .setEnabled(true)
+ .setNetworkId(PreferentialNetworkServiceConfig.PREFERENTIAL_NETWORK_ID_1)
+ .setFallbackToDefaultConnectionAllowed(false)
+ .setShouldBlockNonMatchingNetworks(true)
+ .build();
+ try {
+ sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceConfigs(
+ List.of(blockConfig));
+
+ assertThat(sDeviceState.dpc().devicePolicyManager()
+ .getPreferentialNetworkServiceConfigs().get(0).isEnabled()).isTrue();
+ assertThat(sDeviceState.dpc().devicePolicyManager()
+ .getPreferentialNetworkServiceConfigs().get(0)
+ .shouldBlockNonMatchingNetworks()).isTrue();
+ assertThat(sDeviceState.dpc().devicePolicyManager()
+ .getPreferentialNetworkServiceConfigs().get(0)
+ .isFallbackToDefaultConnectionAllowed()).isFalse();
+ } finally {
+ sDeviceState.dpc().devicePolicyManager().setPreferentialNetworkServiceConfigs(
+ List.of(PreferentialNetworkServiceConfig.DEFAULT));
+ }
+ }
+
+ @CanSetPolicyTest(policy = PreferentialNetworkService.class)
public void setPreferentialNetworkServiceConfigs_enabled_isSet_excludedUids_set() {
UserHandle user = UserHandle.of(sContext.getUserId());
final int currentUid = user.getUid(0 /* appId */);
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/UserRestrictionsTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/UserRestrictionsTest.java
index 61301a5..af4bf24 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/UserRestrictionsTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/UserRestrictionsTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
import static org.testng.Assert.assertThrows;
import com.android.bedstead.harrier.BedsteadJUnit4;
@@ -31,6 +32,9 @@
import com.android.bedstead.harrier.annotations.parameterized.IncludeRunOnUnaffiliatedProfileOwnerSecondaryUser;
import com.android.bedstead.harrier.policies.AffiliatedProfileOwnerOnlyUserRestrictions;
import com.android.bedstead.harrier.policies.UserRestrictions;
+import com.android.bedstead.nene.TestApis;
+import com.android.bedstead.nene.devicepolicy.DeviceOwner;
+import com.android.bedstead.nene.devicepolicy.DeviceOwnerType;
import com.android.bedstead.nene.userrestrictions.CommonUserRestrictions;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
@@ -327,6 +331,8 @@
@Postsubmit(reason = "new test")
public void addUserRestriction_deviceOwnerOnlyRestriction_throwsSecurityException(
@DeviceOwnerOnlyUserRestrictions String restriction) {
+ skipTestForFinancedDevice();
+
try {
assertThrows(SecurityException.class, () -> {
sDeviceState.dpc().devicePolicyManager().addUserRestriction(
@@ -371,4 +377,12 @@
broadcastReceiver.awaitForBroadcastOrFail();
}
}
+
+ private void skipTestForFinancedDevice() {
+ DeviceOwner deviceOwner = TestApis.devicePolicy().getDeviceOwner();
+
+ // TODO(): Determine a pattern to special case states so that they are not considered in
+ // tests.
+ assumeFalse(deviceOwner != null && deviceOwner.getType() == DeviceOwnerType.FINANCED);
+ }
}
diff --git a/tests/framework/base/biometrics/OWNERS b/tests/framework/base/biometrics/OWNERS
index 95749d0..fbd1d59 100644
--- a/tests/framework/base/biometrics/OWNERS
+++ b/tests/framework/base/biometrics/OWNERS
@@ -5,3 +5,4 @@
jaggies@google.com
jbolinger@google.com
joshmccloskey@google.com
+jeffpu@google.com
diff --git a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
index 1bb7eea..fa05e86 100644
--- a/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
+++ b/tests/framework/base/biometrics/src/android/server/biometrics/BiometricTestBase.java
@@ -523,6 +523,13 @@
mInstrumentation.waitForIdleSync();
Utils.waitForBusySensor(sensorId, this::getSensorStates);
+ //Wait for enrollment operation in biometrics sensor to be complete before
+ //retrieving enrollment results. The operation takes a little time especically
+ //on Cutterfish where multiple biometric operations must be completed during
+ //the enrollent
+ //TODO(b/217275524)
+ Thread.sleep(200);
+
session.finishEnroll(userId);
mInstrumentation.waitForIdleSync();
Utils.waitForIdleService(this::getSensorStates);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
index ca5c66c..806f2af 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityVisibilityTests.java
@@ -514,7 +514,8 @@
// Bring launching activity back to the foreground
launchActivityNoWait(LAUNCHING_ACTIVITY);
// Wait for the most front activity of the task.
- mWmState.waitForValidState(ALT_LAUNCHING_ACTIVITY);
+ mWmState.waitForFocusedActivity("Waiting for Alt Launching Activity to be focused",
+ ALT_LAUNCHING_ACTIVITY);
// Ensure the alternate launching activity is still in focus.
mWmState.assertFocusedActivity("Alt Launching Activity must be focused",
@@ -523,7 +524,8 @@
pressBackButton();
// Wait for the bottom activity back to the foreground.
- mWmState.waitForValidState(LAUNCHING_ACTIVITY);
+ mWmState.waitForFocusedActivity("Waiting for Launching Activity to be focused",
+ LAUNCHING_ACTIVITY);
// Ensure launching activity was brought forward.
mWmState.assertFocusedActivity("Launching Activity must be focused",
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTests.java
index 38b3ed7..a8e8c07 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTests.java
@@ -16,6 +16,7 @@
package android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.server.wm.app.Components.MAX_ASPECT_RATIO_ACTIVITY;
import static android.server.wm.app.Components.MAX_ASPECT_RATIO_RESIZABLE_ACTIVITY;
import static android.server.wm.app.Components.MAX_ASPECT_RATIO_UNSET_ACTIVITY;
@@ -52,7 +53,7 @@
@Test
public void testMaxAspectRatio() {
// Activity has a maxAspectRatio, assert that the actual ratio is less than that.
- runAspectRatioTest(MAX_ASPECT_RATIO_ACTIVITY,
+ runAspectRatioTest(MAX_ASPECT_RATIO_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
assertThat(actual, lessThanOrEqualTo(MAX_ASPECT_RATIO));
});
@@ -61,7 +62,7 @@
@Test
public void testMetaDataMaxAspectRatio() {
// Activity has a maxAspectRatio, assert that the actual ratio is less than that.
- runAspectRatioTest(META_DATA_MAX_ASPECT_RATIO_ACTIVITY,
+ runAspectRatioTest(META_DATA_MAX_ASPECT_RATIO_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
assertThat(actual, lessThanOrEqualTo(MAX_ASPECT_RATIO));
});
@@ -70,7 +71,7 @@
@Test
public void testMaxAspectRatioResizeableActivity() {
// Since this activity is resizeable, its max aspect ratio should be ignored.
- runAspectRatioTest(MAX_ASPECT_RATIO_RESIZABLE_ACTIVITY,
+ runAspectRatioTest(MAX_ASPECT_RATIO_RESIZABLE_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
// TODO(b/69982434): Add ability to get native aspect ratio non-default display.
assumeThat(displayId, is(Display.DEFAULT_DISPLAY));
@@ -85,7 +86,7 @@
public void testMaxAspectRatioUnsetActivity() {
// Since this activity didn't set an explicit maxAspectRatio, there should be no such
// ratio enforced.
- runAspectRatioTest(MAX_ASPECT_RATIO_UNSET_ACTIVITY,
+ runAspectRatioTest(MAX_ASPECT_RATIO_UNSET_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
// TODO(b/69982434): Add ability to get native aspect ratio non-default display.
assumeThat(displayId, is(Display.DEFAULT_DISPLAY));
@@ -98,7 +99,7 @@
@Test
public void testMinAspectRatio() {
// Activity has a minAspectRatio, assert the ratio is at least that.
- runAspectRatioTest(MIN_ASPECT_RATIO_ACTIVITY,
+ runAspectRatioTest(MIN_ASPECT_RATIO_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
assertThat(actual, greaterThanOrEqualToInexact(MIN_ASPECT_RATIO));
});
@@ -108,7 +109,7 @@
public void testMinAspectRatioUnsetActivity() {
// Since this activity didn't set an explicit minAspectRatio, there should be no such
// ratio enforced.
- runAspectRatioTest(MIN_ASPECT_RATIO_UNSET_ACTIVITY,
+ runAspectRatioTest(MIN_ASPECT_RATIO_UNSET_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
// TODO(b/69982434): Add ability to get native aspect ratio non-default display.
assumeThat(displayId, is(Display.DEFAULT_DISPLAY));
@@ -121,7 +122,7 @@
@Test
public void testMinAspectLandscapeActivity() {
// Activity has requested a fixed orientation, assert the orientation is that.
- runAspectRatioTest(MIN_ASPECT_RATIO_LANDSCAPE_ACTIVITY,
+ runAspectRatioTest(MIN_ASPECT_RATIO_LANDSCAPE_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
assertThat(activitySize.x, greaterThan(activitySize.y));
// Since activities must fit within the bounds of the display and they should respect
@@ -140,7 +141,7 @@
@Test
public void testMinAspectPortraitActivity() {
- runAspectRatioTest(MIN_ASPECT_RATIO_PORTRAIT_ACTIVITY,
+ runAspectRatioTest(MIN_ASPECT_RATIO_PORTRAIT_ACTIVITY, WINDOWING_MODE_FULLSCREEN,
(actual, displayId, activitySize, displaySize) -> {
assertThat(activitySize.y, greaterThan(activitySize.x));
// Since activities must fit within the bounds of the display and they should respect
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTestsBase.java b/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTestsBase.java
index 459ff76..117a26d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTestsBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AspectRatioTestsBase.java
@@ -45,9 +45,9 @@
void assertAspectRatio(float actual, int displayId, Point activitySize, Point displaySize);
}
- void runAspectRatioTest(final ComponentName componentName,
+ void runAspectRatioTest(final ComponentName componentName, int windowingMode,
final AssertAspectRatioCallback callback) {
- launchActivity(componentName);
+ launchActivity(componentName, windowingMode);
mWmState.computeState();
final int displayId = mWmState.getDisplayByActivity(componentName);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/DisplayAreaPolicyTests.java b/tests/framework/base/windowmanager/src/android/server/wm/DisplayAreaPolicyTests.java
index 7dd3d2b..8101a41 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/DisplayAreaPolicyTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/DisplayAreaPolicyTests.java
@@ -58,16 +58,12 @@
}
/**
- * DisplayContent should have feature id of FEATURE_ROOT. It should be organized.
+ * DisplayContent should have feature id of FEATURE_ROOT.
*/
@Test
public void testDisplayContent() {
for (DisplayContent displayContent : mDisplays) {
assertThat(displayContent.getFeatureId()).isEqualTo(FEATURE_ROOT);
- // DisplayAreaOrganizerController registers the organizer for the trusted displays only.
- if (isTrustedDisplay(displayContent)) {
- assertThat(displayContent.isOrganized()).isTrue();
- }
}
}
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java b/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java
index f882022..be64440 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/SetRequestedOrientationRule.java
@@ -21,6 +21,7 @@
import android.app.WindowConfiguration;
import android.content.Intent;
import android.util.Log;
+import android.util.Pair;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -30,19 +31,12 @@
import org.junit.rules.ExternalResource;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
-import org.junit.runners.model.MultipleFailureException;
import org.junit.runners.model.Statement;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-
/**
* Rule for using setRequestedOrientation API in tests.
*/
public class SetRequestedOrientationRule implements TestRule {
- final Deque<AutoCloseable> mAutoCloseables = new ArrayDeque<>();
-
@Override
public Statement apply(Statement base,
Description description) {
@@ -51,44 +45,35 @@
public void evaluate() throws Throwable {
final DisableFixedToUserRotationRule mDisableFixedToUserRotationRule =
new DisableFixedToUserRotationRule();
+ mDisableFixedToUserRotationRule.before();
try {
- mDisableFixedToUserRotationRule.before();
- mAutoCloseables.push(mDisableFixedToUserRotationRule::after);
- mAutoCloseables.push(
- new IgnoreOrientationRequestSession(false /* don' ignore */));
- base.evaluate();
- } finally {
- final ArrayList<Throwable> throwables = new ArrayList<>();
- while (!mAutoCloseables.isEmpty()) {
- try {
- mAutoCloseables.pop().close();
- } catch (Throwable t) {
- throwables.add(t);
- }
+ try (IgnoreOrientationRequestSession session =
+ new IgnoreOrientationRequestSession(false /* don' ignore */)) {
+ base.evaluate();
}
- MultipleFailureException.assertEmpty(throwables);
+ } finally {
+ mDisableFixedToUserRotationRule.after();
}
}
};
}
/**
- * Launch an activity in fullscreen.
+ * Builds launch args to launch Activity in fullscreen windowing mode.
*
* Activities which request orientation need to be in fullscreen windowing mode.
- * The activity will be finished at the test end.
*/
- public <T extends Activity> T launchActivityInFullscreen(Class<T> klass) {
+ public static <T extends Activity> Pair<Intent, ActivityOptions> buildFullScreenLaunchArgs(
+ Class<T> klass) {
final Intent intent = new Intent(
InstrumentationRegistry.getInstrumentation().getTargetContext(),
klass);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
- final T activity = (T) InstrumentationRegistry.getInstrumentation().startActivitySync(
- intent, options.toBundle());
- mAutoCloseables.push(activity::finish);
- return activity;
+
+ return Pair.create(intent, options);
}
public static class DisableFixedToUserRotationRule extends ExternalResource {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java
index 95eaa02..0fa0307 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/ImeInsetsControllerTest.java
@@ -164,8 +164,8 @@
CountDownLatch insetsLatch = new CountDownLatch(1);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
editText.setOnApplyWindowInsetsListener((v, insets) -> {
- insetsLatch.countDown();
lastInsets[0] = insets;
+ insetsLatch.countDown();
return CONSUMED;
});
animController[0].finish(true);
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
index 2e2516a..10d5bda 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java
@@ -835,7 +835,8 @@
final ImeEventStream stream = imeSession.openEventStream();
final String marker = getTestMarker();
final AtomicReference<EditText> editorRef = new AtomicReference<>();
- TestActivity.startSync(activity -> {
+ new TestActivity.Starter().withWindowingMode(
+ WINDOWING_MODE_FULLSCREEN).startSync(activity -> {
final LinearLayout layout = new LinearLayout(activity);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setGravity(Gravity.BOTTOM);
diff --git a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
index b741a2e..bc2a2a8 100644
--- a/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
+++ b/tests/location/location_fine/src/android/location/cts/fine/LocationManagerFineTest.java
@@ -22,6 +22,7 @@
import static android.app.AppOpsManager.OPSTR_MONITOR_LOCATION;
import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
+import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.location.LocationManager.EXTRA_PROVIDER_ENABLED;
import static android.location.LocationManager.EXTRA_PROVIDER_NAME;
import static android.location.LocationManager.FUSED_PROVIDER;
@@ -754,10 +755,12 @@
}
@Test
+ @AppModeFull(reason = "Instant apps can't access ACTION_BATTERY_CHANGED intent")
public void testRequestLocationUpdates_BatterySaver_GpsDisabledScreenOff() throws Exception {
- // battery saver is unsupported on auto and tv
+ // battery saver is unsupported on auto, tv and watch
assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
assumeTrue(BatteryUtils.isBatterySaverSupported());
PowerManager powerManager = Objects.requireNonNull(
@@ -816,10 +819,12 @@
}
@Test
+ @AppModeFull(reason = "Instant apps can't access ACTION_BATTERY_CHANGED intent")
public void testRequestLocationUpdates_BatterySaver_AllDisabledScreenOff() throws Exception {
- // battery saver is unsupported on auto and tv
+ // battery saver is unsupported on auto, tv and watch
assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
assumeTrue(BatteryUtils.isBatterySaverSupported());
PowerManager powerManager = Objects.requireNonNull(
@@ -859,10 +864,12 @@
}
@Test
+ @AppModeFull(reason = "Instant apps can't access ACTION_BATTERY_CHANGED intent")
public void testRequestLocationUpdates_BatterySaver_ThrottleScreenOff() throws Exception {
- // battery saver is unsupported on auto and tv
+ // battery saver is unsupported on auto, tv and watch
assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_AUTOMOTIVE));
assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_TELEVISION));
+ assumeFalse(mContext.getPackageManager().hasSystemFeature(FEATURE_WATCH));
assumeTrue(BatteryUtils.isBatterySaverSupported());
PowerManager powerManager = Objects.requireNonNull(
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
index daf4abb..cfff01c 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecEncoderTestBase.java
@@ -16,21 +16,31 @@
package android.mediav2.common.cts;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
+import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.annotation.NonNull;
import android.graphics.ImageFormat;
+import android.media.AudioFormat;
import android.media.Image;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
+import android.media.MediaMuxer;
import android.os.PersistableBundle;
import android.util.Log;
import com.android.compatibility.common.util.Preconditions;
+import org.junit.After;
import org.junit.Before;
import java.io.File;
@@ -38,19 +48,63 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
/**
* Wrapper class for trying and testing encoder components.
- * @deprecated This class is marked for future removal. Use {@link EncoderTestBase} instead.
- * {@link EncoderTestBase} offers same functionality as the current class. Besides that, it has
- * utility functions for muxing, offers better control over configuration params, utility
- * functions for better test labelling.
- * TODO (b/260533828) remove this once all encoders are update to use {@link EncoderConfigParams}
*/
-@Deprecated(forRemoval = true)
public class CodecEncoderTestBase extends CodecTestBase {
private static final String LOG_TAG = CodecEncoderTestBase.class.getSimpleName();
+ protected final EncoderConfigParams[] mEncCfgParams;
+
+ protected EncoderConfigParams mActiveEncCfg;
+ protected RawResource mActiveRawRes;
+ protected boolean mIsLoopBack;
+ protected int mLoopBackFrameLimit;
+
+ protected byte[] mInputData;
+ protected int mInputBufferReadOffset;
+ protected int mNumBytesSubmitted;
+ protected long mInputOffsetPts;
+
+ protected ArrayList<MediaCodec.BufferInfo> mInfoList = new ArrayList<>();
+
+ protected boolean mMuxOutput;
+ protected String mMuxedOutputFile;
+ protected MediaMuxer mMuxer;
+ protected int mTrackID = -1;
+
+ public CodecEncoderTestBase(String encoder, String mime, EncoderConfigParams[] encCfgParams,
+ String allTestParams) {
+ super(encoder, mime, allTestParams);
+ mEncCfgParams = encCfgParams;
+ }
+
+ private static final List<String> MEDIATYPE_LIST_FOR_TYPE_MP4 = new ArrayList<>(
+ Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
+ MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
+ MediaFormat.MIMETYPE_AUDIO_AAC));
+ static {
+ if (CodecTestBase.IS_AT_LEAST_U) {
+ MEDIATYPE_LIST_FOR_TYPE_MP4.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+ }
+ }
+ private static final List<String> MEDIATYPE_LIST_FOR_TYPE_WEBM =
+ Arrays.asList(MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
+ MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
+ private static final List<String> MEDIATYPE_LIST_FOR_TYPE_3GP =
+ Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
+ MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_AUDIO_AAC,
+ MediaFormat.MIMETYPE_AUDIO_AMR_NB, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
+ private static final List<String> MEDIATYPE_LIST_FOR_TYPE_OGG =
+ Collections.singletonList(MediaFormat.MIMETYPE_AUDIO_OPUS);
+
+ public static final float ACCEPTABLE_WIRELESS_TX_QUALITY = 20.0f; // psnr in dB
+ public static final float ACCEPTABLE_AV_SYNC_ERROR = 22.0f; // duration in ms
+
/**
* Selects encoder input color format in byte buffer mode. As of now ndk tests support only
* 420p, 420sp. COLOR_FormatYUV420Flexible although can represent any form of yuv, it doesn't
@@ -72,50 +126,90 @@
return colorFormat;
}
- protected final int[] mBitrates;
- protected final int[] mEncParamList1;
- protected final int[] mEncParamList2;
-
- protected RawResource mActiveRawRes;
- protected byte[] mInputData;
- protected int mInputBufferReadOffset;
- protected int mNumBytesSubmitted;
- protected long mInputOffsetPts;
-
- protected ArrayList<MediaFormat> mFormats;
- protected ArrayList<MediaCodec.BufferInfo> mInfoList;
-
- protected int mWidth, mHeight;
- protected int mBytesPerSample;
- protected int mFrameRate;
- protected int mMaxBFrames;
- protected int mChannels;
- protected int mSampleRate;
- protected int mLoopBackFrameLimit;
- protected boolean mIsLoopBack;
-
- public CodecEncoderTestBase(String encoder, String mime, int[] bitrates, int[] encoderInfo1,
- int[] encoderInfo2, RawResource rawResource, String allTestParams) {
- super(encoder, mime, allTestParams);
- mBitrates = bitrates;
- mEncParamList1 = encoderInfo1;
- mEncParamList2 = encoderInfo2;
- mFormats = new ArrayList<>();
- mInfoList = new ArrayList<>();
- mWidth = 0;
- mHeight = 0;
- if (mime.equals(MediaFormat.MIMETYPE_VIDEO_MPEG4)) {
- mFrameRate = 12;
- } else if (mime.equals(MediaFormat.MIMETYPE_VIDEO_H263)) {
- mFrameRate = 12;
- } else {
- mFrameRate = 30;
+ public static void muxOutput(String filePath, int muxerFormat, MediaFormat format,
+ ByteBuffer buffer, ArrayList<MediaCodec.BufferInfo> infos) throws IOException {
+ MediaMuxer muxer = null;
+ try {
+ muxer = new MediaMuxer(filePath, muxerFormat);
+ int trackID = muxer.addTrack(format);
+ muxer.start();
+ for (MediaCodec.BufferInfo info : infos) {
+ muxer.writeSampleData(trackID, buffer, info);
+ }
+ muxer.stop();
+ } finally {
+ if (muxer != null) muxer.release();
}
- mMaxBFrames = 0;
- mChannels = 0;
- mSampleRate = 0;
- mActiveRawRes = rawResource;
- mBytesPerSample = mActiveRawRes.mBytesPerSample;
+ }
+
+ public static boolean isMediaTypeContainerPairValid(String mime, int format) {
+ boolean result = false;
+ if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) {
+ result = MEDIATYPE_LIST_FOR_TYPE_MP4.contains(mime) || mime.startsWith("application/");
+ } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) {
+ result = MEDIATYPE_LIST_FOR_TYPE_WEBM.contains(mime);
+ } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
+ result = MEDIATYPE_LIST_FOR_TYPE_3GP.contains(mime);
+ } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
+ result = MEDIATYPE_LIST_FOR_TYPE_OGG.contains(mime);
+ }
+ return result;
+ }
+
+ public static int getMuxerFormatForMediaType(String mediaType) {
+ for (int muxFormat = MUXER_OUTPUT_FIRST; muxFormat <= MUXER_OUTPUT_LAST; muxFormat++) {
+ if (isMediaTypeContainerPairValid(mediaType, muxFormat)) {
+ return muxFormat;
+ }
+ }
+ fail("no configured muxer support for " + mediaType);
+ return MUXER_OUTPUT_LAST;
+ }
+
+ public static String getTempFilePath(String infix) throws IOException {
+ return File.createTempFile("tmp" + infix, ".bin").getAbsolutePath();
+ }
+
+ public static void validateEncodedPSNR(String inpMediaType, String inpFile,
+ String outMediaType, String outFile, boolean allowInpResize, boolean allowInpLoopBack,
+ double perFramePsnrThreshold)
+ throws IOException, InterruptedException {
+ CompareStreams cs = new CompareStreams(inpMediaType, inpFile, outMediaType, outFile,
+ allowInpResize, allowInpLoopBack);
+ validateEncodedPSNR(cs, perFramePsnrThreshold);
+ cs.cleanUp();
+ }
+
+ public static void validateEncodedPSNR(RawResource inp, String outMediaType, String outFile,
+ boolean allowInpResize, boolean allowInpLoopBack, double perFramePsnrThreshold)
+ throws IOException, InterruptedException {
+ CompareStreams cs = new CompareStreams(inp, outMediaType, outFile, allowInpResize,
+ allowInpLoopBack);
+ validateEncodedPSNR(cs, perFramePsnrThreshold);
+ cs.cleanUp();
+ }
+
+ public static void validateEncodedPSNR(@NonNull CompareStreams cs,
+ double perFramePsnrThreshold) throws IOException {
+ ArrayList<double[]> framesPSNR = cs.getFramesPSNR();
+ StringBuilder msg = new StringBuilder();
+ boolean isOk = true;
+ for (int j = 0; j < framesPSNR.size(); j++) {
+ double[] framePSNR = framesPSNR.get(j);
+ // https://www.itu.int/wftp3/av-arch/jctvc-site/2011_01_D_Daegu/JCTVC-D500.doc
+ // weighted psnr (6 * psnrY + psnrU + psnrV) / 8;
+ double weightPSNR = (6 * framePSNR[0] + framePSNR[1] + framePSNR[2]) / 8;
+ if (weightPSNR < perFramePsnrThreshold) {
+ msg.append(String.format(
+ "Frame %d - PSNR Y: %f, PSNR U: %f, PSNR V: %f, Weighted PSNR: %f < "
+ + "Threshold %f \n",
+ j, framePSNR[0], framePSNR[1], framePSNR[2], weightPSNR,
+ perFramePsnrThreshold));
+ isOk = false;
+ }
+ }
+ assertTrue("Encountered frames with PSNR less than configured threshold "
+ + perFramePsnrThreshold + "dB \n" + msg, isOk);
}
public static String bitRateModeToString(int mode) {
@@ -133,22 +227,96 @@
}
}
+ public static String rangeToString(int range) {
+ switch (range) {
+ case UNSPECIFIED:
+ return "unspecified";
+ case MediaFormat.COLOR_RANGE_FULL:
+ return "full";
+ case MediaFormat.COLOR_RANGE_LIMITED:
+ return "limited";
+ default:
+ return "unknown";
+ }
+ }
+
+ public static String colorStandardToString(int standard) {
+ switch (standard) {
+ case UNSPECIFIED:
+ return "unspecified";
+ case MediaFormat.COLOR_STANDARD_BT709:
+ return "bt709";
+ case MediaFormat.COLOR_STANDARD_BT601_PAL:
+ return "bt601pal";
+ case MediaFormat.COLOR_STANDARD_BT601_NTSC:
+ return "bt601ntsc";
+ case MediaFormat.COLOR_STANDARD_BT2020:
+ return "bt2020";
+ default:
+ return "unknown";
+ }
+ }
+
+ public static String colorTransferToString(int transfer) {
+ switch (transfer) {
+ case UNSPECIFIED:
+ return "unspecified";
+ case MediaFormat.COLOR_TRANSFER_LINEAR:
+ return "linear";
+ case MediaFormat.COLOR_TRANSFER_SDR_VIDEO:
+ return "sdr";
+ case MediaFormat.COLOR_TRANSFER_HLG:
+ return "hlg";
+ case MediaFormat.COLOR_TRANSFER_ST2084:
+ return "st2084";
+ default:
+ return "unknown";
+ }
+ }
+
+ public static String colorFormatToString(int colorFormat, int bitDepth) {
+ switch (colorFormat) {
+ case COLOR_FormatYUV420Flexible:
+ return "yuv420flexible";
+ case COLOR_FormatYUVP010:
+ return "yuvp010";
+ case COLOR_FormatSurface:
+ if (bitDepth == 8) {
+ return "surfacergb888";
+ } else if (bitDepth == 10) {
+ return "surfaceabgr2101010";
+ } else {
+ return "unknown";
+ }
+ default:
+ return "unknown";
+ }
+ }
+
+ public static String audioEncodingToString(int enc) {
+ switch (enc) {
+ case AudioFormat.ENCODING_INVALID:
+ return "invalid";
+ case AudioFormat.ENCODING_PCM_16BIT:
+ return "pcm16";
+ case AudioFormat.ENCODING_PCM_FLOAT:
+ return "pcmfloat";
+ default:
+ return "unknown";
+ }
+ }
+
@Before
public void setUpCodecEncoderTestBase() {
assertTrue("Testing a mime that is neither audio nor video is not supported \n"
+ mTestConfig, mIsAudio || mIsVideo);
}
- @Override
- protected void configureCodec(MediaFormat format, boolean isAsync,
- boolean signalEOSWithLastFrame, boolean isEncoder) {
- super.configureCodec(format, isAsync, signalEOSWithLastFrame, isEncoder);
- if (mIsAudio) {
- mSampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE);
- mChannels = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT);
- } else {
- mWidth = format.getInteger(MediaFormat.KEY_WIDTH);
- mHeight = format.getInteger(MediaFormat.KEY_HEIGHT);
+ @After
+ public void tearDown() {
+ if (mMuxer != null) {
+ mMuxer.release();
+ mMuxer = null;
}
}
@@ -158,6 +326,7 @@
mInputBufferReadOffset = 0;
mNumBytesSubmitted = 0;
mInputOffsetPts = 0;
+ mInfoList.clear();
}
protected void setUpSource(String inpPath) throws IOException {
@@ -175,7 +344,7 @@
format == ImageFormat.YUV_420_888 || format == ImageFormat.YCBCR_P010);
int bytesPerSample = (ImageFormat.getBitsPerPixel(format) * 2) / (8 * 3); // YUV420
assertEquals("Invalid bytes per sample \n" + mTestConfig + mTestEnv, bytesPerSample,
- mBytesPerSample);
+ mActiveRawRes.mBytesPerSample);
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
@@ -237,13 +406,13 @@
void fillByteBuffer(ByteBuffer inputBuffer) {
int offset = 0, frmOffset = mInputBufferReadOffset;
for (int plane = 0; plane < 3; plane++) {
- int width = mWidth;
- int height = mHeight;
+ int width = mActiveEncCfg.mWidth;
+ int height = mActiveEncCfg.mHeight;
int tileWidth = mActiveRawRes.mWidth;
int tileHeight = mActiveRawRes.mHeight;
if (plane != 0) {
- width = mWidth / 2;
- height = mHeight / 2;
+ width = mActiveEncCfg.mWidth / 2;
+ height = mActiveEncCfg.mHeight / 2;
tileWidth = mActiveRawRes.mWidth / 2;
tileHeight = mActiveRawRes.mHeight / 2;
}
@@ -253,14 +422,16 @@
for (int i = 0; i < width; i += tileWidth) {
int colsToCopy = Math.min(width - i, tileWidth);
inputBuffer.position(
- offset + (k + j) * width * mBytesPerSample + i * mBytesPerSample);
- inputBuffer.put(mInputData, frmOffset + j * tileWidth * mBytesPerSample,
- colsToCopy * mBytesPerSample);
+ offset + (k + j) * width * mActiveRawRes.mBytesPerSample
+ + i * mActiveRawRes.mBytesPerSample);
+ inputBuffer.put(mInputData,
+ frmOffset + j * tileWidth * mActiveRawRes.mBytesPerSample,
+ colsToCopy * mActiveRawRes.mBytesPerSample);
}
}
}
- offset += width * height * mBytesPerSample;
- frmOffset += tileWidth * tileHeight * mBytesPerSample;
+ offset += width * height * mActiveRawRes.mBytesPerSample;
+ frmOffset += tileWidth * tileHeight * mActiveRawRes.mBytesPerSample;
}
}
@@ -276,10 +447,11 @@
int flags = 0;
long pts = mInputOffsetPts;
if (mIsAudio) {
- pts += mNumBytesSubmitted * 1000000L / ((long) mBytesPerSample * mChannels
- * mSampleRate);
+ pts += mNumBytesSubmitted * 1000000L / ((long) mActiveRawRes.mBytesPerSample
+ * mActiveEncCfg.mChannelCount * mActiveEncCfg.mSampleRate);
size = Math.min(inputBuffer.capacity(), mInputData.length - mInputBufferReadOffset);
- assertEquals(0, size % ((long) mBytesPerSample * mChannels));
+ assertEquals(0, size % ((long) mActiveRawRes.mBytesPerSample
+ * mActiveEncCfg.mChannelCount));
inputBuffer.put(mInputData, mInputBufferReadOffset, size);
if (mSignalEOSWithLastFrame) {
if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
@@ -290,8 +462,9 @@
}
mInputBufferReadOffset += size;
} else {
- pts += mInputCount * 1000000L / mFrameRate;
- size = mBytesPerSample * mWidth * mHeight * 3 / 2;
+ pts += mInputCount * 1000000L / mActiveEncCfg.mFrameRate;
+ size = mActiveRawRes.mBytesPerSample * mActiveEncCfg.mWidth * mActiveEncCfg.mHeight
+ * 3 / 2;
int frmSize = mActiveRawRes.mBytesPerSample * mActiveRawRes.mWidth
* mActiveRawRes.mHeight * 3 / 2;
if (mInputBufferReadOffset + frmSize > mInputData.length) {
@@ -331,19 +504,26 @@
mSawOutputEOS = true;
}
if (info.size > 0) {
+ ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
if (mSaveToMem) {
MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
info.flags);
mInfoList.add(copy);
- ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
mOutputBuff.saveToMemory(buf, info);
}
if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
mOutputBuff.saveOutPTS(info.presentationTimeUs);
mOutputCount++;
}
+ if (mMuxer != null) {
+ if (mTrackID == -1) {
+ mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
+ mMuxer.start();
+ }
+ mMuxer.writeSampleData(mTrackID, buf, info);
+ }
}
mCodec.releaseOutputBuffer(bufferIndex, false);
}
@@ -351,10 +531,30 @@
@Override
protected void doWork(int frameLimit) throws IOException, InterruptedException {
mLoopBackFrameLimit = frameLimit;
+ if (mMuxOutput) {
+ int muxerFormat = getMuxerFormatForMediaType(mMime);
+ mMuxedOutputFile = getTempFilePath((mActiveEncCfg.mInputBitDepth == 10) ? "10bit" : "");
+ mMuxer = new MediaMuxer(mMuxedOutputFile, muxerFormat);
+ }
super.doWork(frameLimit);
}
@Override
+ public void waitForAllOutputs() throws InterruptedException {
+ super.waitForAllOutputs();
+ if (mMuxOutput) {
+ if (mTrackID != -1) {
+ mMuxer.stop();
+ mTrackID = -1;
+ }
+ if (mMuxer != null) {
+ mMuxer.release();
+ mMuxer = null;
+ }
+ }
+ }
+
+ @Override
protected PersistableBundle validateMetrics(String codec, MediaFormat format) {
PersistableBundle metrics = super.validateMetrics(codec, format);
assertEquals("error! metrics#MetricsConstants.MIME_TYPE is not as expected \n" + mTestConfig
@@ -364,74 +564,39 @@
return metrics;
}
- protected void setUpParams(int limit) {
- int count = 0;
- for (int bitrate : mBitrates) {
- if (mIsAudio) {
- for (int rate : mEncParamList1) {
- for (int channels : mEncParamList2) {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, mMime);
- if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
- format.setInteger(MediaFormat.KEY_FLAC_COMPRESSION_LEVEL, bitrate);
- } else {
- format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
- }
- format.setInteger(MediaFormat.KEY_SAMPLE_RATE, rate);
- format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, channels);
- mFormats.add(format);
- count++;
- if (count >= limit) return;
- }
- }
- } else {
- assertEquals("Wrong number of height, width parameters \n" + mTestConfig + mTestEnv,
- mEncParamList1.length, mEncParamList2.length);
- for (int i = 0; i < mEncParamList1.length; i++) {
- MediaFormat format = new MediaFormat();
- format.setString(MediaFormat.KEY_MIME, mMime);
- format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate);
- format.setInteger(MediaFormat.KEY_WIDTH, mEncParamList1[i]);
- format.setInteger(MediaFormat.KEY_HEIGHT, mEncParamList2[i]);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
- format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
- format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
- MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
- mFormats.add(format);
- count++;
- if (count >= limit) return;
- }
- }
- }
- }
-
- public void encodeToMemory(String file, String encoder, int frameLimit, MediaFormat format,
- boolean saveToMem) throws IOException, InterruptedException {
+ public void encodeToMemory(String encoder, EncoderConfigParams cfg, RawResource res,
+ int frameLimit, boolean saveToMem, boolean muxOutput)
+ throws IOException, InterruptedException {
mSaveToMem = saveToMem;
+ mMuxOutput = muxOutput;
mOutputBuff = new OutputManager();
mInfoList.clear();
+ mActiveEncCfg = cfg;
+ mActiveRawRes = res;
mCodec = MediaCodec.createByCodecName(encoder);
- setUpSource(file);
- configureCodec(format, false, true, true);
+ setUpSource(mActiveRawRes.mFileName);
+ configureCodec(mActiveEncCfg.getFormat(), false, true, true);
mCodec.start();
doWork(frameLimit);
queueEOS();
waitForAllOutputs();
mCodec.stop();
mCodec.release();
+ mActiveRawRes = null;
+ mActiveEncCfg = null;
mSaveToMem = false;
+ mMuxOutput = false;
}
void validateTestState() {
super.validateTestState();
- if ((mIsAudio || (mIsVideo && mMaxBFrames == 0))
+ if ((mIsAudio || (mIsVideo && mActiveEncCfg.mMaxBFrames == 0))
&& !mOutputBuff.isPtsStrictlyIncreasing(mPrevOutputPts)) {
fail("Output timestamps are not strictly increasing \n" + mTestConfig + mTestEnv
+ mOutputBuff.getErrMsg());
}
if (mIsVideo) {
- if (!mOutputBuff.isOutPtsListIdenticalToInpPtsList((mMaxBFrames != 0))) {
+ if (!mOutputBuff.isOutPtsListIdenticalToInpPtsList((mActiveEncCfg.mMaxBFrames != 0))) {
fail("Input pts list and Output pts list are not identical \n" + mTestConfig
+ mTestEnv + mOutputBuff.getErrMsg());
}
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
index a775ca4..08a958f 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
@@ -108,6 +108,7 @@
//TODO(b/248315681) Remove codenameEquals() check once devices return correct version for U
public static final boolean IS_AT_LEAST_U = ApiLevelUtil.isAfter(Build.VERSION_CODES.TIRAMISU)
|| ApiLevelUtil.codenameEquals("UpsideDownCake");
+ public static final boolean IS_BEFORE_U = !IS_AT_LEAST_U;
public static final boolean FIRST_SDK_IS_AT_LEAST_T =
ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU);
public static final boolean VNDK_IS_AT_LEAST_T =
@@ -274,8 +275,8 @@
// SurfaceView or TextureView, ... They hold the responsibility of calling release().
protected CodecTestActivity mActivity;
- private static final MediaCodecList MEDIA_CODEC_LIST_ALL;
- private static final MediaCodecList MEDIA_CODEC_LIST_REGULAR;
+ public static final MediaCodecList MEDIA_CODEC_LIST_ALL;
+ public static final MediaCodecList MEDIA_CODEC_LIST_REGULAR;
static {
MEDIA_CODEC_LIST_ALL = new MediaCodecList(MediaCodecList.ALL_CODECS);
MEDIA_CODEC_LIST_REGULAR = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -581,7 +582,7 @@
return false;
}
- private static String paramToString(Object[] param) {
+ protected static String paramToString(Object[] param) {
StringBuilder paramStr = new StringBuilder("[ ");
for (int j = 0; j < param.length - 1; j++) {
Object o = param[j];
diff --git a/tests/media/common/src/android/mediav2/common/cts/EncoderConfigParams.java b/tests/media/common/src/android/mediav2/common/cts/EncoderConfigParams.java
index b549644..8cac99b 100644
--- a/tests/media/common/src/android/mediav2/common/cts/EncoderConfigParams.java
+++ b/tests/media/common/src/android/mediav2/common/cts/EncoderConfigParams.java
@@ -18,6 +18,8 @@
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
import android.media.AudioFormat;
@@ -29,6 +31,8 @@
* Class to hold encoder configuration settings.
*/
public class EncoderConfigParams {
+ public static final String TOKEN_SEPARATOR = "<>";
+
public final boolean mIsAudio;
public final String mMediaType;
@@ -141,7 +145,9 @@
mLevel = cfg.mLevel;
if (cfg.mColorFormat != COLOR_FormatYUV420Flexible
&& cfg.mColorFormat != COLOR_FormatYUVP010
- && cfg.mColorFormat != COLOR_FormatSurface) {
+ && cfg.mColorFormat != COLOR_FormatSurface
+ && cfg.mColorFormat != COLOR_FormatYUV420SemiPlanar
+ && cfg.mColorFormat != COLOR_FormatYUV420Planar) {
throw new IllegalArgumentException("bad color format config for video component");
}
mColorFormat = cfg.mColorFormat;
@@ -149,6 +155,14 @@
if (cfg.mColorFormat == COLOR_FormatYUV420Flexible && cfg.mInputBitDepth != 8) {
throw new IllegalArgumentException(
"bad bit depth configuration for COLOR_FormatYUV420Flexible");
+ } else if (cfg.mColorFormat == COLOR_FormatYUV420SemiPlanar
+ && cfg.mInputBitDepth != 8) {
+ throw new IllegalArgumentException(
+ "bad bit depth configuration for COLOR_FormatYUV420SemiPlanar");
+ } else if (cfg.mColorFormat == COLOR_FormatYUV420Planar
+ && cfg.mInputBitDepth != 8) {
+ throw new IllegalArgumentException(
+ "bad bit depth configuration for COLOR_FormatYUV420Planar");
} else if (cfg.mColorFormat == COLOR_FormatYUVP010 && cfg.mInputBitDepth != 10) {
throw new IllegalArgumentException(
"bad bit depth configuration for COLOR_FormatYUVP010");
@@ -216,6 +230,30 @@
return new MediaFormat(mFormat);
}
+ /**
+ * Converts MediaFormat object to a string. All Keys, ValueTypes, Values are concatenated with
+ * a separator and sent for further usage.
+ */
+ public static String serializeMediaFormat(MediaFormat format) {
+ StringBuilder msg = new StringBuilder();
+ java.util.Set<String> keys = format.getKeys();
+ for (String key : keys) {
+ int valueTypeForKey = format.getValueTypeForKey(key);
+ msg.append(key).append(TOKEN_SEPARATOR);
+ msg.append(valueTypeForKey).append(TOKEN_SEPARATOR);
+ if (valueTypeForKey == MediaFormat.TYPE_INTEGER) {
+ msg.append(format.getInteger(key)).append(TOKEN_SEPARATOR);
+ } else if (valueTypeForKey == MediaFormat.TYPE_FLOAT) {
+ msg.append(format.getFloat(key)).append(TOKEN_SEPARATOR);
+ } else if (valueTypeForKey == MediaFormat.TYPE_STRING) {
+ msg.append(format.getString(key)).append(TOKEN_SEPARATOR);
+ } else {
+ throw new RuntimeException("unrecognized Type for Key: " + key);
+ }
+ }
+ return msg.toString();
+ }
+
@NonNull
@Override
public String toString() {
diff --git a/tests/media/common/src/android/mediav2/common/cts/EncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/EncoderTestBase.java
deleted file mode 100644
index 4941e39..0000000
--- a/tests/media/common/src/android/mediav2/common/cts/EncoderTestBase.java
+++ /dev/null
@@ -1,557 +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.mediav2.common.cts;
-
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
-import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
-import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_FIRST;
-import static android.media.MediaMuxer.OutputFormat.MUXER_OUTPUT_LAST;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import android.graphics.ImageFormat;
-import android.media.AudioFormat;
-import android.media.Image;
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.media.MediaMuxer;
-import android.os.PersistableBundle;
-import android.util.Log;
-
-import com.android.compatibility.common.util.Preconditions;
-
-import org.junit.After;
-import org.junit.Before;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * Wrapper class for trying and testing encoder components.
- */
-public class EncoderTestBase extends CodecTestBase {
- private static final String LOG_TAG = EncoderTestBase.class.getSimpleName();
-
- protected final EncoderConfigParams[] mEncCfgParams;
-
- protected EncoderConfigParams mActiveEncCfg;
- protected RawResource mActiveRawRes;
- protected boolean mIsLoopBack;
- protected int mLoopBackFrameLimit;
-
- protected byte[] mInputData;
- protected int mInputBufferReadOffset;
- protected int mNumBytesSubmitted;
- protected long mInputOffsetPts;
-
- protected ArrayList<MediaCodec.BufferInfo> mInfoList = new ArrayList<>();
-
- protected boolean mMuxOutput;
- protected String mMuxedOutputFile;
- protected MediaMuxer mMuxer;
- protected int mTrackID = -1;
-
- public EncoderTestBase(String encoder, String mime, EncoderConfigParams[] encCfgParams,
- String allTestParams) {
- super(encoder, mime, allTestParams);
- mEncCfgParams = encCfgParams;
- }
-
- private static final List<String> MEDIATYPE_LIST_FOR_TYPE_MP4 =
- Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
- MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_VIDEO_HEVC,
- MediaFormat.MIMETYPE_AUDIO_AAC);
- private static final List<String> MEDIATYPE_LIST_FOR_TYPE_WEBM =
- Arrays.asList(MediaFormat.MIMETYPE_VIDEO_VP8, MediaFormat.MIMETYPE_VIDEO_VP9,
- MediaFormat.MIMETYPE_AUDIO_VORBIS, MediaFormat.MIMETYPE_AUDIO_OPUS);
- private static final List<String> MEDIATYPE_LIST_FOR_TYPE_3GP =
- Arrays.asList(MediaFormat.MIMETYPE_VIDEO_MPEG4, MediaFormat.MIMETYPE_VIDEO_H263,
- MediaFormat.MIMETYPE_VIDEO_AVC, MediaFormat.MIMETYPE_AUDIO_AAC,
- MediaFormat.MIMETYPE_AUDIO_AMR_NB, MediaFormat.MIMETYPE_AUDIO_AMR_WB);
- private static final List<String> MEDIATYPE_LIST_FOR_TYPE_OGG =
- Collections.singletonList(MediaFormat.MIMETYPE_AUDIO_OPUS);
-
- public static final float ACCEPTABLE_WIRELESS_TX_QUALITY = 20.0f; // psnr in dB
- public static final float ACCEPTABLE_AV_SYNC_ERROR = 22.0f; // duration in ms
-
- /**
- * Selects encoder input color format in byte buffer mode. As of now ndk tests support only
- * 420p, 420sp. COLOR_FormatYUV420Flexible although can represent any form of yuv, it doesn't
- * work in ndk due to lack of AMediaCodec_GetInputImage()
- */
- public static int findByteBufferColorFormat(String encoder, String mime) throws IOException {
- MediaCodec codec = MediaCodec.createByCodecName(encoder);
- MediaCodecInfo.CodecCapabilities cap = codec.getCodecInfo().getCapabilitiesForType(mime);
- int colorFormat = -1;
- for (int c : cap.colorFormats) {
- if (c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar
- || c == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar) {
- Log.v(LOG_TAG, "selecting color format: " + c);
- colorFormat = c;
- break;
- }
- }
- codec.release();
- return colorFormat;
- }
-
- public static void muxOutput(String filePath, int muxerFormat, MediaFormat format,
- ByteBuffer buffer, ArrayList<MediaCodec.BufferInfo> infos) throws IOException {
- MediaMuxer muxer = null;
- try {
- muxer = new MediaMuxer(filePath, muxerFormat);
- int trackID = muxer.addTrack(format);
- muxer.start();
- for (MediaCodec.BufferInfo info : infos) {
- muxer.writeSampleData(trackID, buffer, info);
- }
- muxer.stop();
- } finally {
- if (muxer != null) muxer.release();
- }
- }
-
- public static boolean isMediaTypeContainerPairValid(String mime, int format) {
- boolean result = false;
- if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) {
- result = MEDIATYPE_LIST_FOR_TYPE_MP4.contains(mime) || mime.startsWith("application/");
- } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM) {
- result = MEDIATYPE_LIST_FOR_TYPE_WEBM.contains(mime);
- } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_3GPP) {
- result = MEDIATYPE_LIST_FOR_TYPE_3GP.contains(mime);
- } else if (format == MediaMuxer.OutputFormat.MUXER_OUTPUT_OGG) {
- result = MEDIATYPE_LIST_FOR_TYPE_OGG.contains(mime);
- }
- return result;
- }
-
- public static int getMuxerFormatForMediaType(String mediaType) {
- for (int muxFormat = MUXER_OUTPUT_FIRST; muxFormat <= MUXER_OUTPUT_LAST; muxFormat++) {
- if (isMediaTypeContainerPairValid(mediaType, muxFormat)) {
- return muxFormat;
- }
- }
- fail("no configured muxer support for " + mediaType);
- return MUXER_OUTPUT_LAST;
- }
-
- public static String getTempFilePath(String infix) throws IOException {
- return File.createTempFile("tmp" + infix, ".bin").getAbsolutePath();
- }
-
- public static String bitRateModeToString(int mode) {
- switch (mode) {
- case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR:
- return "cbr";
- case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR:
- return "vbr";
- case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CQ:
- return "cq";
- case MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR_FD:
- return "cbrwithfd";
- default:
- return "unknown";
- }
- }
-
- public static String rangeToString(int range) {
- switch (range) {
- case UNSPECIFIED:
- return "unspecified";
- case MediaFormat.COLOR_RANGE_FULL:
- return "full";
- case MediaFormat.COLOR_RANGE_LIMITED:
- return "limited";
- default:
- return "unknown";
- }
- }
-
- public static String colorStandardToString(int standard) {
- switch (standard) {
- case UNSPECIFIED:
- return "unspecified";
- case MediaFormat.COLOR_STANDARD_BT709:
- return "bt709";
- case MediaFormat.COLOR_STANDARD_BT601_PAL:
- return "bt601pal";
- case MediaFormat.COLOR_STANDARD_BT601_NTSC:
- return "bt601ntsc";
- case MediaFormat.COLOR_STANDARD_BT2020:
- return "bt2020";
- default:
- return "unknown";
- }
- }
-
- public static String colorTransferToString(int transfer) {
- switch (transfer) {
- case UNSPECIFIED:
- return "unspecified";
- case MediaFormat.COLOR_TRANSFER_LINEAR:
- return "linear";
- case MediaFormat.COLOR_TRANSFER_SDR_VIDEO:
- return "sdr";
- case MediaFormat.COLOR_TRANSFER_HLG:
- return "hlg";
- case MediaFormat.COLOR_TRANSFER_ST2084:
- return "st2084";
- default:
- return "unknown";
- }
- }
-
- public static String colorFormatToString(int colorFormat, int bitDepth) {
- switch (colorFormat) {
- case COLOR_FormatYUV420Flexible:
- return "yuv420flexible";
- case COLOR_FormatYUVP010:
- return "yuvp010";
- case COLOR_FormatSurface:
- if (bitDepth == 8) {
- return "surfacergb888";
- } else if (bitDepth == 10) {
- return "surfaceabgr2101010";
- } else {
- return "unknown";
- }
- default:
- return "unknown";
- }
- }
-
- public static String audioEncodingToString(int enc) {
- switch (enc) {
- case AudioFormat.ENCODING_INVALID:
- return "invalid";
- case AudioFormat.ENCODING_PCM_16BIT:
- return "pcm16";
- case AudioFormat.ENCODING_PCM_FLOAT:
- return "pcmfloat";
- default:
- return "unknown";
- }
- }
-
- @Before
- public void setUpCodecEncoderTestBase() {
- assertTrue("Testing a mime that is neither audio nor video is not supported \n"
- + mTestConfig, mIsAudio || mIsVideo);
- }
-
- @After
- public void tearDown() {
- if (mMuxer != null) {
- mMuxer.release();
- mMuxer = null;
- }
- }
-
- @Override
- protected void resetContext(boolean isAsync, boolean signalEOSWithLastFrame) {
- super.resetContext(isAsync, signalEOSWithLastFrame);
- mInputBufferReadOffset = 0;
- mNumBytesSubmitted = 0;
- mInputOffsetPts = 0;
- mInfoList.clear();
- }
-
- protected void setUpSource(String inpPath) throws IOException {
- Preconditions.assertTestFileExists(inpPath);
- try (FileInputStream fInp = new FileInputStream(inpPath)) {
- int size = (int) new File(inpPath).length();
- mInputData = new byte[size];
- fInp.read(mInputData, 0, size);
- }
- }
-
- protected void fillImage(Image image) {
- int format = image.getFormat();
- assertTrue("unexpected image format \n" + mTestConfig + mTestEnv,
- format == ImageFormat.YUV_420_888 || format == ImageFormat.YCBCR_P010);
- int bytesPerSample = (ImageFormat.getBitsPerPixel(format) * 2) / (8 * 3); // YUV420
- assertEquals("Invalid bytes per sample \n" + mTestConfig + mTestEnv, bytesPerSample,
- mActiveRawRes.mBytesPerSample);
-
- int imageWidth = image.getWidth();
- int imageHeight = image.getHeight();
- Image.Plane[] planes = image.getPlanes();
- int offset = mInputBufferReadOffset;
- for (int i = 0; i < planes.length; ++i) {
- ByteBuffer buf = planes[i].getBuffer();
- int width = imageWidth;
- int height = imageHeight;
- int tileWidth = mActiveRawRes.mWidth;
- int tileHeight = mActiveRawRes.mHeight;
- int rowStride = planes[i].getRowStride();
- int pixelStride = planes[i].getPixelStride();
- if (i != 0) {
- width = imageWidth / 2;
- height = imageHeight / 2;
- tileWidth = mActiveRawRes.mWidth / 2;
- tileHeight = mActiveRawRes.mHeight / 2;
- }
- if (pixelStride == bytesPerSample) {
- if (width == rowStride && width == tileWidth && height == tileHeight) {
- buf.put(mInputData, offset, width * height * bytesPerSample);
- } else {
- for (int z = 0; z < height; z += tileHeight) {
- int rowsToCopy = Math.min(height - z, tileHeight);
- for (int y = 0; y < rowsToCopy; y++) {
- for (int x = 0; x < width; x += tileWidth) {
- int colsToCopy = Math.min(width - x, tileWidth);
- buf.position((z + y) * rowStride + x * bytesPerSample);
- buf.put(mInputData, offset + y * tileWidth * bytesPerSample,
- colsToCopy * bytesPerSample);
- }
- }
- }
- }
- } else {
- // do it pixel-by-pixel
- for (int z = 0; z < height; z += tileHeight) {
- int rowsToCopy = Math.min(height - z, tileHeight);
- for (int y = 0; y < rowsToCopy; y++) {
- int lineOffset = (z + y) * rowStride;
- for (int x = 0; x < width; x += tileWidth) {
- int colsToCopy = Math.min(width - x, tileWidth);
- for (int w = 0; w < colsToCopy; w++) {
- for (int bytePos = 0; bytePos < bytesPerSample; bytePos++) {
- buf.position(lineOffset + (x + w) * pixelStride + bytePos);
- buf.put(mInputData[offset + y * tileWidth * bytesPerSample
- + w * bytesPerSample + bytePos]);
- }
- }
- }
- }
- }
- }
- offset += tileWidth * tileHeight * bytesPerSample;
- }
- }
-
- void fillByteBuffer(ByteBuffer inputBuffer) {
- int offset = 0, frmOffset = mInputBufferReadOffset;
- for (int plane = 0; plane < 3; plane++) {
- int width = mActiveEncCfg.mWidth;
- int height = mActiveEncCfg.mHeight;
- int tileWidth = mActiveRawRes.mWidth;
- int tileHeight = mActiveRawRes.mHeight;
- if (plane != 0) {
- width = mActiveEncCfg.mWidth / 2;
- height = mActiveEncCfg.mHeight / 2;
- tileWidth = mActiveRawRes.mWidth / 2;
- tileHeight = mActiveRawRes.mHeight / 2;
- }
- for (int k = 0; k < height; k += tileHeight) {
- int rowsToCopy = Math.min(height - k, tileHeight);
- for (int j = 0; j < rowsToCopy; j++) {
- for (int i = 0; i < width; i += tileWidth) {
- int colsToCopy = Math.min(width - i, tileWidth);
- inputBuffer.position(
- offset + (k + j) * width * mActiveRawRes.mBytesPerSample
- + i * mActiveRawRes.mBytesPerSample);
- inputBuffer.put(mInputData,
- frmOffset + j * tileWidth * mActiveRawRes.mBytesPerSample,
- colsToCopy * mActiveRawRes.mBytesPerSample);
- }
- }
- }
- offset += width * height * mActiveRawRes.mBytesPerSample;
- frmOffset += tileWidth * tileHeight * mActiveRawRes.mBytesPerSample;
- }
- }
-
- protected void enqueueInput(int bufferIndex) {
- if (mIsLoopBack && mInputBufferReadOffset >= mInputData.length) {
- mInputBufferReadOffset = 0;
- }
- ByteBuffer inputBuffer = mCodec.getInputBuffer(bufferIndex);
- if (mInputBufferReadOffset >= mInputData.length) {
- enqueueEOS(bufferIndex);
- } else {
- int size;
- int flags = 0;
- long pts = mInputOffsetPts;
- if (mIsAudio) {
- pts += mNumBytesSubmitted * 1000000L / ((long) mActiveRawRes.mBytesPerSample
- * mActiveEncCfg.mChannelCount * mActiveEncCfg.mSampleRate);
- size = Math.min(inputBuffer.capacity(), mInputData.length - mInputBufferReadOffset);
- assertEquals(0, size % ((long) mActiveRawRes.mBytesPerSample
- * mActiveEncCfg.mChannelCount));
- inputBuffer.put(mInputData, mInputBufferReadOffset, size);
- if (mSignalEOSWithLastFrame) {
- if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
- (mInputBufferReadOffset + size >= mInputData.length)) {
- flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
- mSawInputEOS = true;
- }
- }
- mInputBufferReadOffset += size;
- } else {
- pts += mInputCount * 1000000L / mActiveEncCfg.mFrameRate;
- size = mActiveRawRes.mBytesPerSample * mActiveEncCfg.mWidth * mActiveEncCfg.mHeight
- * 3 / 2;
- int frmSize = mActiveRawRes.mBytesPerSample * mActiveRawRes.mWidth
- * mActiveRawRes.mHeight * 3 / 2;
- if (mInputBufferReadOffset + frmSize > mInputData.length) {
- fail("received partial frame to encode \n" + mTestConfig + mTestEnv);
- } else {
- Image img = mCodec.getInputImage(bufferIndex);
- assertNotNull("getInputImage() expected to return non-null for video \n"
- + mTestConfig + mTestEnv, img);
- fillImage(img);
- }
- if (mSignalEOSWithLastFrame) {
- if (mIsLoopBack ? (mInputCount + 1 >= mLoopBackFrameLimit) :
- (mInputBufferReadOffset + frmSize >= mInputData.length)) {
- flags |= MediaCodec.BUFFER_FLAG_END_OF_STREAM;
- mSawInputEOS = true;
- }
- }
- mInputBufferReadOffset += frmSize;
- }
- mNumBytesSubmitted += size;
- if (ENABLE_LOGS) {
- Log.v(LOG_TAG, "input: id: " + bufferIndex + " size: " + size + " pts: " + pts
- + " flags: " + flags);
- }
- mCodec.queueInputBuffer(bufferIndex, 0, size, pts, flags);
- mOutputBuff.saveInPTS(pts);
- mInputCount++;
- }
- }
-
- protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) {
- if (ENABLE_LOGS) {
- Log.v(LOG_TAG, "output: id: " + bufferIndex + " flags: " + info.flags + " size: "
- + info.size + " timestamp: " + info.presentationTimeUs);
- }
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- mSawOutputEOS = true;
- }
- if (info.size > 0) {
- ByteBuffer buf = mCodec.getOutputBuffer(bufferIndex);
- if (mSaveToMem) {
- MediaCodec.BufferInfo copy = new MediaCodec.BufferInfo();
- copy.set(mOutputBuff.getOutStreamSize(), info.size, info.presentationTimeUs,
- info.flags);
- mInfoList.add(copy);
-
- mOutputBuff.saveToMemory(buf, info);
- }
- if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
- mOutputBuff.saveOutPTS(info.presentationTimeUs);
- mOutputCount++;
- }
- if (mMuxer != null) {
- if (mTrackID == -1) {
- mTrackID = mMuxer.addTrack(mCodec.getOutputFormat());
- mMuxer.start();
- }
- mMuxer.writeSampleData(mTrackID, buf, info);
- }
- }
- mCodec.releaseOutputBuffer(bufferIndex, false);
- }
-
- @Override
- protected void doWork(int frameLimit) throws IOException, InterruptedException {
- mLoopBackFrameLimit = frameLimit;
- if (mMuxOutput) {
- int muxerFormat = getMuxerFormatForMediaType(mMime);
- mMuxedOutputFile = getTempFilePath((mActiveEncCfg.mInputBitDepth == 10) ? "10bit" : "");
- mMuxer = new MediaMuxer(mMuxedOutputFile, muxerFormat);
- }
- super.doWork(frameLimit);
- }
-
- @Override
- public void waitForAllOutputs() throws InterruptedException {
- super.waitForAllOutputs();
- if (mMuxOutput) {
- if (mTrackID != -1) {
- mMuxer.stop();
- mTrackID = -1;
- }
- if (mMuxer != null) {
- mMuxer.release();
- mMuxer = null;
- }
- }
- }
-
- @Override
- protected PersistableBundle validateMetrics(String codec, MediaFormat format) {
- PersistableBundle metrics = super.validateMetrics(codec, format);
- assertEquals("error! metrics#MetricsConstants.MIME_TYPE is not as expected \n" + mTestConfig
- + mTestEnv, metrics.getString(MediaCodec.MetricsConstants.MIME_TYPE), mMime);
- assertEquals("error! metrics#MetricsConstants.ENCODER is not as expected \n" + mTestConfig
- + mTestEnv, 1, metrics.getInt(MediaCodec.MetricsConstants.ENCODER));
- return metrics;
- }
-
- public void encodeToMemory(String encoder, EncoderConfigParams cfg, RawResource res,
- int frameLimit, boolean saveToMem, boolean muxOutput)
- throws IOException, InterruptedException {
- mSaveToMem = saveToMem;
- mMuxOutput = muxOutput;
- mOutputBuff = new OutputManager();
- mInfoList.clear();
- mActiveEncCfg = cfg;
- mActiveRawRes = res;
- mCodec = MediaCodec.createByCodecName(encoder);
- setUpSource(mActiveRawRes.mFileName);
- configureCodec(mActiveEncCfg.getFormat(), false, true, true);
- mCodec.start();
- doWork(frameLimit);
- queueEOS();
- waitForAllOutputs();
- mCodec.stop();
- mCodec.release();
- mActiveRawRes = null;
- mActiveEncCfg = null;
- mSaveToMem = false;
- mMuxOutput = false;
- }
-
- void validateTestState() {
- super.validateTestState();
- if ((mIsAudio || (mIsVideo && mActiveEncCfg.mMaxBFrames == 0))
- && !mOutputBuff.isPtsStrictlyIncreasing(mPrevOutputPts)) {
- fail("Output timestamps are not strictly increasing \n" + mTestConfig + mTestEnv
- + mOutputBuff.getErrMsg());
- }
- if (mIsVideo) {
- if (!mOutputBuff.isOutPtsListIdenticalToInpPtsList((mActiveEncCfg.mMaxBFrames != 0))) {
- fail("Input pts list and Output pts list are not identical \n" + mTestConfig
- + mTestEnv + mOutputBuff.getErrMsg());
- }
- }
- }
-}
diff --git a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
index f5d9186..14ef351 100644
--- a/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/HDREncoderTestBase.java
@@ -35,7 +35,7 @@
/**
* Wrapper class for testing HDR support in video encoder components
*/
-public class HDREncoderTestBase extends EncoderTestBase {
+public class HDREncoderTestBase extends CodecEncoderTestBase {
private static final String LOG_TAG = HDREncoderTestBase.class.getSimpleName();
private ByteBuffer mHdrStaticInfo;
diff --git a/tests/media/common/src/android/mediav2/common/cts/OutputManager.java b/tests/media/common/src/android/mediav2/common/cts/OutputManager.java
index 5d879c6..d59f432 100644
--- a/tests/media/common/src/android/mediav2/common/cts/OutputManager.java
+++ b/tests/media/common/src/android/mediav2/common/cts/OutputManager.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.graphics.ImageFormat;
import android.graphics.Rect;
@@ -25,6 +26,8 @@
import android.media.Image;
import android.media.MediaCodec;
+import java.io.File;
+import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
@@ -38,9 +41,17 @@
* in memory and outPtsList fields of this class. For video decoders, the decoded information can
* be overwhelming as it is uncompressed YUV. For them we compute the CRC32 checksum of the
* output image and buffer and store it instead.
+ *
+ * ByteBuffer output of encoder/decoder components can be written to disk by setting ENABLE_DUMP
+ * to true. Exercise CAUTION while running tests with ENABLE_DUMP set to true as this will crowd
+ * the storage with files. These files are configured to be deleted on exit. So, in order to see
+ * the captured output, File.deleteOnExit() needs to be be commented. Also it might be necessary
+ * to set option name="cleanup-apks" to "false" in AndroidTest.xml.
*/
public class OutputManager {
private static final String LOG_TAG = OutputManager.class.getSimpleName();
+ private static final boolean ENABLE_DUMP = false;
+
private byte[] mMemory;
private int mMemIndex;
private final CRC32 mCrc32UsingImage;
@@ -49,6 +60,11 @@
private final ArrayList<Long> mOutPtsList;
private final StringBuilder mErrorLogs;
private final StringBuilder mSharedErrorLogs;
+ private File mOutFileYuv;
+ private boolean mAppendToYuvFile;
+ private File mOutFileY;
+ private boolean mAppendToYFile;
+ private File mOutFileDefault;
public OutputManager() {
this(new StringBuilder());
@@ -170,6 +186,9 @@
offset += stride;
}
mCrc32UsingBuffer.update(bb, 0, width * height * bytesPerSample);
+ if (ENABLE_DUMP) {
+ dumpY(bb, 0, width * height * bytesPerSample);
+ }
} else {
mCrc32UsingBuffer.update(buf.array(), buf.position() + buf.arrayOffset(), size);
}
@@ -184,6 +203,9 @@
offset += stride;
}
mCrc32UsingBuffer.update(bb, 0, width * height * bytesPerSample);
+ if (ENABLE_DUMP) {
+ dumpY(bb, 0, width * height * bytesPerSample);
+ }
buf.position(pos);
} else {
int pos = buf.position();
@@ -282,6 +304,9 @@
buf.position(base);
}
mCrc32UsingImage.update(bb, 0, width * height * bytesPerSample);
+ if (ENABLE_DUMP) {
+ dumpYuv(bb, 0, width * height * bytesPerSample);
+ }
}
}
@@ -316,6 +341,18 @@
mSharedErrorLogs.setLength(0);
mErrorLogs.setLength(0);
mErrorLogs.append("################## Error Details ####################\n");
+ cleanUp();
+ }
+
+ public void cleanUp() {
+ if (mOutFileYuv != null && mOutFileYuv.exists()) mOutFileYuv.delete();
+ mOutFileYuv = null;
+ mAppendToYuvFile = false;
+ if (mOutFileY != null && mOutFileY.exists()) mOutFileY.delete();
+ mOutFileY = null;
+ mAppendToYFile = false;
+ if (mOutFileDefault != null && mOutFileDefault.exists()) mOutFileDefault.delete();
+ mOutFileDefault = null;
}
public float getRmsError(Object refObject, int audioFormat) {
@@ -418,6 +455,16 @@
mCrc32UsingImage.getValue()));
mSharedErrorLogs.append(String.format("Test CRC32 checksum value is %d \n",
that.mCrc32UsingImage.getValue()));
+ if (ENABLE_DUMP) {
+ mSharedErrorLogs.append(String.format("Decoded Ref YUV file is at : %s \n",
+ mOutFileYuv.getAbsolutePath()));
+ mSharedErrorLogs.append(String.format("Decoded Test YUV file is at : %s \n",
+ that.mOutFileYuv.getAbsolutePath()));
+ } else {
+ mSharedErrorLogs.append("As the reference YUV and test YUV are different, try "
+ + "re-running the test by changing ENABLE_DUMP of OutputManager class to "
+ + "'true' to dump the decoded YUVs for further analysis. \n");
+ }
}
if (mCrc32UsingBuffer.getValue() != that.mCrc32UsingBuffer.getValue()) {
isEqual = false;
@@ -427,6 +474,30 @@
mCrc32UsingBuffer.getValue()));
mSharedErrorLogs.append(String.format("Test CRC32 checksum value is %d \n",
that.mCrc32UsingBuffer.getValue()));
+ if (ENABLE_DUMP) {
+ if (mOutFileY != null) {
+ mSharedErrorLogs.append(String.format("Decoded Ref Y file is at : %s \n",
+ mOutFileY.getAbsolutePath()));
+ }
+ if (that.mOutFileY != null) {
+ mSharedErrorLogs.append(String.format("Decoded Test Y file is at : %s \n",
+ that.mOutFileY.getAbsolutePath()));
+ }
+ if (mMemIndex > 0) {
+ mSharedErrorLogs.append(
+ String.format("Output Ref ByteBuffer is dumped at : %s \n",
+ dumpBuffer()));
+ }
+ if (that.mMemIndex > 0) {
+ mSharedErrorLogs.append(
+ String.format("Output Test ByteBuffer is dumped at : %s \n",
+ that.dumpBuffer()));
+ }
+ } else {
+ mSharedErrorLogs.append("As the output of the component is not consistent, try "
+ + "re-running the test by changing ENABLE_DUMP of OutputManager class to "
+ + "'true' to dump the outputs for further analysis. \n");
+ }
if (mMemIndex == that.mMemIndex) {
int count = 0;
StringBuilder msg = new StringBuilder();
@@ -459,4 +530,58 @@
public String getErrMsg() {
return (mErrorLogs.toString() + mSharedErrorLogs.toString());
}
+
+ public void dumpYuv(byte[] mem, int offset, int size) {
+ try {
+ if (mOutFileYuv == null) {
+ mOutFileYuv = File.createTempFile(LOG_TAG + "YUV", ".bin");
+ mOutFileYuv.deleteOnExit();
+ }
+ try (FileOutputStream outputStream = new FileOutputStream(mOutFileYuv,
+ mAppendToYuvFile)) {
+ outputStream.write(mem, offset, size);
+ mAppendToYuvFile = true;
+ }
+ } catch (Exception e) {
+ fail("Encountered IOException during output image write. Exception is" + e);
+ }
+ }
+
+ public void dumpY(byte[] mem, int offset, int size) {
+ try {
+ if (mOutFileY == null) {
+ mOutFileY = File.createTempFile(LOG_TAG + "Y", ".bin");
+ mOutFileY.deleteOnExit();
+ }
+ try (FileOutputStream outputStream = new FileOutputStream(mOutFileY, mAppendToYFile)) {
+ outputStream.write(mem, offset, size);
+ mAppendToYFile = true;
+ }
+ } catch (Exception e) {
+ fail("Encountered IOException during output image write. Exception is" + e);
+ }
+ }
+
+ public String dumpBuffer() {
+ if (ENABLE_DUMP) {
+ try {
+ if (mOutFileDefault == null) {
+ mOutFileDefault = File.createTempFile(LOG_TAG + "OUT", ".bin");
+ mOutFileDefault.deleteOnExit();
+ }
+ try (FileOutputStream outputStream = new FileOutputStream(mOutFileDefault)) {
+ outputStream.write(mMemory, 0, mMemIndex);
+ }
+ } catch (Exception e) {
+ fail("Encountered IOException during output buffer write. Exception is" + e);
+ }
+ return mOutFileDefault.getAbsolutePath();
+ }
+ return "file not dumped yet, re-run the test by changing ENABLE_DUMP of OutputManager "
+ + "class to 'true' to dump the buffer";
+ }
+
+ public String getOutYuvFileName() {
+ return (mOutFileYuv != null) ? mOutFileYuv.getAbsolutePath() : null;
+ }
}
diff --git a/tests/media/jni/NativeCodecDecoderTestCommon.cpp b/tests/media/jni/NativeCodecDecoderTestCommon.cpp
index e722813..907b9f3 100644
--- a/tests/media/jni/NativeCodecDecoderTestCommon.cpp
+++ b/tests/media/jni/NativeCodecDecoderTestCommon.cpp
@@ -108,7 +108,7 @@
bool CodecDecoderTest::setUpExtractor(const char* srcFile, int colorFormat) {
FILE* fp = fopen(srcFile, "rbe");
- RETURN_IF_TRUE(!fp, StringFormat("Unable to open file %s", srcFile))
+ RETURN_IF_NULL(fp, StringFormat("Unable to open file %s", srcFile))
struct stat buf {};
if (!fstat(fileno(fp), &buf)) {
deleteExtractor();
@@ -143,7 +143,7 @@
}
}
if (fp) fclose(fp);
- RETURN_IF_TRUE(mInpDecFormat == nullptr,
+ RETURN_IF_NULL(mInpDecFormat,
StringFormat("No track with media type %s found in file: %s", mMime, srcFile))
return true;
}
@@ -198,7 +198,7 @@
bool CodecDecoderTest::enqueueCodecConfig(int32_t bufferIndex) {
size_t bufSize;
uint8_t* buf = AMediaCodec_getInputBuffer(mCodec, bufferIndex, &bufSize);
- RETURN_IF_TRUE(buf == nullptr, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
+ RETURN_IF_NULL(buf, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
void* csdBuffer = mCsdBuffers[mCurrCsdIdx].first;
size_t csdSize = mCsdBuffers[mCurrCsdIdx].second;
RETURN_IF_TRUE(bufSize < csdSize,
@@ -218,7 +218,7 @@
uint32_t flags = 0;
size_t bufSize;
uint8_t* buf = AMediaCodec_getInputBuffer(mCodec, bufferIndex, &bufSize);
- RETURN_IF_TRUE(buf == nullptr, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
+ RETURN_IF_NULL(buf, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
ssize_t size = AMediaExtractor_getSampleSize(mExtractor);
int64_t pts = AMediaExtractor_getSampleTime(mExtractor);
RETURN_IF_TRUE(size > bufSize,
@@ -250,8 +250,7 @@
if (mSaveToMem) {
size_t buffSize;
uint8_t* buf = AMediaCodec_getOutputBuffer(mCodec, bufferIndex, &buffSize);
- RETURN_IF_TRUE(buf == nullptr,
- std::string{"AMediaCodec_getOutputBuffer returned nullptr"})
+ RETURN_IF_NULL(buf, std::string{"AMediaCodec_getOutputBuffer returned nullptr"})
if (mIsAudio) {
mOutputBuff->saveToMemory(buf, info);
mOutputBuff->updateChecksum(buf, info);
@@ -277,9 +276,9 @@
bool CodecDecoderTest::isTestStateValid() {
if (!CodecTestBase::isTestStateValid()) return false;
- RETURN_IF_TRUE(!mOutputBuff->isPtsStrictlyIncreasing(mPrevOutputPts),
- std::string{"Output timestamps are not strictly increasing \n"}.append(
- mOutputBuff->getErrorMsg()))
+ RETURN_IF_FALSE(mOutputBuff->isPtsStrictlyIncreasing(mPrevOutputPts),
+ std::string{"Output timestamps are not strictly increasing \n"}.append(
+ mOutputBuff->getErrorMsg()))
RETURN_IF_TRUE(mIsVideo && !mIsInterlaced &&
!mOutputBuff->isOutPtsListIdenticalToInpPtsList(false),
std::string{"Input pts list and Output pts list are not identical \n"}.append(
@@ -338,7 +337,7 @@
mOutputBuff = ref;
AMediaExtractor_seekTo(mExtractor, pts, mode);
mCodec = AMediaCodec_createCodecByName(decoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", decoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
if (!configureCodec(format, false, true, false)) return false;
RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
if (!doWork(frameLimit)) return false;
@@ -370,10 +369,10 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(decoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", decoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
char* name = nullptr;
RETURN_IF_FAIL(AMediaCodec_getName(mCodec, &name), "AMediaCodec_getName failed")
- RETURN_IF_TRUE(!name, std::string{"AMediaCodec_getName returned null"})
+ RETURN_IF_NULL(name, std::string{"AMediaCodec_getName returned null"})
auto res = strcmp(name, decoder) != 0;
AMediaCodec_releaseName(mCodec, name);
RETURN_IF_TRUE(res, StringFormat("Codec name mismatch act/got: %s/%s", decoder, name))
@@ -431,8 +430,8 @@
const int64_t pts = 500000;
const SeekMode mode = AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC;
auto ref = mRefBuff;
- RETURN_IF_TRUE(!decodeToMemory(decoder, mInpDecFormat, INT32_MAX, ref, pts, mode),
- StringFormat("decodeToMemory failed for file: %s codec: %s", testFile, decoder))
+ RETURN_IF_FALSE(decodeToMemory(decoder, mInpDecFormat, INT32_MAX, ref, pts, mode),
+ StringFormat("decodeToMemory failed for file: %s codec: %s", testFile, decoder))
auto test = mTestBuff;
mOutputBuff = test;
const bool boolStates[]{true, false};
@@ -442,7 +441,7 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(decoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", decoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
AMediaExtractor_seekTo(mExtractor, 0, mode);
if (!configureCodec(mInpDecFormat, isAsync, true, false)) return false;
AMediaFormat* defFormat = AMediaCodec_getOutputFormat(mCodec);
@@ -527,7 +526,7 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(decoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", decoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
if (!configureCodec(mInpDecFormat, isAsync, false, false)) return false;
RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
if (!queueEOS()) return false;
@@ -579,7 +578,7 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(decoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", decoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", decoder))
AMediaExtractor_seekTo(mExtractor, 0, AMEDIAEXTRACTOR_SEEK_CLOSEST_SYNC);
if (!configureCodec(fmt, isAsync, eosType, false)) return false;
AMediaFormat* defFormat = AMediaCodec_getOutputFormat(mCodec);
diff --git a/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp b/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp
index a186147..2c1e2b2 100644
--- a/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp
+++ b/tests/media/jni/NativeCodecEncoderSurfaceTest.cpp
@@ -47,8 +47,6 @@
int mDecInputCount;
int mDecOutputCount;
int mEncOutputCount;
- int mEncBitrate;
- int mEncFramerate;
int mMaxBFrames;
int mLatency;
bool mReviseLatency;
@@ -66,7 +64,6 @@
void deleteExtractor();
bool configureCodec(bool isAsync, bool signalEOSWithLastFrame);
void resetContext(bool isAsync, bool signalEOSWithLastFrame);
- void setUpEncoderFormat();
bool enqueueDecoderInput(size_t bufferIndex);
bool dequeueDecoderOutput(size_t bufferIndex, AMediaCodecBufferInfo* bufferInfo);
bool dequeueEncoderOutput(size_t bufferIndex, AMediaCodecBufferInfo* info);
@@ -83,24 +80,28 @@
"################### Error Details #####################\n" +
mErrorLogs;
}
- CodecEncoderSurfaceTest(const char* mime, int bitrate, int framerate);
+ CodecEncoderSurfaceTest(const char* mime, const char* cfgParams, const char* separator);
~CodecEncoderSurfaceTest();
bool testSimpleEncode(const char* encoder, const char* decoder, const char* srcPath,
const char* muxOutPath, int colorFormat);
};
-CodecEncoderSurfaceTest::CodecEncoderSurfaceTest(const char* mime, int bitrate, int framerate)
- : mMime{mime}, mEncBitrate{bitrate}, mEncFramerate{framerate} {
+CodecEncoderSurfaceTest::CodecEncoderSurfaceTest(const char* mime, const char* cfgParams,
+ const char* separator)
+ : mMime{mime} {
mWindow = nullptr;
mExtractor = nullptr;
mDecFormat = nullptr;
- mEncFormat = nullptr;
+ mEncFormat = deSerializeMediaFormat(cfgParams, separator);
mMuxer = nullptr;
mDecoder = nullptr;
mEncoder = nullptr;
resetContext(false, false);
mMaxBFrames = 0;
+ if (mEncFormat != nullptr) {
+ AMediaFormat_getInt32(mEncFormat, TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES, &mMaxBFrames);
+ }
mLatency = mMaxBFrames;
mReviseLatency = false;
mMuxTrackID = -1;
@@ -177,6 +178,8 @@
}
bool CodecEncoderSurfaceTest::configureCodec(bool isAsync, bool signalEOSWithLastFrame) {
+ RETURN_IF_NULL(mEncFormat,
+ std::string{"encountered error during deserialization of media format"})
resetContext(isAsync, signalEOSWithLastFrame);
mTestEnv = "################### Test Environment #####################\n";
{
@@ -243,22 +246,6 @@
mEncOutputCount = 0;
}
-void CodecEncoderSurfaceTest::setUpEncoderFormat() {
- if (mEncFormat) AMediaFormat_delete(mEncFormat);
- mEncFormat = AMediaFormat_new();
- int width, height;
- AMediaFormat_getInt32(mDecFormat, AMEDIAFORMAT_KEY_WIDTH, &width);
- AMediaFormat_getInt32(mDecFormat, AMEDIAFORMAT_KEY_HEIGHT, &height);
- AMediaFormat_setString(mEncFormat, AMEDIAFORMAT_KEY_MIME, mMime);
- AMediaFormat_setInt32(mEncFormat, AMEDIAFORMAT_KEY_WIDTH, width);
- AMediaFormat_setInt32(mEncFormat, AMEDIAFORMAT_KEY_HEIGHT, height);
- AMediaFormat_setInt32(mEncFormat, AMEDIAFORMAT_KEY_BIT_RATE, mEncBitrate);
- AMediaFormat_setInt32(mEncFormat, AMEDIAFORMAT_KEY_FRAME_RATE, mEncFramerate);
- AMediaFormat_setInt32(mEncFormat, TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES, mMaxBFrames);
- AMediaFormat_setInt32(mEncFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, COLOR_FormatSurface);
- AMediaFormat_setFloat(mEncFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1.0F);
-}
-
bool CodecEncoderSurfaceTest::enqueueDecoderEOS(size_t bufferIndex) {
if (!hasSeenError() && !mSawDecInputEOS) {
RETURN_IF_FAIL(AMediaCodec_queueInputBuffer(mDecoder, bufferIndex, 0, 0, 0,
@@ -277,7 +264,7 @@
uint32_t flags = 0;
size_t bufSize = 0;
uint8_t* buf = AMediaCodec_getInputBuffer(mDecoder, bufferIndex, &bufSize);
- RETURN_IF_TRUE(buf == nullptr, std::string{"AMediaCodec_getInputBuffer failed"})
+ RETURN_IF_NULL(buf, std::string{"AMediaCodec_getInputBuffer failed"})
ssize_t size = AMediaExtractor_getSampleSize(mExtractor);
int64_t pts = AMediaExtractor_getSampleTime(mExtractor);
RETURN_IF_TRUE(size > bufSize,
@@ -553,9 +540,8 @@
bool CodecEncoderSurfaceTest::testSimpleEncode(const char* encoder, const char* decoder,
const char* srcPath, const char* muxOutPath,
int colorFormat) {
- RETURN_IF_TRUE(!setUpExtractor(srcPath, colorFormat), std::string{"setUpExtractor failed"})
- setUpEncoderFormat();
- bool muxOutput = true;
+ RETURN_IF_FALSE(setUpExtractor(srcPath, colorFormat), std::string{"setUpExtractor failed"})
+ bool muxOutput = muxOutPath != nullptr;
/* TODO(b/149027258) */
if (true) mSaveToMem = false;
@@ -574,8 +560,8 @@
* once and use it for all iterations and delete before exiting */
mEncoder = AMediaCodec_createCodecByName(encoder);
mDecoder = AMediaCodec_createCodecByName(decoder);
- RETURN_IF_TRUE(!mDecoder, StringFormat("unable to create media codec by name %s", decoder))
- RETURN_IF_TRUE(!mEncoder, StringFormat("unable to create media codec by name %s", encoder))
+ RETURN_IF_NULL(mDecoder, StringFormat("unable to create media codec by name %s", decoder))
+ RETURN_IF_NULL(mEncoder, StringFormat("unable to create media codec by name %s", encoder))
FILE* ofp = nullptr;
if (muxOutput && loopCounter == 0) {
int muxerFormat = 0;
@@ -649,15 +635,16 @@
static jboolean nativeTestSimpleEncode(JNIEnv* env, jobject, jstring jEncoder, jstring jDecoder,
jstring jMime, jstring jtestFile, jstring jmuxFile,
- jint jBitrate, jint jFramerate, jint jColorFormat,
+ jint jColorFormat, jstring jCfgParams, jstring jSeparator,
jobject jRetMsg) {
const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
const char* cDecoder = env->GetStringUTFChars(jDecoder, nullptr);
const char* cMime = env->GetStringUTFChars(jMime, nullptr);
const char* cTestFile = env->GetStringUTFChars(jtestFile, nullptr);
- const char* cMuxFile = env->GetStringUTFChars(jmuxFile, nullptr);
- auto codecEncoderSurfaceTest =
- new CodecEncoderSurfaceTest(cMime, (int)jBitrate, (int)jFramerate);
+ const char* cMuxFile = jmuxFile ? env->GetStringUTFChars(jmuxFile, nullptr) : nullptr;
+ const char* cCfgParams = env->GetStringUTFChars(jCfgParams, nullptr);
+ const char* cSeparator = env->GetStringUTFChars(jSeparator, nullptr);
+ auto codecEncoderSurfaceTest = new CodecEncoderSurfaceTest(cMime, cCfgParams, cSeparator);
bool isPass = codecEncoderSurfaceTest->testSimpleEncode(cEncoder, cDecoder, cTestFile, cMuxFile,
jColorFormat);
std::string msg = isPass ? std::string{} : codecEncoderSurfaceTest->getErrorMsg();
@@ -670,7 +657,10 @@
env->ReleaseStringUTFChars(jDecoder, cDecoder);
env->ReleaseStringUTFChars(jMime, cMime);
env->ReleaseStringUTFChars(jtestFile, cTestFile);
- env->ReleaseStringUTFChars(jmuxFile, cMuxFile);
+ if (cMuxFile) env->ReleaseStringUTFChars(jmuxFile, cMuxFile);
+ env->ReleaseStringUTFChars(jCfgParams, cCfgParams);
+ env->ReleaseStringUTFChars(jSeparator, cSeparator);
+
return isPass;
}
@@ -678,7 +668,7 @@
const JNINativeMethod methodTable[] = {
{"nativeTestSimpleEncode",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
- "String;IIILjava/lang/StringBuilder;)Z",
+ "String;ILjava/lang/String;Ljava/lang/String;Ljava/lang/StringBuilder;)Z",
(void*)nativeTestSimpleEncode},
};
jclass c = env->FindClass("android/mediav2/cts/CodecEncoderSurfaceTest");
diff --git a/tests/media/jni/NativeCodecEncoderTest.cpp b/tests/media/jni/NativeCodecEncoderTest.cpp
index d0fecea..e7c2470 100644
--- a/tests/media/jni/NativeCodecEncoderTest.cpp
+++ b/tests/media/jni/NativeCodecEncoderTest.cpp
@@ -37,13 +37,6 @@
int mNumSyncFramesReceived;
std::vector<int> mSyncFramesPos;
- int32_t* mBitRates;
- int mLen0;
- int32_t* mEncParamList1;
- int mLen1;
- int32_t* mEncParamList2;
- int mLen2;
-
int mWidth, mHeight;
int mChannels;
int mSampleRate;
@@ -56,7 +49,6 @@
void convertyuv420ptoyuv420sp();
void setUpSource(const char* srcPath);
void deleteSource();
- void setUpParams(int limit);
void deleteParams();
bool configureCodec(AMediaFormat* format, bool isAsync, bool signalEOSWithLastFrame,
bool isEncoder) override;
@@ -65,7 +57,7 @@
bool dequeueOutput(size_t bufferIndex, AMediaCodecBufferInfo* bufferInfo) override;
bool doWork(int frameLimit) override;
bool isTestStateValid() override;
- void initFormat(AMediaFormat* format);
+ bool initFormat(AMediaFormat* format);
bool encodeToMemory(const char* file, const char* encoder, int frameLimit, AMediaFormat* format,
OutputManager* ref);
void fillByteBuffer(uint8_t* inputBuffer);
@@ -73,8 +65,8 @@
void updateBitrate(AMediaFormat* format, int bitrate);
public:
- CodecEncoderTest(const char* mime, int32_t* list0, int len0, int32_t* list1, int len1,
- int32_t* list2, int len2, int colorFormat);
+ CodecEncoderTest(const char* mime, const char* cfgParams, const char* cfgReconfigParams,
+ const char* separator);
~CodecEncoderTest();
bool testSimpleEncode(const char* encoder, const char* srcPath);
@@ -84,20 +76,16 @@
bool testOnlyEos(const char* encoder);
};
-CodecEncoderTest::CodecEncoderTest(const char* mime, int32_t* list0, int len0, int32_t* list1,
- int len1, int32_t* list2, int len2, int colorFormat)
- : CodecTestBase(mime),
- mBitRates{list0},
- mLen0{len0},
- mEncParamList1{list1},
- mLen1{len1},
- mEncParamList2{list2},
- mLen2{len2},
- mColorFormat{colorFormat} {
- mDefFrameRate = 30;
- if (!strcmp(mime, AMEDIA_MIMETYPE_VIDEO_H263)) mDefFrameRate = 12;
- else if (!strcmp(mime, AMEDIA_MIMETYPE_VIDEO_MPEG4)) mDefFrameRate = 12;
- mMaxBFrames = 0;
+CodecEncoderTest::CodecEncoderTest(const char* mime, const char* cfgParams,
+ const char* cfgReconfigParams, const char* separator)
+ : CodecTestBase(mime) {
+ mFormats.push_back(deSerializeMediaFormat(cfgParams, separator));
+ if (cfgReconfigParams) {
+ mFormats.push_back(deSerializeMediaFormat(cfgReconfigParams, separator));
+ }
+ if (mIsVideo && mFormats[0] != nullptr) {
+ AMediaFormat_getInt32(mFormats[0], AMEDIAFORMAT_KEY_COLOR_FORMAT, &mColorFormat);
+ }
mInputData = nullptr;
mInputLength = 0;
mInputBufferReadOffset = 0;
@@ -159,52 +147,6 @@
mInputLength = 0;
}
-void CodecEncoderTest::setUpParams(int limit) {
- int count = 0;
- for (int k = 0; k < mLen0; k++) {
- int bitrate = mBitRates[k];
- if (mIsAudio) {
- for (int j = 0; j < mLen1; j++) {
- int rate = mEncParamList1[j];
- for (int i = 0; i < mLen2; i++) {
- int channels = mEncParamList2[i];
- AMediaFormat* format = AMediaFormat_new();
- AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mMime);
- if (!strcmp(mMime, AMEDIA_MIMETYPE_AUDIO_FLAC)) {
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL,
- bitrate);
- } else {
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, bitrate);
- }
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, rate);
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, channels);
- mFormats.push_back(format);
- count++;
- if (count >= limit) break;
- }
- }
- } else {
- for (int j = 0; j < mLen1; j++) {
- int width = mEncParamList1[j];
- int height = mEncParamList2[j];
- AMediaFormat* format = AMediaFormat_new();
- AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, mMime);
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, bitrate);
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_WIDTH, width);
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_HEIGHT, height);
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, mDefFrameRate);
- AMediaFormat_setInt32(format, TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES,
- mMaxBFrames);
- AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 1.0F);
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, mColorFormat);
- mFormats.push_back(format);
- count++;
- if (count >= limit) break;
- }
- }
- }
-}
-
void CodecEncoderTest::deleteParams() {
for (auto format : mFormats) AMediaFormat_delete(format);
mFormats.clear();
@@ -212,9 +154,8 @@
bool CodecEncoderTest::configureCodec(AMediaFormat* format, bool isAsync,
bool signalEOSWithLastFrame, bool isEncoder) {
- bool res = CodecTestBase::configureCodec(format, isAsync, signalEOSWithLastFrame, isEncoder);
- initFormat(format);
- return res;
+ if (!initFormat(format)) return false;
+ return CodecTestBase::configureCodec(format, isAsync, signalEOSWithLastFrame, isEncoder);
}
void CodecEncoderTest::resetContext(bool isAsync, bool signalEOSWithLastFrame) {
@@ -278,8 +219,7 @@
int64_t pts = mInputOffsetPts;
size_t buffSize;
uint8_t* inputBuffer = AMediaCodec_getInputBuffer(mCodec, bufferIndex, &buffSize);
- RETURN_IF_TRUE(inputBuffer == nullptr,
- std::string{"AMediaCodec_getInputBuffer returned nullptr"})
+ RETURN_IF_NULL(inputBuffer, std::string{"AMediaCodec_getInputBuffer returned nullptr"})
if (mIsAudio) {
pts += mNumBytesSubmitted * 1000000LL / (2 * mChannels * mSampleRate);
size = std::min(buffSize, mInputLength - mInputBufferReadOffset);
@@ -334,8 +274,7 @@
if (mSaveToMem) {
size_t buffSize;
uint8_t* buf = AMediaCodec_getOutputBuffer(mCodec, bufferIndex, &buffSize);
- RETURN_IF_TRUE(buf == nullptr,
- std::string{"AMediaCodec_getOutputBuffer returned nullptr"})
+ RETURN_IF_NULL(buf, std::string{"AMediaCodec_getOutputBuffer returned nullptr"})
mOutputBuff->saveToMemory(buf, info);
}
if ((info->flags & TBD_AMEDIACODEC_BUFFER_FLAG_KEY_FRAME) != 0) {
@@ -371,14 +310,27 @@
return true;
}
-void CodecEncoderTest::initFormat(AMediaFormat* format) {
+bool CodecEncoderTest::initFormat(AMediaFormat* format) {
if (mIsAudio) {
- AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate);
- AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &mChannels);
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_SAMPLE_RATE, &mSampleRate),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_SAMPLE_RATE))
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_CHANNEL_COUNT, &mChannels),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_CHANNEL_COUNT))
} else {
- AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &mWidth);
- AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &mHeight);
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_WIDTH, &mWidth),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_WIDTH))
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_HEIGHT, &mHeight),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_HEIGHT))
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES,
+ &mMaxBFrames),
+ StringFormat("format does not have key %s",
+ TBD_AMEDIACODEC_PARAMETER_KEY_MAX_B_FRAMES))
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &mDefFrameRate),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_FRAME_RATE))
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_COLOR_FORMAT, &mColorFormat),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_COLOR_FORMAT))
}
+ return true;
}
bool CodecEncoderTest::encodeToMemory(const char* file, const char* encoder, int32_t frameLimit,
@@ -388,9 +340,9 @@
else mSaveToMem = true;
mOutputBuff = ref;
mCodec = AMediaCodec_createCodecByName(encoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec by name %s \n", encoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec by name %s \n", encoder))
setUpSource(file);
- RETURN_IF_TRUE(!mInputData, StringFormat("unable to open input file %s", file))
+ RETURN_IF_NULL(mInputData, StringFormat("unable to open input file %s", file))
if (!configureCodec(format, false, true, true)) return false;
RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
if (!doWork(frameLimit)) return false;
@@ -417,8 +369,7 @@
bool CodecEncoderTest::testSimpleEncode(const char* encoder, const char* srcPath) {
setUpSource(srcPath);
- RETURN_IF_TRUE(!mInputData, StringFormat("unable to open input file %s", srcPath))
- setUpParams(1);
+ RETURN_IF_NULL(mInputData, StringFormat("unable to open input file %s", srcPath))
/* TODO(b/149027258) */
if (true) mSaveToMem = false;
else mSaveToMem = true;
@@ -426,6 +377,8 @@
auto test = mTestBuff;
const bool boolStates[]{true, false};
for (auto format : mFormats) {
+ RETURN_IF_NULL(format,
+ std::string{"encountered error during deserialization of media format"})
int loopCounter = 0;
for (auto eosType : boolStates) {
for (auto isAsync : boolStates) {
@@ -435,10 +388,10 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(encoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", encoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", encoder))
char* name = nullptr;
RETURN_IF_FAIL(AMediaCodec_getName(mCodec, &name), "AMediaCodec_getName failed")
- RETURN_IF_TRUE(!name, std::string{"AMediaCodec_getName returned null"})
+ RETURN_IF_NULL(name, std::string{"AMediaCodec_getName returned null"})
auto res = strcmp(name, encoder) != 0;
AMediaCodec_releaseName(mCodec, name);
RETURN_IF_TRUE(res,
@@ -463,20 +416,22 @@
bool CodecEncoderTest::testReconfigure(const char* encoder, const char* srcPath) {
setUpSource(srcPath);
- RETURN_IF_TRUE(!mInputData, StringFormat("unable to open input file %s", srcPath))
- setUpParams(2);
+ RETURN_IF_NULL(mInputData, StringFormat("unable to open input file %s", srcPath))
auto configRef = mReconfBuff;
if (mFormats.size() > 1) {
auto format = mFormats[1];
- RETURN_IF_TRUE(!encodeToMemory(srcPath, encoder, INT32_MAX, format, configRef),
- StringFormat("encodeToMemory failed for file: %s codec: %s \n format: %s",
- srcPath, encoder, AMediaFormat_toString(format)))
+ RETURN_IF_NULL(format,
+ std::string{"encountered error during deserialization of media format"})
+ RETURN_IF_FALSE(encodeToMemory(srcPath, encoder, INT32_MAX, format, configRef),
+ StringFormat("encodeToMemory failed for file: %s codec: %s \n format: %s",
+ srcPath, encoder, AMediaFormat_toString(format)))
}
auto format = mFormats[0];
+ RETURN_IF_NULL(format, std::string{"encountered error during deserialization of media format"})
auto ref = mRefBuff;
- RETURN_IF_TRUE(!encodeToMemory(srcPath, encoder, INT32_MAX, format, ref),
- StringFormat("encodeToMemory failed for file: %s codec: %s \n format: %s",
- srcPath, encoder, AMediaFormat_toString(format)))
+ RETURN_IF_FALSE(encodeToMemory(srcPath, encoder, INT32_MAX, format, ref),
+ StringFormat("encodeToMemory failed for file: %s codec: %s \n format: %s",
+ srcPath, encoder, AMediaFormat_toString(format)))
auto test = mTestBuff;
mOutputBuff = test;
@@ -486,7 +441,7 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(encoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec %s", encoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec %s", encoder))
if (!configureCodec(format, isAsync, true, true)) return false;
/* test reconfigure in init state */
if (!reConfigureCodec(format, !isAsync, false, true)) return false;
@@ -546,7 +501,6 @@
}
bool CodecEncoderTest::testOnlyEos(const char* encoder) {
- setUpParams(1);
/* TODO(b/149027258) */
if (true) mSaveToMem = false;
else mSaveToMem = true;
@@ -554,6 +508,8 @@
auto test = mTestBuff;
const bool boolStates[]{true, false};
AMediaFormat* format = mFormats[0];
+ RETURN_IF_NULL(format,
+ std::string{"encountered error during deserialization of media format"})
int loopCounter = 0;
for (auto isAsync : boolStates) {
mOutputBuff = loopCounter == 0 ? ref : test;
@@ -562,7 +518,7 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(encoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec by name %s", encoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec by name %s", encoder))
if (!configureCodec(format, isAsync, false, true)) return false;
RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
if (!queueEOS()) return false;
@@ -580,10 +536,12 @@
bool CodecEncoderTest::testSetForceSyncFrame(const char* encoder, const char* srcPath) {
setUpSource(srcPath);
- RETURN_IF_TRUE(!mInputData, StringFormat("unable to open input file %s", srcPath))
- setUpParams(1);
+ RETURN_IF_NULL(mInputData, StringFormat("unable to open input file %s", srcPath))
AMediaFormat* format = mFormats[0];
- AMediaFormat_setFloat(format, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, 500.f);
+ RETURN_IF_NULL(format,
+ std::string{"encountered error during deserialization of media format"})
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &mDefFrameRate),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_FRAME_RATE))
// Maximum allowed key frame interval variation from the target value.
int kMaxKeyFrameIntervalVariation = 3;
int kKeyFrameInterval = 2; // force key frame every 2 seconds.
@@ -599,7 +557,7 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(encoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec by name%s", encoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec by name%s", encoder))
if (!configureCodec(format, isAsync, false, true)) return false;
RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
for (int i = 0; i < kNumKeyFrameRequests; i++) {
@@ -642,9 +600,12 @@
bool CodecEncoderTest::testAdaptiveBitRate(const char* encoder, const char* srcPath) {
setUpSource(srcPath);
- RETURN_IF_TRUE(!mInputData, StringFormat("unable to open input file %s", srcPath))
- setUpParams(1);
+ RETURN_IF_NULL(mInputData, StringFormat("unable to open input file %s", srcPath))
AMediaFormat* format = mFormats[0];
+ RETURN_IF_NULL(format,
+ std::string{"encountered error during deserialization of media format"})
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_FRAME_RATE, &mDefFrameRate),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_FRAME_RATE))
int kAdaptiveBitrateInterval = 3; // change bitrate every 3 seconds.
int kAdaptiveBitrateDurationFrame = mDefFrameRate * kAdaptiveBitrateInterval;
int kBitrateChangeRequests = 7;
@@ -652,8 +613,6 @@
float kMaxBitrateDeviation = 60.0; // allowed bitrate deviation in %
AMediaFormat* params = AMediaFormat_new();
mFormats.push_back(params);
- // Setting in CBR Mode
- AMediaFormat_setInt32(format, TBD_AMEDIAFORMAT_KEY_BIT_RATE_MODE, kBitrateModeConstant);
mOutputBuff = mTestBuff;
mSaveToMem = true;
const bool boolStates[]{true, false};
@@ -663,12 +622,13 @@
/* Instead of create and delete codec at every iteration, we would like to create
* once and use it for all iterations and delete before exiting */
mCodec = AMediaCodec_createCodecByName(encoder);
- RETURN_IF_TRUE(!mCodec, StringFormat("unable to create codec by name %s", encoder))
+ RETURN_IF_NULL(mCodec, StringFormat("unable to create codec by name %s", encoder))
if (!configureCodec(format, isAsync, false, true)) return false;
RETURN_IF_FAIL(AMediaCodec_start(mCodec), "AMediaCodec_start failed")
int expOutSize = 0;
int bitrate;
- AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate);
+ RETURN_IF_FALSE(AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate),
+ StringFormat("format does not have key %s", AMEDIAFORMAT_KEY_BIT_RATE))
for (int i = 0; i < kBitrateChangeRequests; i++) {
if (!doWork(kAdaptiveBitrateDurationFrame)) return false;
RETURN_IF_TRUE(mSawInputEOS,
@@ -696,19 +656,14 @@
}
static jboolean nativeTestSimpleEncode(JNIEnv* env, jobject, jstring jEncoder, jstring jsrcPath,
- jstring jMime, jintArray jList0, jintArray jList1,
- jintArray jList2, jint colorFormat, jobject jRetMsg) {
+ jstring jMime, jstring jCfgParams, jstring jSeparator,
+ jobject jRetMsg) {
const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
const char* cmime = env->GetStringUTFChars(jMime, nullptr);
const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
- jsize cLen0 = env->GetArrayLength(jList0);
- jint* cList0 = env->GetIntArrayElements(jList0, nullptr);
- jsize cLen1 = env->GetArrayLength(jList1);
- jint* cList1 = env->GetIntArrayElements(jList1, nullptr);
- jsize cLen2 = env->GetArrayLength(jList2);
- jint* cList2 = env->GetIntArrayElements(jList2, nullptr);
- auto codecEncoderTest = new CodecEncoderTest(cmime, cList0, cLen0, cList1, cLen1, cList2, cLen2,
- (int)colorFormat);
+ const char* cCfgParams = env->GetStringUTFChars(jCfgParams, nullptr);
+ const char* cSeparator = env->GetStringUTFChars(jSeparator, nullptr);
+ auto codecEncoderTest = new CodecEncoderTest(cmime, cCfgParams, nullptr, cSeparator);
bool isPass = codecEncoderTest->testSimpleEncode(cEncoder, csrcPath);
std::string msg = isPass ? std::string{} : codecEncoderTest->getErrorMsg();
delete codecEncoderTest;
@@ -716,9 +671,8 @@
jmethodID mId =
env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
- env->ReleaseIntArrayElements(jList0, cList0, 0);
- env->ReleaseIntArrayElements(jList1, cList1, 0);
- env->ReleaseIntArrayElements(jList2, cList2, 0);
+ env->ReleaseStringUTFChars(jCfgParams, cCfgParams);
+ env->ReleaseStringUTFChars(jSeparator, cSeparator);
env->ReleaseStringUTFChars(jEncoder, cEncoder);
env->ReleaseStringUTFChars(jMime, cmime);
env->ReleaseStringUTFChars(jsrcPath, csrcPath);
@@ -726,20 +680,18 @@
}
static jboolean nativeTestReconfigure(JNIEnv* env, jobject, jstring jEncoder, jstring jsrcPath,
- jstring jMime, jintArray jList0, jintArray jList1,
- jintArray jList2, jint colorFormat, jobject jRetMsg) {
+ jstring jMime, jstring jCfgParams, jstring jReconfigCfgParams,
+ jstring jSeparator, jobject jRetMsg) {
bool isPass;
const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
const char* cmime = env->GetStringUTFChars(jMime, nullptr);
const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
- jsize cLen0 = env->GetArrayLength(jList0);
- jint* cList0 = env->GetIntArrayElements(jList0, nullptr);
- jsize cLen1 = env->GetArrayLength(jList1);
- jint* cList1 = env->GetIntArrayElements(jList1, nullptr);
- jsize cLen2 = env->GetArrayLength(jList2);
- jint* cList2 = env->GetIntArrayElements(jList2, nullptr);
- auto codecEncoderTest = new CodecEncoderTest(cmime, cList0, cLen0, cList1, cLen1, cList2, cLen2,
- (int)colorFormat);
+ const char* cCfgParams = env->GetStringUTFChars(jCfgParams, nullptr);
+ const char* cReconfigCfgParams = jReconfigCfgParams != nullptr
+ ? env->GetStringUTFChars(jReconfigCfgParams, nullptr)
+ : nullptr;
+ const char* cSeparator = env->GetStringUTFChars(jSeparator, nullptr);
+ auto codecEncoderTest = new CodecEncoderTest(cmime, cCfgParams, cReconfigCfgParams, cSeparator);
isPass = codecEncoderTest->testReconfigure(cEncoder, csrcPath);
std::string msg = isPass ? std::string{} : codecEncoderTest->getErrorMsg();
delete codecEncoderTest;
@@ -747,9 +699,11 @@
jmethodID mId =
env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
- env->ReleaseIntArrayElements(jList0, cList0, 0);
- env->ReleaseIntArrayElements(jList1, cList1, 0);
- env->ReleaseIntArrayElements(jList2, cList2, 0);
+ env->ReleaseStringUTFChars(jCfgParams, cCfgParams);
+ if (cReconfigCfgParams != nullptr) {
+ env->ReleaseStringUTFChars(jReconfigCfgParams, cReconfigCfgParams);
+ }
+ env->ReleaseStringUTFChars(jSeparator, cSeparator);
env->ReleaseStringUTFChars(jEncoder, cEncoder);
env->ReleaseStringUTFChars(jMime, cmime);
env->ReleaseStringUTFChars(jsrcPath, csrcPath);
@@ -757,20 +711,14 @@
}
static jboolean nativeTestSetForceSyncFrame(JNIEnv* env, jobject, jstring jEncoder,
- jstring jsrcPath, jstring jMime, jintArray jList0,
- jintArray jList1, jintArray jList2, jint colorFormat,
- jobject jRetMsg) {
+ jstring jsrcPath, jstring jMime, jstring jCfgParams,
+ jstring jSeparator, jobject jRetMsg) {
const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
const char* cmime = env->GetStringUTFChars(jMime, nullptr);
const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
- jsize cLen0 = env->GetArrayLength(jList0);
- jint* cList0 = env->GetIntArrayElements(jList0, nullptr);
- jsize cLen1 = env->GetArrayLength(jList1);
- jint* cList1 = env->GetIntArrayElements(jList1, nullptr);
- jsize cLen2 = env->GetArrayLength(jList2);
- jint* cList2 = env->GetIntArrayElements(jList2, nullptr);
- auto codecEncoderTest = new CodecEncoderTest(cmime, cList0, cLen0, cList1, cLen1, cList2, cLen2,
- (int)colorFormat);
+ const char* cCfgParams = env->GetStringUTFChars(jCfgParams, nullptr);
+ const char* cSeparator = env->GetStringUTFChars(jSeparator, nullptr);
+ auto codecEncoderTest = new CodecEncoderTest(cmime, cCfgParams, nullptr, cSeparator);
bool isPass = codecEncoderTest->testSetForceSyncFrame(cEncoder, csrcPath);
std::string msg = isPass ? std::string{} : codecEncoderTest->getErrorMsg();
delete codecEncoderTest;
@@ -778,9 +726,8 @@
jmethodID mId =
env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
- env->ReleaseIntArrayElements(jList0, cList0, 0);
- env->ReleaseIntArrayElements(jList1, cList1, 0);
- env->ReleaseIntArrayElements(jList2, cList2, 0);
+ env->ReleaseStringUTFChars(jCfgParams, cCfgParams);
+ env->ReleaseStringUTFChars(jSeparator, cSeparator);
env->ReleaseStringUTFChars(jEncoder, cEncoder);
env->ReleaseStringUTFChars(jMime, cmime);
env->ReleaseStringUTFChars(jsrcPath, csrcPath);
@@ -788,19 +735,14 @@
}
static jboolean nativeTestAdaptiveBitRate(JNIEnv* env, jobject, jstring jEncoder, jstring jsrcPath,
- jstring jMime, jintArray jList0, jintArray jList1,
- jintArray jList2, jint colorFormat, jobject jRetMsg) {
+ jstring jMime, jstring jCfgParams, jstring jSeparator,
+ jobject jRetMsg) {
const char* csrcPath = env->GetStringUTFChars(jsrcPath, nullptr);
const char* cmime = env->GetStringUTFChars(jMime, nullptr);
const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
- jsize cLen0 = env->GetArrayLength(jList0);
- jint* cList0 = env->GetIntArrayElements(jList0, nullptr);
- jsize cLen1 = env->GetArrayLength(jList1);
- jint* cList1 = env->GetIntArrayElements(jList1, nullptr);
- jsize cLen2 = env->GetArrayLength(jList2);
- jint* cList2 = env->GetIntArrayElements(jList2, nullptr);
- auto codecEncoderTest = new CodecEncoderTest(cmime, cList0, cLen0, cList1, cLen1, cList2, cLen2,
- (int)colorFormat);
+ const char* cCfgParams = env->GetStringUTFChars(jCfgParams, nullptr);
+ const char* cSeparator = env->GetStringUTFChars(jSeparator, nullptr);
+ auto codecEncoderTest = new CodecEncoderTest(cmime, cCfgParams, nullptr, cSeparator);
bool isPass = codecEncoderTest->testAdaptiveBitRate(cEncoder, csrcPath);
std::string msg = isPass ? std::string{} : codecEncoderTest->getErrorMsg();
delete codecEncoderTest;
@@ -808,9 +750,8 @@
jmethodID mId =
env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
- env->ReleaseIntArrayElements(jList0, cList0, 0);
- env->ReleaseIntArrayElements(jList1, cList1, 0);
- env->ReleaseIntArrayElements(jList2, cList2, 0);
+ env->ReleaseStringUTFChars(jCfgParams, cCfgParams);
+ env->ReleaseStringUTFChars(jSeparator, cSeparator);
env->ReleaseStringUTFChars(jEncoder, cEncoder);
env->ReleaseStringUTFChars(jMime, cmime);
env->ReleaseStringUTFChars(jsrcPath, csrcPath);
@@ -818,18 +759,12 @@
}
static jboolean nativeTestOnlyEos(JNIEnv* env, jobject, jstring jEncoder, jstring jMime,
- jintArray jList0, jintArray jList1, jintArray jList2,
- jint colorFormat, jobject jRetMsg) {
+ jstring jCfgParams, jstring jSeparator, jobject jRetMsg) {
const char* cmime = env->GetStringUTFChars(jMime, nullptr);
const char* cEncoder = env->GetStringUTFChars(jEncoder, nullptr);
- jsize cLen0 = env->GetArrayLength(jList0);
- jint* cList0 = env->GetIntArrayElements(jList0, nullptr);
- jsize cLen1 = env->GetArrayLength(jList1);
- jint* cList1 = env->GetIntArrayElements(jList1, nullptr);
- jsize cLen2 = env->GetArrayLength(jList2);
- jint* cList2 = env->GetIntArrayElements(jList2, nullptr);
- auto codecEncoderTest = new CodecEncoderTest(cmime, cList0, cLen0, cList1, cLen1, cList2, cLen2,
- (int)colorFormat);
+ const char* cCfgParams = env->GetStringUTFChars(jCfgParams, nullptr);
+ const char* cSeparator = env->GetStringUTFChars(jSeparator, nullptr);
+ auto codecEncoderTest = new CodecEncoderTest(cmime, cCfgParams, nullptr, cSeparator);
bool isPass = codecEncoderTest->testOnlyEos(cEncoder);
std::string msg = isPass ? std::string{} : codecEncoderTest->getErrorMsg();
delete codecEncoderTest;
@@ -837,9 +772,8 @@
jmethodID mId =
env->GetMethodID(clazz, "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;");
env->CallObjectMethod(jRetMsg, mId, env->NewStringUTF(msg.c_str()));
- env->ReleaseIntArrayElements(jList0, cList0, 0);
- env->ReleaseIntArrayElements(jList1, cList1, 0);
- env->ReleaseIntArrayElements(jList2, cList2, 0);
+ env->ReleaseStringUTFChars(jCfgParams, cCfgParams);
+ env->ReleaseStringUTFChars(jSeparator, cSeparator);
env->ReleaseStringUTFChars(jEncoder, cEncoder);
env->ReleaseStringUTFChars(jMime, cmime);
return static_cast<jboolean>(isPass);
@@ -848,23 +782,24 @@
int registerAndroidMediaV2CtsEncoderTest(JNIEnv* env) {
const JNINativeMethod methodTable[] = {
{"nativeTestSimpleEncode",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I[I[IILjava/lang/"
- "StringBuilder;)Z",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
+ "String;Ljava/lang/StringBuilder;)Z",
(void*)nativeTestSimpleEncode},
{"nativeTestReconfigure",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I[I[IILjava/lang/"
- "StringBuilder;)Z",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
+ "String;Ljava/lang/String;Ljava/lang/StringBuilder;)Z",
(void*)nativeTestReconfigure},
{"nativeTestSetForceSyncFrame",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I[I[IILjava/lang/"
- "StringBuilder;)Z",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
+ "String;Ljava/lang/StringBuilder;)Z",
(void*)nativeTestSetForceSyncFrame},
{"nativeTestAdaptiveBitRate",
- "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I[I[IILjava/lang/"
- "StringBuilder;)Z",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
+ "String;Ljava/lang/StringBuilder;)Z",
(void*)nativeTestAdaptiveBitRate},
{"nativeTestOnlyEos",
- "(Ljava/lang/String;Ljava/lang/String;[I[I[IILjava/lang/StringBuilder;)Z",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/"
+ "StringBuilder;)Z",
(void*)nativeTestOnlyEos},
};
jclass c = env->FindClass("android/mediav2/cts/CodecEncoderTest");
diff --git a/tests/media/jni/NativeCodecTestBase.h b/tests/media/jni/NativeCodecTestBase.h
index f4b60b6..8cbac7e 100644
--- a/tests/media/jni/NativeCodecTestBase.h
+++ b/tests/media/jni/NativeCodecTestBase.h
@@ -46,6 +46,20 @@
return false; \
}
+#define RETURN_IF_FALSE(cond, msg) \
+ if (!(cond)) { \
+ ALOGE("%s", (msg).c_str()); \
+ mErrorLogs.append((msg)).append("\n"); \
+ return false; \
+ }
+
+#define RETURN_IF_NULL(var, msg) \
+ if ((var) == nullptr) { \
+ ALOGE("%s", (msg).c_str()); \
+ mErrorLogs.append((msg)).append("\n"); \
+ return false; \
+ }
+
struct callbackObject {
AMediaCodecBufferInfo bufferInfo;
int32_t bufferIndex;
diff --git a/tests/media/jni/NativeMediaCommon.cpp b/tests/media/jni/NativeMediaCommon.cpp
index 3aabda3..da5cb36 100644
--- a/tests/media/jni/NativeMediaCommon.cpp
+++ b/tests/media/jni/NativeMediaCommon.cpp
@@ -154,3 +154,59 @@
if (strncmp(mediaType, "video/", strlen("video/")) == 0) return true;
return false;
}
+
+AMediaFormat* deSerializeMediaFormat(const char* msg, const char* separator) {
+ // constants to be kept in sync with definitions at MediaFormat.java
+ static const int TYPE_INTEGER = 1;
+ static const int TYPE_FLOAT = 3;
+ static const int TYPE_STRING = 4;
+ std::string limiter{separator};
+ std::string fmtMsg{msg};
+ AMediaFormat* fmt = AMediaFormat_new();
+ if (fmt == nullptr) {
+ ALOGE("no format received");
+ return nullptr;
+ }
+ auto start = 0u;
+ auto end = fmtMsg.find(limiter);
+ std::string keyStr, valueTypeStr, valueStr;
+ for (; end != std::string::npos;) {
+ // key
+ keyStr = fmtMsg.substr(start, end - start);
+ start = end + limiter.length();
+ end = fmtMsg.find(limiter, start);
+ if (end == std::string::npos) {
+ ALOGE("incomplete media format received %s", msg);
+ AMediaFormat_delete(fmt);
+ return nullptr;
+ }
+ // value type
+ valueTypeStr = fmtMsg.substr(start, end - start);
+ start = end + limiter.length();
+ end = fmtMsg.find(limiter, start);
+ if (end == std::string::npos) {
+ ALOGE("incomplete media format received %s", msg);
+ AMediaFormat_delete(fmt);
+ return nullptr;
+ }
+
+ // value
+ valueStr = fmtMsg.substr(start, end - start);
+ start = end + limiter.length();
+ end = fmtMsg.find(limiter, start);
+
+ auto valueType = std::stoi(valueTypeStr);
+ if (valueType == TYPE_INTEGER) {
+ AMediaFormat_setInt32(fmt, keyStr.c_str(), std::stoi(valueStr));
+ } else if (valueType == TYPE_FLOAT) {
+ AMediaFormat_setFloat(fmt, keyStr.c_str(), std::stof(valueStr));
+ } else if (valueType == TYPE_STRING) {
+ AMediaFormat_setString(fmt, keyStr.c_str(), valueStr.c_str());
+ } else {
+ ALOGE("unrecognized type for key %s", keyStr.c_str());
+ AMediaFormat_delete(fmt);
+ return nullptr;
+ }
+ }
+ return fmt;
+}
diff --git a/tests/media/jni/NativeMediaCommon.h b/tests/media/jni/NativeMediaCommon.h
index d50d4fe..08708db 100644
--- a/tests/media/jni/NativeMediaCommon.h
+++ b/tests/media/jni/NativeMediaCommon.h
@@ -83,6 +83,7 @@
// common utility functions
bool isCSDIdentical(AMediaFormat* refFormat, AMediaFormat* testFormat);
bool isFormatSimilar(AMediaFormat* refFormat, AMediaFormat* testFormat);
+AMediaFormat* deSerializeMediaFormat(const char* msg, const char* separator);
bool isMediaTypeOutputUnAffectedBySeek(const char* mediaType);
template <class T>
diff --git a/tests/media/src/android/mediav2/cts/AudioEncoderTest.java b/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
index 12b53d4..f4f1899 100644
--- a/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/AudioEncoderTest.java
@@ -27,8 +27,8 @@
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.mediav2.common.cts.CodecDecoderTestBase;
+import android.mediav2.common.cts.CodecEncoderTestBase;
import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
import android.mediav2.common.cts.OutputManager;
import androidx.test.filters.LargeTest;
@@ -61,7 +61,7 @@
* </ul>
*/
@RunWith(Parameterized.class)
-public class AudioEncoderTest extends EncoderTestBase {
+public class AudioEncoderTest extends CodecEncoderTestBase {
public AudioEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
@SuppressWarnings("unused") String testLabel, String allTestParams) {
super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
index c058f5f..445642f 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderSurfaceTest.java
@@ -19,6 +19,10 @@
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.mediav2.common.cts.CodecEncoderTestBase.ACCEPTABLE_WIRELESS_TX_QUALITY;
+import static android.mediav2.common.cts.CodecEncoderTestBase.colorFormatToString;
+import static android.mediav2.common.cts.CodecEncoderTestBase.getMuxerFormatForMediaType;
+import static android.mediav2.common.cts.CodecEncoderTestBase.getTempFilePath;
import static android.mediav2.common.cts.CodecTestBase.hasSupportForColorFormat;
import static android.mediav2.common.cts.CodecTestBase.isHardwareAcceleratedCodec;
import static android.mediav2.common.cts.CodecTestBase.isSoftwareCodec;
@@ -37,7 +41,9 @@
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.mediav2.common.cts.CodecAsyncHandler;
+import android.mediav2.common.cts.CodecEncoderTestBase;
import android.mediav2.common.cts.CodecTestBase;
+import android.mediav2.common.cts.EncoderConfigParams;
import android.mediav2.common.cts.OutputManager;
import android.util.Log;
import android.util.Pair;
@@ -93,25 +99,23 @@
private static final String MEDIA_DIR = WorkDir.getMediaDirString();
private static final boolean ENABLE_LOGS = false;
- private final String mCompName;
- private final String mMime;
+ private final String mEncoderName;
+ private final String mEncMediaType;
private final String mTestFile;
- private final int mBitrate;
- private final int mFrameRate;
- private final int mMaxBFrames;
- private final boolean mTestToneMap;
+ private final EncoderConfigParams mEncCfgParams;
private final int mColorFormat;
- private int mLatency;
- private boolean mReviseLatency;
- private MediaFormat mEncoderFormat;
+ private final boolean mTestToneMap;
+ private final String mTestArgs;
private MediaExtractor mExtractor;
+ private String mTestFileMediaType;
private MediaCodec mEncoder;
- private CodecAsyncHandler mAsyncHandleEncoder;
+ private MediaFormat mEncoderFormat;
+ private final CodecAsyncHandler mAsyncHandleEncoder = new CodecAsyncHandler();
private String mDecoderName;
private MediaCodec mDecoder;
private MediaFormat mDecoderFormat;
- private CodecAsyncHandler mAsyncHandleDecoder;
+ private final CodecAsyncHandler mAsyncHandleDecoder = new CodecAsyncHandler();
private boolean mIsCodecInAsyncMode;
private boolean mSignalEOSWithLastFrame;
private boolean mSawDecInputEOS;
@@ -120,10 +124,11 @@
private int mDecInputCount;
private int mDecOutputCount;
private int mEncOutputCount;
+ private int mLatency;
+ private boolean mReviseLatency;
- private String mTestArgs;
- private StringBuilder mTestConfig = new StringBuilder();
- private StringBuilder mTestEnv = new StringBuilder();
+ private final StringBuilder mTestConfig = new StringBuilder();
+ private final StringBuilder mTestEnv = new StringBuilder();
private boolean mSaveToMem;
private OutputManager mOutputBuff;
@@ -140,41 +145,33 @@
CodecTestBase.mimeSelKeys = args.getString(CodecTestBase.MIME_SEL_KEY);
}
- public CodecEncoderSurfaceTest(String encoder, String mime, String testFile, int bitrate,
- int frameRate, boolean testToneMap, int colorFormat, int maxBFrames,
- String allTestParams) {
- mCompName = encoder;
- mMime = mime;
+ public CodecEncoderSurfaceTest(String encoder, String mediaType, String testFile,
+ EncoderConfigParams encCfgParams, int colorFormat, boolean testToneMap,
+ @SuppressWarnings("unused") String testLabel, String allTestParams) {
+ mEncoderName = encoder;
+ mEncMediaType = mediaType;
mTestFile = MEDIA_DIR + testFile;
- mBitrate = bitrate;
- mFrameRate = frameRate;
- mTestToneMap = testToneMap;
+ mEncCfgParams = encCfgParams;
mColorFormat = colorFormat;
+ mTestToneMap = testToneMap;
mTestArgs = allTestParams;
- mMaxBFrames = maxBFrames;
- mLatency = mMaxBFrames;
+ mLatency = mEncCfgParams.mMaxBFrames;
mReviseLatency = false;
- mAsyncHandleDecoder = new CodecAsyncHandler();
- mAsyncHandleEncoder = new CodecAsyncHandler();
}
@Rule
public TestName mTestName = new TestName();
@Before
- public void setUp() throws IOException {
+ public void setUp() throws IOException, CloneNotSupportedException {
mTestConfig.setLength(0);
mTestConfig.append("\n################## Test Details ####################\n");
mTestConfig.append("Test Name :- ").append(mTestName.getMethodName()).append("\n");
mTestConfig.append("Test Parameters :- ").append(mTestArgs).append("\n");
- if (mCompName.startsWith(CodecTestBase.INVALID_CODEC)) {
+ if (mEncoderName.startsWith(CodecTestBase.INVALID_CODEC)) {
fail("no valid component available for current test. \n" + mTestConfig);
}
mDecoderFormat = setUpSource(mTestFile);
- if (mTestToneMap) {
- mDecoderFormat.setInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST,
- MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
- }
ArrayList<MediaFormat> decoderFormatList = new ArrayList<>();
decoderFormatList.add(mDecoderFormat);
String decoderMediaType = mDecoderFormat.getString(MediaFormat.KEY_MIME);
@@ -182,8 +179,8 @@
mTestFile.contains("10bit")) {
// Check if encoder is capable of supporting HDR profiles.
// Previous check doesn't verify this as profile isn't set in the format
- Assume.assumeTrue(mCompName + " doesn't support HDR encoding",
- CodecTestBase.doesCodecSupportHDRProfile(mCompName, mMime));
+ Assume.assumeTrue(mEncoderName + " doesn't support HDR encoding",
+ CodecTestBase.doesCodecSupportHDRProfile(mEncoderName, mEncMediaType));
}
MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -193,9 +190,9 @@
if (mColorFormat == COLOR_FormatSurface) {
// TODO(b/253492870) Remove the following assumption check once this is supported
- Assume.assumeFalse(
- mDecoderName + "is hardware accelerated and " + mCompName + "is software only.",
- isHardwareAcceleratedCodec(mDecoderName) && isSoftwareCodec(mCompName));
+ Assume.assumeFalse(mDecoderName + "is hardware accelerated and " + mEncoderName
+ + "is software only.",
+ isHardwareAcceleratedCodec(mDecoderName) && isSoftwareCodec(mEncoderName));
} else {
// findDecoderForFormat() ignores color-format and decoder returned may not be
// supporting the color format set in mDecoderFormat. Following check will
@@ -210,8 +207,21 @@
decoderSupportsColorFormat);
}
}
+ EncoderConfigParams.Builder foreman = mEncCfgParams.getBuilder()
+ .setWidth(mDecoderFormat.getInteger(MediaFormat.KEY_WIDTH))
+ .setHeight(mDecoderFormat.getInteger(MediaFormat.KEY_HEIGHT));
+ mEncoderFormat = foreman.build().getFormat();
+ }
- mEncoderFormat = setUpEncoderFormat(mDecoderFormat);
+ private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
+ int frameRate, int bitDepth, int maxBFrames) {
+ return new EncoderConfigParams.Builder(mediaType)
+ .setBitRate(bitRate)
+ .setFrameRate(frameRate)
+ .setColorFormat(COLOR_FormatSurface)
+ .setInputBitDepth(bitDepth)
+ .setMaxBFrames(maxBFrames)
+ .build();
}
@After
@@ -238,7 +248,7 @@
}
}
- @Parameterized.Parameters(name = "{index}({0}_{1}_{5}_{7})")
+ @Parameterized.Parameters(name = "{index}({0}_{1}_{6})")
public static Collection<Object[]> input() {
final boolean isEncoder = true;
final boolean needAudio = false;
@@ -280,45 +290,58 @@
512000, 30, true},
}));
- int[] argsColorFormats = {COLOR_FormatSurface, COLOR_FormatYUV420Flexible};
+ int[] colorFormats = {COLOR_FormatSurface, COLOR_FormatYUV420Flexible};
int[] maxBFrames = {0, 2};
- int argLength = args.get(0).length;
for (Object[] arg : args) {
- for (int colorFormat : argsColorFormats) {
+ final String mediaType = (String) arg[0];
+ final int br = (int) arg[2];
+ final int fps = (int) arg[3];
+ for (int colorFormat : colorFormats) {
for (int maxBFrame : maxBFrames) {
- String mediaType = arg[0].toString();
if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
&& !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)
&& maxBFrame != 0) {
continue;
}
- Object[] argUpdate = new Object[argLength + 2];
- System.arraycopy(arg, 0, argUpdate, 0, argLength);
- argUpdate[argLength] = colorFormat;
- argUpdate[argLength + 1] = maxBFrame;
- exhaustiveArgsList.add(argUpdate);
+ Object[] testArgs = new Object[6];
+ testArgs[0] = arg[0];
+ testArgs[1] = arg[1];
+ testArgs[2] = getVideoEncoderCfgParams(mediaType, br, fps, 8, maxBFrame);
+ testArgs[3] = colorFormat;
+ testArgs[4] = arg[4];
+ testArgs[5] = String.format("%dkbps_%dfps_%s", br / 1000, fps,
+ colorFormatToString(colorFormat, 8));
+ exhaustiveArgsList.add(testArgs);
}
}
}
// P010 support was added in Android T, hence limit the following tests to Android T and
// above
if (CodecTestBase.IS_AT_LEAST_T) {
- int[] argsHighBitDepthColorFormats = {COLOR_FormatSurface, COLOR_FormatYUVP010};
- int argsHighBitDepthLength = argsHighBitDepth.get(0).length;
+ int[] colorFormatsHbd = {COLOR_FormatSurface, COLOR_FormatYUVP010};
for (Object[] arg : argsHighBitDepth) {
- for (int colorFormat : argsHighBitDepthColorFormats) {
+ final String mediaType = (String) arg[0];
+ final int br = (int) arg[2];
+ final int fps = (int) arg[3];
+ final boolean toneMap = (boolean) arg[4];
+ for (int colorFormat : colorFormatsHbd) {
for (int maxBFrame : maxBFrames) {
- String mediaType = arg[0].toString();
if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
&& !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)
&& maxBFrame != 0) {
continue;
}
- Object[] argUpdate = new Object[argsHighBitDepthLength + 2];
- System.arraycopy(arg, 0, argUpdate, 0, argsHighBitDepthLength);
- argUpdate[argsHighBitDepthLength] = colorFormat;
- argUpdate[argsHighBitDepthLength + 1] = maxBFrame;
- exhaustiveArgsList.add(argUpdate);
+ Object[] testArgs = new Object[6];
+ testArgs[0] = arg[0];
+ testArgs[1] = arg[1];
+ testArgs[2] = getVideoEncoderCfgParams(mediaType, br, fps, toneMap ? 8 : 10,
+ maxBFrame);
+ testArgs[3] = colorFormat;
+ testArgs[4] = arg[4];
+ testArgs[5] = String.format("%dkbps_%dfps_%s_%s", br / 1000, fps,
+ colorFormatToString(colorFormat, 10),
+ toneMap ? "tonemapyes" : "tonemapno");
+ exhaustiveArgsList.add(testArgs);
}
}
}
@@ -339,10 +362,13 @@
MediaFormat format = mExtractor.getTrackFormat(trackID);
String mime = format.getString(MediaFormat.KEY_MIME);
if (mime.startsWith("video/")) {
+ mTestFileMediaType = mime;
mExtractor.selectTrack(trackID);
- ArrayList<MediaFormat> formatList = new ArrayList<>();
- formatList.add(format);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, mColorFormat);
+ if (mTestToneMap) {
+ format.setInteger(MediaFormat.KEY_COLOR_TRANSFER_REQUEST,
+ MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
+ }
return format;
}
}
@@ -379,7 +405,7 @@
mDecoder.configure(decFormat, mSurface, null, 0);
mTestEnv.setLength(0);
mTestEnv.append("################### Test Environment #####################\n");
- mTestEnv.append(String.format("Encoder under test :- %s \n", mCompName));
+ mTestEnv.append(String.format("Encoder under test :- %s \n", mEncoderName));
mTestEnv.append(String.format("Format under test :- %s \n", encFormat));
mTestEnv.append(String.format("Encoder is fed with output of :- %s \n", mDecoderName));
mTestEnv.append(String.format("Format of Decoder Input :- %s", decFormat));
@@ -633,21 +659,6 @@
}
}
- private MediaFormat setUpEncoderFormat(MediaFormat decoderFormat) {
- MediaFormat encoderFormat = new MediaFormat();
- encoderFormat.setString(MediaFormat.KEY_MIME, mMime);
- encoderFormat.setInteger(MediaFormat.KEY_WIDTH,
- decoderFormat.getInteger(MediaFormat.KEY_WIDTH));
- encoderFormat.setInteger(MediaFormat.KEY_HEIGHT,
- decoderFormat.getInteger(MediaFormat.KEY_HEIGHT));
- encoderFormat.setInteger(MediaFormat.KEY_FRAME_RATE, mFrameRate);
- encoderFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate);
- encoderFormat.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 1.0f);
- encoderFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatSurface);
- encoderFormat.setInteger(MediaFormat.KEY_MAX_B_FRAMES, mMaxBFrames);
- return encoderFormat;
- }
-
private void validateToneMappedFormat(MediaFormat format, String descriptor) {
assertEquals("unexpected color transfer in " + descriptor + " after tone mapping",
MediaFormat.COLOR_TRANSFER_SDR_VIDEO,
@@ -657,7 +668,7 @@
format.getInteger(MediaFormat.KEY_COLOR_STANDARD, 0));
int profile = format.getInteger(MediaFormat.KEY_PROFILE, -1);
- int[] profileArray = CodecTestBase.PROFILE_HDR_MAP.get(mMime);
+ int[] profileArray = CodecTestBase.PROFILE_HDR_MAP.get(mEncMediaType);
assertFalse(descriptor + " must not contain HDR profile after tone mapping",
IntStream.of(profileArray).anyMatch(x -> x == profile));
}
@@ -678,8 +689,11 @@
mDecoder = MediaCodec.createByCodecName(mDecoderName);
String tmpPath = null;
boolean muxOutput = true;
+ if (mEncMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) && CodecTestBase.IS_BEFORE_U) {
+ muxOutput = false;
+ }
{
- mEncoder = MediaCodec.createByCodecName(mCompName);
+ mEncoder = MediaCodec.createByCodecName(mEncoderName);
/* TODO(b/149027258) */
mSaveToMem = false;
OutputManager ref = new OutputManager();
@@ -691,15 +705,8 @@
mOutputBuff = loopCounter == 0 ? ref : test;
mOutputBuff.reset();
if (muxOutput && loopCounter == 0) {
- int muxerFormat;
- if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) ||
- mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_WEBM;
- tmpPath = File.createTempFile("tmp", ".webm").getAbsolutePath();
- } else {
- muxerFormat = MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4;
- tmpPath = File.createTempFile("tmp", ".mp4").getAbsolutePath();
- }
+ int muxerFormat = getMuxerFormatForMediaType(mEncMediaType);
+ tmpPath = getTempFilePath(mEncCfgParams.mInputBitDepth > 8 ? "10bit" : "");
mMuxer = new MediaMuxer(tmpPath, muxerFormat);
}
configureCodec(mDecoderFormat, mEncoderFormat, isAsync, false);
@@ -758,11 +765,12 @@
+ test.getErrMsg());
}
if (loopCounter == 0 &&
- !ref.isOutPtsListIdenticalToInpPtsList((mMaxBFrames != 0))) {
+ !ref.isOutPtsListIdenticalToInpPtsList((mEncCfgParams.mMaxBFrames != 0))) {
fail("Input pts list and Output pts list are not identical \n" + mTestConfig
+ mTestEnv + ref.getErrMsg());
}*/
- if (mMaxBFrames == 0 && !mOutputBuff.isPtsStrictlyIncreasing(Long.MIN_VALUE)) {
+ if (mEncCfgParams.mMaxBFrames == 0 && !mOutputBuff.isPtsStrictlyIncreasing(
+ Long.MIN_VALUE)) {
fail("Output timestamps are not strictly increasing \n" + mTestConfig + mTestEnv
+ mOutputBuff.getErrMsg());
}
@@ -786,11 +794,16 @@
}
mDecoder.release();
mExtractor.release();
+ // Skip stream validation as there is no reference for tone mapped input
+ if (muxOutput && !mTestToneMap) {
+ CodecEncoderTestBase.validateEncodedPSNR(mTestFileMediaType, mTestFile, mEncMediaType,
+ tmpPath, false, false, ACCEPTABLE_WIRELESS_TX_QUALITY);
+ }
if (muxOutput) new File(tmpPath).delete();
}
private native boolean nativeTestSimpleEncode(String encoder, String decoder, String mime,
- String testFile, String muxFile, int bitrate, int framerate, int colorFormat,
+ String testFile, String muxFile, int colorFormat, String cfgParams, String separator,
StringBuilder retMsg);
/**
@@ -799,20 +812,22 @@
@ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
@LargeTest
@Test(timeout = CodecTestBase.PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testSimpleEncodeFromSurfaceNative() throws IOException {
+ public void testSimpleEncodeFromSurfaceNative() throws IOException, InterruptedException {
assumeFalse("tone mapping tests are skipped in native mode", mTestToneMap);
- {
- String tmpPath;
- if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP8) ||
- mMime.equals(MediaFormat.MIMETYPE_VIDEO_VP9)) {
- tmpPath = File.createTempFile("tmp", ".webm").getAbsolutePath();
- } else {
- tmpPath = File.createTempFile("tmp", ".mp4").getAbsolutePath();
- }
- int colorFormat = mDecoderFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT, -1);
- boolean isPass = nativeTestSimpleEncode(mCompName, mDecoderName, mMime, mTestFile,
- tmpPath, mBitrate, mFrameRate, colorFormat, mTestConfig);
- assertTrue(mTestConfig.toString(), isPass);
+ String tmpPath = null;
+ if (!mEncMediaType.equals(MediaFormat.MIMETYPE_VIDEO_AV1) || CodecTestBase.IS_AT_LEAST_U) {
+ tmpPath = getTempFilePath(mEncCfgParams.mInputBitDepth > 8 ? "10bit" : "");
+ }
+ int colorFormat = mDecoderFormat.getInteger(MediaFormat.KEY_COLOR_FORMAT, -1);
+ boolean isPass = nativeTestSimpleEncode(mEncoderName, mDecoderName, mEncMediaType,
+ mTestFile, tmpPath, colorFormat,
+ EncoderConfigParams.serializeMediaFormat(mEncoderFormat),
+ EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+ assertTrue(mTestConfig.toString(), isPass);
+ if (tmpPath != null) {
+ CodecEncoderTestBase.validateEncodedPSNR(mTestFileMediaType, mTestFile, mEncMediaType,
+ tmpPath, false, false, ACCEPTABLE_WIRELESS_TX_QUALITY);
+ new File(tmpPath).delete();
}
}
}
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
index 06dc853..cc86e76 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
@@ -17,13 +17,14 @@
package android.mediav2.cts;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.mediav2.common.cts.CodecEncoderTestBase;
+import android.mediav2.common.cts.EncoderConfigParams;
import android.mediav2.common.cts.OutputManager;
import android.os.Bundle;
import android.util.Log;
@@ -34,6 +35,7 @@
import com.android.compatibility.common.util.ApiTest;
import org.junit.Assume;
+import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -71,26 +73,24 @@
@RunWith(Parameterized.class)
public class CodecEncoderTest extends CodecEncoderTestBase {
private static final String LOG_TAG = CodecEncoderTest.class.getSimpleName();
- private static ArrayList<String> sAdaptiveBitrateMimeList = new ArrayList<>();
+ private static final ArrayList<String> ABR_MEDIATYPE_LIST = new ArrayList<>();
private int mNumSyncFramesReceived;
- private ArrayList<Integer> mSyncFramesPos;
+ private final ArrayList<Integer> mSyncFramesPos = new ArrayList<>();
static {
System.loadLibrary("ctsmediav2codecenc_jni");
- sAdaptiveBitrateMimeList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
- sAdaptiveBitrateMimeList.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
- sAdaptiveBitrateMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP8);
- sAdaptiveBitrateMimeList.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ ABR_MEDIATYPE_LIST.add(MediaFormat.MIMETYPE_VIDEO_AVC);
+ ABR_MEDIATYPE_LIST.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
+ ABR_MEDIATYPE_LIST.add(MediaFormat.MIMETYPE_VIDEO_VP8);
+ ABR_MEDIATYPE_LIST.add(MediaFormat.MIMETYPE_VIDEO_VP9);
+ ABR_MEDIATYPE_LIST.add(MediaFormat.MIMETYPE_VIDEO_AV1);
}
- public CodecEncoderTest(String encoder, String mime, int[] bitrates, int[] encoderInfo1,
- int[] encoderInfo2, int maxBFrames, String allTestParams) {
- super(encoder, mime, bitrates, encoderInfo1, encoderInfo2,
- EncoderInput.getRawResource(mime, /* isHighBitDepth */ false), allTestParams);
- mMaxBFrames = maxBFrames;
- mSyncFramesPos = new ArrayList<>();
+ public CodecEncoderTest(String encoder, String mime, EncoderConfigParams[] cfgParams,
+ String allTestParams) {
+ super(encoder, mime, cfgParams, allTestParams);
}
@Override
@@ -126,62 +126,156 @@
mCodec.setParameters(bitrateUpdate);
}
- @Parameterized.Parameters(name = "{index}({0}_{1}_{5})")
+ private static EncoderConfigParams getVideoEncoderCfgParam(String mediaType, int width,
+ int height, int bitRate, int maxBFrames) {
+ return new EncoderConfigParams.Builder(mediaType).setWidth(width).setHeight(height)
+ .setMaxBFrames(maxBFrames).setBitRate(bitRate).build();
+ }
+
+ private static EncoderConfigParams getAudioEncoderCfgParam(String mediaType, int sampleRate,
+ int channelCount, int qualityPreset) {
+ EncoderConfigParams.Builder foreman =
+ new EncoderConfigParams.Builder(mediaType).setSampleRate(sampleRate)
+ .setChannelCount(channelCount);
+ if (mediaType.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+ foreman = foreman.setCompressionLevel(qualityPreset);
+ } else {
+ foreman = foreman.setBitRate(qualityPreset);
+ }
+ return foreman.build();
+ }
+
+ private static EncoderConfigParams[] getAacCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_AAC, 8000, 1, 128000);
+ params[1] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_AAC, 48000, 2, 128000);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getOpusCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_OPUS, 16000, 1, 64000);
+ params[1] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_OPUS, 16000, 1, 128000);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getAmrnbCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_AMR_NB, 8000, 1, 4750);
+ params[1] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_AMR_NB, 8000, 1, 12200);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getAmrwbCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_AMR_WB, 16000, 1, 6600);
+ params[1] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_AMR_WB, 16000, 1, 23850);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getFlacCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_FLAC, 8000, 1, 6);
+ params[1] = getAudioEncoderCfgParam(MediaFormat.MIMETYPE_AUDIO_FLAC, 48000, 2, 5);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getH263CfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_H263, 176, 144, 32000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_H263, 176, 144, 64000, 0);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getMpeg4CfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_MPEG4, 176, 144, 32000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_MPEG4, 176, 144, 64000, 0);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getAvcCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_AVC, 176, 144, 512000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_AVC, 352, 288, 512000, 0);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getHevcCfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_HEVC, 176, 144, 512000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_HEVC, 352, 288, 512000, 0);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getAvcCfgParamsWithBFrames() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_AVC, 320, 240, 512000, 2);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_AVC, 480, 360, 768000, 2);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getHevcCfgParamsWithBFrames() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_HEVC, 320, 240, 384000, 2);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_HEVC, 480, 360, 512000, 2);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getVp8CfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_VP8, 176, 144, 512000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_VP8, 352, 288, 512000, 0);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getVp9CfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_VP9, 176, 144, 512000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_VP9, 352, 288, 512000, 0);
+ return params;
+ }
+
+ private static EncoderConfigParams[] getAv1CfgParams() {
+ EncoderConfigParams[] params = new EncoderConfigParams[2];
+ params[0] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_AV1, 176, 144, 512000, 0);
+ params[1] = getVideoEncoderCfgParam(MediaFormat.MIMETYPE_VIDEO_AV1, 352, 288, 512000, 0);
+ return params;
+ }
+
+ @Parameterized.Parameters(name = "{index}({0}_{1})")
public static Collection<Object[]> input() {
final boolean isEncoder = true;
final boolean needAudio = true;
final boolean needVideo = true;
- final List<Object[]> exhaustiveArgsList = new ArrayList<>();
- final List<Object[]> args = new ArrayList<>(Arrays.asList(new Object[][]{
- // Audio - CodecMime, arrays of bit-rates, sample rates, channel counts
- {MediaFormat.MIMETYPE_AUDIO_AAC, new int[]{128000}, new int[]{8000, 48000},
- new int[]{1, 2}},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new int[]{6600, 23850}, new int[]{16000},
- new int[]{1}},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new int[]{4750, 12200}, new int[]{8000},
- new int[]{1}},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new int[]{6600, 23850}, new int[]{16000},
- new int[]{1}},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new int[]{5}, new int[]{8000, 48000},
- new int[]{1, 2}},
-
- // Video - CodecMime, arrays of bit-rates, height, width
- {MediaFormat.MIMETYPE_VIDEO_H263, new int[]{32000, 64000}, new int[]{176},
- new int[]{144}},
- {MediaFormat.MIMETYPE_VIDEO_MPEG4, new int[]{32000, 64000}, new int[]{176},
- new int[]{144}},
- {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{512000}, new int[]{176, 352},
- new int[]{144, 288}},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{512000}, new int[]{176, 352},
- new int[]{144, 288}},
- {MediaFormat.MIMETYPE_VIDEO_VP8, new int[]{512000}, new int[]{176, 352},
- new int[]{144, 288}},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{512000}, new int[]{176, 352},
- new int[]{144, 288}},
- {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{512000}, new int[]{176, 352},
- new int[]{144, 288}},
+ final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
+ // mediaType, cfg params
+ {MediaFormat.MIMETYPE_AUDIO_AAC, getAacCfgParams()},
+ {MediaFormat.MIMETYPE_AUDIO_OPUS, getOpusCfgParams()},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_NB, getAmrnbCfgParams()},
+ {MediaFormat.MIMETYPE_AUDIO_AMR_WB, getAmrwbCfgParams()},
+ {MediaFormat.MIMETYPE_AUDIO_FLAC, getFlacCfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_H263, getH263CfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_MPEG4, getMpeg4CfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, getAvcCfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, getAvcCfgParamsWithBFrames()},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, getHevcCfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, getHevcCfgParamsWithBFrames()},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, getVp8CfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, getVp9CfgParams()},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, getAv1CfgParams()},
}));
-
- int[] maxBFrames = {0, 2};
- int argLength = args.get(0).length;
- for (Object[] arg : args) {
- for (int maxBFrame : maxBFrames) {
- String mediaType = arg[0].toString();
- if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
- && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)
- && maxBFrame != 0) {
- continue;
- }
- Object[] argUpdate = new Object[argLength + 1];
- System.arraycopy(arg, 0, argUpdate, 0, argLength);
- argUpdate[argLength] = maxBFrame;
- exhaustiveArgsList.add(argUpdate);
- }
- }
-
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, true);
}
+ @Before
+ public void setUp() throws IOException {
+ mActiveEncCfg = mEncCfgParams[0];
+ mActiveRawRes = EncoderInput.getRawResource(mActiveEncCfg);
+ assertNotNull("no raw resource found for testing config : " + mActiveEncCfg + mTestConfig
+ + mTestEnv, mActiveRawRes);
+ }
+
/**
* Checks if the component under test can encode the test file correctly. The encoding
* happens in synchronous, asynchronous mode, eos flag signalled with last raw frame and
@@ -198,7 +292,6 @@
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testSimpleEncode() throws IOException, InterruptedException {
- setUpParams(1);
boolean[] boolStates = {true, false};
setUpSource(mActiveRawRes.mFileName);
OutputManager ref = new OutputManager();
@@ -210,7 +303,8 @@
assertTrue("error! codec canonical name is null or empty",
mCodec.getCanonicalName() != null && !mCodec.getCanonicalName().isEmpty());
mSaveToMem = false; /* TODO(b/149027258) */
- for (MediaFormat format : mFormats) {
+ MediaFormat format = mActiveEncCfg.getFormat();
+ {
int loopCounter = 0;
for (boolean eosType : boolStates) {
for (boolean isAsync : boolStates) {
@@ -240,7 +334,7 @@
}
private native boolean nativeTestSimpleEncode(String encoder, String file, String mime,
- int[] list0, int[] list1, int[] list2, int colorFormat, StringBuilder retMsg);
+ String cfgParams, String separator, StringBuilder retMsg);
/**
* Test is similar to {@link #testSimpleEncode()} but uses ndk api
@@ -249,18 +343,18 @@
"android.media.AudioFormat#ENCODING_PCM_16BIT"})
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testSimpleEncodeNative() throws IOException {
- int colorFormat = -1;
- {
- if (mIsVideo) {
- colorFormat = findByteBufferColorFormat(mCodecName, mMime);
- assertTrue("no valid color formats received \n" + mTestConfig + mTestEnv,
- colorFormat != -1);
- }
- boolean isPass = nativeTestSimpleEncode(mCodecName, mActiveRawRes.mFileName, mMime,
- mBitrates, mEncParamList1, mEncParamList2, colorFormat, mTestConfig);
- assertTrue(mTestConfig.toString(), isPass);
+ public void testSimpleEncodeNative() throws IOException, CloneNotSupportedException {
+ MediaFormat format = mActiveEncCfg.getFormat();
+ if (mIsVideo) {
+ int colorFormat = findByteBufferColorFormat(mCodecName, mMime);
+ assertTrue("no valid color formats received \n" + mTestConfig + mTestEnv,
+ colorFormat != -1);
+ format = mActiveEncCfg.getBuilder().setColorFormat(colorFormat).build().getFormat();
}
+ boolean isPass = nativeTestSimpleEncode(mCodecName, mActiveRawRes.mFileName, mMime,
+ EncoderConfigParams.serializeMediaFormat(format),
+ EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+ assertTrue(mTestConfig.toString(), isPass);
}
/**
@@ -296,25 +390,23 @@
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testReconfigure() throws IOException, InterruptedException {
- setUpParams(2);
- setUpSource(mActiveRawRes.mFileName);
+
boolean[] boolStates = {true, false};
{
boolean saveToMem = false; /* TODO(b/149027258) */
OutputManager configRef = null;
OutputManager configTest = null;
- if (mFormats.size() > 1) {
- MediaFormat format = mFormats.get(1);
- encodeToMemory(mActiveRawRes.mFileName, mCodecName, Integer.MAX_VALUE,
- format, saveToMem);
+ if (mEncCfgParams.length > 1) {
+ encodeToMemory(mCodecName, mEncCfgParams[1], mActiveRawRes, Integer.MAX_VALUE,
+ saveToMem, mMuxOutput);
configRef = mOutputBuff;
configTest = new OutputManager(configRef.getSharedErrorLogs());
}
- MediaFormat format = mFormats.get(0);
- encodeToMemory(mActiveRawRes.mFileName, mCodecName, Integer.MAX_VALUE,
- format, saveToMem);
+ encodeToMemory(mCodecName, mEncCfgParams[0], mActiveRawRes, Integer.MAX_VALUE,
+ saveToMem, mMuxOutput);
OutputManager ref = mOutputBuff;
OutputManager test = new OutputManager(ref.getSharedErrorLogs());
+ MediaFormat format = mEncCfgParams[0].getFormat();
mCodec = MediaCodec.createByCodecName(mCodecName);
for (boolean isAsync : boolStates) {
mOutputBuff = test;
@@ -363,9 +455,9 @@
}
/* test reconfigure codec for new format */
- if (mFormats.size() > 1) {
+ if (mEncCfgParams.length > 1) {
mOutputBuff = configTest;
- reConfigureCodec(mFormats.get(1), isAsync, false, true);
+ reConfigureCodec(mEncCfgParams[1].getFormat(), isAsync, false, true);
mCodec.start();
configTest.reset();
doWork(Integer.MAX_VALUE);
@@ -386,7 +478,7 @@
}
private native boolean nativeTestReconfigure(String encoder, String file, String mime,
- int[] list0, int[] list1, int[] list2, int colorFormat, StringBuilder retMsg);
+ String cfgParams, String cfgReconfigParams, String separator, StringBuilder retMsg);
/**
* Test is similar to {@link #testReconfigure()} but uses ndk api
@@ -395,17 +487,24 @@
@ApiTest(apis = {"android.media.MediaCodec#configure"})
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testReconfigureNative() throws IOException {
- int colorFormat = -1;
- {
- if (mIsVideo) {
- colorFormat = findByteBufferColorFormat(mCodecName, mMime);
- assertTrue("no valid color formats received", colorFormat != -1);
+ public void testReconfigureNative() throws IOException, CloneNotSupportedException {
+ MediaFormat format = mEncCfgParams[0].getFormat();
+ MediaFormat reconfigFormat = mEncCfgParams.length > 1 ? mEncCfgParams[1].getFormat() : null;
+ if (mIsVideo) {
+ int colorFormat = findByteBufferColorFormat(mCodecName, mMime);
+ assertTrue("no valid color formats received \n" + mTestConfig + mTestEnv,
+ colorFormat != -1);
+ format = mEncCfgParams[0].getBuilder().setColorFormat(colorFormat).build().getFormat();
+ if (mEncCfgParams.length > 1) {
+ reconfigFormat = mEncCfgParams[1].getBuilder().setColorFormat(colorFormat).build()
+ .getFormat();
}
- boolean isPass = nativeTestReconfigure(mCodecName, mActiveRawRes.mFileName, mMime,
- mBitrates, mEncParamList1, mEncParamList2, colorFormat, mTestConfig);
- assertTrue(mTestConfig.toString(), isPass);
}
+ boolean isPass = nativeTestReconfigure(mCodecName, mActiveRawRes.mFileName, mMime,
+ EncoderConfigParams.serializeMediaFormat(format), reconfigFormat == null ? null :
+ EncoderConfigParams.serializeMediaFormat(reconfigFormat),
+ EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+ assertTrue(mTestConfig.toString(), isPass);
}
/**
@@ -417,7 +516,6 @@
@SmallTest
@Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
public void testOnlyEos() throws IOException, InterruptedException {
- setUpParams(1);
boolean[] boolStates = {true, false};
OutputManager ref = new OutputManager();
OutputManager test = new OutputManager(ref.getSharedErrorLogs());
@@ -425,8 +523,9 @@
mCodec = MediaCodec.createByCodecName(mCodecName);
mSaveToMem = false; /* TODO(b/149027258) */
int loopCounter = 0;
+ MediaFormat format = mActiveEncCfg.getFormat();
for (boolean isAsync : boolStates) {
- configureCodec(mFormats.get(0), isAsync, false, true);
+ configureCodec(format, isAsync, false, true);
mOutputBuff = loopCounter == 0 ? ref : test;
mOutputBuff.reset();
mInfoList.clear();
@@ -446,8 +545,8 @@
}
}
- private native boolean nativeTestOnlyEos(String encoder, String mime, int[] list0, int[] list1,
- int[] list2, int colorFormat, StringBuilder retMsg);
+ private native boolean nativeTestOnlyEos(String encoder, String mime, String cfgParams,
+ String separator, StringBuilder retMsg);
/**
* Test is similar to {@link #testOnlyEos()} but uses ndk api
@@ -455,17 +554,18 @@
@ApiTest(apis = "android.media.MediaCodec#BUFFER_FLAG_END_OF_STREAM")
@SmallTest
@Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
- public void testOnlyEosNative() throws IOException {
- int colorFormat = -1;
- {
- if (mIsVideo) {
- colorFormat = findByteBufferColorFormat(mCodecName, mMime);
- assertTrue("no valid color formats received", colorFormat != -1);
- }
- boolean isPass = nativeTestOnlyEos(mCodecName, mMime, mBitrates, mEncParamList1,
- mEncParamList2, colorFormat, mTestConfig);
- assertTrue(mTestConfig.toString(), isPass);
+ public void testOnlyEosNative() throws IOException, CloneNotSupportedException {
+ MediaFormat format = mActiveEncCfg.getFormat();
+ if (mIsVideo) {
+ int colorFormat = findByteBufferColorFormat(mCodecName, mMime);
+ assertTrue("no valid color formats received \n" + mTestConfig + mTestEnv,
+ colorFormat != -1);
+ format = mActiveEncCfg.getBuilder().setColorFormat(colorFormat).build().getFormat();
}
+ boolean isPass = nativeTestOnlyEos(mCodecName, mMime,
+ EncoderConfigParams.serializeMediaFormat(format),
+ EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+ assertTrue(mTestConfig.toString(), isPass);
}
/**
@@ -477,20 +577,20 @@
@ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testSetForceSyncFrame() throws IOException, InterruptedException {
+ public void testSetForceSyncFrame()
+ throws IOException, InterruptedException, CloneNotSupportedException {
Assume.assumeTrue("Test is applicable only for video encoders", mIsVideo);
+ EncoderConfigParams currCfg = mActiveEncCfg.getBuilder().setKeyFrameInterval(500.f).build();
+ MediaFormat format = currCfg.getFormat();
// Maximum allowed key frame interval variation from the target value.
- final int MAX_KEYFRAME_INTERVAL_VARIATION = 3;
- setUpParams(1);
- boolean[] boolStates = {true, false};
+ final int maxKeyframeIntervalVariation = 3;
+ final int keyFrameInterval = 2; // force key frame every 2 seconds.
+ final int keyFramePos = currCfg.mFrameRate * keyFrameInterval;
+ final int numKeyFrameRequests = 7;
+
setUpSource(mActiveRawRes.mFileName);
- MediaFormat format = mFormats.get(0);
- format.removeKey(MediaFormat.KEY_I_FRAME_INTERVAL);
- format.setFloat(MediaFormat.KEY_I_FRAME_INTERVAL, 500.f);
- final int KEY_FRAME_INTERVAL = 2; // force key frame every 2 seconds.
- final int KEY_FRAME_POS = mFrameRate * KEY_FRAME_INTERVAL;
- final int NUM_KEY_FRAME_REQUESTS = 7;
mOutputBuff = new OutputManager();
+ boolean[] boolStates = {true, false};
{
mCodec = MediaCodec.createByCodecName(mCodecName);
for (boolean isAsync : boolStates) {
@@ -498,11 +598,11 @@
mInfoList.clear();
configureCodec(format, isAsync, false, true);
mCodec.start();
- for (int i = 0; i < NUM_KEY_FRAME_REQUESTS; i++) {
- doWork(KEY_FRAME_POS);
+ for (int i = 0; i < numKeyFrameRequests; i++) {
+ doWork(keyFramePos);
if (mSawInputEOS) {
fail(String.format("Unable to encode %d frames as the input resource "
- + "contains only %d frames \n", KEY_FRAME_POS, mInputCount));
+ + "contains only %d frames \n", keyFramePos, mInputCount));
}
forceSyncFrame();
mInputBufferReadOffset = 0;
@@ -513,17 +613,17 @@
if (false) mCodec.stop();
else mCodec.reset();
String msg = String.format("Received only %d key frames for %d key frame "
- + "requests \n", mNumSyncFramesReceived, NUM_KEY_FRAME_REQUESTS);
+ + "requests \n", mNumSyncFramesReceived, numKeyFrameRequests);
assertTrue(msg + mTestConfig + mTestEnv,
- mNumSyncFramesReceived >= NUM_KEY_FRAME_REQUESTS);
- for (int i = 0, expPos = 0, index = 0; i < NUM_KEY_FRAME_REQUESTS; i++) {
+ mNumSyncFramesReceived >= numKeyFrameRequests);
+ for (int i = 0, expPos = 0, index = 0; i < numKeyFrameRequests; i++) {
int j = index;
for (; j < mSyncFramesPos.size(); j++) {
// Check key frame intervals:
// key frame position should not be greater than target value + 3
// key frame position should not be less than target value - 3
if (Math.abs(expPos - mSyncFramesPos.get(j)) <=
- MAX_KEYFRAME_INTERVAL_VARIATION) {
+ maxKeyframeIntervalVariation) {
index = j;
break;
}
@@ -532,7 +632,7 @@
Log.w(LOG_TAG, "requested key frame at frame index " + expPos +
" none found near by");
}
- expPos += KEY_FRAME_POS;
+ expPos += keyFramePos;
}
}
mCodec.release();
@@ -540,7 +640,7 @@
}
private native boolean nativeTestSetForceSyncFrame(String encoder, String file, String mime,
- int[] list0, int[] list1, int[] list2, int colorFormat, StringBuilder retMsg);
+ String cfgParams, String separator, StringBuilder retMsg);
/**
* Test is similar to {@link #testSetForceSyncFrame()} but uses ndk api
@@ -548,18 +648,19 @@
@ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testSetForceSyncFrameNative() throws IOException {
+ public void testSetForceSyncFrameNative() throws IOException, CloneNotSupportedException {
Assume.assumeTrue("Test is applicable only for encoders", mIsVideo);
- int colorFormat = -1;
- {
- if (mIsVideo) {
- colorFormat = findByteBufferColorFormat(mCodecName, mMime);
- assertTrue("no valid color formats received", colorFormat != -1);
- }
- boolean isPass = nativeTestSetForceSyncFrame(mCodecName, mActiveRawRes.mFileName, mMime,
- mBitrates, mEncParamList1, mEncParamList2, colorFormat, mTestConfig);
- assertTrue(mTestConfig.toString(), isPass);
- }
+
+ int colorFormat = findByteBufferColorFormat(mCodecName, mMime);
+ assertTrue("no valid color formats received \n" + mTestConfig + mTestEnv,
+ colorFormat != -1);
+ MediaFormat format =
+ mActiveEncCfg.getBuilder().setColorFormat(colorFormat).setKeyFrameInterval(500.f)
+ .build().getFormat();
+ boolean isPass = nativeTestSetForceSyncFrame(mCodecName, mActiveRawRes.mFileName, mMime,
+ EncoderConfigParams.serializeMediaFormat(format),
+ EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+ assertTrue(mTestConfig.toString(), isPass);
}
/**
@@ -574,30 +675,20 @@
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testAdaptiveBitRate() throws IOException, InterruptedException {
Assume.assumeTrue("Skipping AdaptiveBitrate test for " + mMime,
- sAdaptiveBitrateMimeList.contains(mMime));
- setUpParams(1);
+ ABR_MEDIATYPE_LIST.contains(mMime));
+ MediaFormat format = mActiveEncCfg.getFormat();
+ final int adaptiveBrInterval = 3; // change br every 3 seconds.
+ final int adaptiveBrDurFrm = mActiveEncCfg.mFrameRate * adaptiveBrInterval;
+ final int brChangeRequests = 7;
+ // TODO(b/251265293) Reduce the allowed deviation after improving the test conditions
+ final float maxBitrateDeviation = 60.0f; // allowed bitrate deviation in %
+
boolean[] boolStates = {true, false};
setUpSource(mActiveRawRes.mFileName);
- MediaFormat format = mFormats.get(0);
- final int ADAPTIVE_BR_INTERVAL = 3; // change br every 3 seconds.
- final int ADAPTIVE_BR_DUR_FRM = mFrameRate * ADAPTIVE_BR_INTERVAL;
- final int BR_CHANGE_REQUESTS = 7;
- // TODO(b/251265293) Reduce the allowed deviation after improving the test conditions
- final float MAX_BITRATE_DEVIATION = 60.0f; // allowed bitrate deviation in %
mOutputBuff = new OutputManager();
mSaveToMem = true;
{
mCodec = MediaCodec.createByCodecName(mCodecName);
- format.removeKey(MediaFormat.KEY_BITRATE_MODE);
- MediaCodecInfo.EncoderCapabilities cap =
- mCodec.getCodecInfo().getCapabilitiesForType(mMime).getEncoderCapabilities();
- if (cap.isBitrateModeSupported(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR)) {
- format.setInteger(MediaFormat.KEY_BITRATE_MODE,
- MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR);
- } else {
- format.setInteger(MediaFormat.KEY_BITRATE_MODE,
- MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR);
- }
for (boolean isAsync : boolStates) {
mOutputBuff.reset();
mInfoList.clear();
@@ -605,13 +696,13 @@
mCodec.start();
int expOutSize = 0;
int bitrate = format.getInteger(MediaFormat.KEY_BIT_RATE);
- for (int i = 0; i < BR_CHANGE_REQUESTS; i++) {
- doWork(ADAPTIVE_BR_DUR_FRM);
+ for (int i = 0; i < brChangeRequests; i++) {
+ doWork(adaptiveBrDurFrm);
if (mSawInputEOS) {
fail(String.format("Unable to encode %d frames as the input resource "
- + "contains only %d frames \n", ADAPTIVE_BR_DUR_FRM, mInputCount));
+ + "contains only %d frames \n", adaptiveBrDurFrm, mInputCount));
}
- expOutSize += ADAPTIVE_BR_INTERVAL * bitrate;
+ expOutSize += adaptiveBrInterval * bitrate;
if ((i & 1) == 1) bitrate *= 2;
else bitrate /= 2;
updateBitrate(bitrate);
@@ -625,7 +716,7 @@
/* TODO: validate output br with sliding window constraints Sec 5.2 cdd */
int outSize = mOutputBuff.getOutStreamSize() * 8;
float brDev = Math.abs(expOutSize - outSize) * 100.0f / expOutSize;
- if (brDev > MAX_BITRATE_DEVIATION) {
+ if (brDev > maxBitrateDeviation) {
fail("Relative Bitrate error is too large " + brDev + "\n" + mTestConfig
+ mTestEnv);
}
@@ -635,7 +726,7 @@
}
private native boolean nativeTestAdaptiveBitRate(String encoder, String file, String mime,
- int[] list0, int[] list1, int[] list2, int colorFormat, StringBuilder retMsg);
+ String cfgParams, String separator, StringBuilder retMsg);
/**
* Test is similar to {@link #testAdaptiveBitRate()} but uses ndk api
@@ -643,18 +734,17 @@
@ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
- public void testAdaptiveBitRateNative() throws IOException {
+ public void testAdaptiveBitRateNative() throws IOException, CloneNotSupportedException {
Assume.assumeTrue("Skipping Native AdaptiveBitrate test for " + mMime,
- sAdaptiveBitrateMimeList.contains(mMime));
- int colorFormat = -1;
- {
- if (mIsVideo) {
- colorFormat = findByteBufferColorFormat(mCodecName, mMime);
- assertTrue("no valid color formats received", colorFormat != -1);
- }
- boolean isPass = nativeTestAdaptiveBitRate(mCodecName, mActiveRawRes.mFileName, mMime,
- mBitrates, mEncParamList1, mEncParamList2, colorFormat, mTestConfig);
- assertTrue(mTestConfig.toString(), isPass);
- }
+ ABR_MEDIATYPE_LIST.contains(mMime));
+ int colorFormat = findByteBufferColorFormat(mCodecName, mMime);
+ assertTrue("no valid color formats received \n" + mTestConfig + mTestEnv,
+ colorFormat != -1);
+ MediaFormat format =
+ mActiveEncCfg.getBuilder().setColorFormat(colorFormat).build().getFormat();
+ boolean isPass = nativeTestAdaptiveBitRate(mCodecName, mActiveRawRes.mFileName, mMime,
+ EncoderConfigParams.serializeMediaFormat(format),
+ EncoderConfigParams.TOKEN_SEPARATOR, mTestConfig);
+ assertTrue(mTestConfig.toString(), isPass);
}
}
diff --git a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
index 2c20d23..bac7169 100644
--- a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
@@ -143,6 +143,9 @@
"bikes_qcif_color_bt2020_smpte2086Hlg_bt2020Ncl_fr_hevc.mp4",
MediaFormat.COLOR_RANGE_FULL, MediaFormat.COLOR_STANDARD_BT2020,
MediaFormat.COLOR_TRANSFER_HLG, true, CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, "cosmat_352x288_hlg_hevc.mkv",
+ MediaFormat.COLOR_RANGE_LIMITED, MediaFormat.COLOR_STANDARD_BT709,
+ MediaFormat.COLOR_TRANSFER_HLG, true, CODEC_OPTIONAL},
// Mpeg2 clips
{MediaFormat.MIMETYPE_VIDEO_MPEG2, "bbb_qcif_color_bt709_lr_sdr_mpeg2.mp4",
@@ -227,6 +230,9 @@
"bikes_qcif_color_bt2020_smpte2086Hlg_bt2020Ncl_fr_vp9.mkv",
MediaFormat.COLOR_RANGE_FULL, MediaFormat.COLOR_STANDARD_BT2020,
MediaFormat.COLOR_TRANSFER_HLG, false, CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, "cosmat_352x288_hlg_vp9.mkv",
+ MediaFormat.COLOR_RANGE_LIMITED, MediaFormat.COLOR_STANDARD_BT709,
+ MediaFormat.COLOR_TRANSFER_HLG, false, CODEC_OPTIONAL},
// AV1 clips
{MediaFormat.MIMETYPE_VIDEO_AV1, "bbb_qcif_color_bt709_lr_sdr_av1.mp4",
@@ -254,6 +260,9 @@
"bikes_qcif_color_bt2020_smpte2086Hlg_bt2020Ncl_fr_av1.mp4",
MediaFormat.COLOR_RANGE_FULL, MediaFormat.COLOR_STANDARD_BT2020,
MediaFormat.COLOR_TRANSFER_HLG, true, CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, "cosmat_352x288_hlg_av1.mkv",
+ MediaFormat.COLOR_RANGE_LIMITED, MediaFormat.COLOR_STANDARD_BT709,
+ MediaFormat.COLOR_TRANSFER_HLG, true, CODEC_ALL},
});
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
}
diff --git a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
index db0bf9e..df21ded 100644
--- a/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
+++ b/tests/media/src/android/mediav2/cts/EncodeDecodeAccuracyTest.java
@@ -19,7 +19,7 @@
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
-import static android.mediav2.common.cts.EncoderTestBase.colorFormatToString;
+import static android.mediav2.common.cts.CodecEncoderTestBase.colorFormatToString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
diff --git a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
index a07dc4d..a2f4b76 100644
--- a/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderColorAspectsTest.java
@@ -28,9 +28,9 @@
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.mediav2.common.cts.CodecDecoderTestBase;
+import android.mediav2.common.cts.CodecEncoderTestBase;
import android.mediav2.common.cts.CodecTestBase;
import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
import android.mediav2.common.cts.OutputManager;
import android.opengl.GLES20;
import android.os.Build;
@@ -73,7 +73,7 @@
* restricted to HLG/HDR profiles.
*/
@RunWith(Parameterized.class)
-public class EncoderColorAspectsTest extends EncoderTestBase {
+public class EncoderColorAspectsTest extends CodecEncoderTestBase {
private static final String LOG_TAG = EncoderColorAspectsTest.class.getSimpleName();
private Surface mInpSurface;
@@ -285,11 +285,6 @@
public void testColorAspects() throws IOException, InterruptedException {
Assume.assumeTrue("Test introduced with Android 11", sIsAtLeastR);
- if (mCodecName.equals("OMX.google.h264.encoder")) { // TODO(b/189883530)
- Log.d(LOG_TAG, "test skipped due to b/189883530");
- return;
- }
-
mActiveEncCfg = mEncCfgParams[0];
if (mActiveEncCfg.mInputBitDepth > 8) {
// Check if encoder is capable of supporting HDR profiles.
diff --git a/tests/media/src/android/mediav2/cts/EncoderInput.java b/tests/media/src/android/mediav2/cts/EncoderInput.java
index 2b7daa8..7b879b8 100644
--- a/tests/media/src/android/mediav2/cts/EncoderInput.java
+++ b/tests/media/src/android/mediav2/cts/EncoderInput.java
@@ -85,18 +85,4 @@
}
return null;
}
-
- /**
- * TODO (b/260533828) remove this once all encoders are update to use
- * @deprecated This function is marked for future removal. Use
- * {@link EncoderInput#getRawResource(EncoderConfigParams)} instead.
- */
- @Deprecated(forRemoval = true)
- public static RawResource getRawResource(String mediaType, boolean isHighBitDepth) {
- if (mediaType.startsWith("audio/")) {
- return isHighBitDepth ? INPUT_AUDIO_FILE_HBD : INPUT_AUDIO_FILE;
- } else {
- return isHighBitDepth ? INPUT_VIDEO_FILE_HBD : INPUT_VIDEO_FILE;
- }
- }
}
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index a5eb22c..c5c9a32 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -31,8 +31,8 @@
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMuxer;
+import android.mediav2.common.cts.CodecEncoderTestBase;
import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
import android.mediav2.common.cts.OutputManager;
import android.util.Log;
import android.util.Pair;
@@ -75,7 +75,7 @@
* handle certain profile and level configurations. This is verified as well.
*/
@RunWith(Parameterized.class)
-public class EncoderProfileLevelTest extends EncoderTestBase {
+public class EncoderProfileLevelTest extends CodecEncoderTestBase {
private static final String LOG_TAG = EncoderProfileLevelTest.class.getSimpleName();
private static final HashMap<String, Pair<int[], Integer>> PROFILE_LEVEL_CDD = new HashMap<>();
diff --git a/tests/media/src/android/mediav2/cts/MuxerTest.java b/tests/media/src/android/mediav2/cts/MuxerTest.java
index 938df1b..7804408 100644
--- a/tests/media/src/android/mediav2/cts/MuxerTest.java
+++ b/tests/media/src/android/mediav2/cts/MuxerTest.java
@@ -16,7 +16,7 @@
package android.mediav2.cts;
-import static android.mediav2.common.cts.EncoderTestBase.isMediaTypeContainerPairValid;
+import static android.mediav2.common.cts.CodecEncoderTestBase.isMediaTypeContainerPairValid;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
diff --git a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
index 8a94a85..82cfae0 100644
--- a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
@@ -24,8 +24,9 @@
import static org.junit.Assert.assertTrue;
import android.media.MediaFormat;
+import android.mediav2.common.cts.CodecEncoderTestBase;
+import android.mediav2.common.cts.CodecTestBase;
import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
import android.mediav2.common.cts.RawResource;
import androidx.test.filters.LargeTest;
@@ -55,7 +56,7 @@
* </ul>
*/
@RunWith(Parameterized.class)
-public class VideoEncoderTest extends EncoderTestBase {
+public class VideoEncoderTest extends CodecEncoderTestBase {
public VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
@SuppressWarnings("unused") String testLabel, String allTestParams) {
super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
@@ -170,10 +171,19 @@
RawResource res = EncoderInput.getRawResource(mEncCfgParams[0]);
assertNotNull("no raw resource found for testing config : " + mActiveEncCfg + mTestConfig
+ mTestEnv, res);
- encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, false);
+
+ boolean muxOutput = true;
+ if (mMime.equals(MediaFormat.MIMETYPE_VIDEO_AV1) && CodecTestBase.IS_BEFORE_U) {
+ muxOutput = false;
+ }
+ encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, muxOutput);
// cleanup tmp files
- if (mMuxOutput) {
+ if (muxOutput) {
+ // validate output
+ validateEncodedPSNR(res, mMime, mMuxedOutputFile, true, mIsLoopBack,
+ ACCEPTABLE_WIRELESS_TX_QUALITY);
+
File tmp = new File(mMuxedOutputFile);
if (tmp.exists()) {
assertTrue("unable to delete tmp file" + mMuxedOutputFile, tmp.delete());
diff --git a/tests/mediapc/AndroidTest.xml b/tests/mediapc/AndroidTest.xml
index a91a0f0..2a2bfab 100644
--- a/tests/mediapc/AndroidTest.xml
+++ b/tests/mediapc/AndroidTest.xml
@@ -39,7 +39,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="CtsMediaPerformanceClassTestCases-2.0" />
+ <option name="media-folder-name" value="CtsMediaPerformanceClassTestCases-2.1" />
<option name="dynamic-config-module" value="CtsMediaPerformanceClassTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
diff --git a/tests/mediapc/DynamicConfig.xml b/tests/mediapc/DynamicConfig.xml
index 1d44a69..d1a7b1f 100644
--- a/tests/mediapc/DynamicConfig.xml
+++ b/tests/mediapc/DynamicConfig.xml
@@ -1,6 +1,6 @@
<dynamicConfig>
<entry key="media_files_url">
- <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-2.0.zip</value>
+ <value>https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-2.1.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/mediapc/README.md b/tests/mediapc/README.md
index f29aedd..d212c32 100644
--- a/tests/mediapc/README.md
+++ b/tests/mediapc/README.md
@@ -1,7 +1,7 @@
## Media Performance Class CTS Tests
Current folder comprises of files necessary for testing media performance class.
-The test vectors used by the test suite is available at [link](https://storage.googleapis.com/android_media/cts/tests/mediapc/CtsMediaPerformanceClassTestCases-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/mediapc/CtsMediaPerformanceClassTestCases-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.
### Commands
#### To run all tests in CtsMediaPerformanceClassTestCases
diff --git a/tests/mediapc/common/Android.bp b/tests/mediapc/common/Android.bp
index 663dabc..02fd714 100644
--- a/tests/mediapc/common/Android.bp
+++ b/tests/mediapc/common/Android.bp
@@ -25,7 +25,8 @@
"compatibility-device-util-axt",
"android.test.base",
"auto_value_annotations",
- "guava"
+ "guava",
+ "cts-verifier-framework",
],
plugins: ["auto_value_plugin"],
}
@@ -35,7 +36,7 @@
compile_multilib: "both",
static_libs: [
"compatibility-device-util-axt",
- "MediaPerformanceClassCommon"
+ "MediaPerformanceClassCommon",
],
platform_apis: true,
srcs: ["tests/src/**/*.java"],
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
index 91db865..1e803c2 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java
@@ -23,6 +23,12 @@
import android.hardware.camera2.CameraMetadata;
import android.media.MediaFormat;
import android.os.Build;
+import android.util.Log;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.cts.verifier.CtsVerifierReportLog;
import com.google.common.base.Preconditions;
@@ -1494,6 +1500,46 @@
}
}
+ public static class AudioTap2ToneLatencyRequirement extends Requirement {
+ private static final String TAG = AudioTap2ToneLatencyRequirement.class.getSimpleName();
+
+ private AudioTap2ToneLatencyRequirement(String id, RequiredMeasurement<?> ... reqs) {
+ super(id, reqs);
+ }
+
+ public void setNativeLatency(double latency) {
+ this.setMeasuredValue(RequirementConstants.API_NATIVE_LATENCY, latency);
+ }
+
+ public void setJavaLatency(double latency) {
+ this.setMeasuredValue(RequirementConstants.API_JAVA_LATENCY, latency);
+ }
+
+ public static AudioTap2ToneLatencyRequirement createR5_6__H_1_1() {
+ RequiredMeasurement<Double> apiNativeLatency = RequiredMeasurement
+ .<Double>builder()
+ .setId(RequirementConstants.API_NATIVE_LATENCY)
+ .setPredicate(RequirementConstants.DOUBLE_LTE)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 80.0)
+ .addRequiredValue(Build.VERSION_CODES.S, 100.0)
+ .addRequiredValue(Build.VERSION_CODES.R, 100.0)
+ .build();
+ RequiredMeasurement<Double> apiJavaLatency = RequiredMeasurement
+ .<Double>builder()
+ .setId(RequirementConstants.API_JAVA_LATENCY)
+ .setPredicate(RequirementConstants.DOUBLE_LTE)
+ .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 80.0)
+ .addRequiredValue(Build.VERSION_CODES.S, 100.0)
+ .addRequiredValue(Build.VERSION_CODES.R, 100.0)
+ .build();
+
+ return new AudioTap2ToneLatencyRequirement(
+ RequirementConstants.R5_6__H_1_1,
+ apiNativeLatency,
+ apiJavaLatency);
+ }
+ }
+
public <R extends Requirement> R addRequirement(R req) {
if (!this.mRequirements.add(req)) {
throw new IllegalStateException("Requirement " + req.id() + " already added");
@@ -1725,21 +1771,51 @@
return this.addRequirement(StreamUseCaseRequirement.createStreamUseCaseReq());
}
+ public AudioTap2ToneLatencyRequirement addR5_6__H_1_1() {
+ return this.addRequirement(AudioTap2ToneLatencyRequirement.createR5_6__H_1_1());
+ }
+
+ private enum SubmitType {
+ TRADEFED, VERIFIER
+ }
+
public void submitAndCheck() {
- boolean perfClassMet = submit();
+ boolean perfClassMet = submit(SubmitType.TRADEFED);
// check performance class
assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass());
assertThat(perfClassMet).isTrue();
}
- public boolean submit() {
+ public void submitAndVerify() {
+ boolean perfClassMet = submit(SubmitType.VERIFIER);
+
+ if (!perfClassMet && Utils.isPerfClass()) {
+ Log.w(TAG, "Device did not meet specified performance class: " + Utils.getPerfClass());
+ }
+ }
+
+ private boolean submit(SubmitType type) {
boolean perfClassMet = true;
for (Requirement req: this.mRequirements) {
- perfClassMet &= req.writeLogAndCheck(this.mTestName);
+ switch (type) {
+ case VERIFIER:
+ CtsVerifierReportLog verifierLog = new CtsVerifierReportLog(
+ RequirementConstants.REPORT_LOG_NAME, req.id());
+ perfClassMet &= req.writeLogAndCheck(verifierLog, this.mTestName);
+ verifierLog.submit();
+ break;
+
+ case TRADEFED:
+ default:
+ DeviceReportLog tradefedLog = new DeviceReportLog(
+ RequirementConstants.REPORT_LOG_NAME, req.id());
+ perfClassMet &= req.writeLogAndCheck(tradefedLog, this.mTestName);
+ tradefedLog.submit(InstrumentationRegistry.getInstrumentation());
+ break;
+ }
}
this.mRequirements.clear(); // makes sure report isn't submitted twice
return perfClassMet;
}
-
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
index cf2633f..efa7e96 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequiredMeasurement.java
@@ -16,9 +16,10 @@
package android.mediapc.cts.common;
-import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
@@ -113,7 +114,7 @@
+ "\n\tExpected Values: " + this.expectedValues();
}
- public void writeValue(DeviceReportLog log) throws IllegalStateException {
+ public void writeValue(ReportLog log) throws IllegalStateException {
if (!this.measuredValueSet) {
throw new IllegalStateException("measured value not set for required measurement "
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java b/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
index 445c5c6..2160b10 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Requirement.java
@@ -18,15 +18,13 @@
import android.util.Log;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.compatibility.common.util.DeviceReportLog;
+import com.android.compatibility.common.util.ReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -113,7 +111,7 @@
/**
* @return whether or not the requirement meets the device's specified performance class
*/
- public boolean writeLogAndCheck(String testName) {
+ public boolean writeLogAndCheck(ReportLog log, String testName) {
if (this.id == RequirementConstants.RTBD) {
// skip upload on any requirement without a specified id
Log.i(this.TAG, testName + "has requirement without set requirement id and test " +
@@ -123,7 +121,6 @@
int perfClass = this.computePerformanceClass();
- DeviceReportLog log = new DeviceReportLog(RequirementConstants.REPORT_LOG_NAME, this.id);
log.addValue(RequirementConstants.TN_FIELD_NAME, testName, ResultType.NEUTRAL,
ResultUnit.NONE);
for (RequiredMeasurement rm: this.mRequiredMeasurements.values()) {
@@ -131,7 +128,6 @@
}
log.addValue(RequirementConstants.PC_FIELD_NAME, perfClass, ResultType.NEUTRAL,
ResultUnit.NONE);
- log.submit(InstrumentationRegistry.getInstrumentation());
return this.checkPerformanceClass(Utils.getPerfClass());
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
index 7bccbeb..6893e62 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/RequirementConstants.java
@@ -50,8 +50,11 @@
public static final String R7_5__H_1_2 = "r7_5__h_1_2"; // 7.5/H-1-2
public static final String R7_5__H_1_3 = "r7_5__h_1_3"; // 7.5/H-1-3
public static final String R7_5__H_1_4 = "r7_5__h_1_4"; // 7.5/H-1-4
- public static final String R7_5__H_1_5 = "r7_5__h_1_5"; // 7.5/H-1-5
- public static final String R7_5__H_1_6 = "r7_5__h_1_6"; // 7.5/H-1-6
+
+ // these includes "its" because the proto in google3 was originally implemented incorrectly
+ public static final String R7_5__H_1_5 = "r7_5__h_1_5__its"; // 7.5/H-1-5
+ public static final String R7_5__H_1_6 = "r7_5__h_1_6__its"; // 7.5/H-1-6
+
public static final String R7_5__H_1_8 = "r7_5__h_1_8"; // 7.5/H-1-8
public static final String R7_5__H_1_9 = "r7_5__h_1_9"; // 7.5/H-1-9
public static final String R7_5__H_1_10 = "r7_5__h_1_10"; // 7.5/H-1-10
@@ -128,6 +131,8 @@
"rear_camera_stream_usecase_supported";
public static final String FRONT_CAMERA_STREAM_USECASE_SUPPORTED =
"front_camera_stream_usecase_supported";
+ public static final String API_NATIVE_LATENCY = "native_latency_ms";
+ public static final String API_JAVA_LATENCY = "java_latency_ms";
public enum Result {
NA, MET, UNMET
@@ -140,6 +145,7 @@
public static final BiPredicate<Integer, Integer> INTEGER_LTE = RequirementConstants.lte();
public static final BiPredicate<Integer, Integer> INTEGER_EQ = RequirementConstants.eq();
public static final BiPredicate<Double, Double> DOUBLE_GTE = RequirementConstants.gte();
+ public static final BiPredicate<Double, Double> DOUBLE_LTE = RequirementConstants.lte();
public static final BiPredicate<Double, Double> DOUBLE_EQ = RequirementConstants.eq();
public static final BiPredicate<Boolean, Boolean> BOOLEAN_EQ = RequirementConstants.eq();
diff --git a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
index daa9d27..1c5035b 100644
--- a/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
+++ b/tests/mediapc/common/tests/src/android/mediapc/cts/common/RequirementTest.java
@@ -22,6 +22,8 @@
import android.os.Build;
+import com.android.compatibility.common.util.DeviceReportLog;
+
import org.junit.Test;
public class RequirementTest {
@@ -197,9 +199,10 @@
@Test
public void writeLogAndCheck_UnsetMeasurement() {
TestReq testReq = TestReq.create();
+ DeviceReportLog testLog = new DeviceReportLog("test", "test");
assertThrows(
IllegalStateException.class,
- () -> testReq.writeLogAndCheck("writeLogAndCheck_UnsetMeasurement"));
+ () -> testReq.writeLogAndCheck(testLog, "writeLogAndCheck_UnsetMeasurement"));
}
}
diff --git a/tests/mediapc/copy_media.sh b/tests/mediapc/copy_media.sh
index d63eb0a..25d98ce 100644
--- a/tests/mediapc/copy_media.sh
+++ b/tests/mediapc/copy_media.sh
@@ -17,7 +17,7 @@
## script to install media performance class test files manually
adbOptions=" "
-resLabel=CtsMediaPerformanceClassTestCases-2.0
+resLabel=CtsMediaPerformanceClassTestCases-2.1
srcDir="/tmp/$resLabel"
tgtDir="/sdcard/test"
usage="Usage: $0 [-h] [-s serial]"
diff --git a/tests/mediapc/src/android/mediapc/cts/WorkDir.java b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
index c9d689a..4076e88 100644
--- a/tests/mediapc/src/android/mediapc/cts/WorkDir.java
+++ b/tests/mediapc/src/android/mediapc/cts/WorkDir.java
@@ -40,7 +40,7 @@
// user has specified the mediaDirString via instrumentation-arg
return mediaDirString + ((mediaDirString.endsWith("/")) ? "" : "/");
} else {
- return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-2.0/");
+ return (getTopDirString() + "test/CtsMediaPerformanceClassTestCases-2.1/");
}
}
}
diff --git a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
index 0e1bcd1..b2292f4 100644
--- a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
+++ b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
@@ -281,6 +281,11 @@
public void testOpenFile_onMediaDocumentsProvider_failsWithoutAccess() throws Exception {
if (!supportsHardware()) return;
+ String rawText = "TEST";
+ // Read and write grants will be provided to the file associated with this pair.
+ // Stages a text file which contains raw text "TEST"
+ Pair<Uri, File> uriFilePairWithGrants = prepareFileAndFetchDetails(rawText);
+
clearDocumentsUi();
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
@@ -289,10 +294,6 @@
mActivity.startActivityForResult(intent, REQUEST_CODE);
mDevice.waitForIdle();
- String rawText = "TEST";
- // Read and write grants will be provided to the file associated with this pair.
- // Stages a text file which contains raw text "TEST"
- Pair<Uri, File> uriFilePairWithGrants = prepareFileAndFetchDetails(rawText);
// Read and write grants will not be provided to the file associated with this pair
// Stages a text file which contains raw text "TEST"
Pair<Uri, File> uriFilePairWithoutGrants = prepareFileAndFetchDetails(rawText);
diff --git a/tests/quickaccesswallet/OWNERS b/tests/quickaccesswallet/OWNERS
index 271c1e6..b633530 100644
--- a/tests/quickaccesswallet/OWNERS
+++ b/tests/quickaccesswallet/OWNERS
@@ -1,6 +1,8 @@
-# Bug component: 480956
+# Bug component: 802986
seanpont@google.com
steell@google.com
granger@google.com
sbasi@google.com
franksalim@google.com
+juliacr@google.com
+asc@google.com
diff --git a/tests/signature/OWNERS b/tests/signature/OWNERS
new file mode 100644
index 0000000..0577cf8
--- /dev/null
+++ b/tests/signature/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 24949
+ngeoffray@google.com
+paulduffin@google.com
+andreionea@google.com
+
+include platform/art:/OWNERS
\ No newline at end of file
diff --git a/tests/signature/lib/common/src/android/signature/cts/DexApiDocumentParser.java b/tests/signature/lib/common/src/android/signature/cts/DexApiDocumentParser.java
index 8bb3062..5d0e6a3 100644
--- a/tests/signature/lib/common/src/android/signature/cts/DexApiDocumentParser.java
+++ b/tests/signature/lib/common/src/android/signature/cts/DexApiDocumentParser.java
@@ -19,6 +19,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer;
+import java.text.ParseException;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
@@ -26,7 +27,6 @@
import java.util.regex.Pattern;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
-import java.text.ParseException;
/**
* Parses an API definition given as a text file with DEX signatures of class
@@ -38,8 +38,18 @@
*/
public class DexApiDocumentParser {
- // Regex patterns which match DEX signatures of methods and fields.
- // See comment by next() for more details.
+ /*
+ * Regex patterns which match DEX signatures of methods and fields.
+ *
+ * The following two line formats are supported:
+ * 1) [class descriptor]->[field name]:[field type]
+ * - e.g. Lcom/example/MyClass;->myField:I
+ * - these lines are parsed as field signatures
+ * 2) [class descriptor]->[method name]([method parameter types])[method return type]
+ * - e.g. Lcom/example/MyClass;->myMethod(Lfoo;Lbar;)J
+ * - these lines are parsed as method signatures
+ * NB there are parens present in method signatures but not field signatures.
+ */
private static final Pattern REGEX_FIELD = Pattern.compile("^(L[^>]*;)->(.*):(.*)$");
private static final Pattern REGEX_METHOD =
Pattern.compile("^(L[^>]*;)->(.*)(\\(.*\\).*)$");
@@ -83,7 +93,7 @@
return parseAsStream(buffer, LINE_LENGTH_ESTIMATE);
}
public Stream<DexMember> parseAsStream(ByteBuffer buffer, int lineLengthEstimate) {
- // TODO: Ensurance that the input conforms to ByteBufferLineSpliterator requirements.
+ // TODO: Ensure that the input conforms to ByteBufferLineSpliterator requirements.
return StreamSupport.stream(new ByteBufferLineSpliterator<DexMember>(buffer,
lineLengthEstimate, DEX_MEMBER_CONVERTER), true);
}
@@ -94,26 +104,21 @@
String signature = splitLine[0];
String[] flags = Arrays.copyOfRange(splitLine, 1, splitLine.length);
- // Match line against regex patterns.
- Matcher matchField = REGEX_FIELD.matcher(signature);
- Matcher matchMethod = REGEX_METHOD.matcher(signature);
-
- // Check that *exactly* one pattern matches.
- int matchCount = (matchField.matches() ? 1 : 0) + (matchMethod.matches() ? 1 : 0);
- if (matchCount == 0) {
- throw new ParseException("Could not parse: \"" + line + "\"", lineNum);
- } else if (matchCount > 1) {
- throw new ParseException("Ambiguous parse: \"" + line + "\"", lineNum);
+ // Check if the signature has the form of a field signature (no parens present).
+ final boolean memberIsField = (signature.indexOf('(') < 0);
+ if (memberIsField) {
+ Matcher matchField = REGEX_FIELD.matcher(signature);
+ if (matchField.matches()) {
+ return new DexField(
+ matchField.group(1), matchField.group(2), matchField.group(3), flags);
+ }
+ } else {
+ Matcher matchMethod = REGEX_METHOD.matcher(signature);
+ if (matchMethod.matches()) {
+ return new DexMethod(
+ matchMethod.group(1), matchMethod.group(2), matchMethod.group(3), flags);
+ }
}
-
- // Extract information from the signature.
- if (matchField.matches()) {
- return new DexField(
- matchField.group(1), matchField.group(2), matchField.group(3), flags);
- } else if (matchMethod.matches()) {
- return new DexMethod(
- matchMethod.group(1),matchMethod.group(2), matchMethod.group(3), flags);
- }
- throw new IllegalStateException();
+ throw new ParseException("Could not parse: \"" + line + "\"", lineNum);
}
}
diff --git a/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java b/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java
index b642efa..a6614a3 100644
--- a/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java
+++ b/tests/signature/lib/common/src/android/signature/cts/InterfaceChecker.java
@@ -83,6 +83,7 @@
HIDDEN_INTERFACE_METHOD_ALLOW_LIST.add("public abstract void android.view.inputmethod.InputMethod.setCurrentShowInputToken(android.os.IBinder)");
HIDDEN_INTERFACE_METHOD_ALLOW_LIST.add("public abstract void android.view.inputmethod.InputMethodSession.notifyImeHidden()");
HIDDEN_INTERFACE_METHOD_ALLOW_LIST.add("public abstract void android.view.inputmethod.InputMethodSession.removeImeSurface()");
+ HIDDEN_INTERFACE_METHOD_ALLOW_LIST.add("public abstract void android.bluetooth.BluetoothProfile.close()");
}
private final ResultObserver resultObserver;
diff --git a/tests/tests/background/Android.bp b/tests/tests/background/Android.bp
index ad0efa0..03030212 100644
--- a/tests/tests/background/Android.bp
+++ b/tests/tests/background/Android.bp
@@ -25,7 +25,6 @@
"mockito-target-minus-junit4",
"compatibility-device-util-axt",
"ctstestrunner-axt",
- "ub-uiautomator",
],
libs: ["android.test.runner"],
srcs: ["src/**/*.java"],
diff --git a/tests/tests/bluetooth/AndroidTest.xml b/tests/tests/bluetooth/AndroidTest.xml
index caf9428..7b42874 100644
--- a/tests/tests/bluetooth/AndroidTest.xml
+++ b/tests/tests/bluetooth/AndroidTest.xml
@@ -25,6 +25,12 @@
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsBluetoothTestCases.apk" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="cmd bluetooth_manager enable" />
+ <option name="run-command" value="cmd bluetooth_manager wait-for-state:STATE_ON" />
+ <option name="teardown-command" value="cmd bluetooth_manager disable" />
+ <option name="teardown-command" value="cmd bluetooth_manager wait-for-state:STATE_OFF" />
+ </target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.bluetooth.cts" />
<option name="runtime-hint" value="1m11s" />
diff --git a/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java b/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java
index 6807c39..32d37fc 100644
--- a/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java
+++ b/tests/tests/bluetooth/bluetoothTestUtilLib/src/android/bluetooth/cts/BTAdapterUtils.java
@@ -280,12 +280,7 @@
try {
adoptPermissionAsShellUid(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);
bluetoothAdapter.disable();
- if (waitForAdapterStateLocked(BluetoothAdapter.STATE_OFF, bluetoothAdapter)) {
- //TODO b/234892968
- Thread.sleep(2000);
- return true;
- }
- return false;
+ return waitForAdapterStateLocked(BluetoothAdapter.STATE_OFF, bluetoothAdapter);
} catch (InterruptedException e) {
Log.w(TAG, "disableAdapter(): interrupted", e);
} finally {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertiseSettingsTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertiseSettingsTest.java
index 4f472c7..f351498 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertiseSettingsTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertiseSettingsTest.java
@@ -49,6 +49,7 @@
AdvertiseSettings settings = new AdvertiseSettings.Builder()
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
.setConnectable(false)
+ .setDiscoverable(false)
.setTimeout(timeoutMillis)
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM)
.setOwnAddressType(AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT)
@@ -61,6 +62,7 @@
settingsFromParcel.getTxPowerLevel());
assertEquals(timeoutMillis, settingsFromParcel.getTimeout());
assertFalse(settings.isConnectable());
+ assertFalse(settings.isDiscoverable());
assertEquals(AdvertisingSetParameters.ADDRESS_TYPE_DEFAULT, settings.getOwnAddressType());
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertisingSetParametersTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertisingSetParametersTest.java
index a6ec271..6484f53 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertisingSetParametersTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/AdvertisingSetParametersTest.java
@@ -65,6 +65,7 @@
AdvertisingSetParameters params = new AdvertisingSetParameters.Builder().build();
assertFalse(params.isConnectable());
+ assertTrue(params.isDiscoverable());
assertFalse(params.isScannable());
assertFalse(params.isLegacy());
assertFalse(params.isAnonymous());
@@ -84,6 +85,15 @@
}
@Test
+ public void testIsDiscoverable() {
+ AdvertisingSetParameters params = new AdvertisingSetParameters.Builder()
+ .setDiscoverable(false)
+ .build();
+ assertFalse(params.isDiscoverable());
+ }
+
+
+ @Test
public void testIsScannable() {
AdvertisingSetParameters params = new AdvertisingSetParameters.Builder()
.setScannable(true)
@@ -237,6 +247,7 @@
}
assertEquals(p.isConnectable(), other.isConnectable());
+ assertEquals(p.isDiscoverable(), other.isDiscoverable());
assertEquals(p.isScannable(), other.isScannable());
assertEquals(p.isLegacy(), other.isLegacy());
assertEquals(p.isAnonymous(), other.isAnonymous());
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java
index f9531fb..22d3447 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicBluetoothGattTest.java
@@ -16,6 +16,8 @@
package android.bluetooth.cts;
+import static org.junit.Assert.assertThrows;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
@@ -23,6 +25,7 @@
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.test.AndroidTestCase;
+import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -33,6 +36,7 @@
* Other tests that run with real bluetooth connections are located in CtsVerifier.
*/
public class BasicBluetoothGattTest extends AndroidTestCase {
+ private static final String TAG = BasicBluetoothGattTest.class.getSimpleName();
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mBluetoothDevice;
@@ -53,6 +57,17 @@
mBluetoothDevice = mBluetoothAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
mBluetoothGatt = mBluetoothDevice.connectGatt(
mContext, /*autoConnect=*/ true, new BluetoothGattCallback() {});
+ if (mBluetoothGatt == null) {
+ try {
+ Thread.sleep(500); // Bt is not binded yet. Wait and retry
+ } catch (InterruptedException e) {
+ Log.e(TAG, "delay connectGatt interrupted");
+ }
+ mBluetoothGatt = mBluetoothDevice.connectGatt(
+ mContext, /*autoConnect=*/ true, new BluetoothGattCallback() {});
+ }
+ assertNotNull(mBluetoothGatt);
+
}
@Override
@@ -61,8 +76,9 @@
// mBluetoothAdapter == null.
return;
}
- mBluetoothGatt.disconnect();
- assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
+ if (mBluetoothGatt != null) {
+ mBluetoothGatt.disconnect();
+ }
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
}
@@ -83,11 +99,7 @@
return;
}
- try {
- mBluetoothGatt.connect();
- } catch (Exception e) {
- fail("Exception caught from connect(): " + e.toString());
- }
+ mBluetoothGatt.connect();
}
public void testSetPreferredPhy() throws Exception {
@@ -95,47 +107,34 @@
return;
}
- try {
- mBluetoothGatt.setPreferredPhy(BluetoothDevice.PHY_LE_1M, BluetoothDevice.PHY_LE_1M,
- BluetoothDevice.PHY_OPTION_NO_PREFERRED);
- } catch (Exception e) {
- fail("Exception caught from setPreferredPhy(): " + e.toString());
- }
+ mBluetoothGatt.setPreferredPhy(BluetoothDevice.PHY_LE_1M, BluetoothDevice.PHY_LE_1M,
+ BluetoothDevice.PHY_OPTION_NO_PREFERRED);
}
public void testGetConnectedDevices() {
if (!TestUtils.isBleSupported(getContext())) {
return;
}
- try {
- mBluetoothGatt.getConnectedDevices();
- fail("Should throw UnsupportedOperationException!");
- } catch (UnsupportedOperationException ex) {
- // Expected
- }
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mBluetoothGatt.getConnectedDevices());
}
public void testGetConnectionState() {
if (!TestUtils.isBleSupported(getContext())) {
return;
}
- try {
- mBluetoothGatt.getConnectionState(null);
- fail("Should throw UnsupportedOperationException!");
- } catch (UnsupportedOperationException ex) {
- // Expected
- }
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mBluetoothGatt.getConnectionState(null));
}
public void testGetDevicesMatchingConnectionStates() {
if (!TestUtils.isBleSupported(getContext())) {
return;
}
- try {
- mBluetoothGatt.getDevicesMatchingConnectionStates(null);
- fail("Should throw UnsupportedOperationException!");
- } catch (UnsupportedOperationException ex) {
- // Expected
- }
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mBluetoothGatt.getDevicesMatchingConnectionStates(null));
}
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java
index 7a20e9b..27708a6 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpSinkTest.java
@@ -88,10 +88,6 @@
mBluetoothA2dpSink = null;
mIsProfileReady = false;
}
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mUiAutomation.dropShellPermissionIdentity();
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
index 515f0ef..21a5cad 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothA2dpTest.java
@@ -89,9 +89,6 @@
mBluetoothA2dp = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
mUiAutomation.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
index 0017efb..592bee7 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothAdapterTest.java
@@ -36,6 +36,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.os.Bundle;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -89,8 +90,6 @@
@Override
public void tearDown() throws Exception {
if (mHasBluetooth) {
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mUiAutomation.dropShellPermissionIdentity();
}
}
@@ -626,6 +625,109 @@
}
+ public void test_setPreferredAudioProfiles_getPreferredAudioProfiles() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+
+ Bundle preferences = new Bundle();
+ preferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, BluetoothProfile.HEADSET);
+
+ // Test invalid input
+ assertThrows(NullPointerException.class, () ->
+ mAdapter.setPreferredAudioProfiles(device, null));
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.setPreferredAudioProfiles(device, preferences));
+ assertThrows(NullPointerException.class, () -> mAdapter.getPreferredAudioProfiles(null));
+
+ preferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, BluetoothProfile.HID_HOST);
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.setPreferredAudioProfiles(device, preferences));
+
+ preferences.putInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY, BluetoothProfile.LE_AUDIO);
+ preferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, BluetoothProfile.A2DP);
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.setPreferredAudioProfiles(device, preferences));
+
+ preferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, BluetoothProfile.GATT);
+ assertThrows(IllegalArgumentException.class,
+ () -> mAdapter.setPreferredAudioProfiles(device, preferences));
+
+ preferences.putInt(BluetoothAdapter.AUDIO_MODE_DUPLEX, BluetoothProfile.HEADSET);
+
+ assertThrows(NullPointerException.class, () ->
+ mAdapter.setPreferredAudioProfiles(null, preferences));
+
+ // Check what happens when the device is not bonded
+ assertTrue(mAdapter.getPreferredAudioProfiles(device).isEmpty());
+ assertEquals(BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED,
+ mAdapter.setPreferredAudioProfiles(device, preferences));
+ }
+
+ public void test_preferredAudioProfileCallbacks() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+
+ Executor executor = mContext.getMainExecutor();
+ BluetoothAdapter.PreferredAudioProfilesChangedCallback callback =
+ new BluetoothAdapter.PreferredAudioProfilesChangedCallback() {
+ @Override
+ public void onPreferredAudioProfilesChanged(
+ @androidx.annotation.NonNull BluetoothDevice device,
+ @androidx.annotation.NonNull Bundle preferredAudioProfiles, int status) {}
+ };
+
+ callback.onPreferredAudioProfilesChanged(device, Bundle.EMPTY,
+ BluetoothStatusCodes.SUCCESS);
+
+ assertThrows(NullPointerException.class, () ->
+ mAdapter.registerPreferredAudioProfilesChangedCallback(null, callback));
+ assertThrows(NullPointerException.class, () ->
+ mAdapter.registerPreferredAudioProfilesChangedCallback(executor, null));
+ assertThrows(NullPointerException.class, () ->
+ mAdapter.unregisterPreferredAudiProfilesChangedCallback(null));
+
+ // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
+ assertThrows(SecurityException.class, () ->
+ mAdapter.registerPreferredAudioProfilesChangedCallback(executor, callback));
+ assertThrows(IllegalArgumentException.class, () ->
+ mAdapter.unregisterPreferredAudiProfilesChangedCallback(callback));
+
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);
+
+ // Try the happy path
+ assertEquals(BluetoothStatusCodes.SUCCESS,
+ mAdapter.registerPreferredAudioProfilesChangedCallback(executor, callback));
+ assertEquals(BluetoothStatusCodes.SUCCESS,
+ mAdapter.unregisterPreferredAudiProfilesChangedCallback(callback));
+ }
+
+ public void test_notifyPreferredAudioProfileChangeApplied() {
+ if (!mHasBluetooth) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+ String deviceAddress = "00:11:22:AA:BB:CC";
+ BluetoothDevice device = mAdapter.getRemoteDevice(deviceAddress);
+
+ assertThrows(NullPointerException.class, () ->
+ mAdapter.notifyPreferredAudioProfileChangeApplied(null));
+
+
+ assertEquals(BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED,
+ mAdapter.notifyPreferredAudioProfileChangeApplied(device));
+ }
+
private static void sleep(long t) {
try {
Thread.sleep(t);
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothConfigTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothConfigTest.java
index f6336bf..4c641ac 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothConfigTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothConfigTest.java
@@ -60,7 +60,6 @@
super.tearDown();
if (!mHasBluetooth) return;
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
mUiAutomation.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java
index 9a43e6f..24f8c12 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothCsipSetCoordinatorTest.java
@@ -135,10 +135,7 @@
mTestCallback = null;
mTestExecutor = null;
}
- if (mAdapter != null ) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- mAdapter = null;
- }
+ mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
index 046acfc..ca5b4f3 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothDeviceTest.java
@@ -34,12 +34,10 @@
import android.bluetooth.BluetoothAudioPolicy;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
-import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.OobData;
import android.content.AttributionSource;
import android.content.pm.PackageManager;
-import android.os.Bundle;
import android.test.AndroidTestCase;
import androidx.test.InstrumentationRegistry;
@@ -79,7 +77,6 @@
public void tearDown() throws Exception {
super.tearDown();
if (mHasBluetooth && mHasCompanionDevice) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
mUiAutomation.dropShellPermissionIdentity();
}
@@ -145,8 +142,24 @@
}
// This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
- assertThrows("No BLUETOOTH_PRIVILEGED permission",
- SecurityException.class, () -> mFakeDevice.getIdentityAddress());
+ assertThrows("No BLUETOOTH_PRIVILEGED permission", SecurityException.class,
+ () -> mFakeDevice.getIdentityAddress());
+ }
+
+ public void test_getConnectionHandle() {
+ if (!mHasBluetooth || !mHasCompanionDevice) {
+ // Skip the test if bluetooth or companion device are not present.
+ return;
+ }
+
+ // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
+ assertThrows("No BLUETOOTH_PRIVILEGED permission", SecurityException.class,
+ () -> mFakeDevice.getConnectionHandle(TRANSPORT_LE));
+
+ // but it should work after we get the permission
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);
+ var handle = mFakeDevice.getConnectionHandle(TRANSPORT_LE);
+ assertEquals(handle, BluetoothDevice.ERROR);
}
public void test_getAnonymizedAddress() {
@@ -511,39 +524,4 @@
}
return pinBytes;
}
-
- public void test_setPreferredAudioProfiles_getPreferredAudioProfiles() {
- 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);
-
- Bundle preferences = new Bundle();
- preferences.putInt(BluetoothDevice.AUDIO_MODE_OUTPUT_ONLY, BluetoothProfile.HEADSET);
-
- // Test invalid input
- assertThrows(NullPointerException.class, () -> device.setPreferredAudioProfiles(null));
- assertThrows(IllegalArgumentException.class,
- () -> device.setPreferredAudioProfiles(preferences));
-
- preferences.putInt(BluetoothDevice.AUDIO_MODE_OUTPUT_ONLY, BluetoothProfile.LE_AUDIO);
- preferences.putInt(BluetoothDevice.AUDIO_MODE_DUPLEX, BluetoothProfile.A2DP);
- assertThrows(IllegalArgumentException.class,
- () -> device.setPreferredAudioProfiles(preferences));
-
- preferences.putInt(BluetoothDevice.AUDIO_MODE_DUPLEX, BluetoothProfile.HEADSET);
-
- // This should throw a SecurityException because no BLUETOOTH_PRIVILEGED permission
- assertThrows(SecurityException.class, () -> device.setPreferredAudioProfiles(preferences));
- assertThrows(SecurityException.class, () -> device.getPreferredAudioProfiles());
-
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED);
-
- // Verify that the default is an empty bundle for an unknown device
- assertTrue(device.getPreferredAudioProfiles().isEmpty());
- assertEquals(BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED,
- device.setPreferredAudioProfiles(preferences));
- }
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerCallbackTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerCallbackTest.java
index f247d5e..4ee4038 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerCallbackTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerCallbackTest.java
@@ -122,8 +122,6 @@
public void tearDown() throws Exception {
super.tearDown();
if (mHasBluetooth) {
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
mBluetoothDevice = null;
mBluetoothGattService = null;
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerTest.java
index 6c9959a..a859e73 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothGattServerTest.java
@@ -70,7 +70,6 @@
mBluetoothGattServer.close();
mBluetoothGattServer = null;
}
- assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
mBluetoothAdapter = null;
mUIAutomation.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
index f7479e5..9a486a7 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
@@ -127,10 +127,7 @@
mBluetoothHapClient = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- mAdapter = null;
- }
+ mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
index 80f4bbd..2f65320 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
@@ -77,9 +77,6 @@
if (!(mHasBluetooth && mIsHapSupported)) {
return;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java
index 69b5747..439e217 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetClientTest.java
@@ -90,9 +90,6 @@
mBluetoothHeadsetClient = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
index cb2c2b4..5315f33 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
@@ -89,9 +89,6 @@
mBluetoothHeadset = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
mUiAutomation.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java
index d94deab..f09ef85 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidDeviceTest.java
@@ -101,10 +101,6 @@
mBluetoothHidDevice = null;
mIsProfileReady = false;
}
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
mUiAutomation.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java
index 5c2e86e..f401ba7 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHidHostTest.java
@@ -90,9 +90,6 @@
mHidHost = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java
index e7f59b8..6cf572b 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAdvertiserTest.java
@@ -73,7 +73,6 @@
mAdvertiser.stopAdvertisingSet(mCallback);
assertTrue(mCallback.mAdvertisingSetStoppedLatch.await(TIMEOUT_MS,
TimeUnit.MILLISECONDS));
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdvertiser = null;
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
index b40b52d..21ad04f 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
@@ -93,9 +93,6 @@
@After
public void tearDown() {
if (mHasBluetooth) {
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
index ddb6bca..0e156cf 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
@@ -101,9 +101,6 @@
@After
public void tearDown() {
if (mHasBluetooth) {
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
index 9aba70c..f6e02de 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioTest.java
@@ -151,9 +151,6 @@
mBluetoothLeAudio = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
TestUtils.dropPermissionAsShellUid();
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
index 6138f38..bd49353 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
@@ -147,9 +147,6 @@
mBluetoothLeBroadcastAssistant = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
index e4d0577..424a64e 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
@@ -90,9 +90,6 @@
@After
public void tearDown() {
if (mHasBluetooth) {
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
index 7ff121a..5edeb38 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
@@ -114,9 +114,6 @@
@After
public void tearDown() {
if (mHasBluetooth) {
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
index 8f9b0f7..fad215d 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
@@ -105,9 +105,6 @@
@After
public void tearDown() {
if (mHasBluetooth) {
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
index 7279ef6..c87a95e 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
@@ -104,9 +104,6 @@
@After
public void tearDown() {
if (mHasBluetooth) {
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
index 64d3000..b69cfda 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
@@ -199,9 +199,6 @@
mBluetoothLeBroadcast = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
index 2278e86..f63e02e 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeScanTest.java
@@ -102,7 +102,6 @@
if (!mLocationOn) {
TestUtils.disableLocation(getContext());
}
- assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java
index 4a6cd06..c0a3037 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapClientTest.java
@@ -105,9 +105,6 @@
mBluetoothMapClient = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java
index 6a7fe34..bdc5d42 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothMapTest.java
@@ -93,9 +93,6 @@
mBluetoothMap = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java
index 733d9f3..11954a3 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPanTest.java
@@ -86,9 +86,6 @@
mBluetoothPan = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java
index 7b3df4e..1ce2b0b 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapClientTest.java
@@ -89,9 +89,6 @@
mBluetoothPbapClient = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
index 382a292..fadffd9 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothPbapTest.java
@@ -91,9 +91,6 @@
mBluetoothPbap = null;
mIsProfileReady = false;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
index ad5cfff..9dad13a 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothSapTest.java
@@ -88,10 +88,6 @@
mBluetoothSap = null;
mIsProfileReady = false;
}
- mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mUiAutomation.dropShellPermissionIdentity();
mAdapter = null;
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServerSocketTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServerSocketTest.java
index 134e4bd..ba3cc71 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServerSocketTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothServerSocketTest.java
@@ -60,7 +60,6 @@
if (mHasBluetooth && mBluetoothServerSocket != null) {
mBluetoothServerSocket.close();
}
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
mBluetoothServerSocket = null;
mUiAutomation.dropShellPermissionIdentity();
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java
index 26237c1..32eeb02 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothVolumeControlTest.java
@@ -117,10 +117,7 @@
mTestCallback = null;
mTestExecutor = null;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- mAdapter = null;
- }
+ mAdapter = null;
TestUtils.dropPermissionAsShellUid();
}
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
index 7818a04..945e6ee 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/HearingAidProfileTest.java
@@ -108,9 +108,6 @@
if (!(mIsBleSupported && mIsHearingAidSupported)) {
return;
}
- if (mBluetoothAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mBluetoothAdapter, mContext));
- }
mUiAutomation.dropShellPermissionIdentity();
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java
index 62d1c6a..7973808 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/LeL2capSocketTest.java
@@ -51,9 +51,6 @@
if (!TestUtils.isBleSupported(getContext())) {
return;
}
- if (mAdapter != null) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
mAdapter = null;
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java
index e9a9314..bfaf557 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/SystemBluetoothTest.java
@@ -82,9 +82,6 @@
@Override
public void tearDown() throws Exception {
super.tearDown();
- if (mHasBluetooth) {
- assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
- }
}
/**
diff --git a/tests/tests/contactsproviderwipe/Android.bp b/tests/tests/contactsproviderwipe/Android.bp
index 2a82727..62cf0c0 100644
--- a/tests/tests/contactsproviderwipe/Android.bp
+++ b/tests/tests/contactsproviderwipe/Android.bp
@@ -25,7 +25,6 @@
"mockito-target-minus-junit4",
"compatibility-device-util-axt",
"ctstestrunner-axt",
- "ub-uiautomator",
],
libs: [
"android.test.runner",
diff --git a/tests/tests/content/Android.bp b/tests/tests/content/Android.bp
index 7a691f9..d7d1424 100644
--- a/tests/tests/content/Android.bp
+++ b/tests/tests/content/Android.bp
@@ -26,6 +26,7 @@
// Include both the 32 and 64 bit versions
compile_multilib: "both",
jni_libs: [
+ "libcts_jni",
"libnativecursorwindow_jni",
"libnativehelper_compat_libc++",
],
diff --git a/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java b/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java
index b519f7b..086c607 100644
--- a/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/ChecksumsTest.java
@@ -71,6 +71,8 @@
import com.android.server.pm.PackageManagerShellCommandDataLoader;
import com.android.server.pm.PackageManagerShellCommandDataLoader.Metadata;
+import com.android.compatibility.common.util.CpuFeatures;
+
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
@@ -157,8 +159,6 @@
new Checksum(TYPE_WHOLE_SHA256, hexStringToBytes(TEST_FIXED_APK_SHA256)),
new Checksum(TYPE_WHOLE_MD5, hexStringToBytes(TEST_FIXED_APK_MD5))};
- private static final String PRIMARY_ABI = Build.SUPPORTED_ABIS[0];
-
/** Default is to not use fs-verity since it depends on kernel support. */
private static final int FSVERITY_DISABLED = 0;
@@ -338,19 +338,18 @@
assertNotNull(checksums);
assertEquals(checksums.length, 2);
assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
- if ("x86_64".equals(PRIMARY_ABI) || "x86".equals(PRIMARY_ABI)) {
- assertEquals(bytesToHexString(checksums[0].getValue()),
- TEST_FIXED_APK_FSVERITY_SHA256_X86_64);
- assertEquals(bytesToHexString(checksums[1].getValue()),
- "6f7cfa569c4a25d7241e26c1c8ff274badbdefd7854d91b842b1a97a985d5917");
- } else if ("arm64-v8a".equals(PRIMARY_ABI) || "armeabi".equals(PRIMARY_ABI)
- || "armeabi-v7a".equals(PRIMARY_ABI)) {
+ if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArmCpu()) {
assertEquals(bytesToHexString(checksums[0].getValue()),
TEST_FIXED_APK_FSVERITY_SHA256_ARM64);
assertEquals(bytesToHexString(checksums[1].getValue()),
"8c61bc2548521aa0005276af68e42253957e1e24c122f7d8bf10f1832d4014e5");
+ } else if (CpuFeatures.isX86_64Cpu() || CpuFeatures.isX86Cpu()) {
+ assertEquals(bytesToHexString(checksums[0].getValue()),
+ TEST_FIXED_APK_FSVERITY_SHA256_X86_64);
+ assertEquals(bytesToHexString(checksums[1].getValue()),
+ "6f7cfa569c4a25d7241e26c1c8ff274badbdefd7854d91b842b1a97a985d5917");
} else {
- Assert.fail("Unsupported ABI: " + PRIMARY_ABI);
+ Assert.fail("Unsupported CPU ABI");
}
assertEquals(checksums[1].getType(), TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256);
}
@@ -373,15 +372,14 @@
assertNotNull(checksums);
assertEquals(checksums.length, 1);
assertEquals(checksums[0].getType(), TYPE_WHOLE_MERKLE_ROOT_4K_SHA256);
- if ("x86_64".equals(PRIMARY_ABI) || "x86".equals(PRIMARY_ABI)) {
- assertEquals(bytesToHexString(checksums[0].getValue()),
- TEST_FIXED_APK_FSVERITY_SHA256_X86_64);
- } else if ("arm64-v8a".equals(PRIMARY_ABI) || "armeabi".equals(PRIMARY_ABI)
- || "armeabi-v7a".equals(PRIMARY_ABI)) {
+ if (CpuFeatures.isArm64Cpu() || CpuFeatures.isArmCpu()) {
assertEquals(bytesToHexString(checksums[0].getValue()),
TEST_FIXED_APK_FSVERITY_SHA256_ARM64);
+ } else if (CpuFeatures.isX86_64Cpu() || CpuFeatures.isX86Cpu()) {
+ assertEquals(bytesToHexString(checksums[0].getValue()),
+ TEST_FIXED_APK_FSVERITY_SHA256_X86_64);
} else {
- Assert.fail("Unsupported ABI: " + PRIMARY_ABI);
+ Assert.fail("Unsupported CPU ABI");
}
}
diff --git a/tests/tests/drm/TEST_MAPPING b/tests/tests/drm/TEST_MAPPING
index 437c95c..d2fb8f4 100644
--- a/tests/tests/drm/TEST_MAPPING
+++ b/tests/tests/drm/TEST_MAPPING
@@ -3,5 +3,16 @@
{
"name": "CtsDrmTestCases"
}
+ ],
+ "kernel-presubmit": [
+ {
+ "name": "CtsDrmTestCases",
+ "options": [
+ {
+ // TODO(b/244594813)
+ "exclude-filter": "android.drm.cts.DRMTest#testForwardLockAccess"
+ }
+ ]
+ }
]
}
diff --git a/tests/tests/gameservice/TEST_MAPPING b/tests/tests/gameservice/TEST_MAPPING
index 8d6b802..6a5661b 100644
--- a/tests/tests/gameservice/TEST_MAPPING
+++ b/tests/tests/gameservice/TEST_MAPPING
@@ -1,7 +1,12 @@
{
"presubmit": [
{
- "name": "CtsGameServiceTestCases"
+ "name": "CtsGameServiceTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
]
}
\ No newline at end of file
diff --git a/tests/tests/gameservice/src/android/service/games/GameServiceTest.java b/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
index aada0a0..d31f61c 100644
--- a/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
+++ b/tests/tests/gameservice/src/android/service/games/GameServiceTest.java
@@ -60,6 +60,7 @@
import android.view.WindowMetrics;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.PollingCheck;
@@ -88,6 +89,7 @@
/**
* CTS tests for {@link android.service.games.GameService}.
*/
+@FlakyTest(bugId = 263181277)
@RunWith(AndroidJUnit4.class)
public final class GameServiceTest {
static final String TAG = "GameServiceTest";
diff --git a/tests/tests/graphics/jni/android_graphics_cts_AImageDecoderTest.cpp b/tests/tests/graphics/jni/android_graphics_cts_AImageDecoderTest.cpp
index 829855a..bb0c651 100644
--- a/tests/tests/graphics/jni/android_graphics_cts_AImageDecoderTest.cpp
+++ b/tests/tests/graphics/jni/android_graphics_cts_AImageDecoderTest.cpp
@@ -45,6 +45,8 @@
AImageDecoder* decoderPtr = nullptr;
for (AImageDecoder** outDecoder : { &decoderPtr, (AImageDecoder**) nullptr }) {
for (AAsset* asset : { nullptr }) {
+ // Intentional negative test to pass nullptr.
+ // NOLINTNEXTLINE(clang-analyzer-nullability.NullPassedToNonnull)
int result = AImageDecoder_createFromAAsset(asset, outDecoder);
ASSERT_EQ(ANDROID_IMAGE_DECODER_BAD_PARAMETER, result);
if (outDecoder) {
@@ -53,6 +55,8 @@
}
for (int fd : { 0, -1 }) {
+ // Intentional negative test to pass nullptr.
+ // NOLINTNEXTLINE(clang-analyzer-nullability.NullPassedToNonnull)
int result = AImageDecoder_createFromFd(fd, outDecoder);
ASSERT_EQ(ANDROID_IMAGE_DECODER_BAD_PARAMETER, result);
if (outDecoder) {
@@ -61,6 +65,8 @@
}
auto testEmptyBuffer = [env, outDecoder](void* buffer, size_t length) {
+ // Intentional negative test to pass nullptr.
+ // NOLINTNEXTLINE(clang-analyzer-nullability.NullPassedToNonnull)
int result = AImageDecoder_createFromBuffer(buffer, length, outDecoder);
ASSERT_EQ(ANDROID_IMAGE_DECODER_BAD_PARAMETER, result);
if (outDecoder) {
diff --git a/tests/tests/hardware/Android.bp b/tests/tests/hardware/Android.bp
index ad603cc..9d337e4 100644
--- a/tests/tests/hardware/Android.bp
+++ b/tests/tests/hardware/Android.bp
@@ -65,7 +65,6 @@
"cts-wm-util",
"mockito-target-minus-junit4",
"platform-test-annotations",
- "ub-uiautomator",
"ctshardware-aidl-java",
],
jni_libs: [
diff --git a/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java b/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java
index a834b0d..2e13f30 100644
--- a/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java
+++ b/tests/tests/hardware/src/android/hardware/input/cts/tests/UsbVoiceCommandTest.java
@@ -31,7 +31,6 @@
import android.hardware.input.cts.InputAssistantActivity;
import android.server.wm.WindowManagerStateHelper;
import android.speech.RecognizerIntent;
-import android.support.test.uiautomator.UiDevice;
import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -50,8 +49,6 @@
public class UsbVoiceCommandTest extends InputHidTestCase {
private static final String TAG = "UsbVoiceCommandTest";
- private final UiDevice mUiDevice =
- UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
private final UiAutomation mUiAutomation =
InstrumentationRegistry.getInstrumentation().getUiAutomation();
private final PackageManager mPackageManager =
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c b/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c
index 597f03b..2e41c93 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c
+++ b/tests/tests/jni/libjnitest/android_jni_cts_InstanceNonce.c
@@ -31,56 +31,135 @@
// This space intentionally left blank.
}
+// public native void nopDlsym();
+JNIEXPORT void Java_android_jni_cts_InstanceNonce_nopDlsym(JNIEnv *env,
+ jobject this) {
+ // This space intentionally left blank.
+}
+
+// @FastNative
+// public native void nopFast();
+static void InstanceNonce_nopFast(JNIEnv *env, jobject this) {
+ // This space intentionally left blank.
+}
+
+// @FastNative
+// public native void nopFastDlsym();
+JNIEXPORT void Java_android_jni_cts_InstanceNonce_nopFastDlsym(JNIEnv *env,
+ jobject this) {
+ // This space intentionally left blank.
+}
+
// public native boolean returnBoolean();
static jboolean InstanceNonce_returnBoolean(JNIEnv *env, jobject this) {
return (jboolean) false;
}
+// @FastNative
+// public native boolean returnBooleanFast();
+static jboolean InstanceNonce_returnBooleanFast(JNIEnv *env, jobject this) {
+ return (jboolean) false;
+}
+
// public native byte returnByte();
static jbyte InstanceNonce_returnByte(JNIEnv *env, jobject this) {
return (jbyte) 123;
}
+// @FastNative
+// public native byte returnByteFast();
+static jbyte InstanceNonce_returnByteFast(JNIEnv *env, jobject this) {
+ return (jbyte) 123;
+}
+
// public native short returnShort();
static jshort InstanceNonce_returnShort(JNIEnv *env, jobject this) {
return (jshort) -12345;
}
+// @FastNative
+// public native short returnShortFast();
+static jshort InstanceNonce_returnShortFast(JNIEnv *env, jobject this) {
+ return (jshort) -12345;
+}
+
// public native char returnChar();
static jchar InstanceNonce_returnChar(JNIEnv *env, jobject this) {
return (jchar) 34567;
}
+// @FastNative
+// public native char returnCharFast();
+static jchar InstanceNonce_returnCharFast(JNIEnv *env, jobject this) {
+ return (jchar) 34567;
+}
+
// public native int returnInt();
static jint InstanceNonce_returnInt(JNIEnv *env, jobject this) {
return 12345678;
}
+// @FastNative
+// public native int returnIntFast();
+static jint InstanceNonce_returnIntFast(JNIEnv *env, jobject this) {
+ return 12345678;
+}
+
// public native long returnLong();
static jlong InstanceNonce_returnLong(JNIEnv *env, jobject this) {
return (jlong) -1098765432109876543LL;
}
+// @FastNative
+// public native long returnLongFast();
+static jlong InstanceNonce_returnLongFast(JNIEnv *env, jobject this) {
+ return (jlong) -1098765432109876543LL;
+}
+
// public native float returnFloat();
static jfloat InstanceNonce_returnFloat(JNIEnv *env, jobject this) {
return (jfloat) -98765.4321F;
}
+// @FastNative
+// public native float returnFloatFast();
+static jfloat InstanceNonce_returnFloatFast(JNIEnv *env, jobject this) {
+ return (jfloat) -98765.4321F;
+}
+
// public native double returnDouble();
static jdouble InstanceNonce_returnDouble(JNIEnv *env, jobject this) {
return 12345678.9;
}
+// @FastNative
+// public native double returnDoubleFast();
+static jdouble InstanceNonce_returnDoubleFast(JNIEnv *env, jobject this) {
+ return 12345678.9;
+}
+
// public native Object returnNull();
static jobject InstanceNonce_returnNull(JNIEnv *env, jobject this) {
return NULL;
}
+// @FastNative
+// public native Object returnNullFast();
+static jobject InstanceNonce_returnNullFast(JNIEnv *env, jobject this) {
+ return NULL;
+}
+
// public native String returnString();
static jstring InstanceNonce_returnString(JNIEnv *env, jobject this) {
return (*env)->NewStringUTF(env, "blort");
}
+// @FastNative
+// public native String returnStringFast();
+static jstring InstanceNonce_returnStringFast(JNIEnv *env, jobject this) {
+ return (*env)->NewStringUTF(env, "blort");
+}
+
// public native short[] returnShortArray();
static jshortArray InstanceNonce_returnShortArray(JNIEnv *env, jobject this) {
static jshort contents[] = { 10, 20, 30 };
@@ -95,6 +174,13 @@
return result;
}
+// @FastNative
+// public native short[] returnShortArrayFast();
+static jshortArray InstanceNonce_returnShortArrayFast(JNIEnv *env,
+ jobject this) {
+ return InstanceNonce_returnShortArray(env, this);
+}
+
// public String[] returnStringArray();
static jobjectArray InstanceNonce_returnStringArray(JNIEnv *env,
jobject this) {
@@ -136,58 +222,133 @@
return result;
}
+// @FastNative
+// public String[] returnStringArrayFast();
+static jobjectArray InstanceNonce_returnStringArrayFast(JNIEnv *env,
+ jobject this) {
+ return InstanceNonce_returnStringArray(env, this);
+}
+
// public native Class returnThisClass();
static jobject InstanceNonce_returnThis(JNIEnv *env, jobject this) {
return this;
}
+// @FastNative
+// public native Class returnThisClassFast();
+static jobject InstanceNonce_returnThisFast(JNIEnv *env, jobject this) {
+ return this;
+}
+
// public native boolean takeBoolean(boolean v);
static jboolean InstanceNonce_takeBoolean(JNIEnv *env, jobject this,
jboolean v) {
return v == false;
}
+// @FastNative
+// public native boolean takeBooleanFast(boolean v);
+static jboolean InstanceNonce_takeBooleanFast(JNIEnv *env, jobject this,
+ jboolean v) {
+ return v == false;
+}
+
// public native boolean takeByte(byte v);
static jboolean InstanceNonce_takeByte(JNIEnv *env, jobject this, jbyte v) {
return v == -99;
}
+// @FastNative
+// public native boolean takeByteFast(byte v);
+static jboolean InstanceNonce_takeByteFast(JNIEnv *env, jobject this,
+ jbyte v) {
+ return v == -99;
+}
+
// public native boolean takeShort(short v);
static jboolean InstanceNonce_takeShort(JNIEnv *env, jobject this, jshort v) {
return v == 19991;
}
+// @FastNative
+// public native boolean takeShortFast(short v);
+static jboolean InstanceNonce_takeShortFast(JNIEnv *env, jobject this,
+ jshort v) {
+ return v == 19991;
+}
+
// public native boolean takeChar(char v);
static jboolean InstanceNonce_takeChar(JNIEnv *env, jobject this, jchar v) {
return v == 999;
}
+// @FastNative
+// public native boolean takeCharFast(char v);
+static jboolean InstanceNonce_takeCharFast(JNIEnv *env, jobject this,
+ jchar v) {
+ return v == 999;
+}
+
// public native boolean takeInt(int v);
static jboolean InstanceNonce_takeInt(JNIEnv *env, jobject this, jint v) {
return v == -999888777;
}
+// @FastNative
+// public native boolean takeIntFast(int v);
+static jboolean InstanceNonce_takeIntFast(JNIEnv *env, jobject this, jint v) {
+ return v == -999888777;
+}
+
// public native boolean takeLong(long v);
static jboolean InstanceNonce_takeLong(JNIEnv *env, jobject this, jlong v) {
return v == 999888777666555444LL;
}
+// @FastNative
+// public native boolean takeLongFast(long v);
+static jboolean InstanceNonce_takeLongFast(JNIEnv *env, jobject this,
+ jlong v) {
+ return v == 999888777666555444LL;
+}
+
// public native boolean takeFloat(float v);
static jboolean InstanceNonce_takeFloat(JNIEnv *env, jobject this, jfloat v) {
return v == -9988.7766F;
}
+// @FastNative
+// public native boolean takeFloatFast(float v);
+static jboolean InstanceNonce_takeFloatFast(JNIEnv *env, jobject this,
+ jfloat v) {
+ return v == -9988.7766F;
+}
+
// public native boolean takeDouble(double v);
static jboolean InstanceNonce_takeDouble(JNIEnv *env, jobject this,
jdouble v) {
return v == 999888777.666555;
}
+// @FastNative
+// public native boolean takeDoubleFast(double v);
+static jboolean InstanceNonce_takeDoubleFast(JNIEnv *env, jobject this,
+ jdouble v) {
+ return v == 999888777.666555;
+}
+
// public native boolean takeNull(Object v);
static jboolean InstanceNonce_takeNull(JNIEnv *env, jobject this, jobject v) {
return v == NULL;
}
+// @FastNative
+// public native boolean takeNullFast(Object v);
+static jboolean InstanceNonce_takeNullFast(JNIEnv *env, jobject this,
+ jobject v) {
+ return v == NULL;
+}
+
// public native boolean takeString(String v);
static jboolean InstanceNonce_takeString(JNIEnv *env, jobject this,
jstring v) {
@@ -202,23 +363,51 @@
return result;
}
+// @FastNative
+// public native boolean takeStringFast(String v);
+static jboolean InstanceNonce_takeStringFast(JNIEnv *env, jobject this,
+ jstring v) {
+ return InstanceNonce_takeString(env, this, v);
+}
+
// public native boolean takeThis(InstanceNonce v);
static jboolean InstanceNonce_takeThis(JNIEnv *env, jobject this, jobject v) {
return (*env)->IsSameObject(env, this, v);
}
+// @FastNative
+// public native boolean takeThisFast(InstanceNonce v);
+static jboolean InstanceNonce_takeThisFast(JNIEnv *env, jobject this,
+ jobject v) {
+ return (*env)->IsSameObject(env, this, v);
+}
+
// public native boolean takeIntLong(int v1, long v2);
static jboolean InstanceNonce_takeIntLong(JNIEnv *env, jobject this,
jint v1, jlong v2) {
return (v1 == 914) && (v2 == 9140914091409140914LL);
}
+// @FastNative
+// public native boolean takeIntLongFast(int v1, long v2);
+static jboolean InstanceNonce_takeIntLongFast(JNIEnv *env, jobject this,
+ jint v1, jlong v2) {
+ return (v1 == 914) && (v2 == 9140914091409140914LL);
+}
+
// public native boolean takeLongInt(long v1, int v2);
static jboolean InstanceNonce_takeLongInt(JNIEnv *env, jobject this,
jlong v1, jint v2) {
return (v1 == -4321LL) && (v2 == 12341234);
}
+// @FastNative
+// public native boolean takeLongIntFast(long v1, int v2);
+static jboolean InstanceNonce_takeLongIntFast(JNIEnv *env, jobject this,
+ jlong v1, jint v2) {
+ return (v1 == -4321LL) && (v2 == 12341234);
+}
+
// public native boolean takeOneOfEach(boolean v0, byte v1, short v2,
// char v3, int v4, long v5, String v6, float v7, double v8,
// int[] v9);
@@ -262,6 +451,38 @@
return result;
}
+// public native boolean takeOneOfEachDlsym(boolean v0, byte v1, short v2,
+// char v3, int v4, long v5, String v6, float v7, double v8,
+// int[] v9);
+JNIEXPORT jboolean Java_android_jni_cts_InstanceNonce_takeOneOfEachDlsym(
+ JNIEnv *env, jobject this, jboolean v0, jbyte v1, jshort v2, jchar v3,
+ jint v4, jlong v5, jstring v6, jfloat v7, jdouble v8, jintArray v9) {
+ return InstanceNonce_takeOneOfEach(
+ env, this, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
+}
+
+// @FastNative
+// public native boolean takeOneOfEachFast(boolean v0, byte v1, short v2,
+// char v3, int v4, long v5, String v6, float v7, double v8,
+// int[] v9);
+static jboolean InstanceNonce_takeOneOfEachFast(JNIEnv *env, jobject this,
+ jboolean v0, jbyte v1, jshort v2, jchar v3, jint v4, jlong v5,
+ jstring v6, jfloat v7, jdouble v8, jintArray v9) {
+ return InstanceNonce_takeOneOfEach(
+ env, this, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
+}
+
+// @FastNative
+// public native boolean takeOneOfEachFastDlsym(boolean v0, byte v1, short v2,
+// char v3, int v4, long v5, String v6, float v7, double v8,
+// int[] v9);
+JNIEXPORT jboolean Java_android_jni_cts_InstanceNonce_takeOneOfEachFastDlsym(
+ JNIEnv *env, jobject this, jboolean v0, jbyte v1, jshort v2, jchar v3,
+ jint v4, jlong v5, jstring v6, jfloat v7, jdouble v8, jintArray v9) {
+ return InstanceNonce_takeOneOfEach(
+ env, this, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
+}
+
// public native boolean takeCoolHandLuke(
// int v1, int v2, int v3, int v4,
// int v5, int v6, int v7, int v8, int v9,
@@ -304,44 +525,116 @@
(v50 == 50);
}
+// @FastNative
+// public native boolean takeCoolHandLukeFast(
+// int v1, int v2, int v3, int v4,
+// int v5, int v6, int v7, int v8, int v9,
+// int v10, int v11, int v12, int v13, int v14,
+// int v15, int v16, int v17, int v18, int v19,
+// int v20, int v21, int v22, int v23, int v24,
+// int v25, int v26, int v27, int v28, int v29,
+// int v30, int v31, int v32, int v33, int v34,
+// int v35, int v36, int v37, int v38, int v39,
+// int v40, int v41, int v42, int v43, int v44,
+// int v45, int v46, int v47, int v48, int v49,
+// int v50);
+static jboolean InstanceNonce_takeCoolHandLukeFast(JNIEnv *env, jobject this,
+ jint v1, jint v2, jint v3, jint v4,
+ jint v5, jint v6, jint v7, jint v8, jint v9,
+ jint v10, jint v11, jint v12, jint v13, jint v14,
+ jint v15, jint v16, jint v17, jint v18, jint v19,
+ jint v20, jint v21, jint v22, jint v23, jint v24,
+ jint v25, jint v26, jint v27, jint v28, jint v29,
+ jint v30, jint v31, jint v32, jint v33, jint v34,
+ jint v35, jint v36, jint v37, jint v38, jint v39,
+ jint v40, jint v41, jint v42, jint v43, jint v44,
+ jint v45, jint v46, jint v47, jint v48, jint v49,
+ jint v50) {
+ return InstanceNonce_takeCoolHandLuke(
+ env, this, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20,
+ v21, v22, v23, v24, v25, v26, v27, v28, v29, v30,
+ v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+ v41, v42, v43, v44, v45, v46, v47, v48, v49, v50);
+}
+
static JNINativeMethod methods[] = {
// name, signature, function
{ "nop", "()V", InstanceNonce_nop },
+ { "nopFast", "()V", InstanceNonce_nopFast },
{ "returnBoolean", "()Z", InstanceNonce_returnBoolean },
+ { "returnBooleanFast", "()Z", InstanceNonce_returnBooleanFast },
{ "returnByte", "()B", InstanceNonce_returnByte },
+ { "returnByteFast", "()B", InstanceNonce_returnByteFast },
{ "returnShort", "()S", InstanceNonce_returnShort },
+ { "returnShortFast", "()S", InstanceNonce_returnShortFast },
{ "returnChar", "()C", InstanceNonce_returnChar },
+ { "returnCharFast", "()C", InstanceNonce_returnCharFast },
{ "returnInt", "()I", InstanceNonce_returnInt },
+ { "returnIntFast", "()I", InstanceNonce_returnIntFast },
{ "returnLong", "()J", InstanceNonce_returnLong },
+ { "returnLongFast", "()J", InstanceNonce_returnLongFast },
{ "returnFloat", "()F", InstanceNonce_returnFloat },
+ { "returnFloatFast", "()F", InstanceNonce_returnFloatFast },
{ "returnDouble", "()D", InstanceNonce_returnDouble },
+ { "returnDoubleFast", "()D", InstanceNonce_returnDoubleFast },
{ "returnNull", "()Ljava/lang/Object;", InstanceNonce_returnNull },
+ { "returnNullFast", "()Ljava/lang/Object;",
+ InstanceNonce_returnNullFast },
{ "returnString", "()Ljava/lang/String;",
InstanceNonce_returnString },
+ { "returnStringFast", "()Ljava/lang/String;",
+ InstanceNonce_returnStringFast },
{ "returnShortArray", "()[S", InstanceNonce_returnShortArray },
+ { "returnShortArrayFast", "()[S", InstanceNonce_returnShortArrayFast },
{ "returnStringArray", "()[Ljava/lang/String;",
InstanceNonce_returnStringArray },
+ { "returnStringArrayFast", "()[Ljava/lang/String;",
+ InstanceNonce_returnStringArrayFast },
{ "returnThis", "()Landroid/jni/cts/InstanceNonce;",
InstanceNonce_returnThis },
+ { "returnThisFast", "()Landroid/jni/cts/InstanceNonce;",
+ InstanceNonce_returnThisFast },
{ "takeBoolean", "(Z)Z", InstanceNonce_takeBoolean },
+ { "takeBooleanFast", "(Z)Z", InstanceNonce_takeBooleanFast },
{ "takeByte", "(B)Z", InstanceNonce_takeByte },
+ { "takeByteFast", "(B)Z", InstanceNonce_takeByteFast },
{ "takeShort", "(S)Z", InstanceNonce_takeShort },
+ { "takeShortFast", "(S)Z", InstanceNonce_takeShortFast },
{ "takeChar", "(C)Z", InstanceNonce_takeChar },
+ { "takeCharFast", "(C)Z", InstanceNonce_takeCharFast },
{ "takeInt", "(I)Z", InstanceNonce_takeInt },
+ { "takeIntFast", "(I)Z", InstanceNonce_takeIntFast },
{ "takeLong", "(J)Z", InstanceNonce_takeLong },
+ { "takeLongFast", "(J)Z", InstanceNonce_takeLongFast },
{ "takeFloat", "(F)Z", InstanceNonce_takeFloat },
+ { "takeFloatFast", "(F)Z", InstanceNonce_takeFloatFast },
{ "takeDouble", "(D)Z", InstanceNonce_takeDouble },
+ { "takeDoubleFast", "(D)Z", InstanceNonce_takeDoubleFast },
{ "takeNull", "(Ljava/lang/Object;)Z", InstanceNonce_takeNull },
+ { "takeNullFast", "(Ljava/lang/Object;)Z",
+ InstanceNonce_takeNullFast },
{ "takeString", "(Ljava/lang/String;)Z", InstanceNonce_takeString },
+ { "takeStringFast", "(Ljava/lang/String;)Z",
+ InstanceNonce_takeStringFast },
{ "takeThis", "(Landroid/jni/cts/InstanceNonce;)Z",
InstanceNonce_takeThis },
+ { "takeThisFast", "(Landroid/jni/cts/InstanceNonce;)Z",
+ InstanceNonce_takeThisFast },
{ "takeIntLong", "(IJ)Z", InstanceNonce_takeIntLong },
+ { "takeIntLongFast", "(IJ)Z", InstanceNonce_takeIntLongFast },
{ "takeLongInt", "(JI)Z", InstanceNonce_takeLongInt },
+ { "takeLongIntFast", "(JI)Z", InstanceNonce_takeLongIntFast },
{ "takeOneOfEach", "(ZBSCIJLjava/lang/String;FD[I)Z",
InstanceNonce_takeOneOfEach },
+ { "takeOneOfEachFast", "(ZBSCIJLjava/lang/String;FD[I)Z",
+ InstanceNonce_takeOneOfEachFast },
{ "takeCoolHandLuke",
"(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z",
InstanceNonce_takeCoolHandLuke },
+ { "takeCoolHandLukeFast",
+ "(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z",
+ InstanceNonce_takeCoolHandLukeFast },
};
int register_InstanceNonce(JNIEnv *env) {
diff --git a/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c b/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c
index 7fb7f11..f3ed593 100644
--- a/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c
+++ b/tests/tests/jni/libjnitest/android_jni_cts_StaticNonce.c
@@ -31,56 +31,195 @@
// This space intentionally left blank.
}
+// public static native void nopDlsym();
+JNIEXPORT void Java_android_jni_cts_StaticNonce_nopDlsym(JNIEnv *env,
+ jclass clazz) {
+ // This space intentionally left blank.
+}
+
+// @FastNative
+// public static native void nopFast();
+static void StaticNonce_nopFast(JNIEnv *env, jclass clazz) {
+ // This space intentionally left blank.
+}
+
+// @FastNative
+// public static native void nopFastDlsym();
+JNIEXPORT void Java_android_jni_cts_StaticNonce_nopFastDlsym(JNIEnv *env,
+ jclass clazz) {
+ // This space intentionally left blank.
+}
+
+// @CriticalNative
+// public static native void nopCritical();
+static void StaticNonce_nopCritical() {
+ // This space intentionally left blank.
+}
+
+// @CriticalNative
+// public static native void nopCriticalDlsym();
+JNIEXPORT void Java_android_jni_cts_StaticNonce_nopCriticalDlsym() {
+ // This space intentionally left blank.
+}
+
// public static native boolean returnBoolean();
static jboolean StaticNonce_returnBoolean(JNIEnv *env, jclass clazz) {
return (jboolean) true;
}
+// @FastNative
+// public static native boolean returnBooleanFast();
+static jboolean StaticNonce_returnBooleanFast(JNIEnv *env, jclass clazz) {
+ return (jboolean) true;
+}
+
+// @CriticalNative
+// public static native boolean returnBooleanCritical();
+static jboolean StaticNonce_returnBooleanCritical() {
+ return (jboolean) true;
+}
+
// public static native byte returnByte();
static jbyte StaticNonce_returnByte(JNIEnv *env, jclass clazz) {
return (jbyte) 123;
}
+// @FastNative
+// public static native byte returnByteFast();
+static jbyte StaticNonce_returnByteFast(JNIEnv *env, jclass clazz) {
+ return (jbyte) 123;
+}
+
+// @CriticalNative
+// public static native byte returnByteCritical();
+static jbyte StaticNonce_returnByteCritical() {
+ return (jbyte) 123;
+}
+
// public static native short returnShort();
static jshort StaticNonce_returnShort(JNIEnv *env, jclass clazz) {
return (jshort) -12345;
}
+// @FastNative
+// public static native short returnShortFast();
+static jshort StaticNonce_returnShortFast(JNIEnv *env, jclass clazz) {
+ return (jshort) -12345;
+}
+
+// @CriticalNative
+// public static native short returnShortCritical();
+static jshort StaticNonce_returnShortCritical() {
+ return (jshort) -12345;
+}
+
// public static native char returnChar();
static jchar StaticNonce_returnChar(JNIEnv *env, jclass clazz) {
return (jchar) 34567;
}
+// @FastNative
+// public static native char returnCharFast();
+static jchar StaticNonce_returnCharFast(JNIEnv *env, jclass clazz) {
+ return (jchar) 34567;
+}
+
+// @CriticalNative
+// public static native char returnCharCritical();
+static jchar StaticNonce_returnCharCritical() {
+ return (jchar) 34567;
+}
+
// public static native int returnInt();
static jint StaticNonce_returnInt(JNIEnv *env, jclass clazz) {
return 12345678;
}
+// @FastNative
+// public static native int returnIntFast();
+static jint StaticNonce_returnIntFast(JNIEnv *env, jclass clazz) {
+ return 12345678;
+}
+
+// @CriticalNative
+// public static native int returnIntCritical();
+static jint StaticNonce_returnIntCritical() {
+ return 12345678;
+}
+
// public static native long returnLong();
static jlong StaticNonce_returnLong(JNIEnv *env, jclass clazz) {
return (jlong) -1098765432109876543LL;
}
+// @FastNative
+// public static native long returnLongFast();
+static jlong StaticNonce_returnLongFast(JNIEnv *env, jclass clazz) {
+ return (jlong) -1098765432109876543LL;
+}
+
+// @CriticalNative
+// public static native long returnLongCritical();
+static jlong StaticNonce_returnLongCritical() {
+ return (jlong) -1098765432109876543LL;
+}
+
// public static native float returnFloat();
static jfloat StaticNonce_returnFloat(JNIEnv *env, jclass clazz) {
return (jfloat) -98765.4321F;
}
+// @FastNative
+// public static native float returnFloatFast();
+static jfloat StaticNonce_returnFloatFast(JNIEnv *env, jclass clazz) {
+ return (jfloat) -98765.4321F;
+}
+
+// @CriticalNative
+// public static native float returnFloatCritical();
+static jfloat StaticNonce_returnFloatCritical() {
+ return (jfloat) -98765.4321F;
+}
+
// public static native double returnDouble();
static jdouble StaticNonce_returnDouble(JNIEnv *env, jclass clazz) {
return 12345678.9;
}
+// @FastNative
+// public static native double returnDoubleFast();
+static jdouble StaticNonce_returnDoubleFast(JNIEnv *env, jclass clazz) {
+ return 12345678.9;
+}
+
+// @CriticalNative
+// public static native double returnDoubleCritical();
+static jdouble StaticNonce_returnDoubleCritical() {
+ return 12345678.9;
+}
+
// public static native Object returnNull();
static jobject StaticNonce_returnNull(JNIEnv *env, jclass clazz) {
return NULL;
}
+// @FastNative
+// public static native Object returnNullFast();
+static jobject StaticNonce_returnNullFast(JNIEnv *env, jclass clazz) {
+ return NULL;
+}
+
// public static native String returnString();
static jstring StaticNonce_returnString(JNIEnv *env, jclass clazz) {
return (*env)->NewStringUTF(env, "blort");
}
+// @FastNative
+// public static native String returnStringFast();
+static jstring StaticNonce_returnStringFast(JNIEnv *env, jclass clazz) {
+ return (*env)->NewStringUTF(env, "blort");
+}
+
// public static native short[] returnShortArray();
static jshortArray StaticNonce_returnShortArray(JNIEnv *env, jclass clazz) {
static jshort contents[] = { 10, 20, 30 };
@@ -95,6 +234,13 @@
return result;
}
+// @FastNative
+// public static native short[] returnShortArrayFast();
+static jshortArray StaticNonce_returnShortArrayFast(JNIEnv *env,
+ jclass clazz) {
+ return StaticNonce_returnShortArray(env, clazz);
+}
+
// public static native String[] returnStringArray();
static jobjectArray StaticNonce_returnStringArray(JNIEnv *env, jclass clazz) {
static int indices[] = { 0, 50, 99 };
@@ -136,11 +282,24 @@
return result;
}
+// @FastNative
+// public static native String[] returnStringArrayFast();
+static jobjectArray StaticNonce_returnStringArrayFast(JNIEnv *env,
+ jclass clazz) {
+ return StaticNonce_returnStringArray(env, clazz);
+}
+
// public static native Class returnThisClass();
static jclass StaticNonce_returnThisClass(JNIEnv *env, jclass clazz) {
return clazz;
}
+// @FastNative
+// public static native Class returnThisClassFast();
+static jclass StaticNonce_returnThisClassFast(JNIEnv *env, jclass clazz) {
+ return clazz;
+}
+
// public static native StaticNonce returnInstance();
static jobject StaticNonce_returnInstance(JNIEnv *env, jclass clazz) {
jmethodID id = (*env)->GetMethodID(env, clazz, "<init>", "()V");
@@ -158,52 +317,165 @@
return (*env)->NewObjectA(env, clazz, id, NULL);
}
+// @FastNative
+// public static native StaticNonce returnInstanceFast();
+static jobject StaticNonce_returnInstanceFast(JNIEnv *env, jclass clazz) {
+ return StaticNonce_returnInstance(env, clazz);
+}
+
// public static native boolean takeBoolean(boolean v);
static jboolean StaticNonce_takeBoolean(JNIEnv *env, jclass clazz,
jboolean v) {
return v == true;
}
+// @FastNative
+// public static native boolean takeBooleanFast(boolean v);
+static jboolean StaticNonce_takeBooleanFast(JNIEnv *env, jclass clazz,
+ jboolean v) {
+ return v == true;
+}
+
+// @CriticalNative
+// public static native boolean takeBooleanCritical(boolean v);
+static jboolean StaticNonce_takeBooleanCritical(jboolean v) {
+ return v == true;
+}
+
// public static native boolean takeByte(byte v);
static jboolean StaticNonce_takeByte(JNIEnv *env, jclass clazz, jbyte v) {
return v == -99;
}
+// @FastNative
+// public static native boolean takeByteFast(byte v);
+static jboolean StaticNonce_takeByteFast(JNIEnv *env, jclass clazz, jbyte v) {
+ return v == -99;
+}
+
+// @CriticalNative
+// public static native boolean takeByteCritical(byte v);
+static jboolean StaticNonce_takeByteCritical(jbyte v) {
+ return v == -99;
+}
+
// public static native boolean takeShort(short v);
static jboolean StaticNonce_takeShort(JNIEnv *env, jclass clazz, jshort v) {
return v == 19991;
}
+// @FastNative
+// public static native boolean takeShortFast(short v);
+static jboolean StaticNonce_takeShortFast(JNIEnv *env, jclass clazz,
+ jshort v) {
+ return v == 19991;
+}
+
+// @CriticalNative
+// public static native boolean takeShortCritical(short v);
+static jboolean StaticNonce_takeShortCritical(jshort v) {
+ return v == 19991;
+}
+
// public static native boolean takeChar(char v);
static jboolean StaticNonce_takeChar(JNIEnv *env, jclass clazz, jchar v) {
return v == 999;
}
+// @FastNative
+// public static native boolean takeCharFast(char v);
+static jboolean StaticNonce_takeCharFast(JNIEnv *env, jclass clazz, jchar v) {
+ return v == 999;
+}
+
+// @CriticalNative
+// public static native boolean takeCharCritical(char v);
+static jboolean StaticNonce_takeCharCritical(jchar v) {
+ return v == 999;
+}
+
// public static native boolean takeInt(int v);
static jboolean StaticNonce_takeInt(JNIEnv *env, jclass clazz, jint v) {
return v == -999888777;
}
+// @FastNative
+// public static native boolean takeIntFast(int v);
+static jboolean StaticNonce_takeIntFast(JNIEnv *env, jclass clazz, jint v) {
+ return v == -999888777;
+}
+
+// @CriticalNative
+// public static native boolean takeIntCritical(int v);
+static jboolean StaticNonce_takeIntCritical(jint v) {
+ return v == -999888777;
+}
+
// public static native boolean takeLong(long v);
static jboolean StaticNonce_takeLong(JNIEnv *env, jclass clazz, jlong v) {
return v == 999888777666555444LL;
}
+// @FastNative
+// public static native boolean takeLongFast(long v);
+static jboolean StaticNonce_takeLongFast(JNIEnv *env, jclass clazz, jlong v) {
+ return v == 999888777666555444LL;
+}
+
+// @CriticalNative
+// public static native boolean takeLongCritical(long v);
+static jboolean StaticNonce_takeLongCritical(jlong v) {
+ return v == 999888777666555444LL;
+}
+
// public static native boolean takeFloat(float v);
static jboolean StaticNonce_takeFloat(JNIEnv *env, jclass clazz, jfloat v) {
return v == -9988.7766F;
}
+// @FastNative
+// public static native boolean takeFloatFast(float v);
+static jboolean StaticNonce_takeFloatFast(JNIEnv *env, jclass clazz,
+ jfloat v) {
+ return v == -9988.7766F;
+}
+
+// @CriticalNative
+// public static native boolean takeFloatCritical(float v);
+static jboolean StaticNonce_takeFloatCritical(jfloat v) {
+ return v == -9988.7766F;
+}
+
// public static native boolean takeDouble(double v);
static jboolean StaticNonce_takeDouble(JNIEnv *env, jclass clazz, jdouble v) {
return v == 999888777.666555;
}
+// @FastNative
+// public static native boolean takeDoubleFast(double v);
+static jboolean StaticNonce_takeDoubleFast(JNIEnv *env, jclass clazz,
+ jdouble v) {
+ return v == 999888777.666555;
+}
+
+// @CriticalNative
+// public static native boolean takeDoubleCritical(double v);
+static jboolean StaticNonce_takeDoubleCritical(jdouble v) {
+ return v == 999888777.666555;
+}
+
// public static native boolean takeNull(Object v);
static jboolean StaticNonce_takeNull(JNIEnv *env, jclass clazz, jobject v) {
return v == NULL;
}
+// @FastNative
+// public static native boolean takeNullFast(Object v);
+static jboolean StaticNonce_takeNullFast(JNIEnv *env, jclass clazz,
+ jobject v) {
+ return v == NULL;
+}
+
// public static native boolean takeString(String v);
static jboolean StaticNonce_takeString(JNIEnv *env, jclass clazz, jstring v) {
if (v == NULL) {
@@ -217,24 +489,64 @@
return result;
}
+// @FastNative
+// public static native boolean takeStringFast(String v);
+static jboolean StaticNonce_takeStringFast(JNIEnv *env, jclass clazz,
+ jstring v) {
+ return StaticNonce_takeString(env, clazz, v);
+}
+
// public static native boolean takeThisClass(Class v);
static jboolean StaticNonce_takeThisClass(JNIEnv *env, jclass clazz,
jclass v) {
return (*env)->IsSameObject(env, clazz, v);
}
+// @FastNative
+// public static native boolean takeThisClassFast(Class v);
+static jboolean StaticNonce_takeThisClassFast(JNIEnv *env, jclass clazz,
+ jclass v) {
+ return (*env)->IsSameObject(env, clazz, v);
+}
+
// public static native boolean takeIntLong(int v1, long v2);
static jboolean StaticNonce_takeIntLong(JNIEnv *env, jclass clazz,
jint v1, jlong v2) {
return (v1 == 914) && (v2 == 9140914091409140914LL);
}
+// @FastNative
+// public static native boolean takeIntLongFast(int v1, long v2);
+static jboolean StaticNonce_takeIntLongFast(JNIEnv *env, jclass clazz,
+ jint v1, jlong v2) {
+ return (v1 == 914) && (v2 == 9140914091409140914LL);
+}
+
+// @CriticalNative
+// public static native boolean takeIntLongCritical(int v1, long v2);
+static jboolean StaticNonce_takeIntLongCritical(jint v1, jlong v2) {
+ return (v1 == 914) && (v2 == 9140914091409140914LL);
+}
+
// public static native boolean takeLongInt(long v1, int v2);
static jboolean StaticNonce_takeLongInt(JNIEnv *env, jclass clazz,
jlong v1, jint v2) {
return (v1 == -4321LL) && (v2 == 12341234);
}
+// @FastNative
+// public static native boolean takeLongIntFast(long v1, int v2);
+static jboolean StaticNonce_takeLongIntFast(JNIEnv *env, jclass clazz,
+ jlong v1, jint v2) {
+ return (v1 == -4321LL) && (v2 == 12341234);
+}
+
+// @CriticalNative
+// public static native boolean takeLongIntCritical(long v1, int v2);
+static jboolean StaticNonce_takeLongIntCritical(jlong v1, jint v2) {
+ return (v1 == -4321LL) && (v2 == 12341234);
+}
+
// public static native boolean takeOneOfEach(boolean v0, byte v1, short v2,
// char v3, int v4, long v5, String v6, float v7, double v8,
// int[] v9);
@@ -280,6 +592,57 @@
return result;
}
+// public static native boolean takeOneOfEachDlsym(boolean v0, byte v1,
+// short v2, char v3, int v4, long v5, String v6, float v7, double v8,
+// int[] v9);
+JNIEXPORT jboolean Java_android_jni_cts_StaticNonce_takeOneOfEachDlsym(
+ JNIEnv *env, jclass clazz, jboolean v0, jbyte v1, jshort v2, jchar v3,
+ jint v4, jlong v5, jstring v6, jfloat v7, jdouble v8, jintArray v9) {
+ return StaticNonce_takeOneOfEach(
+ env, clazz, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
+}
+
+// @FastNative
+// public static native boolean takeOneOfEachFast(boolean v0, byte v1,
+// short v2, char v3, int v4, long v5, String v6, float v7, double v8,
+// int[] v9);
+static jboolean StaticNonce_takeOneOfEachFast(JNIEnv *env, jclass clazz,
+ jboolean v0, jbyte v1, jshort v2, jchar v3, jint v4, jlong v5,
+ jstring v6, jfloat v7, jdouble v8, jintArray v9) {
+ return StaticNonce_takeOneOfEach(
+ env, clazz, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
+}
+
+// @FastNative
+// public static native boolean takeOneOfEachFastDlsym(boolean v0, byte v1,
+// short v2, char v3, int v4, long v5, String v6, float v7, double v8,
+// int[] v9);
+JNIEXPORT jboolean Java_android_jni_cts_StaticNonce_takeOneOfEachFastDlsym(
+ JNIEnv *env, jclass clazz, jboolean v0, jbyte v1, jshort v2, jchar v3,
+ jint v4, jlong v5, jstring v6, jfloat v7, jdouble v8, jintArray v9) {
+ return StaticNonce_takeOneOfEach(
+ env, clazz, v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
+}
+
+// @CriticalNative
+// public static native boolean takeOneOfEachCritical(boolean v0, byte v1,
+// short v2, char v3, int v4, long v5, float v6, double v7);
+static jboolean StaticNonce_takeOneOfEachCritical(
+ jboolean v0, jbyte v1, jshort v2, jchar v3, jint v4, jlong v5,
+ jfloat v6, jdouble v7) {
+ return (v0 == false) && (v1 == 1) && (v2 == 2) && (v3 == 3) &&
+ (v4 == 4) && (v5 == 5) && (v6 == 6.0f) && (v7 == 7.0);
+}
+
+// @CriticalNative
+// public static native boolean takeOneOfEachCriticalDlsym(boolean v0, byte v1,
+// short v2, char v3, int v4, long v5, float v6, double v7);
+JNIEXPORT jboolean Java_android_jni_cts_StaticNonce_takeOneOfEachCriticalDlsym(
+ jboolean v0, jbyte v1, jshort v2, jchar v3, jint v4, jlong v5,
+ jfloat v6, jdouble v7) {
+ return StaticNonce_takeOneOfEachCritical(v0, v1, v2, v3, v4, v5, v6, v7);
+}
+
// public static native boolean takeCoolHandLuke(
// int v1, int v2, int v3, int v4,
// int v5, int v6, int v7, int v8, int v9,
@@ -322,44 +685,174 @@
(v50 == 50);
}
+// @FastNative
+// public static native boolean takeCoolHandLukeFast(
+// int v1, int v2, int v3, int v4,
+// int v5, int v6, int v7, int v8, int v9,
+// int v10, int v11, int v12, int v13, int v14,
+// int v15, int v16, int v17, int v18, int v19,
+// int v20, int v21, int v22, int v23, int v24,
+// int v25, int v26, int v27, int v28, int v29,
+// int v30, int v31, int v32, int v33, int v34,
+// int v35, int v36, int v37, int v38, int v39,
+// int v40, int v41, int v42, int v43, int v44,
+// int v45, int v46, int v47, int v48, int v49,
+// int v50);
+static jboolean StaticNonce_takeCoolHandLukeFast(JNIEnv *env, jclass clazz,
+ jint v1, jint v2, jint v3, jint v4,
+ jint v5, jint v6, jint v7, jint v8, jint v9,
+ jint v10, jint v11, jint v12, jint v13, jint v14,
+ jint v15, jint v16, jint v17, jint v18, jint v19,
+ jint v20, jint v21, jint v22, jint v23, jint v24,
+ jint v25, jint v26, jint v27, jint v28, jint v29,
+ jint v30, jint v31, jint v32, jint v33, jint v34,
+ jint v35, jint v36, jint v37, jint v38, jint v39,
+ jint v40, jint v41, jint v42, jint v43, jint v44,
+ jint v45, jint v46, jint v47, jint v48, jint v49,
+ jint v50) {
+ return StaticNonce_takeCoolHandLuke(
+ env, clazz, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20,
+ v21, v22, v23, v24, v25, v26, v27, v28, v29, v30,
+ v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+ v41, v42, v43, v44, v45, v46, v47, v48, v49, v50);
+}
+
+// @CriticalNative
+// public static native boolean takeCoolHandLukeCritical(
+// int v1, int v2, int v3, int v4,
+// int v5, int v6, int v7, int v8, int v9,
+// int v10, int v11, int v12, int v13, int v14,
+// int v15, int v16, int v17, int v18, int v19,
+// int v20, int v21, int v22, int v23, int v24,
+// int v25, int v26, int v27, int v28, int v29,
+// int v30, int v31, int v32, int v33, int v34,
+// int v35, int v36, int v37, int v38, int v39,
+// int v40, int v41, int v42, int v43, int v44,
+// int v45, int v46, int v47, int v48, int v49,
+// int v50);
+static jboolean StaticNonce_takeCoolHandLukeCritical(
+ jint v1, jint v2, jint v3, jint v4,
+ jint v5, jint v6, jint v7, jint v8, jint v9,
+ jint v10, jint v11, jint v12, jint v13, jint v14,
+ jint v15, jint v16, jint v17, jint v18, jint v19,
+ jint v20, jint v21, jint v22, jint v23, jint v24,
+ jint v25, jint v26, jint v27, jint v28, jint v29,
+ jint v30, jint v31, jint v32, jint v33, jint v34,
+ jint v35, jint v36, jint v37, jint v38, jint v39,
+ jint v40, jint v41, jint v42, jint v43, jint v44,
+ jint v45, jint v46, jint v47, jint v48, jint v49,
+ jint v50) {
+ return StaticNonce_takeCoolHandLuke(
+ NULL, NULL, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10,
+ v11, v12, v13, v14, v15, v16, v17, v18, v19, v20,
+ v21, v22, v23, v24, v25, v26, v27, v28, v29, v30,
+ v31, v32, v33, v34, v35, v36, v37, v38, v39, v40,
+ v41, v42, v43, v44, v45, v46, v47, v48, v49, v50);
+}
+
static JNINativeMethod methods[] = {
// name, signature, function
{ "nop", "()V", StaticNonce_nop },
+ { "nopFast", "()V", StaticNonce_nopFast },
+ { "nopCritical", "()V", StaticNonce_nopCritical },
{ "returnBoolean", "()Z", StaticNonce_returnBoolean },
+ { "returnBooleanFast", "()Z", StaticNonce_returnBooleanFast },
+ { "returnBooleanCritical", "()Z", StaticNonce_returnBooleanCritical },
{ "returnByte", "()B", StaticNonce_returnByte },
+ { "returnByteFast", "()B", StaticNonce_returnByteFast },
+ { "returnByteCritical", "()B", StaticNonce_returnByteCritical },
{ "returnShort", "()S", StaticNonce_returnShort },
+ { "returnShortFast", "()S", StaticNonce_returnShortFast },
+ { "returnShortCritical", "()S", StaticNonce_returnShortCritical },
{ "returnChar", "()C", StaticNonce_returnChar },
+ { "returnCharFast", "()C", StaticNonce_returnCharFast },
+ { "returnCharCritical", "()C", StaticNonce_returnCharCritical },
{ "returnInt", "()I", StaticNonce_returnInt },
+ { "returnIntFast", "()I", StaticNonce_returnIntFast },
+ { "returnIntCritical", "()I", StaticNonce_returnIntCritical },
{ "returnLong", "()J", StaticNonce_returnLong },
+ { "returnLongFast", "()J", StaticNonce_returnLongFast },
+ { "returnLongCritical", "()J", StaticNonce_returnLongCritical },
{ "returnFloat", "()F", StaticNonce_returnFloat },
+ { "returnFloatFast", "()F", StaticNonce_returnFloatFast },
+ { "returnFloatCritical", "()F", StaticNonce_returnFloatCritical },
{ "returnDouble", "()D", StaticNonce_returnDouble },
+ { "returnDoubleFast", "()D", StaticNonce_returnDoubleFast },
+ { "returnDoubleCritical", "()D", StaticNonce_returnDoubleCritical },
{ "returnNull", "()Ljava/lang/Object;", StaticNonce_returnNull },
+ { "returnNullFast", "()Ljava/lang/Object;",
+ StaticNonce_returnNullFast },
{ "returnString", "()Ljava/lang/String;", StaticNonce_returnString },
+ { "returnStringFast", "()Ljava/lang/String;",
+ StaticNonce_returnStringFast },
{ "returnShortArray", "()[S", StaticNonce_returnShortArray },
+ { "returnShortArrayFast", "()[S", StaticNonce_returnShortArrayFast },
{ "returnStringArray", "()[Ljava/lang/String;",
StaticNonce_returnStringArray },
+ { "returnStringArrayFast", "()[Ljava/lang/String;",
+ StaticNonce_returnStringArrayFast },
{ "returnThisClass", "()Ljava/lang/Class;",
StaticNonce_returnThisClass },
+ { "returnThisClassFast", "()Ljava/lang/Class;",
+ StaticNonce_returnThisClassFast },
{ "returnInstance", "()Landroid/jni/cts/StaticNonce;",
StaticNonce_returnInstance },
+ { "returnInstanceFast", "()Landroid/jni/cts/StaticNonce;",
+ StaticNonce_returnInstanceFast },
{ "takeBoolean", "(Z)Z", StaticNonce_takeBoolean },
+ { "takeBooleanFast", "(Z)Z", StaticNonce_takeBooleanFast },
+ { "takeBooleanCritical", "(Z)Z", StaticNonce_takeBooleanCritical },
{ "takeByte", "(B)Z", StaticNonce_takeByte },
+ { "takeByteFast", "(B)Z", StaticNonce_takeByteFast },
+ { "takeByteCritical", "(B)Z", StaticNonce_takeByteCritical },
{ "takeShort", "(S)Z", StaticNonce_takeShort },
+ { "takeShortFast", "(S)Z", StaticNonce_takeShortFast },
+ { "takeShortCritical", "(S)Z", StaticNonce_takeShortCritical },
{ "takeChar", "(C)Z", StaticNonce_takeChar },
+ { "takeCharFast", "(C)Z", StaticNonce_takeCharFast },
+ { "takeCharCritical", "(C)Z", StaticNonce_takeCharCritical },
{ "takeInt", "(I)Z", StaticNonce_takeInt },
+ { "takeIntFast", "(I)Z", StaticNonce_takeIntFast },
+ { "takeIntCritical", "(I)Z", StaticNonce_takeIntCritical },
{ "takeLong", "(J)Z", StaticNonce_takeLong },
+ { "takeLongFast", "(J)Z", StaticNonce_takeLongFast },
+ { "takeLongCritical", "(J)Z", StaticNonce_takeLongCritical },
{ "takeFloat", "(F)Z", StaticNonce_takeFloat },
+ { "takeFloatFast", "(F)Z", StaticNonce_takeFloatFast },
+ { "takeFloatCritical", "(F)Z", StaticNonce_takeFloatCritical },
{ "takeDouble", "(D)Z", StaticNonce_takeDouble },
+ { "takeDoubleFast", "(D)Z", StaticNonce_takeDoubleFast },
+ { "takeDoubleCritical", "(D)Z", StaticNonce_takeDoubleCritical },
{ "takeNull", "(Ljava/lang/Object;)Z", StaticNonce_takeNull },
+ { "takeNullFast", "(Ljava/lang/Object;)Z", StaticNonce_takeNullFast },
{ "takeString", "(Ljava/lang/String;)Z", StaticNonce_takeString },
+ { "takeStringFast", "(Ljava/lang/String;)Z",
+ StaticNonce_takeStringFast },
{ "takeThisClass", "(Ljava/lang/Class;)Z", StaticNonce_takeThisClass },
+ { "takeThisClassFast", "(Ljava/lang/Class;)Z",
+ StaticNonce_takeThisClassFast },
{ "takeIntLong", "(IJ)Z", StaticNonce_takeIntLong },
+ { "takeIntLongFast", "(IJ)Z", StaticNonce_takeIntLongFast },
+ { "takeIntLongCritical", "(IJ)Z", StaticNonce_takeIntLongCritical },
{ "takeLongInt", "(JI)Z", StaticNonce_takeLongInt },
+ { "takeLongIntFast", "(JI)Z", StaticNonce_takeLongIntFast },
+ { "takeLongIntCritical", "(JI)Z", StaticNonce_takeLongIntCritical },
{ "takeOneOfEach", "(ZBSCIJLjava/lang/String;FD[I)Z",
StaticNonce_takeOneOfEach },
+ { "takeOneOfEachFast", "(ZBSCIJLjava/lang/String;FD[I)Z",
+ StaticNonce_takeOneOfEachFast },
+ { "takeOneOfEachCritical", "(ZBSCIJFD)Z",
+ StaticNonce_takeOneOfEachCritical },
{ "takeCoolHandLuke",
"(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z",
StaticNonce_takeCoolHandLuke },
+ { "takeCoolHandLukeFast",
+ "(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z",
+ StaticNonce_takeCoolHandLukeFast },
+ { "takeCoolHandLukeCritical",
+ "(IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII)Z",
+ StaticNonce_takeCoolHandLukeCritical },
};
int register_StaticNonce(JNIEnv *env) {
diff --git a/tests/tests/jni/src/android/jni/cts/InstanceNonce.java b/tests/tests/jni/src/android/jni/cts/InstanceNonce.java
index e1a7dea..82ead49 100644
--- a/tests/tests/jni/src/android/jni/cts/InstanceNonce.java
+++ b/tests/tests/jni/src/android/jni/cts/InstanceNonce.java
@@ -16,6 +16,8 @@
package android.jni.cts;
+import dalvik.annotation.optimization.FastNative;
+
/**
* Class with a bunch of native instance methods. These methods are called by
* the various tests in {@link JniInstanceTest}.
@@ -36,38 +38,137 @@
// See JniInstanceTest for the expected behavior of these methods.
+ public static native void missing();
+ @FastNative
+ public static native void missingFast();
+
+ public static native void nopDlsym();
+ @FastNative
+ public static native void nopFastDlsym();
+
public native void nop();
+ @FastNative
+ public native void nopFast();
public native boolean returnBoolean();
+ @FastNative
+ public native boolean returnBooleanFast();
+
public native byte returnByte();
+ @FastNative
+ public native byte returnByteFast();
+
public native short returnShort();
+ @FastNative
+ public native short returnShortFast();
+
public native char returnChar();
+ @FastNative
+ public native char returnCharFast();
+
public native int returnInt();
+ @FastNative
+ public native int returnIntFast();
+
public native long returnLong();
+ @FastNative
+ public native long returnLongFast();
+
public native float returnFloat();
+ @FastNative
+ public native float returnFloatFast();
+
public native double returnDouble();
+ @FastNative
+ public native double returnDoubleFast();
+
public native Object returnNull();
+ @FastNative
+ public native Object returnNullFast();
+
public native String returnString();
+ @FastNative
+ public native String returnStringFast();
+
public native short[] returnShortArray();
+ @FastNative
+ public native short[] returnShortArrayFast();
+
public native String[] returnStringArray();
+ @FastNative
+ public native String[] returnStringArrayFast();
+
public native InstanceNonce returnThis();
+ @FastNative
+ public native InstanceNonce returnThisFast();
public native boolean takeBoolean(boolean v);
+ @FastNative
+ public native boolean takeBooleanFast(boolean v);
+
public native boolean takeByte(byte v);
+ @FastNative
+ public native boolean takeByteFast(byte v);
+
public native boolean takeShort(short v);
+ @FastNative
+ public native boolean takeShortFast(short v);
+
public native boolean takeChar(char v);
+ @FastNative
+ public native boolean takeCharFast(char v);
+
public native boolean takeInt(int v);
+ @FastNative
+ public native boolean takeIntFast(int v);
+
public native boolean takeLong(long v);
+ @FastNative
+ public native boolean takeLongFast(long v);
+
public native boolean takeFloat(float v);
+ @FastNative
+ public native boolean takeFloatFast(float v);
+
public native boolean takeDouble(double v);
+ @FastNative
+ public native boolean takeDoubleFast(double v);
+
public native boolean takeNull(Object v);
+ @FastNative
+ public native boolean takeNullFast(Object v);
+
public native boolean takeString(String v);
+ @FastNative
+ public native boolean takeStringFast(String v);
+
public native boolean takeThis(InstanceNonce v);
+ @FastNative
+ public native boolean takeThisFast(InstanceNonce v);
+
public native boolean takeIntLong(int v1, long v2);
+ @FastNative
+ public native boolean takeIntLongFast(int v1, long v2);
+
public native boolean takeLongInt(long v1, int v2);
+ @FastNative
+ public native boolean takeLongIntFast(long v1, int v2);
+
public native boolean takeOneOfEach(boolean v0, byte v1, short v2,
char v3, int v4, long v5, String v6, float v7, double v8,
int[] v9);
+ public native boolean takeOneOfEachDlsym(boolean v0, byte v1, short v2,
+ char v3, int v4, long v5, String v6, float v7, double v8,
+ int[] v9);
+ @FastNative
+ public native boolean takeOneOfEachFast(boolean v0, byte v1, short v2,
+ char v3, int v4, long v5, String v6, float v7, double v8,
+ int[] v9);
+ @FastNative
+ public native boolean takeOneOfEachFastDlsym(boolean v0, byte v1, short v2,
+ char v3, int v4, long v5, String v6, float v7, double v8,
+ int[] v9);
+
public native boolean takeCoolHandLuke(
int v1, int v2, int v3, int v4,
int v5, int v6, int v7, int v8, int v9,
@@ -80,4 +181,17 @@
int v40, int v41, int v42, int v43, int v44,
int v45, int v46, int v47, int v48, int v49,
int v50);
+ @FastNative
+ public native boolean takeCoolHandLukeFast(
+ int v1, int v2, int v3, int v4,
+ int v5, int v6, int v7, int v8, int v9,
+ int v10, int v11, int v12, int v13, int v14,
+ int v15, int v16, int v17, int v18, int v19,
+ int v20, int v21, int v22, int v23, int v24,
+ int v25, int v26, int v27, int v28, int v29,
+ int v30, int v31, int v32, int v33, int v34,
+ int v35, int v36, int v37, int v38, int v39,
+ int v40, int v41, int v42, int v43, int v44,
+ int v45, int v46, int v47, int v48, int v49,
+ int v50);
}
diff --git a/tests/tests/jni/src/android/jni/cts/JniInstanceTest.java b/tests/tests/jni/src/android/jni/cts/JniInstanceTest.java
index 7c16a3a..b242519 100644
--- a/tests/tests/jni/src/android/jni/cts/JniInstanceTest.java
+++ b/tests/tests/jni/src/android/jni/cts/JniInstanceTest.java
@@ -32,11 +32,41 @@
}
/**
+ * Test native method call without implementation.
+ */
+ public void test_missing() {
+ try {
+ target.missing();
+ throw new Error("Unreachable");
+ } catch (UnsatisfiedLinkError expected) {
+ }
+ }
+ public void test_missingFast() {
+ try {
+ target.missingFast();
+ throw new Error("Unreachable");
+ } catch (UnsatisfiedLinkError expected) {
+ }
+ }
+
+ /**
* Test a simple no-op and void-returning method call.
+ *
+ * The "Dlsym" versions use dynamic lookup instead of explicitly
+ * registering the native method implementation.
*/
public void test_nop() {
target.nop();
}
+ public void test_nopDlsym() {
+ target.nopDlsym();
+ }
+ public void test_nopFast() {
+ target.nopFast();
+ }
+ public void test_nopFastDlsym() {
+ target.nopFastDlsym();
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -44,6 +74,9 @@
public void test_returnBoolean() {
assertEquals(false, target.returnBoolean());
}
+ public void test_returnBooleanFast() {
+ assertEquals(false, target.returnBooleanFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -51,6 +84,10 @@
public void test_returnByte() {
assertEquals(123, target.returnByte());
}
+ public void test_returnByteFast() {
+ assertEquals(123, target.returnByteFast());
+ }
+
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -58,6 +95,9 @@
public void test_returnShort() {
assertEquals(-12345, target.returnShort());
}
+ public void test_returnShortFast() {
+ assertEquals(-12345, target.returnShortFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -65,6 +105,9 @@
public void test_returnChar() {
assertEquals(34567, target.returnChar());
}
+ public void test_returnCharFast() {
+ assertEquals(34567, target.returnCharFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -72,6 +115,9 @@
public void test_returnInt() {
assertEquals(12345678, target.returnInt());
}
+ public void test_returnIntFast() {
+ assertEquals(12345678, target.returnIntFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -79,6 +125,9 @@
public void test_returnLong() {
assertEquals(-1098765432109876543L, target.returnLong());
}
+ public void test_returnLongFast() {
+ assertEquals(-1098765432109876543L, target.returnLongFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -86,6 +135,9 @@
public void test_returnFloat() {
assertEquals(-98765.4321F, target.returnFloat());
}
+ public void test_returnFloatFast() {
+ assertEquals(-98765.4321F, target.returnFloatFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -93,6 +145,9 @@
public void test_returnDouble() {
assertEquals(12345678.9, target.returnDouble());
}
+ public void test_returnDoubleFast() {
+ assertEquals(12345678.9, target.returnDoubleFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -100,6 +155,9 @@
public void test_returnNull() {
assertNull(target.returnNull());
}
+ public void test_returnNullFast() {
+ assertNull(target.returnNullFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -107,12 +165,20 @@
public void test_returnString() {
assertEquals("blort", target.returnString());
}
+ public void test_returnStringFast() {
+ assertEquals("blort", target.returnStringFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
*/
public void test_returnShortArray() {
- short[] array = target.returnShortArray();
+ checkShortArray(target.returnShortArray());
+ }
+ public void test_returnShortArrayFast() {
+ checkShortArray(target.returnShortArrayFast());
+ }
+ private void checkShortArray(short[] array) {
assertSame(short[].class, array.getClass());
assertEquals(3, array.length);
assertEquals(10, array[0]);
@@ -124,7 +190,12 @@
* Test a simple value-returning (but otherwise no-op) method call.
*/
public void test_returnStringArray() {
- String[] array = target.returnStringArray();
+ checkStringArray(target.returnStringArray());
+ }
+ public void test_returnStringArrayFast() {
+ checkStringArray(target.returnStringArrayFast());
+ }
+ private void checkStringArray(String[] array) {
assertSame(String[].class, array.getClass());
assertEquals(100, array.length);
assertEquals("blort", array[0]);
@@ -140,6 +211,9 @@
public void test_returnThis() {
assertSame(target, target.returnThis());
}
+ public void test_returnThisFast() {
+ assertSame(target, target.returnThis());
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -148,6 +222,9 @@
public void test_takeBoolean() {
assertTrue(target.takeBoolean(false));
}
+ public void test_takeBooleanFast() {
+ assertTrue(target.takeBooleanFast(false));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -156,6 +233,9 @@
public void test_takeByte() {
assertTrue(target.takeByte((byte) -99));
}
+ public void test_takeByteFast() {
+ assertTrue(target.takeByteFast((byte) -99));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -164,6 +244,9 @@
public void test_takeShort() {
assertTrue(target.takeShort((short) 19991));
}
+ public void test_takeShortFast() {
+ assertTrue(target.takeShortFast((short) 19991));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -172,6 +255,9 @@
public void test_takeChar() {
assertTrue(target.takeChar((char) 999));
}
+ public void test_takeCharFast() {
+ assertTrue(target.takeCharFast((char) 999));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -180,6 +266,9 @@
public void test_takeInt() {
assertTrue(target.takeInt(-999888777));
}
+ public void test_takeIntFast() {
+ assertTrue(target.takeIntFast(-999888777));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -188,6 +277,9 @@
public void test_takeLong() {
assertTrue(target.takeLong(999888777666555444L));
}
+ public void test_takeLongFast() {
+ assertTrue(target.takeLongFast(999888777666555444L));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -196,6 +288,9 @@
public void test_takeFloat() {
assertTrue(target.takeFloat(-9988.7766F));
}
+ public void test_takeFloatFast() {
+ assertTrue(target.takeFloatFast(-9988.7766F));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -204,6 +299,9 @@
public void test_takeDouble() {
assertTrue(target.takeDouble(999888777.666555));
}
+ public void test_takeDoubleFast() {
+ assertTrue(target.takeDoubleFast(999888777.666555));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -212,6 +310,9 @@
public void test_takeNull() {
assertTrue(target.takeNull(null));
}
+ public void test_takeNullFast() {
+ assertTrue(target.takeNullFast(null));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -220,6 +321,9 @@
public void test_takeString() {
assertTrue(target.takeString("fuzzbot"));
}
+ public void test_takeStringFast() {
+ assertTrue(target.takeStringFast("fuzzbot"));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -229,6 +333,9 @@
public void test_takeThis() {
assertTrue(target.takeThis(target));
}
+ public void test_takeThisFast() {
+ assertTrue(target.takeThisFast(target));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
@@ -237,6 +344,9 @@
public void test_takeIntLong() {
assertTrue(target.takeIntLong(914, 9140914091409140914L));
}
+ public void test_takeIntLongFast() {
+ assertTrue(target.takeIntLongFast(914, 9140914091409140914L));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
@@ -245,16 +355,37 @@
public void test_takeLongInt() {
assertTrue(target.takeLongInt(-4321L, 12341234));
}
+ public void test_takeLongIntFast() {
+ assertTrue(target.takeLongIntFast(-4321L, 12341234));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
* got the expected values.
+ *
+ * The "Dlsym" versions use dynamic lookup instead of explicitly
+ * registering the native method implementation.
*/
public void test_takeOneOfEach() {
assertTrue(target.takeOneOfEach((boolean) false, (byte) 1,
(short) 2, (char) 3, (int) 4, 5L, "six", 7.0f, 8.0,
new int[] { 9, 10 }));
}
+ public void test_takeOneOfEachDlsym() {
+ assertTrue(target.takeOneOfEachDlsym((boolean) false, (byte) 1,
+ (short) 2, (char) 3, (int) 4, 5L, "six", 7.0f, 8.0,
+ new int[] { 9, 10 }));
+ }
+ public void test_takeOneOfEachFast() {
+ assertTrue(target.takeOneOfEachFast((boolean) false, (byte) 1,
+ (short) 2, (char) 3, (int) 4, 5L, "six", 7.0f, 8.0,
+ new int[] { 9, 10 }));
+ }
+ public void test_takeOneOfEachFastDlsym() {
+ assertTrue(target.takeOneOfEachFastDlsym((boolean) false, (byte) 1,
+ (short) 2, (char) 3, (int) 4, 5L, "six", 7.0f, 8.0,
+ new int[] { 9, 10 }));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
@@ -268,4 +399,12 @@
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50));
}
+ public void test_takeCoolHandLukeFast() {
+ assertTrue(target.takeCoolHandLukeFast(1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50));
+ }
}
diff --git a/tests/tests/jni/src/android/jni/cts/JniStaticTest.java b/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
index e2bbcd7..d1bfac6 100644
--- a/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
+++ b/tests/tests/jni/src/android/jni/cts/JniStaticTest.java
@@ -18,7 +18,9 @@
import android.os.Build;
import android.os.Process;
+
import com.android.compatibility.common.util.PropertyUtil;
+
import java.io.File;
import java.io.IOException;
@@ -69,11 +71,54 @@
}
/**
+ * Test native method call without implementation.
+ */
+ public void test_missing() {
+ try {
+ StaticNonce.missing();
+ throw new Error("Unreachable");
+ } catch (UnsatisfiedLinkError expected) {
+ }
+ }
+ public void test_missingFast() {
+ try {
+ StaticNonce.missingFast();
+ throw new Error("Unreachable");
+ } catch (UnsatisfiedLinkError expected) {
+ }
+ }
+ public void test_missingCritical() {
+ try {
+ StaticNonce.missingCritical();
+ throw new Error("Unreachable");
+ } catch (UnsatisfiedLinkError expected) {
+ }
+ }
+
+ /**
* Test a simple no-op and void-returning method call.
+ *
+ * The "Dlsym" versions use dynamic lookup instead of explicitly
+ * registering the native method implementation.
*/
public void test_nop() {
StaticNonce.nop();
}
+ public void test_nopDlsym() {
+ StaticNonce.nopDlsym();
+ }
+ public void test_nopFast() {
+ StaticNonce.nopFast();
+ }
+ public void test_nopFastDlsym() {
+ StaticNonce.nopFastDlsym();
+ }
+ public void test_nopCritical() {
+ StaticNonce.nopCritical();
+ }
+ public void test_nopCriticalDlsym() {
+ StaticNonce.nopCriticalDlsym();
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -81,6 +126,12 @@
public void test_returnBoolean() {
assertEquals(true, StaticNonce.returnBoolean());
}
+ public void test_returnBooleanFast() {
+ assertEquals(true, StaticNonce.returnBooleanFast());
+ }
+ public void test_returnBooleanCritical() {
+ assertEquals(true, StaticNonce.returnBooleanCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -88,6 +139,12 @@
public void test_returnByte() {
assertEquals(123, StaticNonce.returnByte());
}
+ public void test_returnByteFast() {
+ assertEquals(123, StaticNonce.returnByteFast());
+ }
+ public void test_returnByteCritical() {
+ assertEquals(123, StaticNonce.returnByteCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -95,6 +152,12 @@
public void test_returnShort() {
assertEquals(-12345, StaticNonce.returnShort());
}
+ public void test_returnShortFast() {
+ assertEquals(-12345, StaticNonce.returnShortFast());
+ }
+ public void test_returnShortCritical() {
+ assertEquals(-12345, StaticNonce.returnShortCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -102,6 +165,12 @@
public void test_returnChar() {
assertEquals(34567, StaticNonce.returnChar());
}
+ public void test_returnCharFast() {
+ assertEquals(34567, StaticNonce.returnCharFast());
+ }
+ public void test_returnCharCritical() {
+ assertEquals(34567, StaticNonce.returnCharCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -109,6 +178,12 @@
public void test_returnInt() {
assertEquals(12345678, StaticNonce.returnInt());
}
+ public void test_returnIntFast() {
+ assertEquals(12345678, StaticNonce.returnIntFast());
+ }
+ public void test_returnIntCritical() {
+ assertEquals(12345678, StaticNonce.returnIntCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -116,6 +191,12 @@
public void test_returnLong() {
assertEquals(-1098765432109876543L, StaticNonce.returnLong());
}
+ public void test_returnLongFast() {
+ assertEquals(-1098765432109876543L, StaticNonce.returnLongFast());
+ }
+ public void test_returnLongCritical() {
+ assertEquals(-1098765432109876543L, StaticNonce.returnLongCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -123,6 +204,12 @@
public void test_returnFloat() {
assertEquals(-98765.4321F, StaticNonce.returnFloat());
}
+ public void test_returnFloatFast() {
+ assertEquals(-98765.4321F, StaticNonce.returnFloatFast());
+ }
+ public void test_returnFloatCritical() {
+ assertEquals(-98765.4321F, StaticNonce.returnFloatCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -130,6 +217,12 @@
public void test_returnDouble() {
assertEquals(12345678.9, StaticNonce.returnDouble());
}
+ public void test_returnDoubleFast() {
+ assertEquals(12345678.9, StaticNonce.returnDoubleFast());
+ }
+ public void test_returnDoubleCritical() {
+ assertEquals(12345678.9, StaticNonce.returnDoubleCritical());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -137,6 +230,9 @@
public void test_returnNull() {
assertNull(StaticNonce.returnNull());
}
+ public void test_returnNullFast() {
+ assertNull(StaticNonce.returnNullFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
@@ -144,12 +240,20 @@
public void test_returnString() {
assertEquals("blort", StaticNonce.returnString());
}
+ public void test_returnStringFast() {
+ assertEquals("blort", StaticNonce.returnStringFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call.
*/
public void test_returnShortArray() {
- short[] array = StaticNonce.returnShortArray();
+ checkShortArray(StaticNonce.returnShortArray());
+ }
+ public void test_returnShortArrayFast() {
+ checkShortArray(StaticNonce.returnShortArrayFast());
+ }
+ private void checkShortArray(short[] array) {
assertSame(short[].class, array.getClass());
assertEquals(3, array.length);
assertEquals(10, array[0]);
@@ -161,7 +265,12 @@
* Test a simple value-returning (but otherwise no-op) method call.
*/
public void test_returnStringArray() {
- String[] array = StaticNonce.returnStringArray();
+ checkStringArray(StaticNonce.returnStringArray());
+ }
+ public void test_returnStringArrayFast() {
+ checkStringArray(StaticNonce.returnStringArrayFast());
+ }
+ private void checkStringArray(String[] array) {
assertSame(String[].class, array.getClass());
assertEquals(100, array.length);
assertEquals("blort", array[0]);
@@ -177,6 +286,9 @@
public void test_returnThisClass() {
assertSame(StaticNonce.class, StaticNonce.returnThisClass());
}
+ public void test_returnThisClassFast() {
+ assertSame(StaticNonce.class, StaticNonce.returnThisClassFast());
+ }
/**
* Test a simple value-returning (but otherwise no-op) method call,
@@ -186,6 +298,10 @@
StaticNonce nonce = StaticNonce.returnInstance();
assertSame(StaticNonce.class, nonce.getClass());
}
+ public void test_returnInstanceFast() {
+ StaticNonce nonce = StaticNonce.returnInstanceFast();
+ assertSame(StaticNonce.class, nonce.getClass());
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -194,6 +310,12 @@
public void test_takeBoolean() {
assertTrue(StaticNonce.takeBoolean(true));
}
+ public void test_takeBooleanFast() {
+ assertTrue(StaticNonce.takeBooleanFast(true));
+ }
+ public void test_takeBooleanCritical() {
+ assertTrue(StaticNonce.takeBooleanCritical(true));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -202,6 +324,12 @@
public void test_takeByte() {
assertTrue(StaticNonce.takeByte((byte) -99));
}
+ public void test_takeByteFast() {
+ assertTrue(StaticNonce.takeByteFast((byte) -99));
+ }
+ public void test_takeByteCritical() {
+ assertTrue(StaticNonce.takeByteCritical((byte) -99));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -210,6 +338,12 @@
public void test_takeShort() {
assertTrue(StaticNonce.takeShort((short) 19991));
}
+ public void test_takeShortFast() {
+ assertTrue(StaticNonce.takeShortFast((short) 19991));
+ }
+ public void test_takeShortCritical() {
+ assertTrue(StaticNonce.takeShortCritical((short) 19991));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -218,6 +352,12 @@
public void test_takeChar() {
assertTrue(StaticNonce.takeChar((char) 999));
}
+ public void test_takeCharFast() {
+ assertTrue(StaticNonce.takeCharFast((char) 999));
+ }
+ public void test_takeCharCritical() {
+ assertTrue(StaticNonce.takeCharCritical((char) 999));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -226,6 +366,12 @@
public void test_takeInt() {
assertTrue(StaticNonce.takeInt(-999888777));
}
+ public void test_takeIntFast() {
+ assertTrue(StaticNonce.takeIntFast(-999888777));
+ }
+ public void test_takeIntCritical() {
+ assertTrue(StaticNonce.takeIntCritical(-999888777));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -234,6 +380,12 @@
public void test_takeLong() {
assertTrue(StaticNonce.takeLong(999888777666555444L));
}
+ public void test_takeLongFast() {
+ assertTrue(StaticNonce.takeLongFast(999888777666555444L));
+ }
+ public void test_takeLongCritical() {
+ assertTrue(StaticNonce.takeLongCritical(999888777666555444L));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -242,6 +394,12 @@
public void test_takeFloat() {
assertTrue(StaticNonce.takeFloat(-9988.7766F));
}
+ public void test_takeFloatFast() {
+ assertTrue(StaticNonce.takeFloatFast(-9988.7766F));
+ }
+ public void test_takeFloatCritical() {
+ assertTrue(StaticNonce.takeFloatCritical(-9988.7766F));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -250,6 +408,12 @@
public void test_takeDouble() {
assertTrue(StaticNonce.takeDouble(999888777.666555));
}
+ public void test_takeDoubleFast() {
+ assertTrue(StaticNonce.takeDoubleFast(999888777.666555));
+ }
+ public void test_takeDoubleCritical() {
+ assertTrue(StaticNonce.takeDoubleCritical(999888777.666555));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -258,6 +422,9 @@
public void test_takeNull() {
assertTrue(StaticNonce.takeNull(null));
}
+ public void test_takeNullFast() {
+ assertTrue(StaticNonce.takeNullFast(null));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -266,6 +433,9 @@
public void test_takeString() {
assertTrue(StaticNonce.takeString("fuzzbot"));
}
+ public void test_takeStringFast() {
+ assertTrue(StaticNonce.takeStringFast("fuzzbot"));
+ }
/**
* Test a simple value-taking method call, that returns whether it
@@ -275,6 +445,9 @@
public void test_takeThisClass() {
assertTrue(StaticNonce.takeThisClass(StaticNonce.class));
}
+ public void test_takeThisClassFast() {
+ assertTrue(StaticNonce.takeThisClassFast(StaticNonce.class));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
@@ -283,6 +456,12 @@
public void test_takeIntLong() {
assertTrue(StaticNonce.takeIntLong(914, 9140914091409140914L));
}
+ public void test_takeIntLongFast() {
+ assertTrue(StaticNonce.takeIntLongFast(914, 9140914091409140914L));
+ }
+ public void test_takeIntLongCritical() {
+ assertTrue(StaticNonce.takeIntLongCritical(914, 9140914091409140914L));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
@@ -291,16 +470,49 @@
public void test_takeLongInt() {
assertTrue(StaticNonce.takeLongInt(-4321L, 12341234));
}
+ public void test_takeLongIntFast() {
+ assertTrue(StaticNonce.takeLongIntFast(-4321L, 12341234));
+ }
+ public void test_takeLongIntCritical() {
+ assertTrue(StaticNonce.takeLongIntCritical(-4321L, 12341234));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
* got the expected values.
+ *
+ * The "Dlsym" versions use dynamic lookup instead of explicitly
+ * registering the native method implementation.
*/
public void test_takeOneOfEach() {
assertTrue(StaticNonce.takeOneOfEach((boolean) false, (byte) 1,
(short) 2, (char) 3, (int) 4, 5L, "six", 7.0f, 8.0,
new int[] { 9, 10 }));
}
+ public void test_takeOneOfEachDlsym() {
+ assertTrue(StaticNonce.takeOneOfEachDlsym((boolean) false,
+ (byte) 1, (short) 2, (char) 3, (int) 4, 5L, "six",
+ 7.0f, 8.0, new int[] { 9, 10 }));
+ }
+ public void test_takeOneOfEachFast() {
+ assertTrue(StaticNonce.takeOneOfEachFast((boolean) false, (byte) 1,
+ (short) 2, (char) 3, (int) 4, 5L, "six", 7.0f, 8.0,
+ new int[] { 9, 10 }));
+ }
+ public void test_takeOneOfEachFastDlsym() {
+ assertTrue(StaticNonce.takeOneOfEachFastDlsym((boolean) false,
+ (byte) 1, (short) 2, (char) 3, (int) 4, 5L, "six",
+ 7.0f, 8.0, new int[] { 9, 10 }));
+ }
+ public void test_takeOneOfEachCritical() {
+ assertTrue(StaticNonce.takeOneOfEachCritical((boolean) false, (byte) 1,
+ (short) 2, (char) 3, (int) 4, 5L, 6.0f, 7.0));
+ }
+ public void test_takeOneOfEachCriticalDlsym() {
+ assertTrue(StaticNonce.takeOneOfEachCriticalDlsym((boolean) false,
+ (byte) 1, (short) 2, (char) 3, (int) 4, 5L, 6.0f,
+ 7.0));
+ }
/**
* Test a simple multiple value-taking method call, that returns whether it
@@ -314,6 +526,22 @@
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50));
}
+ public void test_takeCoolHandLukeFast() {
+ assertTrue(StaticNonce.takeCoolHandLukeFast(1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+ 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+ 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+ 50));
+ }
+ public void test_takeCoolHandLukeCritical() {
+ assertTrue(StaticNonce.takeCoolHandLukeCritical(
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50));
+ }
/**
* dlopen(3) any of the public lib via file name (non-absolute path) should succeed.
diff --git a/tests/tests/jni/src/android/jni/cts/StaticNonce.java b/tests/tests/jni/src/android/jni/cts/StaticNonce.java
index c84e899..071d52c 100644
--- a/tests/tests/jni/src/android/jni/cts/StaticNonce.java
+++ b/tests/tests/jni/src/android/jni/cts/StaticNonce.java
@@ -16,6 +16,9 @@
package android.jni.cts;
+import dalvik.annotation.optimization.CriticalNative;
+import dalvik.annotation.optimization.FastNative;
+
/**
* Class with a bunch of native static methods. These methods are called by
* the various tests in {@link JniStaticTest}.
@@ -36,39 +39,188 @@
// See JniStaticTest for the expected behavior of these methods.
+ public static native void missing();
+ @FastNative
+ public static native void missingFast();
+ @CriticalNative
+ public static native void missingCritical();
+
public static native void nop();
+ public static native void nopDlsym();
+ @FastNative
+ public static native void nopFast();
+ @FastNative
+ public static native void nopFastDlsym();
+ @CriticalNative
+ public static native void nopCritical();
+ @CriticalNative
+ public static native void nopCriticalDlsym();
public static native boolean returnBoolean();
+ @FastNative
+ public static native boolean returnBooleanFast();
+ @CriticalNative
+ public static native boolean returnBooleanCritical();
+
public static native byte returnByte();
+ @FastNative
+ public static native byte returnByteFast();
+ @CriticalNative
+ public static native byte returnByteCritical();
+
public static native short returnShort();
+ @FastNative
+ public static native short returnShortFast();
+ @CriticalNative
+ public static native short returnShortCritical();
+
public static native char returnChar();
+ @FastNative
+ public static native char returnCharFast();
+ @CriticalNative
+ public static native char returnCharCritical();
+
public static native int returnInt();
+ @FastNative
+ public static native int returnIntFast();
+ @CriticalNative
+ public static native int returnIntCritical();
+
public static native long returnLong();
+ @FastNative
+ public static native long returnLongFast();
+ @CriticalNative
+ public static native long returnLongCritical();
+
public static native float returnFloat();
+ @FastNative
+ public static native float returnFloatFast();
+ @CriticalNative
+ public static native float returnFloatCritical();
+
public static native double returnDouble();
+ @FastNative
+ public static native double returnDoubleFast();
+ @CriticalNative
+ public static native double returnDoubleCritical();
+
public static native Object returnNull();
+ @FastNative
+ public static native Object returnNullFast();
+
public static native String returnString();
+ @FastNative
+ public static native String returnStringFast();
+
public static native short[] returnShortArray();
+ @FastNative
+ public static native short[] returnShortArrayFast();
+
public static native String[] returnStringArray();
+ @FastNative
+ public static native String[] returnStringArrayFast();
+
public static native Class returnThisClass();
+ @FastNative
+ public static native Class returnThisClassFast();
+
public static native StaticNonce returnInstance();
+ @FastNative
+ public static native StaticNonce returnInstanceFast();
public static native boolean takeBoolean(boolean v);
+ @FastNative
+ public static native boolean takeBooleanFast(boolean v);
+ @CriticalNative
+ public static native boolean takeBooleanCritical(boolean v);
+
public static native boolean takeByte(byte v);
+ @FastNative
+ public static native boolean takeByteFast(byte v);
+ @CriticalNative
+ public static native boolean takeByteCritical(byte v);
+
public static native boolean takeShort(short v);
+ @FastNative
+ public static native boolean takeShortFast(short v);
+ @CriticalNative
+ public static native boolean takeShortCritical(short v);
+
public static native boolean takeChar(char v);
+ @FastNative
+ public static native boolean takeCharFast(char v);
+ @CriticalNative
+ public static native boolean takeCharCritical(char v);
+
public static native boolean takeInt(int v);
+ @FastNative
+ public static native boolean takeIntFast(int v);
+ @CriticalNative
+ public static native boolean takeIntCritical(int v);
+
public static native boolean takeLong(long v);
+ @FastNative
+ public static native boolean takeLongFast(long v);
+ @CriticalNative
+ public static native boolean takeLongCritical(long v);
+
public static native boolean takeFloat(float v);
+ @FastNative
+ public static native boolean takeFloatFast(float v);
+ @CriticalNative
+ public static native boolean takeFloatCritical(float v);
+
public static native boolean takeDouble(double v);
+ @FastNative
+ public static native boolean takeDoubleFast(double v);
+ @CriticalNative
+ public static native boolean takeDoubleCritical(double v);
+
public static native boolean takeNull(Object v);
+ @FastNative
+ public static native boolean takeNullFast(Object v);
+
public static native boolean takeString(String v);
+ @FastNative
+ public static native boolean takeStringFast(String v);
+
public static native boolean takeThisClass(Class v);
+ @FastNative
+ public static native boolean takeThisClassFast(Class v);
+
public static native boolean takeIntLong(int v1, long v2);
+ @FastNative
+ public static native boolean takeIntLongFast(int v1, long v2);
+ @CriticalNative
+ public static native boolean takeIntLongCritical(int v1, long v2);
+
public static native boolean takeLongInt(long v1, int v2);
+ @FastNative
+ public static native boolean takeLongIntFast(long v1, int v2);
+ @CriticalNative
+ public static native boolean takeLongIntCritical(long v1, int v2);
+
public static native boolean takeOneOfEach(boolean v0, byte v1, short v2,
char v3, int v4, long v5, String v6, float v7, double v8,
int[] v9);
+ public static native boolean takeOneOfEachDlsym(boolean v0, byte v1,
+ short v2, char v3, int v4, long v5, String v6, float v7, double v8,
+ int[] v9);
+ @FastNative
+ public static native boolean takeOneOfEachFast(boolean v0, byte v1,
+ short v2, char v3, int v4, long v5, String v6, float v7, double v8,
+ int[] v9);
+ @FastNative
+ public static native boolean takeOneOfEachFastDlsym(boolean v0, byte v1,
+ short v2, char v3, int v4, long v5, String v6, float v7, double v8,
+ int[] v9);
+ @CriticalNative
+ public static native boolean takeOneOfEachCritical(boolean v0, byte v1,
+ short v2, char v3, int v4, long v5, float v6, double v7);
+ @CriticalNative
+ public static native boolean takeOneOfEachCriticalDlsym(boolean v0,
+ byte v1, short v2, char v3, int v4, long v5, float v6, double v7);
+
public static native boolean takeCoolHandLuke(
int v1, int v2, int v3, int v4,
int v5, int v6, int v7, int v8, int v9,
@@ -81,4 +233,30 @@
int v40, int v41, int v42, int v43, int v44,
int v45, int v46, int v47, int v48, int v49,
int v50);
+ @FastNative
+ public static native boolean takeCoolHandLukeFast(
+ int v1, int v2, int v3, int v4,
+ int v5, int v6, int v7, int v8, int v9,
+ int v10, int v11, int v12, int v13, int v14,
+ int v15, int v16, int v17, int v18, int v19,
+ int v20, int v21, int v22, int v23, int v24,
+ int v25, int v26, int v27, int v28, int v29,
+ int v30, int v31, int v32, int v33, int v34,
+ int v35, int v36, int v37, int v38, int v39,
+ int v40, int v41, int v42, int v43, int v44,
+ int v45, int v46, int v47, int v48, int v49,
+ int v50);
+ @CriticalNative
+ public static native boolean takeCoolHandLukeCritical(
+ int v1, int v2, int v3, int v4,
+ int v5, int v6, int v7, int v8, int v9,
+ int v10, int v11, int v12, int v13, int v14,
+ int v15, int v16, int v17, int v18, int v19,
+ int v20, int v21, int v22, int v23, int v24,
+ int v25, int v26, int v27, int v28, int v29,
+ int v30, int v31, int v32, int v33, int v34,
+ int v35, int v36, int v37, int v38, int v39,
+ int v40, int v41, int v42, int v43, int v44,
+ int v45, int v46, int v47, int v48, int v49,
+ int v50);
}
diff --git a/tests/tests/keystore/Android.bp b/tests/tests/keystore/Android.bp
index 8f7306c..27d3c16 100644
--- a/tests/tests/keystore/Android.bp
+++ b/tests/tests/keystore/Android.bp
@@ -64,6 +64,7 @@
"DeviceAdminApp",
"Harrier",
"Nene",
+ "android-key-attestation",
"androidx.test.rules",
"compatibility-device-util-axt",
"core-tests-support",
diff --git a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
index 676793b..6d2e950 100644
--- a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
@@ -21,6 +21,7 @@
import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL;
+import static com.google.android.attestation.ParsedAttestationRecord.createParsedAttestationRecord;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -47,10 +48,13 @@
import com.android.bedstead.nene.permissions.PermissionContext;
import com.android.compatibility.common.util.ApiTest;
+import com.google.android.attestation.ParsedAttestationRecord;
+
import org.junit.ClassRule;
import org.junit.Rule;
import org.junit.Test;
+import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.PrivateKey;
@@ -138,6 +142,10 @@
assertThat(teeAttestation.getImei()).isEqualTo(expectedImei);
assertThat(teeAttestation.getMeid()).isEqualTo(expectedMeid);
+ validateSecondImei(teeAttestation.getSecondImei(), expectedSecondImei);
+ }
+
+ private void validateSecondImei(String attestedSecondImei, String expectedSecondImei) {
/**
* Test attestation support for 2nd IMEI:
* * Attestation of 2nd IMEI (if present on the device) is required for devices shipping
@@ -155,25 +163,69 @@
if (!isKeyMintV3) {
// Earlier versions of KeyMint must not attest to second IMEI values as they are not
// allowed to emit an attestation extension version that includes it.
- assertThat(teeAttestation.getSecondImei()).isNull();
+ assertThat(attestedSecondImei).isNull();
} else if (emptySecondImei) {
// Device doesn't have a second IMEI, so none should be included in the attestation
// extension.
- assertThat(teeAttestation.getSecondImei()).isNull();
+ assertThat(attestedSecondImei).isNull();
} else if (deviceShippedWithKeyMint3) {
// The device has a second IMEI and should attest to it.
- assertThat(teeAttestation.getSecondImei()).isEqualTo(expectedSecondImei);
+ assertThat(attestedSecondImei).isEqualTo(expectedSecondImei);
} else {
// Device has KeyMint 3, but originally shipped with an earlier KeyMint and
// may not have provisioned the second IMEI as an attestation ID.
// It does not have to support attesting to the second IMEI, but if there is something
// in the attestation record, it must match the platform-provided second IMEI.
- if (!TextUtils.isEmpty(teeAttestation.getSecondImei())) {
- assertThat(teeAttestation.getSecondImei()).isEqualTo(expectedSecondImei);
+ if (!TextUtils.isEmpty(attestedSecondImei)) {
+ assertThat(attestedSecondImei).isEqualTo(expectedSecondImei);
}
}
}
+ private void validateDeviceIdAttestationDataUsingExtLib(Certificate leaf,
+ String expectedSerial,
+ String expectedImei,
+ String expectedMeid,
+ String expectedSecondImei)
+ throws CertificateParsingException, IOException {
+ ParsedAttestationRecord parsedAttestationRecord =
+ createParsedAttestationRecord((X509Certificate) leaf);
+
+ com.google.android.attestation.AuthorizationList teeAttestation =
+ parsedAttestationRecord.teeEnforced;
+
+ assertThat(teeAttestation).isNotNull();
+ assertThat(new String(teeAttestation.attestationIdBrand.get())).isEqualTo(Build.BRAND);
+ assertThat(new String(teeAttestation.attestationIdDevice.get())).isEqualTo(Build.DEVICE);
+ assertThat(new String(teeAttestation.attestationIdProduct.get())).isEqualTo(Build.PRODUCT);
+ assertThat(new String(teeAttestation.attestationIdManufacturer.get()))
+ .isEqualTo(Build.MANUFACTURER);
+ assertThat(new String(teeAttestation.attestationIdModel.get())).isEqualTo(Build.MODEL);
+
+ assertThat(!TextUtils.isEmpty(expectedSerial))
+ .isEqualTo(teeAttestation.attestationIdSerial.isPresent());
+ if (!TextUtils.isEmpty(expectedSerial)) {
+ assertThat(new String(teeAttestation.attestationIdSerial.get()))
+ .isEqualTo(expectedSerial);
+ }
+ assertThat(!TextUtils.isEmpty(expectedImei))
+ .isEqualTo(teeAttestation.attestationIdImei.isPresent());
+ if (!TextUtils.isEmpty(expectedImei)) {
+ assertThat(new String(teeAttestation.attestationIdImei.get()))
+ .isEqualTo(expectedImei);
+ }
+ assertThat(!TextUtils.isEmpty(expectedMeid))
+ .isEqualTo(teeAttestation.attestationIdMeid.isPresent());
+ if (!TextUtils.isEmpty(expectedMeid)) {
+ assertThat(new String(teeAttestation.attestationIdMeid.get()))
+ .isEqualTo(expectedMeid);
+ }
+ // TODO: Second IMEI parsing is not supported by external library yet,
+ // hence skipping for now.
+ /* validateSecondImei(new String(teeAttestation.attestationIdSecondImei.get()),
+ expectedSecondImei); */
+ }
+
private void validateAttestationRecord(List<Certificate> attestation, byte[] providedChallenge)
throws CertificateParsingException {
assertThat(attestation).isNotNull();
@@ -376,6 +428,10 @@
}
validateDeviceIdAttestationData(attestation, expectedSerial,
expectedImei, expectedMeid, expectedSecondImei);
+ // Validate attestation record using external library. As above validation
+ // is successful external library validation should also pass.
+ validateDeviceIdAttestationDataUsingExtLib(attestation, expectedSerial,
+ expectedImei, expectedMeid, expectedSecondImei);
}
} catch (UnsupportedOperationException expected) {
// Make sure the test only fails if the device is not meant to support Device
diff --git a/tests/tests/libcorefileio/TEST_MAPPING b/tests/tests/libcorefileio/TEST_MAPPING
index 0ba15be..0a3423f 100644
--- a/tests/tests/libcorefileio/TEST_MAPPING
+++ b/tests/tests/libcorefileio/TEST_MAPPING
@@ -1,16 +1,7 @@
{
- "kernel-presubmit": [
+ "kernel-postsubmit": [
{
- "name": "CtsLibcoreFileIOTestCases",
- "options": [
- {
- // TODO(b/236710517)
- "exclude-filter": "android.cts.FileChannelInterProcessLockTest#test_lockJJZ_Exclusive_asyncChannel"
- },
- {
- "exclude-filter": "android.cts.FileChannelInterProcessLockTest#test_tryLockJJZ_Exclusive_syncChannel"
- }
- ]
+ "name": "CtsLibcoreFileIOTestCases"
}
]
}
diff --git a/tests/tests/match_flags/src/android/matchflags/cts/MatchFlagTests.java b/tests/tests/match_flags/src/android/matchflags/cts/MatchFlagTests.java
index ddc8a63..aa9aa29 100644
--- a/tests/tests/match_flags/src/android/matchflags/cts/MatchFlagTests.java
+++ b/tests/tests/match_flags/src/android/matchflags/cts/MatchFlagTests.java
@@ -27,6 +27,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.FeatureUtil;
import com.android.compatibility.common.util.ShellUtils;
import org.junit.After;
@@ -121,6 +122,7 @@
@Test
public void startNoBrowserRequireDefaultUnapproved() throws Exception {
+ assumeFalse("Skipping test for watch", FeatureUtil.isWatch());
setDomainUserSelectionApproval(false);
startNoBrowserRequireDefaultInternal(false);
}
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
index 2faed09..212642b 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
@@ -23,7 +23,6 @@
import static android.media.MediaCodecInfo.CodecProfileLevel.VP9Profile2;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
@@ -230,17 +229,30 @@
}
}
- @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{4})")
+ @Parameterized.Parameters(name = "{index}({0}_{1}_{2}_{3}_{4}_{5})")
public static Collection<Object[]> input() {
- final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
- // mediaType, width, height, bitrate, useHighBitDepth
- {MediaFormat.MIMETYPE_VIDEO_AVC, 176, 144, 1000000, false},
- {MediaFormat.MIMETYPE_VIDEO_AVC, 320, 240, 2000000, false},
- {MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720, 6000000, false},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, 176, 144, 1000000, true},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, 320, 240, 2000000, true},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, 1280, 720, 6000000, true},
+ final List<Object[]> baseArgsList = Arrays.asList(new Object[][]{
+ // width, height, bitrate
+ {176, 144, 1000000},
+ {320, 240, 2000000},
+ {1280, 720, 6000000}
});
+ final String[] mediaTypes = {MediaFormat.MIMETYPE_VIDEO_AVC,
+ MediaFormat.MIMETYPE_VIDEO_HEVC, MediaFormat.MIMETYPE_VIDEO_VP8,
+ MediaFormat.MIMETYPE_VIDEO_VP9, MediaFormat.MIMETYPE_VIDEO_AV1};
+ final boolean[] useHighBitDepthModes = {false, true};
+ final List<Object[]> exhaustiveArgsList = new ArrayList<>();
+ for (boolean useHighBitDepth : useHighBitDepthModes) {
+ for (String mediaType : mediaTypes) {
+ for (Object[] obj : baseArgsList) {
+ if (mediaType.equals(MediaFormat.MIMETYPE_VIDEO_VP8) && useHighBitDepth) {
+ continue;
+ }
+ exhaustiveArgsList.add(
+ new Object[]{mediaType, obj[0], obj[1], obj[2], useHighBitDepth});
+ }
+ }
+ }
return prepareParamList(exhaustiveArgsList);
}
@@ -304,10 +316,7 @@
throws IOException {
VideoChunks sourceChunks = new VideoChunks();
- if (!generateVideoFile(sourceChunks)) {
- // No AVC codec? Fail silently.
- return;
- }
+ generateVideoFile(sourceChunks);
if (DEBUG_SAVE_FILE) {
// Save a copy to a file. We call it ".mp4", but it's actually just an elementary
@@ -333,10 +342,8 @@
/**
* Generates a test video file, saving it as VideoChunks. We generate frames with GL to
* avoid having to deal with multiple YUV formats.
- *
- * @return true on success, false on "soft" failure
*/
- private boolean generateVideoFile(VideoChunks output)
+ private void generateVideoFile(VideoChunks output)
throws IOException {
if (VERBOSE) Log.d(TAG, "generateVideoFile " + mWidth + "x" + mHeight);
MediaCodec encoder = null;
@@ -390,8 +397,6 @@
inputSurface.release();
}
}
-
- return true;
}
/**
@@ -463,18 +468,15 @@
fail("encoderOutputBuffer " + encoderStatus + " was null");
}
- // Codec config flag must be set iff this is the first chunk of output. This
- // may not hold for all codecs, but it appears to be the case for video/avc.
- assertTrue((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0 ||
- outputCount != 0);
-
if (info.size != 0) {
// Adjust the ByteBuffer values to match BufferInfo.
encodedData.position(info.offset);
encodedData.limit(info.offset + info.size);
output.addChunk(encodedData, info.flags, info.presentationTimeUs);
- outputCount++;
+ if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) {
+ outputCount++;
+ }
}
encoder.releaseOutputBuffer(encoderStatus, false);
@@ -486,8 +488,7 @@
}
}
- // One chunk per frame, plus one for the config data.
- assertEquals("Frame count", NUM_FRAMES + 1, outputCount);
+ assertEquals("Frame count", NUM_FRAMES, outputCount);
}
/**
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 b712fdf..30e8477 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
@@ -708,7 +708,7 @@
if (VERBOSE) Log.d(TAG, "decoder output format changed: " +
decoderOutputFormat);
} else if (decoderStatus < 0) {
- fail("unexpected result from deocder.dequeueOutputBuffer: " + decoderStatus);
+ fail("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
} else { // decoderStatus >= 0
if (!toSurface) {
ByteBuffer outputFrame = decoderOutputBuffers[decoderStatus];
@@ -863,7 +863,7 @@
if (VERBOSE) Log.d(TAG, "decoder output format changed: " +
decoderOutputFormat);
} else if (decoderStatus < 0) {
- fail("unexpected result from deocder.dequeueOutputBuffer: " + decoderStatus);
+ fail("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
} else { // decoderStatus >= 0
if (VERBOSE) Log.d(TAG, "surface decoder given buffer " + decoderStatus +
" (size=" + info.size + ")");
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
index 2baad3f..96f05c6 100755
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -359,7 +359,7 @@
if (VERBOSE) Log.d(TAG, "decoder output format changed: " +
decoderOutputFormat);
} else if (decoderStatus < 0) {
- fail("unexpected result from deocder.dequeueOutputBuffer: " + decoderStatus);
+ fail("unexpected result from decoder.dequeueOutputBuffer: " + decoderStatus);
} else { // decoderStatus >= 0
if (VERBOSE) Log.d(TAG, "surface decoder given buffer " + decoderStatus +
" (size=" + info.size + ")");
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecCapabilitiesTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecCapabilitiesTest.java
index 32b0e3a..341c822 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecCapabilitiesTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecCapabilitiesTest.java
@@ -747,7 +747,15 @@
int minFrameRate = Math.max(vcaps.getSupportedFrameRatesFor(minWidth, minHeight)
.getLower().intValue(), 1);
format = MediaFormat.createVideoFormat(mime, minWidth, minHeight);
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT, caps.colorFormats[0]);
+ int colorFormat = caps.colorFormats[0];
+ for (int i = 0; i < caps.colorFormats.length; ++i) {
+ colorFormat = caps.colorFormats[i];
+ // Avoid COLOR_FormatSurface as we will be configuring the codec without a surface.
+ if (colorFormat != CodecCapabilities.COLOR_FormatSurface) {
+ break;
+ }
+ }
+ format.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat);
format.setInteger(MediaFormat.KEY_BIT_RATE, minBitrate);
format.setInteger(MediaFormat.KEY_FRAME_RATE, minFrameRate);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
diff --git a/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java b/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
index 785c83d..97158b0 100644
--- a/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
+++ b/tests/tests/media/common/src/android/media/cts/MediaCodecClearKeyPlayer.java
@@ -15,6 +15,8 @@
*/
package android.media.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.content.Context;
import android.content.res.Resources;
import android.media.AudioManager;
@@ -325,6 +327,8 @@
}
mMediaCas.provision(sProvisionStr);
+ // If AIDL CAS service is being used, then setMediaCas will not work.
+ assumeFalse(mMediaCas.isAidlHal());
extractor.setMediaCas(mMediaCas);
break;
}
diff --git a/tests/tests/media/decoder/jni/native-media-jni.cpp b/tests/tests/media/decoder/jni/native-media-jni.cpp
index d9a265e..236a97a 100755
--- a/tests/tests/media/decoder/jni/native-media-jni.cpp
+++ b/tests/tests/media/decoder/jni/native-media-jni.cpp
@@ -300,13 +300,12 @@
int numtracks = AMediaExtractor_getTrackCount(ex);
- AMediaCodec **codec = new AMediaCodec*[numtracks];
- AMediaFormat **format = new AMediaFormat*[numtracks];
- memset(format, 0, sizeof(AMediaFormat*) * numtracks);
- bool *sawInputEOS = new bool[numtracks];
- bool *sawOutputEOS = new bool[numtracks];
- simplevector<int> *sizes = new simplevector<int>[numtracks];
- CallbackData *callbackData = new CallbackData[numtracks];
+ std::unique_ptr<AMediaCodec*[]> codec(new AMediaCodec*[numtracks]());
+ std::unique_ptr<AMediaFormat*[]> format(new AMediaFormat*[numtracks]());
+ std::unique_ptr<bool[]> sawInputEOS(new bool[numtracks]);
+ std::unique_ptr<bool[]> sawOutputEOS(new bool[numtracks]);
+ std::unique_ptr<simplevector<int>[]> sizes(new simplevector<int>[numtracks]);
+ std::unique_ptr<CallbackData[]> callbackData(new CallbackData[numtracks]);
ALOGV("input has %d tracks", numtracks);
for (int i = 0; i < numtracks; i++) {
@@ -458,17 +457,11 @@
}
env->ReleaseIntArrayElements(ret, org, 0);
- delete[] callbackData;
- delete[] sizes;
- delete[] sawOutputEOS;
- delete[] sawInputEOS;
for (int i = 0; i < numtracks; i++) {
AMediaFormat_delete(format[i]);
AMediaCodec_stop(codec[i]);
AMediaCodec_delete(codec[i]);
}
- delete[] format;
- delete[] codec;
AMediaExtractor_delete(ex);
AMediaDataSource_delete(ndkSrc);
return ret;
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 48eaa42..9750f30 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
@@ -507,7 +507,7 @@
if (VERBOSE) Log.v(TAG, "decoder output format changed: " + outFormat);
} else if (res < 0) {
// Should be decoding error.
- fail("unexpected result from deocder.dequeueOutputBuffer: " + res);
+ fail("unexpected result from decoder.dequeueOutputBuffer: " + res);
} else {
if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
sawOutputEOS = true;
diff --git a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index f879528..3c2ca72 100644
--- a/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -20,6 +20,7 @@
import android.media.MediaDrm.KeyStatus;
import android.media.MediaDrm.MediaDrmStateException;
import android.media.MediaDrmException;
+import android.media.MediaDrmThrowable;
import android.media.MediaFormat;
import android.media.NotProvisionedException;
import android.media.ResourceBusyException;
@@ -51,6 +52,7 @@
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.junit.Assert;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -968,6 +970,10 @@
if (!Arrays.equals(deviceId, getByteArrayProperty(drm, DEVICEID_PROPERTY_KEY))) {
throw new Error("Failed to set byte array for key=" + DEVICEID_PROPERTY_KEY);
}
+
+ for (String k: new String[] {"oemError", "errorContext"}) {
+ testIntegerProperties(drm, k);
+ }
} finally {
stopDrm(drm);
}
@@ -1232,10 +1238,16 @@
MediaDrm drm = null;
boolean gotException = false;
+ final int OEM_ERROR = 123;
+ final int ERROR_CONTEXT = 456;
try {
drm = new MediaDrm(CLEARKEY_SCHEME_UUID);
drm.setPropertyString("drmErrorTest", "resourceContention");
+ if (getClearkeyVersionInt(drm) >= 14) {
+ drm.setPropertyString("oemError", Integer.toString(OEM_ERROR));
+ drm.setPropertyString("errorContext", Integer.toString(ERROR_CONTEXT));
+ }
byte[] sessionId = drm.openSession();
try {
@@ -1248,6 +1260,13 @@
if(sIsAtLeastS && !e.isTransient()) {
throw new Error("Expected transient ERROR_RESOURCE_CONTENTION");
}
+ if (getClearkeyVersionInt(drm) >= 14) {
+ final MediaDrmThrowable mdt = e;
+ final int RESOURCE_CONTENTION_AIDL = 16;
+ assertEquals("Vendor Error mismatch", mdt.getVendorError(), RESOURCE_CONTENTION_AIDL);
+ assertEquals("OEM Error mismatch", mdt.getOemError(), OEM_ERROR);
+ assertEquals("Error context mismatch", mdt.getErrorContext(), ERROR_CONTEXT);
+ }
gotException = true;
}
} catch(Exception e) {
@@ -1643,8 +1662,6 @@
assertTrue("Expected ERROR_SESSION_NOT_OPENED value in info",
e.getDiagnosticInfo().contains(
String.valueOf(MediaDrm.ErrorCodes.ERROR_SESSION_NOT_OPENED)));
- assertEquals("No vendor error expected from Clearkey", 0, e.getVendorError());
- assertEquals("No OEM error expected from Clearkey", 0, e.getOemError());
} finally {
if (drm != null) {
drm.close();
@@ -1652,6 +1669,25 @@
}
}
+ private void testIntegerProperties(MediaDrm drm, String testKey)
+ throws ResourceBusyException, UnsupportedSchemeException, NotProvisionedException {
+ if (getClearkeyVersionInt(drm) < 14) {
+ return;
+ }
+ String testValue = "123456";
+ assertEquals("Default value not 0", drm.getPropertyString(testKey), "0");
+ Assert.assertThrows("Non-numeric must throw", Exception.class, () -> {
+ drm.setPropertyString(testKey, "xyz"); });
+ Assert.assertThrows("Non-integral must throw", Exception.class, () -> {
+ drm.setPropertyString(testKey, "3.141"); });
+ Assert.assertThrows("Out-of-range (MAX) must throw", Exception.class, () -> {
+ drm.setPropertyString(testKey, Long.toString(Long.MAX_VALUE)); });
+ Assert.assertThrows("Out-of-range (MIN) must throw", Exception.class, () -> {
+ drm.setPropertyString(testKey, Long.toString(Long.MIN_VALUE)); });
+ drm.setPropertyString(testKey, testValue);
+ assertEquals("Property didn't match", drm.getPropertyString(testKey), testValue);
+ }
+
private String getClearkeyVersion(MediaDrm drm) {
try {
return drm.getPropertyString("version");
@@ -1660,6 +1696,14 @@
}
}
+ private int getClearkeyVersionInt(MediaDrm drm) {
+ try {
+ return Integer.parseInt(drm.getPropertyString("version"));
+ } catch (Exception e) {
+ return Integer.MIN_VALUE;
+ }
+ }
+
private boolean cannotHandleGetPropertyByteArray(MediaDrm drm) {
boolean apiNotSupported = false;
byte[] bytes = new byte[0];
diff --git a/tests/tests/ndef/OWNERS b/tests/tests/ndef/OWNERS
index d92b2ab..5a93fd0 100644
--- a/tests/tests/ndef/OWNERS
+++ b/tests/tests/ndef/OWNERS
@@ -2,4 +2,5 @@
alisher@google.com
jackcwyu@google.com
georgekgchang@google.com
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
diff --git a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java
index d114ab5..b527e77 100644
--- a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java
+++ b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/TestUtils.java
@@ -18,28 +18,29 @@
import android.net.http.AndroidHttpClient;
-import java.io.InputStream;
+import junit.framework.Assert;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+
import java.io.IOException;
+import java.io.InputStream;
import java.net.HttpURLConnection;
-import java.net.Socket;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import java.util.List;
import java.util.ArrayList;
+import java.util.List;
+
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
-import junit.framework.Assert;
-
-import org.apache.http.HttpResponse;
-import org.apache.http.client.methods.HttpGet;
-
public final class TestUtils extends Assert {
private TestUtils() {
@@ -91,8 +92,9 @@
private static void assertSslSocketFails(String host, int port)
throws Exception {
try {
- Socket s = SSLContext.getDefault().getSocketFactory().createSocket(host, port);
- s.getInputStream();
+ SSLSocket s =
+ (SSLSocket) SSLContext.getDefault().getSocketFactory().createSocket(host, port);
+ s.startHandshake();
fail("Connection to " + host + ":" + port + " succeeded");
} catch (SSLHandshakeException expected) {
}
@@ -100,8 +102,9 @@
private static void assertSslSocketSucceeds(String host, int port)
throws Exception {
- Socket s = SSLContext.getDefault().getSocketFactory().createSocket(host, port);
- s.getInputStream();
+ SSLSocket s =
+ (SSLSocket) SSLContext.getDefault().getSocketFactory().createSocket(host, port);
+ s.startHandshake();
}
private static void assertUrlConnectionFails(String host, int port, boolean https)
diff --git a/tests/tests/nfc/AndroidManifest.xml b/tests/tests/nfc/AndroidManifest.xml
index 3e1d16a..ae7fa49 100644
--- a/tests/tests/nfc/AndroidManifest.xml
+++ b/tests/tests/nfc/AndroidManifest.xml
@@ -33,6 +33,9 @@
<meta-data android:name="android.nfc.cardemulation.host_apdu_service"
android:resource="@xml/payment_aid_list"/>
</service>
+ <activity android:name="android.nfc.cts.NfcFCardEmulationActivity"
+ android:exported="false">
+ </activity>
</application>
<!-- This is a self-instrumenting test package. -->
@@ -43,4 +46,4 @@
android:value="com.android.cts.runner.CtsTestRunListener"/>
</instrumentation>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/tests/tests/nfc/OWNERS b/tests/tests/nfc/OWNERS
index d92b2ab..5a93fd0 100644
--- a/tests/tests/nfc/OWNERS
+++ b/tests/tests/nfc/OWNERS
@@ -2,4 +2,5 @@
alisher@google.com
jackcwyu@google.com
georgekgchang@google.com
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
diff --git a/tests/tests/nfc/src/android/nfc/cts/CardEmulationTest.java b/tests/tests/nfc/src/android/nfc/cts/CardEmulationTest.java
new file mode 100644
index 0000000..b1e83b4
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/CardEmulationTest.java
@@ -0,0 +1,281 @@
+package android.nfc.cts;
+
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.nfc.cardemulation.*;
+import android.nfc.INfcCardEmulation;
+import android.nfc.NfcAdapter;
+import android.os.RemoteException;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.internal.util.reflection.FieldSetter;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(JUnit4.class)
+public class CardEmulationTest {
+ private NfcAdapter mAdapter;
+ private static final ComponentName mService =
+ new ComponentName("android.nfc.cts", "android.nfc.cts.CtsMyHostApduService");
+
+ @Mock private INfcCardEmulation mEmulation;
+
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ assumeTrue(supportsHardware());
+ Context mContext = InstrumentationRegistry.getContext();
+ mAdapter = NfcAdapter.getDefaultAdapter(mContext);
+ Assert.assertNotNull(mAdapter);
+ }
+
+ @Test
+ public void getNonNullInstance() {
+ CardEmulation instance = CardEmulation.getInstance(mAdapter);
+ Assert.assertNotNull(instance);
+ }
+
+ @Test
+ public void testIsDefaultServiceForCategory() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ when(mEmulation.isDefaultServiceForCategory(anyInt(), any(ComponentName.class),
+ anyString())).thenReturn(true);
+ boolean result = instance.isDefaultServiceForCategory(mService,
+ CardEmulation.CATEGORY_PAYMENT);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testIsDefaultServiceForAid() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ String aid = "00000000000000";
+ when(mEmulation.isDefaultServiceForAid(anyInt(), any(ComponentName.class), anyString()))
+ .thenReturn(true);
+ boolean result = instance.isDefaultServiceForAid(mService, aid);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testCategoryAllowsForegroundPreferenceWithCategoryPayment() {
+ CardEmulation instance = CardEmulation.getInstance(mAdapter);
+ boolean result
+ = instance.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_PAYMENT);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testCategoryAllowsForegroundPrefenceWithCategoryOther() {
+ CardEmulation instance = CardEmulation.getInstance(mAdapter);
+ boolean result
+ = instance.categoryAllowsForegroundPreference(CardEmulation.CATEGORY_OTHER);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testGetSelectionModeForCategoryWithCategoryPaymentAndPaymentRegistered()
+ throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ when(mEmulation.isDefaultPaymentRegistered()).thenReturn(true);
+ int result = instance.getSelectionModeForCategory(CardEmulation.CATEGORY_PAYMENT);
+ Assert.assertEquals(CardEmulation.SELECTION_MODE_PREFER_DEFAULT, result);
+ }
+
+ @Test
+ public void testGetSelectionModeForCategoryWithCategoryPaymentAndWithoutPaymentRegistered()
+ throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ when(mEmulation.isDefaultPaymentRegistered()).thenReturn(false);
+ int result = instance.getSelectionModeForCategory(CardEmulation.CATEGORY_PAYMENT);
+ Assert.assertEquals(CardEmulation.SELECTION_MODE_ALWAYS_ASK, result);
+ }
+
+ @Test
+ public void testGetSelectionModeForCategoryWithCategoryOther() {
+ CardEmulation instance = CardEmulation.getInstance(mAdapter);
+ int result = instance.getSelectionModeForCategory(CardEmulation.CATEGORY_OTHER);
+ Assert.assertEquals(CardEmulation.SELECTION_MODE_ASK_IF_CONFLICT, result);
+ }
+
+ @Test
+ public void testRegisterAidsForService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ ArrayList<String> aids = new ArrayList<String>();
+ aids.add("00000000000000");
+ when(mEmulation.registerAidGroupForService(anyInt(), any(ComponentName.class),
+ any(AidGroup.class))).thenReturn(true);
+ boolean result
+ = instance.registerAidsForService(mService, CardEmulation.CATEGORY_PAYMENT, aids);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testUnsetOffHostForService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ when(mEmulation.unsetOffHostForService(anyInt(), any(ComponentName.class)))
+ .thenReturn(true);
+ boolean result = instance.unsetOffHostForService(mService);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testSetOffHostForService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ String offHostSecureElement = "eSE";
+ when(mEmulation.setOffHostForService(anyInt(), any(ComponentName.class), anyString()))
+ .thenReturn(true);
+ boolean result = instance.setOffHostForService(mService, offHostSecureElement);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testGetAidsForService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ ArrayList<String> aids = new ArrayList<String>();
+ aids.add("00000000000000");
+ AidGroup aidGroup = new AidGroup(aids, CardEmulation.CATEGORY_PAYMENT);
+ when(mEmulation.getAidGroupForService(anyInt(), any(ComponentName.class), anyString()))
+ .thenReturn(aidGroup);
+ List<String> result = instance.getAidsForService(mService, CardEmulation.CATEGORY_PAYMENT);
+ Assert.assertEquals(aids, result);
+ }
+
+ @Test
+ public void testRemoveAidsForService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ when(mEmulation.removeAidGroupForService(anyInt(), any(ComponentName.class), anyString()))
+ .thenReturn(true);
+ boolean result = instance.removeAidsForService(mService, CardEmulation.CATEGORY_PAYMENT);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testSetPreferredService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ Activity activity = createAndResumeActivity();
+ when(mEmulation.setPreferredService(any(ComponentName.class))).thenReturn(true);
+ boolean result = instance.setPreferredService(activity, mService);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testUnsetPreferredService() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ Activity activity = createAndResumeActivity();
+ when(mEmulation.unsetPreferredService()).thenReturn(true);
+ boolean result = instance.unsetPreferredService(activity);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testSupportsAidPrefixRegistration() throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ when(mEmulation.supportsAidPrefixRegistration()).thenReturn(true);
+ boolean result = instance.supportsAidPrefixRegistration();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testGetAidsForPreferredPaymentService() throws NoSuchFieldException,
+ RemoteException {
+ CardEmulation instance = createMockedInstance();
+ ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>();
+ ArrayList<String> aids = new ArrayList<String>();
+ aids.add("00000000000000");
+ AidGroup aidGroup = new AidGroup(aids, CardEmulation.CATEGORY_PAYMENT);
+ dynamicAidGroups.add(aidGroup);
+ ApduServiceInfo serviceInfo = new ApduServiceInfo(new ResolveInfo(), false, "",
+ new ArrayList<AidGroup>(), dynamicAidGroups, false, 0, 0, "", "", "");
+ when(mEmulation.getPreferredPaymentService(anyInt())).thenReturn(serviceInfo);
+ List<String> result = instance.getAidsForPreferredPaymentService();
+ Assert.assertEquals(aids, result);
+ }
+
+ @Test
+ public void testGetRouteDestinationForPreferredPaymentServiceWithOnHost()
+ throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ ApduServiceInfo serviceInfo = new ApduServiceInfo(new ResolveInfo(), /* onHost = */ true,
+ "", new ArrayList<AidGroup>(), new ArrayList<AidGroup>(), false, 0, 0, "", "", "");
+ when(mEmulation.getPreferredPaymentService(anyInt())).thenReturn(serviceInfo);
+ String result = instance.getRouteDestinationForPreferredPaymentService();
+ Assert.assertEquals("Host", result);
+ }
+
+ @Test
+ public void testGetRouteDestinationForPreferredPaymentServiceWithOffHostAndNoSecureElement()
+ throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ ApduServiceInfo serviceInfo = new ApduServiceInfo(new ResolveInfo(), /* onHost = */ false,
+ "", new ArrayList<AidGroup>(), new ArrayList<AidGroup>(), false, 0, 0, "",
+ /* offHost = */ null, "");
+ when(mEmulation.getPreferredPaymentService(anyInt())).thenReturn(serviceInfo);
+ String result = instance.getRouteDestinationForPreferredPaymentService();
+ Assert.assertEquals("OffHost", result);
+ }
+
+ @Test
+ public void testGetRouteDestinationForPreferredPaymentServiceWithOffHostAndSecureElement()
+ throws NoSuchFieldException, RemoteException {
+ CardEmulation instance = createMockedInstance();
+ String offHostSecureElement = "OffHost Secure Element";
+ ApduServiceInfo serviceInfo = new ApduServiceInfo(new ResolveInfo(), /* onHost = */ false,
+ "", new ArrayList<AidGroup>(), new ArrayList<AidGroup>(), false, 0, 0, "",
+ /* offHost = */ offHostSecureElement, "");
+ when(mEmulation.getPreferredPaymentService(anyInt())).thenReturn(serviceInfo);
+ String result = instance.getRouteDestinationForPreferredPaymentService();
+ Assert.assertEquals(offHostSecureElement, result);
+ }
+
+ @Test
+ public void testGetDescriptionForPreferredPaymentService() throws NoSuchFieldException,
+ RemoteException {
+ CardEmulation instance = createMockedInstance();
+ String description = "Preferred Payment Service Description";
+ ApduServiceInfo serviceInfo = new ApduServiceInfo(new ResolveInfo(), false,
+ /* description */ description, new ArrayList<AidGroup>(), new ArrayList<AidGroup>(),
+ false, 0, 0, "", "", "");
+ when(mEmulation.getPreferredPaymentService(anyInt())).thenReturn(serviceInfo);
+ CharSequence result = instance.getDescriptionForPreferredPaymentService();
+ Assert.assertEquals(description, result);
+ }
+
+ private Activity createAndResumeActivity() {
+ Intent intent
+ = new Intent(ApplicationProvider.getApplicationContext(),
+ NfcFCardEmulationActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
+ InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
+ return activity;
+ }
+
+ private CardEmulation createMockedInstance() throws NoSuchFieldException {
+ CardEmulation instance = CardEmulation.getInstance(mAdapter);
+ FieldSetter.setField(instance, instance.getClass().getDeclaredField("sService"), mEmulation);
+ return instance;
+ }
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/CtsMyHostNfcFService.java b/tests/tests/nfc/src/android/nfc/cts/CtsMyHostNfcFService.java
new file mode 100644
index 0000000..32095ff
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/CtsMyHostNfcFService.java
@@ -0,0 +1,16 @@
+package android.nfc.cts;
+
+import android.nfc.cardemulation.*;
+import android.os.Bundle;
+
+public class CtsMyHostNfcFService extends HostNfcFService {
+ @Override
+ public byte[] processNfcFPacket(byte[] commandPacket, Bundle extras) {
+ return new byte[0];
+ }
+
+ @Override
+ public void onDeactivated(int reason) {
+ return;
+ }
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/HostNfcFServiceTest.java b/tests/tests/nfc/src/android/nfc/cts/HostNfcFServiceTest.java
new file mode 100644
index 0000000..cf41790
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/HostNfcFServiceTest.java
@@ -0,0 +1,56 @@
+package android.nfc.cts;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Looper;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class HostNfcFServiceTest {
+ private CtsMyHostNfcFService service;
+
+ @Before
+ public void setUp() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ service = new CtsMyHostNfcFService();
+ }
+
+ @Test
+ public void testOnBind() {
+ Intent serviceIntent
+ = new Intent(CtsMyHostNfcFService.SERVICE_INTERFACE);
+ Assert.assertNotNull(service.onBind(serviceIntent));
+ }
+
+ @Test
+ public void testSendResponsePacket() {
+ try {
+ byte[] responsePacket = new byte[0];
+ service.sendResponsePacket(responsePacket);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+
+ @Test
+ public void testProcessNfcFPacket() {
+ byte[] result = service.processNfcFPacket(new byte[0], new Bundle());
+ Assert.assertNotNull(result);
+ Assert.assertTrue(result.length == 0);
+ }
+
+ @Test
+ public void testOnDeactivated() {
+ try {
+ service.onDeactivated(CtsMyHostNfcFService.DEACTIVATION_LINK_LOSS);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcAdapterTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcAdapterTest.java
new file mode 100644
index 0000000..5453adb
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcAdapterTest.java
@@ -0,0 +1,249 @@
+package android.nfc.cts;
+
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doNothing;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.nfc.*;
+import android.nfc.tech.*;
+import android.os.Bundle;
+import android.os.RemoteException;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+import java.util.HashMap;
+
+@RunWith(JUnit4.class)
+public class NfcAdapterTest {
+ @Mock private INfcAdapter mService;
+ private Context mContext;
+
+ private boolean supportsHardware() {
+ final PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC);
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = InstrumentationRegistry.getContext();
+ assumeTrue(supportsHardware());
+ }
+
+ @Test
+ public void testGetDefaultAdapter() {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ Assert.assertNotNull(adapter);
+ }
+
+ @Test
+ public void testAddNfcUnlockHandler() {
+ try {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ adapter.addNfcUnlockHandler(new CtsNfcUnlockHandler(), new String[]{"IsoDep"});
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+
+ @Test
+ public void testDisableWithNoParams() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.disable(anyBoolean())).thenReturn(true);
+ boolean result = adapter.disable();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testDisableWithParam() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.disable(anyBoolean())).thenReturn(true);
+ boolean result = adapter.disable(true);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testDisableForegroundDispatch() {
+ try {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ Activity activity = createAndResumeActivity();
+ adapter.disableForegroundDispatch(activity);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+
+ @Test
+ public void testDisableReaderMode() {
+ try {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ Activity activity = createAndResumeActivity();
+ adapter.disableReaderMode(activity);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+
+ @Test
+ public void testEnable() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.enable()).thenReturn(true);
+ boolean result = adapter.enable();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testEnableForegroundDispatch() {
+ try {
+ NfcAdapter adapter = createMockedInstance();
+ Activity activity = createAndResumeActivity();
+ Intent intent = new Intent(ApplicationProvider.getApplicationContext(),
+ NfcFCardEmulationActivity.class);
+ PendingIntent pendingIntent
+ = PendingIntent.getActivity(ApplicationProvider.getApplicationContext(),
+ 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
+ String[][] techLists = new String[][]{new String[]{}};
+ doNothing().when(mService).setForegroundDispatch(any(PendingIntent.class),
+ any(IntentFilter[].class), any(TechListParcel.class));
+ adapter.enableForegroundDispatch(activity, pendingIntent, null, techLists);
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+
+ @Test
+ public void testEnableReaderMode() {
+ try {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ Activity activity = createAndResumeActivity();
+ adapter.enableReaderMode(activity, new CtsReaderCallback(),
+ NfcAdapter.FLAG_READER_NFC_A, new Bundle());
+ } catch (Exception e) {
+ throw new IllegalStateException("Unexpected Exception: " + e);
+ }
+ }
+
+ @Test
+ public void testEnableSecureNfc() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.setNfcSecure(anyBoolean())).thenReturn(true);
+ boolean result = adapter.enableSecureNfc(true);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testGetNfcAntennaInfo() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ NfcAntennaInfo info = new NfcAntennaInfo(0, 0, false,
+ new ArrayList<AvailableNfcAntenna>());
+ when(mService.getNfcAntennaInfo()).thenReturn(info);
+ NfcAntennaInfo result = adapter.getNfcAntennaInfo();
+ Assert.assertEquals(info, result);
+ }
+
+ @Test
+ public void testIgnore() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ Tag tag = new Tag(new byte[]{0x00}, new int[]{}, new Bundle[]{}, 0, 0L, null);
+ when(mService.ignore(anyInt(), anyInt(), eq(null))).thenReturn(true);
+ boolean result = adapter.ignore(tag, 0, null, null);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testIsControllerAlwaysOn() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.isControllerAlwaysOn()).thenReturn(true);
+ boolean result = adapter.isControllerAlwaysOn();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testIsControllerAlwaysOnSupported() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.isControllerAlwaysOnSupported()).thenReturn(true);
+ boolean result = adapter.isControllerAlwaysOnSupported();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testIsEnabled() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.getState()).thenReturn(NfcAdapter.STATE_ON);
+ boolean result = adapter.isEnabled();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testIsSecureNfcEnabled() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.isNfcSecureEnabled()).thenReturn(true);
+ boolean result = adapter.isSecureNfcEnabled();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testIsSecureNfcSupported() throws NoSuchFieldException, RemoteException {
+ NfcAdapter adapter = createMockedInstance();
+ when(mService.deviceSupportsNfcSecure()).thenReturn(true);
+ boolean result = adapter.isSecureNfcSupported();
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testRemoveNfcUnlockHandler() {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ boolean result = adapter.removeNfcUnlockHandler(new CtsNfcUnlockHandler());
+ Assert.assertTrue(result);
+ }
+
+ private class CtsReaderCallback implements NfcAdapter.ReaderCallback {
+ @Override
+ public void onTagDiscovered(Tag tag) {}
+ }
+
+ private class CtsNfcUnlockHandler implements NfcAdapter.NfcUnlockHandler {
+ @Override
+ public boolean onUnlockAttempted(Tag tag) {
+ return true;
+ }
+ }
+
+ private Activity createAndResumeActivity() {
+ Intent intent = new Intent(ApplicationProvider.getApplicationContext(),
+ NfcFCardEmulationActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
+ InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
+ return activity;
+ }
+
+ private NfcAdapter createMockedInstance() throws NoSuchFieldException {
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
+ FieldSetter.setField(adapter, adapter.getClass().getDeclaredField("sService"), mService);
+ return adapter;
+ }
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java
index 7746d3a..18ca614 100644
--- a/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java
@@ -28,16 +28,16 @@
import androidx.test.InstrumentationRegistry;
+import java.util.ArrayList;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class NfcAntennaLocationApiTest {
- private static int sDeviceWidth = 111;
- private static int sDeviceHeight = 112;
- private static boolean sDeviceFoldable = true;
- private static int sAntennaX = 12;
- private static int sAntennaY = 13;
+
+ private static final int ANTENNA_X = 12;
+ private static final int ANTENNA_Y = 13;
private boolean supportsHardware() {
final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
@@ -61,23 +61,41 @@
/** Tests getNfcAntennaInfo API */
@Test
- public void testNfcAntennaInfoIsReturned() {
+ public void testGetNfcAntennaInfo() {
NfcAntennaInfo nfcAntennaInfo = mAdapter.getNfcAntennaInfo();
- assertEquals("Device widths do not match", sDeviceWidth,
+ assertEquals("Device widths do not match", 0,
nfcAntennaInfo.getDeviceWidth());
- assertEquals("Device heights do not match", sDeviceHeight,
+ assertEquals("Device heights do not match", 0,
nfcAntennaInfo.getDeviceHeight());
- assertEquals("Device foldable do not match", sDeviceFoldable,
+ assertEquals("Device foldable do not match", false,
nfcAntennaInfo.isDeviceFoldable());
- assertEquals("Wrong number of available antennas", 1,
+ assertEquals("Wrong number of available antennas", 0,
nfcAntennaInfo.getAvailableNfcAntennas().size());
- AvailableNfcAntenna availableNfcAntenna = nfcAntennaInfo.getAvailableNfcAntennas().get(0);
+ AvailableNfcAntenna availableNfcAntenna = new AvailableNfcAntenna(ANTENNA_X, ANTENNA_Y);
assertEquals("Wrong nfc antenna X axis",
- availableNfcAntenna.getLocationX(), sAntennaX);
+ availableNfcAntenna.getLocationX(), ANTENNA_X);
assertEquals("Wrong nfc antenna Y axis",
- availableNfcAntenna.getLocationY(), sAntennaY);
+ availableNfcAntenna.getLocationY(), ANTENNA_Y);
+ }
+
+ @Test
+ public void testNfcAntennaInfoConstructor() {
+ int deviceWidth = 0;
+ int deviceHeight = 0;
+ boolean deviceFoldable = false;
+ NfcAntennaInfo nfcAntennaInfo = new NfcAntennaInfo(deviceWidth, deviceHeight,
+ deviceFoldable, new ArrayList<AvailableNfcAntenna>());
+
+ assertEquals("Device widths do not match", deviceWidth,
+ nfcAntennaInfo.getDeviceWidth());
+ assertEquals("Device heights do not match", deviceHeight,
+ nfcAntennaInfo.getDeviceHeight());
+ assertEquals("Device foldable do not match", deviceFoldable,
+ nfcAntennaInfo.isDeviceFoldable());
+ assertEquals("Wrong number of available antennas", 0,
+ nfcAntennaInfo.getAvailableNfcAntennas().size());
}
}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcFCardEmulationActivity.java b/tests/tests/nfc/src/android/nfc/cts/NfcFCardEmulationActivity.java
new file mode 100644
index 0000000..ff9c115
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcFCardEmulationActivity.java
@@ -0,0 +1,6 @@
+package android.nfc.cts;
+
+import android.app.Activity;
+
+public class NfcFCardEmulationActivity extends Activity {
+}
diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcFCardEmulationTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcFCardEmulationTest.java
new file mode 100644
index 0000000..0d3828a
--- /dev/null
+++ b/tests/tests/nfc/src/android/nfc/cts/NfcFCardEmulationTest.java
@@ -0,0 +1,142 @@
+package android.nfc.cts;
+
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.nfc.cardemulation.*;
+import android.nfc.INfcFCardEmulation;
+import android.nfc.NfcAdapter;
+import android.os.RemoteException;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.io.IOException;
+
+@RunWith(JUnit4.class)
+public class NfcFCardEmulationTest {
+ private NfcAdapter mAdapter;
+ private static final ComponentName mService =
+ new ComponentName("android.nfc.cts", "android.nfc.cts.CtsMyHostApduService");
+
+ @Mock private INfcFCardEmulation mockEmulation;
+
+ private boolean supportsHardware() {
+ final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION_NFCF);
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ assumeTrue(supportsHardware());
+ Context mContext = InstrumentationRegistry.getContext();
+ mAdapter = NfcAdapter.getDefaultAdapter(mContext);
+ Assert.assertNotNull(mAdapter);
+ }
+
+ @Test
+ public void getNonNullInstance() {
+ NfcFCardEmulation instance = NfcFCardEmulation.getInstance(mAdapter);
+ Assert.assertNotNull(instance);
+ }
+
+ @Test
+ public void testGetSystemCodeForService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ String code = "System Code";
+ when(mockEmulation.getSystemCodeForService(anyInt(),any(ComponentName.class)))
+ .thenReturn(code);
+ String result = instance.getSystemCodeForService(mService);
+ Assert.assertEquals(result, code);
+ }
+
+ @Test
+ public void testRegisterCodeForService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ String code = "4000";
+ when(mockEmulation.registerSystemCodeForService(anyInt(), any(ComponentName.class), anyString()))
+ .thenReturn(true);
+ boolean result = instance.registerSystemCodeForService(mService, code);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testUnregisterSystemCodeForService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ when(mockEmulation.removeSystemCodeForService(anyInt(), any(ComponentName.class)))
+ .thenReturn(true);
+ boolean result = instance.unregisterSystemCodeForService(mService);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testGetNfcid2ForService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ String testNfcid2 = "02FE000000000000";
+ when(mockEmulation.getNfcid2ForService(anyInt(), any(ComponentName.class)))
+ .thenReturn(testNfcid2);
+ String result = instance.getNfcid2ForService(mService);
+ Assert.assertEquals(result, testNfcid2);
+ }
+
+ @Test
+ public void testSetNfcid2ForService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ String testNfcid2 = "02FE000000000000";
+ when(mockEmulation.setNfcid2ForService(anyInt(), any(ComponentName.class), anyString()))
+ .thenReturn(true);
+ boolean result = instance.setNfcid2ForService(mService, testNfcid2);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testEnableService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ Activity activity = createAndResumeActivity();
+ when(mockEmulation.enableNfcFForegroundService(any(ComponentName.class))).thenReturn(true);
+ boolean result = instance.enableService(activity, mService);
+ Assert.assertTrue(result);
+ }
+
+ @Test
+ public void testDisableService() throws NoSuchFieldException, RemoteException {
+ NfcFCardEmulation instance = createMockedInstance();
+ Activity activity = createAndResumeActivity();
+ when(mockEmulation.disableNfcFForegroundService()).thenReturn(true);
+ boolean result = instance.disableService(activity);
+ Assert.assertTrue(result);
+ }
+
+ private Activity createAndResumeActivity() {
+ Intent intent
+ = new Intent(ApplicationProvider.getApplicationContext(),
+ NfcFCardEmulationActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent);
+ InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity);
+ return activity;
+ }
+
+ private NfcFCardEmulation createMockedInstance() throws NoSuchFieldException {
+ NfcFCardEmulation instance = NfcFCardEmulation.getInstance(mAdapter);
+ FieldSetter.setField(instance, instance.getClass().getDeclaredField("sService"), mockEmulation);
+ return instance;
+ }
+}
diff --git a/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt b/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt
index 29638bd..6a1077c 100644
--- a/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt
+++ b/tests/tests/notificationlegacy/notificationlegacy30/src/android/app/notification/legacy30/cts/NotificationTemplateApi30Test.kt
@@ -19,7 +19,6 @@
import android.app.Notification
import android.app.cts.NotificationTemplateTestBase
import android.content.pm.PackageManager
-import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.TextView
@@ -58,11 +57,10 @@
}
fun testWideIcon_inBigPicture_isSquareForLegacyApps() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testWideIcon_inBigPicture_isSquareForLegacyApps" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val icon = createBitmap(200, 100)
val views = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -92,11 +90,10 @@
}
fun testPromoteBigPicture_withoutLargeIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withoutLargeIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_media_play)
@@ -111,8 +108,7 @@
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(40)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(30)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
// there should be no icon in the large state
checkIconView(builder.createBigContentView()) { iconView ->
@@ -121,11 +117,10 @@
}
fun testPromoteBigPicture_withLargeIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withLargeIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val icon = createBitmap(80, 65)
val builder = Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID)
@@ -137,36 +132,26 @@
.showBigPictureWhenCollapsed(true)
)
- // At really high densities the size of rendered icon can dip below the
- // tested size - we allow rendering of smaller icon with the same
- // aspect ratio then.
- val expectedIconWidth = minOf(rightIconSize(), 80)
- val expectedIconHeight = minOf(rightIconSize() * 65 / 80, 65)
-
// the promoted big picture is shown with enlarged aspect ratio
checkIconView(builder.createContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(40)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(30)
}
// because it doesn't target S, the icon is still shown in a square
checkIconView(builder.createBigContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width).isEqualTo(iconView.height)
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(expectedIconWidth)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(expectedIconHeight)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
fun testPromoteBigPicture_withBigLargeIcon() {
- if (isPlatformAutomotive()) {
- Log.i(TAG, "Skipping: testPromoteBigPicture_withBigLargeIcon" +
- " - BigPictureStyle is not supported in automotive.")
+ if (skipIfPlatformDoesNotSupportNotificationStyles()) {
return
}
+
val picture = createBitmap(40, 30)
val inputWidth = 400
val inputHeight = 300
@@ -180,24 +165,19 @@
.showBigPictureWhenCollapsed(true)
)
- val expectedIconWidth = minOf(rightIconSize(), inputWidth)
- val expectedIconHeight = minOf(rightIconSize() * inputHeight / inputWidth, inputHeight)
-
// the promoted big picture is shown with enlarged aspect ratio
checkIconView(builder.createContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width.toFloat())
.isWithin(1f)
.of((iconView.height * 4 / 3).toFloat())
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(40)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(30)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
// because it doesn't target S, the icon is still shown in a square
checkIconView(builder.createBigContentView()) { iconView ->
assertThat(iconView.visibility).isEqualTo(View.VISIBLE)
assertThat(iconView.width).isEqualTo(iconView.height)
- assertThat(iconView.drawable.intrinsicWidth).isEqualTo(expectedIconWidth)
- assertThat(iconView.drawable.intrinsicHeight).isEqualTo(expectedIconHeight)
+ assertThat(iconView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
@@ -314,17 +294,18 @@
}
}
- private fun rightIconSize(): Int {
- return mContext.resources.getDimensionPixelSize(
- getAndroidRDimen("notification_right_icon_size"))
- }
-
- private fun isPlatformAutomotive(): Boolean {
- return mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ /**
+ * Assume that we're running on the platform that supports styled notifications.
+ *
+ * If the current platform does not support notification styles, skip this test without failure.
+ */
+ private fun skipIfPlatformDoesNotSupportNotificationStyles(): Boolean {
+ return mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE) ||
+ mContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
}
companion object {
val TAG = NotificationTemplateApi30Test::class.java.simpleName
const val NOTIFICATION_CHANNEL_ID = "NotificationTemplateApi30Test"
}
-}
\ No newline at end of file
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/MatrixTest.java b/tests/tests/opengl/src/android/opengl/cts/MatrixTest.java
new file mode 100644
index 0000000..574905b
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/MatrixTest.java
@@ -0,0 +1,606 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.graphics.cts;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
+
+import android.opengl.Matrix;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class MatrixTest {
+
+ @Test
+ public void testMultiplyMM() {
+ // Assert legal arguments
+ float[] mat = new float[16];
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM(null, 0, mat, 0, mat, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( mat, 0, null, 0, mat, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( mat, 0, mat, 0, null, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( mat, 1, mat, 0, mat, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( mat, 0, mat, 1, mat, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( mat, 0, mat, 0, mat, 1));
+
+ float[] matResult = new float[16];
+ float[] matLhs = new float[16];
+ float[] matRhs = new float[16];
+
+ // Test that identity = identity * identity
+ Matrix.setIdentityM(matLhs, 0);
+ Matrix.setIdentityM(matRhs, 0);
+ Matrix.multiplyMM(matResult, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matResult, new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f});
+
+ // Test that checks mult of two diagonal matrices
+ matLhs = new float[] {
+ 2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 3.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 5.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 7.0f,
+ };
+ matRhs = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 3.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 5.0f,
+ };
+ Matrix.multiplyMM(matResult, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matResult, new float[] {
+ 2.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 6.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 15.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 35.0f});
+
+ // Tests that checks mult of two triangular matrices
+ matLhs = new float[] {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 0.0f, 5.0f, 6.0f, 7.0f,
+ 0.0f, 0.0f, 8.0f, 9.0f,
+ 0.0f, 0.0f, 0.0f, 10.0f,
+ };
+ matRhs = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 2.0f, 5.0f, 0.0f, 0.0f,
+ 3.0f, 6.0f, 8.0f, 0.0f,
+ 4.0f, 7.0f, 9.0f, 10.0f,
+ };
+ Matrix.multiplyMM(matResult, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matResult, new float[] {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 2.0f, 29.0f, 36.0f, 43.0f,
+ 3.0f, 36.0f, 109.0f, 126.0f,
+ 4.0f, 43.0f, 126.0f, 246.0f});
+
+ matLhs = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 2.0f, 5.0f, 0.0f, 0.0f,
+ 3.0f, 6.0f, 8.0f, 0.0f,
+ 4.0f, 7.0f, 9.0f, 10.0f,
+ };
+ matRhs = new float[] {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 0.0f, 5.0f, 6.0f, 7.0f,
+ 0.0f, 0.0f, 8.0f, 9.0f,
+ 0.0f, 0.0f, 0.0f, 10.0f,
+ };
+ Matrix.multiplyMM(matResult, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matResult, new float[] {
+ 30.0f, 56.0f, 60.0f, 40.0f,
+ 56.0f, 110.0f, 111.0f, 70.0f,
+ 60.0f, 111.0f, 145.0f, 90.0f,
+ 40.0f, 70.0f, 90.0f, 100.0f});
+
+ // Test that checks mult of two filled matrices
+ matLhs = new float[] {
+ 1.0f, 7.0f, 19.0f, 37.0f,
+ 2.0f, 11.0f, 23.0f, 41.0f,
+ 3.0f, 13.0f, 29.0f, 43.0f,
+ 5.0f, 17.0f, 31.0f, 47.0f,
+ };
+ matRhs = new float[] {
+ 1.0f, 5.0f, 9.0f, 13.0f,
+ 2.0f, 6.0f, 10.0f, 14.0f,
+ 3.0f, 7.0f, 11.0f, 15.0f,
+ 4.0f, 8.0f, 12.0f, 16.0f,
+ };
+ Matrix.multiplyMM(matResult, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matResult, new float[] {
+ 103.0f, 400.0f, 798.0f, 1240.0f,
+ 114.0f, 448.0f, 900.0f, 1408.0f,
+ 125.0f, 496.0f, 1002.0f, 1576.0f,
+ 136.0f, 544.0f, 1104.0f, 1744.0f});
+ }
+
+ @Test
+ public void testMultiplyMMInPlace() {
+ float[] matLhs = new float[16];
+ float[] matRhs = new float[16];
+
+ // Multiply RHS in place
+ matLhs = new float[] {
+ 1.0f, 7.0f, 19.0f, 37.0f,
+ 2.0f, 11.0f, 23.0f, 41.0f,
+ 3.0f, 13.0f, 29.0f, 43.0f,
+ 5.0f, 17.0f, 31.0f, 47.0f,
+ };
+ matRhs = new float[] {
+ 1.0f, 5.0f, 9.0f, 13.0f,
+ 2.0f, 6.0f, 10.0f, 14.0f,
+ 3.0f, 7.0f, 11.0f, 15.0f,
+ 4.0f, 8.0f, 12.0f, 16.0f,
+ };
+ Matrix.multiplyMM(matRhs, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matRhs, new float[] {
+ 103.0f, 400.0f, 798.0f, 1240.0f,
+ 114.0f, 448.0f, 900.0f, 1408.0f,
+ 125.0f, 496.0f, 1002.0f, 1576.0f,
+ 136.0f, 544.0f, 1104.0f, 1744.0f});
+
+ // Multiply LHS in place
+ matLhs = new float[] {
+ 1.0f, 7.0f, 19.0f, 37.0f,
+ 2.0f, 11.0f, 23.0f, 41.0f,
+ 3.0f, 13.0f, 29.0f, 43.0f,
+ 5.0f, 17.0f, 31.0f, 47.0f,
+ };
+ matRhs = new float[] {
+ 1.0f, 5.0f, 9.0f, 13.0f,
+ 2.0f, 6.0f, 10.0f, 14.0f,
+ 3.0f, 7.0f, 11.0f, 15.0f,
+ 4.0f, 8.0f, 12.0f, 16.0f,
+ };
+ Matrix.multiplyMM(matLhs, 0, matLhs, 0, matRhs, 0);
+ verifyMatrix(matLhs, new float[] {
+ 103.0f, 400.0f, 798.0f, 1240.0f,
+ 114.0f, 448.0f, 900.0f, 1408.0f,
+ 125.0f, 496.0f, 1002.0f, 1576.0f,
+ 136.0f, 544.0f, 1104.0f, 1744.0f});
+
+ // Multiply both in place
+ float[] mat = new float[] {
+ 1.0f, 7.0f, 19.0f, 37.0f,
+ 2.0f, 11.0f, 23.0f, 41.0f,
+ 3.0f, 13.0f, 29.0f, 43.0f,
+ 5.0f, 17.0f, 31.0f, 47.0f,
+ };
+ Matrix.multiplyMM(mat, 0, mat, 0, mat, 0);
+ verifyMatrix(mat, new float[] {
+ 257.0f, 960.0f, 1878.0f, 2880.0f,
+ 298.0f, 1131.0f, 2229.0f, 3441.0f,
+ 331.0f, 1272.0f, 2530.0f, 3912.0f,
+ 367.0f, 1424.0f, 2842.0f, 4424.0f});
+ }
+
+ @Test
+ public void testMultiplyMV() {
+ // Assert legal arguments
+ float[] mat = new float[16];
+ float[] vec = new float[4];
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMV(null, 0, mat, 0, vec, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( vec, 0, null, 0, vec, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( vec, 0, mat, 0, null, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( vec, 1, mat, 0, vec, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( vec, 0, mat, 1, vec, 0));
+ assertThrows(IllegalArgumentException.class,
+ () -> Matrix.multiplyMM( vec, 0, mat, 0, vec, 1));
+
+ float[] vecResult = new float[4];
+ float[] matLhs = new float[16];
+ float[] vecRhs = new float[4];
+
+ // Test that vector = identity * vector
+ Matrix.setIdentityM(matLhs, 0);
+ vecRhs = new float[] {1.0f, 2.0f, 3.0f, 4.0f};
+ Matrix.multiplyMV(vecResult, 0, matLhs, 0, vecRhs, 0);
+ verifyVector(vecResult, new float[] {1.0f, 2.0f, 3.0f, 4.0f});
+
+ // Test that checks mult of a diagonal matrix with an arbitrary vector
+ matLhs = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 2.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 3.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 5.0f,
+ };
+ vecRhs = new float[] {2.0f, 3.0f, 5.0f, 7.0f};
+ Matrix.multiplyMV(vecResult, 0, matLhs, 0, vecRhs, 0);
+ verifyVector(vecResult, new float[] {2.0f, 6.0f, 15.0f, 35.0f});
+
+ // Tests that checks mult of a triangular matrix with an arbitrary vector
+ matLhs = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 2.0f, 5.0f, 0.0f, 0.0f,
+ 3.0f, 6.0f, 8.0f, 0.0f,
+ 4.0f, 7.0f, 9.0f, 10.0f,
+ };
+ vecRhs = new float[] {1.0f, 2.0f, 3.0f, 5.0f};
+ Matrix.multiplyMV(vecResult, 0, matLhs, 0, vecRhs, 0);
+ verifyVector(vecResult, new float[] {34.0f, 63.0f, 69.0f, 50.0f});
+
+ matLhs = new float[] {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 0.0f, 5.0f, 6.0f, 7.0f,
+ 0.0f, 0.0f, 8.0f, 9.0f,
+ 0.0f, 0.0f, 0.0f, 10.0f,
+ };
+ vecRhs = new float[] {1.0f, 2.0f, 3.0f, 5.0f};
+ Matrix.multiplyMV(vecResult, 0, matLhs, 0, vecRhs, 0);
+ verifyVector(vecResult, new float[] {1.0f, 12.0f, 39.0f, 95.0f});
+
+ // Arbitrary filled matrix times arbitrary vector
+ matLhs = new float[] {
+ 1.0f, 7.0f, 19.0f, 37.0f,
+ 2.0f, 11.0f, 23.0f, 41.0f,
+ 3.0f, 13.0f, 29.0f, 43.0f,
+ 5.0f, 17.0f, 31.0f, 47.0f,
+ };
+ vecRhs = new float[] {2.0f, 3.0f, 5.0f, 7.0f};
+ Matrix.multiplyMV(vecResult, 0, matLhs, 0, vecRhs, 0);
+ verifyVector(vecResult, new float[] {58.0f, 231.0f, 469.0f, 741.0f});
+ }
+
+ @Test
+ public void testMultiplyMVInPlace() {
+ float[] matLhs = new float[] {
+ 1.0f, 7.0f, 19.0f, 37.0f,
+ 2.0f, 11.0f, 23.0f, 41.0f,
+ 3.0f, 13.0f, 29.0f, 43.0f,
+ 5.0f, 17.0f, 31.0f, 47.0f,
+ };
+ float[] vecRhs = new float[] {2.0f, 3.0f, 5.0f, 7.0f};
+ Matrix.multiplyMV(vecRhs, 0, matLhs, 0, vecRhs, 0);
+ verifyVector(vecRhs, new float[] {58.0f, 231.0f, 469.0f, 741.0f});
+ }
+
+ @Test
+ public void testTransposeM() {
+ /* matrices are stored in column-major order.
+ *
+ * | 1 0 0 0 |
+ * | 2 5 0 0 |
+ * | 3 6 8 0 |
+ * | 4 7 9 10 |
+ *
+ * is initialized as
+ */
+ float[] mat = new float[] {
+ 1.0f, 2.0f, 3.0f, 4.0f,
+ 0.0f, 5.0f, 6.0f, 7.0f,
+ 0.0f, 0.0f, 8.0f, 9.0f,
+ 0.0f, 0.0f, 0.0f, 10.0f,
+ };
+
+ /* the matrix once transposed should be:
+ * | 1 2 3 4 |
+ * | 0 5 6 7 |
+ * | 0 0 8 9 |
+ * | 0 0 0 10 |
+ *
+ * and represented as
+ */
+ float[] matTranspose = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 2.0f, 5.0f, 0.0f, 0.0f,
+ 3.0f, 6.0f, 8.0f, 0.0f,
+ 4.0f, 7.0f, 9.0f, 10.0f,
+ };
+
+ float[] matResult = new float[16];
+ Matrix.transposeM(matResult, 0, mat, 0);
+ verifyMatrix(matResult, matTranspose);
+ }
+
+ @Test
+ public void testInvertM() {
+ // Inverse of identity is identity
+ float[] matIden = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+
+ float[] mat = matIden;
+ float[] matResult = new float[16];
+
+ Matrix.invertM(matResult, 0, mat, 0);
+ verifyMatrix(matResult, matIden);
+
+ // Inverse of arbitrary nonsingular matrix
+ mat = new float[] {
+ 0.814f, 4.976f, -3.858f, 7.206f,
+ 5.112f, -2.420f, 8.791f, 6.426f,
+ 2.945f, 1.801f, -2.594f, 2.663f,
+ -5.003f, -4.188f, 3.340f, -1.235f
+ };
+ float[] matInv = new float[] {
+ -0.112707f, 0.033867f, 0.189963f, -0.071792f,
+ 0.158030f, 0.011872f, -0.603463f, -0.317385f,
+ 0.056107f, 0.076268f, -0.406444f, -0.152194f,
+ 0.072418f, 0.028810f, 0.177650f, 0.145793f,
+ };
+ Matrix.invertM(matResult, 0, mat, 0);
+ verifyMatrix(matResult, matInv, 0.001f);
+ }
+
+ @Test
+ public void testLength() {
+ float zeroLength = Matrix.length(0.0f, 0.0f, 0.0f);
+ assertEquals(zeroLength, 0.0f, 0.001f);
+
+ float unitLength = Matrix.length(1.0f, 0.0f, 0.0f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+ unitLength = Matrix.length(0.0f, 1.0f, 0.0f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+ unitLength = Matrix.length(0.0f, 0.0f, 1.0f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+
+ unitLength = Matrix.length(0.707107f, 0.707107f, 0.0f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+ unitLength = Matrix.length(0.0f, 0.707107f, 0.707107f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+ unitLength = Matrix.length(0.707107f, 0.0f, 0.707107f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+
+ unitLength = Matrix.length(0.577350f, 0.577350f, 0.577350f);
+ assertEquals(unitLength, 1.0f, 0.001f);
+
+ float length = Matrix.length(1.0f, 1.0f, 1.0f);
+ assertEquals(length, 1.732051f, 0.001f);
+
+ length = Matrix.length(2.0f, 3.0f, 4.0f);
+ assertEquals(length, 5.385165f, 0.001f);
+ }
+
+ @Test
+ public void testSetIdentityM() {
+ float[] mat = new float[16];
+ Matrix.setIdentityM(mat, 0);
+ verifyMatrix(mat, new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f});
+ }
+
+ @Test
+ public void testRotateM() {
+ float[] mat = new float[16];
+ float[] matResult = new float[16];
+
+ // Rotate around X
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setIdentityM(matResult, 0);
+ Matrix.rotateM(matResult, 0, mat, 0, 45.0f, 1.0f, 0.0f, 0.0f);
+ float[] matRotate = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.7071f, 0.7071f, 0.0f,
+ 0.0f, -0.7071f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(matResult, matRotate, 0.001f);
+
+ // Rotate around Y
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setIdentityM(matResult, 0);
+ Matrix.rotateM(matResult, 0, mat, 0, 45.0f, 0.0f, 1.0f, 0.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.0f, -0.7071f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.7071f, 0.0f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(matResult, matRotate, 0.001f);
+
+ // Rotate around Z
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setIdentityM(matResult, 0);
+ Matrix.rotateM(matResult, 0, mat, 0, 45.0f, 0.0f, 0.0f, 1.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.7071f, 0.0f, 0.0f,
+ -0.7071f, 0.7071f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(matResult, matRotate, 0.001f);
+ }
+
+ @Test
+ public void testRotateMInPlace() {
+ float[] mat = new float[16];
+
+ // Rotate around X
+ Matrix.setIdentityM(mat, 0);
+ Matrix.rotateM(mat, 0, 45.0f, 1.0f, 0.0f, 0.0f);
+ float[] matRotate = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.7071f, 0.7071f, 0.0f,
+ 0.0f, -0.7071f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // Rotate around Y
+ Matrix.setIdentityM(mat, 0);
+ Matrix.rotateM(mat, 0, 45.0f, 0.0f, 1.0f, 0.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.0f, -0.7071f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.7071f, 0.0f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // Rotate around Z
+ Matrix.setIdentityM(mat, 0);
+ Matrix.rotateM(mat, 0, 45.0f, 0.0f, 0.0f, 1.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.7071f, 0.0f, 0.0f,
+ -0.7071f, 0.7071f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+ }
+
+ @Test
+ public void testSetRotateM() {
+ float[] mat = new float[16];
+
+ // Rotate around X
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateM(mat, 0, 45.0f, 1.0f, 0.0f, 0.0f);
+ float[] matRotate = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.7071f, 0.7071f, 0.0f,
+ 0.0f, -0.7071f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // Rotate around Y
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateM(mat, 0, 45.0f, 0.0f, 1.0f, 0.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.0f, -0.7071f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ 0.7071f, 0.0f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // Rotate around Z
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateM(mat, 0, 45.0f, 0.0f, 0.0f, 1.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.7071f, 0.0f, 0.0f,
+ -0.7071f, 0.7071f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+ }
+
+ @Test
+ public void testSetRotateEulerM() {
+ float[] mat = new float[16];
+
+ // Rotate around X
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateEulerM(mat, 0, 45.0f, 0.0f, 0.0f);
+ float[] matRotate = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.7071f, -0.7071f, 0.0f,
+ 0.0f, 0.7071f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // setRotateEulerM is broken around the Y axis
+
+ // Rotate around Z
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateEulerM(mat, 0, 0.0f, 0.0f, 45.0f);
+ matRotate = new float[] {
+ 0.7071f, -0.7071f, 0.0f, 0.0f,
+ 0.7071f, 0.7071f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+ }
+
+ @Test
+ public void testSetRotateEulerM2() {
+ float[] mat = new float[16];
+
+ // Rotate around X
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateEulerM2(mat, 0, 45.0f, 0.0f, 0.0f);
+ float[] matRotate = new float[] {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.7071f, -0.7071f, 0.0f,
+ 0.0f, 0.7071f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // Rotate around y
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateEulerM2(mat, 0, 0.0f, 45.0f, 0.0f);
+ matRotate = new float[] {
+ 0.7071f, 0.0f, 0.7071f, 0.0f,
+ 0.0f, 1.0f, 0.0f, 0.0f,
+ -0.7071f, 0.0f, 0.7071f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+
+ // Rotate around Z
+ Matrix.setIdentityM(mat, 0);
+ Matrix.setRotateEulerM2(mat, 0, 0.0f, 0.0f, 45.0f);
+ matRotate = new float[] {
+ 0.7071f, -0.7071f, 0.0f, 0.0f,
+ 0.7071f, 0.7071f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f
+ };
+ verifyMatrix(mat, matRotate, 0.001f);
+ }
+
+ private void verifyMatrix(float[] actual, float[] expected) {
+ if ((expected == null) || (expected.length != 16)) {
+ fail("Expected does not have 16 elements");
+ }
+ assertArrayEquals(actual, expected, 0.0f);
+ }
+
+ private void verifyMatrix(float[] actual, float[] expected, float delta) {
+ if ((expected == null) || (expected.length != 16)) {
+ fail("Expected does not have 16 elements");
+ }
+ assertArrayEquals(actual, expected, delta);
+ }
+
+ private void verifyVector(float[] actual, float[] expected) {
+ if ((expected == null) || (expected.length != 4)) {
+ fail("Expected does not have 4 elements");
+ }
+ assertArrayEquals(actual, expected, 0.0f);
+ }
+}
diff --git a/tests/tests/packageinstaller/OWNERS b/tests/tests/packageinstaller/OWNERS
new file mode 100644
index 0000000..a370d8a
--- /dev/null
+++ b/tests/tests/packageinstaller/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 36137
+include platform/frameworks/base:/PACKAGE_MANAGER_OWNERS
diff --git a/tests/tests/packageinstaller/install_appop_denied/src/android/packageinstaller/install_appop_denied/cts/ExternalSourcesTestAppOpDenied.kt b/tests/tests/packageinstaller/install_appop_denied/src/android/packageinstaller/install_appop_denied/cts/ExternalSourcesTestAppOpDenied.kt
index 4c95738..1717f69 100644
--- a/tests/tests/packageinstaller/install_appop_denied/src/android/packageinstaller/install_appop_denied/cts/ExternalSourcesTestAppOpDenied.kt
+++ b/tests/tests/packageinstaller/install_appop_denied/src/android/packageinstaller/install_appop_denied/cts/ExternalSourcesTestAppOpDenied.kt
@@ -34,7 +34,7 @@
import org.junit.runner.RunWith
private const val INSTALL_CONFIRM_TEXT_ID = "install_confirm_question"
-private const val ALERT_DIALOG_TITLE_ID = "android:id/alertTitle"
+private const val ALERT_DIALOG_MESSAGE_ID = "android:id/message"
@RunWith(AndroidJUnit4::class)
@MediumTest
@@ -50,7 +50,7 @@
}
private fun assertInstallBlocked(errorMessage: String) {
- assertUiObject(errorMessage, By.res(ALERT_DIALOG_TITLE_ID))
+ assertUiObject(errorMessage, By.res(ALERT_DIALOG_MESSAGE_ID))
uiDevice.pressBack()
}
diff --git a/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java
index c2eae01..1b3f65e 100644
--- a/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NfcPermissionTest.java
@@ -19,6 +19,7 @@
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
+import android.app.ActivityManager;
import android.content.pm.PackageManager;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.ControllerAlwaysOnListener;
@@ -37,6 +38,7 @@
public final class NfcPermissionTest {
private NfcAdapter mNfcAdapter;
+ private static final String PKG_NAME = "com.android.packagename";
private boolean supportsHardware() {
final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
@@ -152,6 +154,58 @@
}
}
+ /**
+ * Verifies that isTagIntentAppPreferenceSupported() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission.WRITE_SECURE_SETTINGS}.
+ */
+ @Test
+ @AppModeFull
+ public void testIsTagIntentAppPreferenceSupported() {
+ try {
+ mNfcAdapter.isTagIntentAppPreferenceSupported();
+ fail("mNfcAdapter.isTagIntentAppPreferenceSupported() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that getTagIntentAppPreferenceForUser() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission.WRITE_SECURE_SETTINGS}.
+ */
+ @Test
+ @AppModeFull
+ public void testGetTagIntentAppPreferenceForUser() {
+ try {
+ mNfcAdapter.getTagIntentAppPreferenceForUser(ActivityManager.getCurrentUser());
+ fail("mNfcAdapter.getTagIntentAppPreferenceForUser() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
+ /**
+ * Verifies that setTagIntentAppPreferenceForUser() requires Permission.
+ * <p>
+ * Requires Permission: {@link android.Manifest.permission.WRITE_SECURE_SETTINGS}.
+ */
+ @Test
+ @AppModeFull
+ public void testSetTagIntentAppPreferenceForUser() {
+ try {
+ mNfcAdapter.setTagIntentAppPreferenceForUser(ActivityManager.getCurrentUser(),
+ PKG_NAME, true);
+ fail("mNfcAdapter.setTagIntentAppPreferenceForUser() did not throw SecurityException"
+ + " as expected");
+ } catch (SecurityException se) {
+ // Expected Exception
+ }
+ }
+
private class SynchronousExecutor implements Executor {
public void execute(Runnable r) {
r.run();
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index dfefabc..f2e6aff 100755
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -597,8 +597,8 @@
button.click()
}
- val shouldShowStorageWarning = !isWatch &&
- SdkLevel.isAtLeastT() && targetSdk <= Build.VERSION_CODES.S_V2 &&
+ val shouldShowStorageWarning = SdkLevel.isAtLeastT() &&
+ targetSdk <= Build.VERSION_CODES.S_V2 &&
permission in MEDIA_PERMISSIONS
if (shouldShowStorageWarning) {
click(By.res(ALERT_DIALOG_OK_BUTTON))
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
index 2a57406..0f80633 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionHistoryTest.kt
@@ -28,6 +28,7 @@
import org.junit.After
import org.junit.Assume.assumeFalse
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
import java.util.regex.Pattern
@@ -122,6 +123,7 @@
}
@Test
+ @Ignore
fun testToggleSystemApps() {
// I had some hard time mocking a system app.
// Hence here I am only testing if the toggle is there.
@@ -191,6 +193,7 @@
}
@Test
+ @Ignore
fun testToggleFrom24HoursTo7DaysInTimeline() {
// Auto doesn't support the 7 day view
assumeFalse(isAutomotive)
@@ -219,6 +222,7 @@
}
@Test
+ @Ignore
fun testMicrophoneTimelineWithOneApp() {
openMicrophoneApp(INTENT_ACTION_1)
waitFindObject(By.textContains(APP_LABEL_1))
@@ -242,6 +246,7 @@
}
@Test
+ @Ignore
fun testCameraTimelineWithMultipleApps() {
openMicrophoneApp(INTENT_ACTION_1)
waitFindObject(By.textContains(APP_LABEL_1))
diff --git a/tests/tests/print/printTestUtilLib/Android.bp b/tests/tests/print/printTestUtilLib/Android.bp
index 9abb4ee..da85b79 100644
--- a/tests/tests/print/printTestUtilLib/Android.bp
+++ b/tests/tests/print/printTestUtilLib/Android.bp
@@ -24,7 +24,6 @@
static_libs: [
"mockito-target-minus-junit4",
"ctstestrunner-axt",
- "ub-uiautomator",
"compatibility-device-util-axt",
"androidx.test.rules",
"platformprotosnano",
diff --git a/tests/tests/resolverservice/OWNERS b/tests/tests/resolverservice/OWNERS
index 978b1b4..87f734b 100644
--- a/tests/tests/resolverservice/OWNERS
+++ b/tests/tests/resolverservice/OWNERS
@@ -1,4 +1,2 @@
-# Bug component: 24950
-kanlig@google.com
-patb@google.com
-chiuwinson@google.com
\ No newline at end of file
+# Bug component: 36137
+include platform/frameworks/base:/PACKAGE_MANAGER_OWNERS
\ No newline at end of file
diff --git a/tests/tests/secure_element/access_control/OWNERS b/tests/tests/secure_element/access_control/OWNERS
index 6c4d2b3..f568bc3 100644
--- a/tests/tests/secure_element/access_control/OWNERS
+++ b/tests/tests/secure_element/access_control/OWNERS
@@ -2,4 +2,5 @@
alisher@google.com
jackcwyu@google.com
georgekgchang@google.com
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
diff --git a/tests/tests/secure_element/omapi/OWNERS b/tests/tests/secure_element/omapi/OWNERS
index 6c4d2b3..f568bc3 100644
--- a/tests/tests/secure_element/omapi/OWNERS
+++ b/tests/tests/secure_element/omapi/OWNERS
@@ -2,4 +2,5 @@
alisher@google.com
jackcwyu@google.com
georgekgchang@google.com
-zachoverflow@google.com
+sattiraju@google.com
+henrichataing@google.com
diff --git a/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp b/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp
index 9243595..41c9683 100644
--- a/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp
+++ b/tests/tests/security/native/verified_boot/VerifiedBootTest.cpp
@@ -97,6 +97,7 @@
// as current recommendations from NIST for hashing algorithms (SHA-256).
// @CddTest = 9.10/C-1-5
TEST(VerifiedBootTest, avbHashtreeNotUsingSha1) {
+ GTEST_SKIP() << "Skipping due to broken test. See b/264937051";
if (isExemptFromAVBTests()) {
GTEST_SKIP();
}
diff --git a/tests/tests/settings/src/android/settings/cts/AppLocaleSettingsTest.java b/tests/tests/settings/src/android/settings/cts/AppLocaleSettingsTest.java
index 85f5e5d..5bd31a7 100644
--- a/tests/tests/settings/src/android/settings/cts/AppLocaleSettingsTest.java
+++ b/tests/tests/settings/src/android/settings/cts/AppLocaleSettingsTest.java
@@ -17,6 +17,7 @@
package android.settings.cts;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeFalse;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -39,6 +40,9 @@
public class AppLocaleSettingsTest {
@Test
public void testAppLocaleSettingsExist() throws RemoteException {
+ assumeFalse(
+ "Skipping test: AppLocaleSettings is not supported in Wear OS",
+ isWatch());
final Intent intent = new Intent(Settings.ACTION_APP_LOCALE_SETTINGS);
intent.setData(Uri.parse("package:com.my.app"));
final ResolveInfo ri = InstrumentationRegistry.getTargetContext()
@@ -46,4 +50,9 @@
intent, PackageManager.MATCH_DEFAULT_ONLY);
assertTrue(ri != null);
}
+
+ private boolean isWatch() {
+ return InstrumentationRegistry.getTargetContext()
+ .getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
}
diff --git a/tests/tests/slice/Android.bp b/tests/tests/slice/Android.bp
index 891a682..d3d75f8 100644
--- a/tests/tests/slice/Android.bp
+++ b/tests/tests/slice/Android.bp
@@ -34,7 +34,6 @@
"metrics-helper-lib",
"mockito-target-inline-minus-junit4",
"platform-test-annotations",
- "ub-uiautomator",
],
compile_multilib: "both",
jni_libs: [
diff --git a/tests/tests/syncmanager/Android.bp b/tests/tests/syncmanager/Android.bp
index 2042319..b3d9216 100644
--- a/tests/tests/syncmanager/Android.bp
+++ b/tests/tests/syncmanager/Android.bp
@@ -26,7 +26,6 @@
"mockito-target-minus-junit4",
"compatibility-device-util-axt",
"ctstestrunner-axt",
- "ub-uiautomator",
],
libs: [
"android.test.runner",
diff --git a/tests/tests/syncmanager/apps/Android.bp b/tests/tests/syncmanager/apps/Android.bp
index cbcfe29..0cb4cb8 100644
--- a/tests/tests/syncmanager/apps/Android.bp
+++ b/tests/tests/syncmanager/apps/Android.bp
@@ -26,7 +26,6 @@
"androidx.legacy_legacy-support-v4",
"mockito-target-minus-junit4",
"compatibility-device-util-axt",
- "ub-uiautomator",
],
sdk_version: "test_current",
// tag this module as a cts test artifact
@@ -48,7 +47,6 @@
"androidx.legacy_legacy-support-v4",
"mockito-target-minus-junit4",
"compatibility-device-util-axt",
- "ub-uiautomator",
],
sdk_version: "test_current",
// tag this module as a cts test artifact
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
index 3f6d02f..f969182 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -18,6 +18,8 @@
import static androidx.test.InstrumentationRegistry.getInstrumentation;
+import static com.android.internal.telephony.SmsConstants.ENCODING_8BIT;
+
import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
@@ -425,7 +427,7 @@
/**
* Setup the SMS filter with only the {@code clientPrefix}, and sends {@code text} to the
* device. The SMS sent should not be written to the SMS provider. <p> If {@code expectVvmSms}
- * is {@code true}, the SMS should be be caught by the SMS filter. The user should not receive
+ * is {@code true}, the SMS should be caught by the SMS filter. The user should not receive
* the text, and the parsed result will be returned.* <p> If {@code expectVvmSms} is {@code
* false}, the SMS should pass through the SMS filter. The user should receive the text, and
* {@code null} be returned.
@@ -461,7 +463,7 @@
future.get(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
throw new RuntimeException("Unexpected visual voicemail SMS received");
} catch (TimeoutException e) {
- // expected
+ Log.i(TAG, "Expected TimeoutException" + e);
return null;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
@@ -473,7 +475,6 @@
@Nullable
private VisualVoicemailSms getSmsFromData(VisualVoicemailSmsFilterSettings settings, short port,
String text, boolean expectVvmSms) {
-
mTelephonyManager.setVisualVoicemailSmsFilterSettings(settings);
CompletableFuture<VisualVoicemailSms> future = new CompletableFuture<>();
@@ -497,7 +498,7 @@
future.get(EVENT_NOT_RECEIVED_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
throw new RuntimeException("Unexpected visual voicemail SMS received");
} catch (TimeoutException e) {
- // expected
+ Log.i(TAG, "Expected TimeoutException!" + e);
return null;
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
@@ -529,16 +530,28 @@
StringBuilder messageBody = new StringBuilder();
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
for (SmsMessage message : messages) {
- if (message.getMessageBody() != null) {
- messageBody.append(message.getMessageBody());
- } else if (message.getUserData() != null) {
+ String body = message.getMessageBody();
+
+ if ((body == null || (message.is3gpp()
+ && message.getReceivedEncodingType() == ENCODING_8BIT))
+ && message.getUserData() != null) {
+ Log.d(TAG, "onReceive decode using UTF-8");
+ // Attempt to interpret the user data as UTF-8. UTF-8 string over data SMS using
+ // 8BIT data coding scheme is our recommended way to send VVM SMS and is used in
+ // CTS Tests. The OMTP visual voicemail specification does not specify the SMS
+ // type and encoding.
ByteBuffer byteBuffer = ByteBuffer.wrap(message.getUserData());
try {
- messageBody.append(decoder.decode(byteBuffer).toString());
+ body = decoder.decode(byteBuffer).toString();
} catch (CharacterCodingException e) {
+ Log.e(TAG, "onReceive: got CharacterCodingException"
+ + " when decoding with UTF-8, e = " + e);
return;
}
}
+ if (body != null) {
+ messageBody.append(body);
+ }
}
if (!TextUtils.equals(mText, messageBody.toString())) {
return;
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
index 2256374..a268ea8558 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputManagerTest.java
@@ -20,6 +20,7 @@
import android.app.ActivityManager;
import android.app.ActivityManager.RunningAppProcessInfo;
import android.app.Instrumentation;
+import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -29,7 +30,6 @@
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
-import android.media.tv.cts.TvViewTest.MockCallback;
import android.media.tv.TunedInfo;
import android.media.tv.TvContentRating;
import android.media.tv.TvContract;
@@ -43,6 +43,7 @@
import android.media.tv.TvInputService;
import android.media.tv.TvStreamConfig;
import android.media.tv.TvView;
+import android.media.tv.cts.TvViewTest.MockCallback;
import android.media.tv.tunerresourcemanager.TunerResourceManager;
import android.net.Uri;
import android.os.Binder;
@@ -52,11 +53,8 @@
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase2;
import android.tv.cts.R;
-
-import com.android.compatibility.common.util.PollingCheck;
-
import androidx.test.InstrumentationRegistry;
-
+import com.android.compatibility.common.util.PollingCheck;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -64,7 +62,6 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
-
import org.xmlpull.v1.XmlPullParserException;
/**
@@ -119,6 +116,7 @@
};
private String mStubId;
+ private Context mContext;
private TvInputManager mManager;
private LoggingCallback mCallback = new LoggingCallback();
private TvInputInfo mStubTvInputInfo;
@@ -215,6 +213,7 @@
.adoptShellPermissionIdentity(BASE_SHELL_PERMISSIONS);
mInstrumentation = getInstrumentation();
+ mContext = mInstrumentation.getTargetContext();
mTvView = findTvViewById(R.id.tvview);
mManager = (TvInputManager) mActivity.getSystemService(Context.TV_INPUT_SERVICE);
mStubId = getInfoForClassName(
@@ -702,7 +701,7 @@
Handler handler = new Handler(Looper.getMainLooper());
final SessionCallback sessionCallback = new SessionCallback();
- mManager.createSession(mStubId, sessionCallback, handler);
+ mManager.createSession(mStubId, mContext.getAttributionSource(), sessionCallback, handler);
PollingCheck.waitFor(TIME_OUT_MS, () -> sessionCallback.getSession() != null);
Session session = sessionCallback.getSession();
String sessionId = StubTvInputService2.getSessionId();
@@ -743,7 +742,7 @@
Handler handler = new Handler(Looper.getMainLooper());
final SessionCallback sessionCallback = new SessionCallback();
- mManager.createSession(mStubId, sessionCallback, handler);
+ mManager.createSession(mStubId, mContext.getAttributionSource(), sessionCallback, handler);
PollingCheck.waitFor(TIME_OUT_MS, () -> sessionCallback.getSession() != null);
Session session = sessionCallback.getSession();
String sessionId = StubTvInputService2.getSessionId();
diff --git a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
index cd70293..e0b63b1 100644
--- a/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
+++ b/tests/tests/tv/src/android/media/tv/cts/TvInputServiceTest.java
@@ -17,13 +17,13 @@
package android.media.tv.cts;
import static androidx.test.ext.truth.view.MotionEventSubject.assertThat;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Instrumentation;
+import android.content.AttributionSource;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.PlaybackParams;
@@ -50,30 +50,25 @@
import android.view.SurfaceView;
import android.view.View;
import android.widget.LinearLayout;
-
import androidx.test.core.app.ActivityScenario;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
-
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.RequiredFeatureRule;
-
import com.google.common.truth.Truth;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Function;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
/**
* Test {@link android.media.tv.TvInputService}.
@@ -104,6 +99,7 @@
private TvRecordingClient mTvRecordingClient;
private Instrumentation mInstrumentation;
+ private Context mContext;
private TvInputManager mManager;
private TvInputInfo mStubInfo;
private TvInputInfo mFaultyStubInfo;
@@ -244,11 +240,10 @@
public void setUp() {
mInstrumentation = InstrumentationRegistry
.getInstrumentation();
- mTvRecordingClient = new TvRecordingClient(mInstrumentation.getTargetContext(),
- "TvInputServiceTest",
- mRecordingCallback, null);
- mManager = (TvInputManager) mInstrumentation.getTargetContext().getSystemService(
- Context.TV_INPUT_SERVICE);
+ mContext = mInstrumentation.getTargetContext();
+ mTvRecordingClient =
+ new TvRecordingClient(mContext, "TvInputServiceTest", mRecordingCallback, null);
+ mManager = (TvInputManager) mContext.getSystemService(Context.TV_INPUT_SERVICE);
for (TvInputInfo info : mManager.getTvInputList()) {
if (info.getServiceInfo().name.equals(CountingTvInputService.class.getName())) {
mStubInfo = info;
@@ -1037,6 +1032,7 @@
private CountingSession tune(Uri uri) {
onTvView(tvView -> {
tvView.setCallback(mCallback);
+ tvView.overrideTvAppAttributionSource(mContext.getAttributionSource());
tvView.tune(mStubInfo.getId(), CHANNEL_0);
});
return waitForSessionCheck(session -> session.mTuneCount > 0);
@@ -1095,6 +1091,13 @@
}
@Override
+ public Session onCreateSession(
+ String inputId, String tvInputSessionId, AttributionSource tvAppAttributionSource) {
+ // todo: add AttributionSource equal check
+ return onCreateSession(inputId, tvInputSessionId);
+ }
+
+ @Override
public RecordingSession onCreateRecordingSession(String inputId) {
return onCreateRecordingSession(inputId, null);
}
@@ -1169,7 +1172,6 @@
public volatile Integer mOverlayViewSizeChangedHeight;
public volatile Boolean mInteractiveAppNotificationEnabled;
-
CountingSession(Context context, @Nullable String sessionId) {
super(context);
diff --git a/tests/tests/uiautomation/Android.bp b/tests/tests/uiautomation/Android.bp
index b4d80a8..b41d2fb 100644
--- a/tests/tests/uiautomation/Android.bp
+++ b/tests/tests/uiautomation/Android.bp
@@ -27,7 +27,6 @@
static_libs: [
"CtsAccessibilityCommon",
"ctstestrunner-axt",
- "ub-uiautomator",
],
libs: ["android.test.base"],
srcs: ["src/**/*.java"],
diff --git a/tests/tests/usb/src/android/usb/cts/UsbManagerApiTest.java b/tests/tests/usb/src/android/usb/cts/UsbManagerApiTest.java
index beac44d..edb8131 100644
--- a/tests/tests/usb/src/android/usb/cts/UsbManagerApiTest.java
+++ b/tests/tests/usb/src/android/usb/cts/UsbManagerApiTest.java
@@ -105,7 +105,9 @@
// Should pass with permission.
int version = mUsbManagerSys.getGadgetHalVersion();
int usbBandwidth = mUsbManagerSys.getUsbBandwidthMbps();
- if (version > UsbManager.GADGET_HAL_V1_1) {
+ if (version > UsbManager.GADGET_HAL_V1_2) {
+ Assert.assertTrue(usbBandwidth >= UsbManager.USB_DATA_TRANSFER_RATE_UNKNOWN);
+ } else if (version > UsbManager.GADGET_HAL_V1_1) {
Assert.assertTrue(usbBandwidth > UsbManager.USB_DATA_TRANSFER_RATE_UNKNOWN);
} else {
Assert.assertEquals(usbBandwidth, UsbManager.USB_DATA_TRANSFER_RATE_UNKNOWN);
diff --git a/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java b/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java
index 68c4a77..20f7283 100644
--- a/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewUnbufferedTest.java
@@ -246,7 +246,7 @@
}
mReceivedEvents.add(new ReceivedEvent(event.getEventTime(), event.getAction(),
- (int) event.getX(), (int) event.getY(), event.getSource()));
+ Math.round(event.getX()), Math.round(event.getY()), event.getSource()));
// Always return true to make sure the event has been handled.
return true;
diff --git a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
index 82ee4d3..f7edd76 100644
--- a/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
+++ b/tests/tests/voiceRecognition/src/android/voicerecognition/cts/RecognitionServiceMicIndicatorTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import android.Manifest;
@@ -114,6 +115,10 @@
DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PRIVACY, INDICATORS_FLAG);
Log.v(TAG, "setup(): mOriginalIndicatorsState=" + mOriginalIndicatorsState);
});
+
+ // TODO(http://b/259941077): Remove once privacy indicators are implemented.
+ assumeFalse("Privacy indicators not supported", isWatch());
+
setIndicatorsEnabledState(Boolean.toString(true));
// Wait for any privacy indicator to disappear to avoid the test becoming flaky.
SystemClock.sleep(INDICATOR_DISMISS_TIMEOUT);
@@ -286,4 +291,9 @@
PackageManager pm = mContext.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
}
+
+ private boolean isWatch() {
+ PackageManager pm = mContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
+ }
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java b/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java
index ee6f11f..26f699d 100644
--- a/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/PacProcessorTest.java
@@ -20,11 +20,13 @@
import android.net.ConnectivityManager;
import android.net.Network;
import android.webkit.PacProcessor;
+import com.android.compatibility.common.util.NullWebViewUtils;
import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.After;
import org.junit.Assert;
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
@@ -79,6 +81,7 @@
*/
@Test
public void testCreatePacProcessor() throws Throwable {
+ Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable());
mProcess.run(TestCreatePacProcessor.class);
}
@@ -97,6 +100,7 @@
*/
@Test
public void testDefaultNetworkIsNull() throws Throwable {
+ Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable());
mProcess.run(TestDefaultNetworkIsNull.class);
}
@@ -131,6 +135,7 @@
*/
@Test
public void testSetNetwork() throws Throwable {
+ Assume.assumeTrue("WebView is not available", NullWebViewUtils.isWebViewAvailable());
mProcess.run(TestSetNetwork.class);
}
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index dd10626..01d866a 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -38,6 +38,8 @@
import android.webkit.cts.WebViewSyncLoader.WaitForLoadedClient;
import android.util.Pair;
+import androidx.test.filters.FlakyTest;
+
import com.android.compatibility.common.util.NullWebViewUtils;
import com.android.compatibility.common.util.PollingCheck;
import com.google.common.util.concurrent.SettableFuture;
@@ -141,6 +143,7 @@
// Verify shouldoverrideurlloading called on webview called via onCreateWindow
// TODO(sgurun) upstream this test to Aw.
+ @FlakyTest(bugId = 253448914)
public void testShouldOverrideUrlLoadingOnCreateWindow() throws Exception {
if (!NullWebViewUtils.isWebViewAvailable()) {
return;
diff --git a/tests/tests/widget/res/layout-round/edittext_layout.xml b/tests/tests/widget/res/layout-round/edittext_layout.xml
index 4f7f62b..1213d65 100644
--- a/tests/tests/widget/res/layout-round/edittext_layout.xml
+++ b/tests/tests/widget/res/layout-round/edittext_layout.xml
@@ -56,5 +56,12 @@
android:autoSizeTextType="uniform"
android:textSize="50dp"
android:autoSizeStepGranularity="2dp" />
+
+ <EditText
+ android:id="@+id/edittext_conversion_suggestion"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textEnableTextConversionSuggestions"
+ android:text="@string/edit_text" />
</LinearLayout>
</ScrollView>
diff --git a/tests/tests/widget/res/values/themes.xml b/tests/tests/widget/res/values/themes.xml
index bbce31f..938452e 100644
--- a/tests/tests/widget/res/values/themes.xml
+++ b/tests/tests/widget/res/values/themes.xml
@@ -24,4 +24,8 @@
<item name="themeColor">@color/remoteviews_theme_color</item>
<item name="themeString">@string/remoteviews_theme_string</item>
</style>
-</resources>
\ No newline at end of file
+
+ <style name="HorizontalScrollViewCtsActivityTheme" parent="@android:style/Theme.DeviceDefault">
+ <item name="android:windowSwipeToDismiss">false</item>
+ </style>
+</resources>
diff --git a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
index 96d8279..489aa54 100644
--- a/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
+++ b/tests/tests/widget/src/android/widget/cts/HorizontalScrollViewCtsActivity.java
@@ -24,6 +24,7 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ setTheme(R.style.HorizontalScrollViewCtsActivityTheme);
setContentView(R.layout.horizontal_scrollview);
}
}
diff --git a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
index 9908432..db698fd 100644
--- a/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
+++ b/tests/video/src/android/video/cts/VideoEncoderDecoderTest.java
@@ -146,6 +146,7 @@
private int mWidth;
private int mHeight;
private String mEncoderName;
+ private int mMaxBFrames;
private class TestConfig {
public boolean mTestPixels = true;
@@ -201,26 +202,29 @@
}
/** run performance test. */
- private void perf(String mimeType, int w, int h, String encoder) throws Exception {
- doTest(mimeType, w, h, true /* isPerf */, encoder);
+ private void perf(String mimeType, int w, int h, String encoder, int maxBFrames)
+ throws Exception {
+ doTest(mimeType, w, h, true /* isPerf */, encoder, maxBFrames);
}
/** run quality test. */
- private void qual(String mimeType, int w, int h, String encoder) throws Exception {
- doTest(mimeType, w, h, false /* isPerf */, encoder);
+ private void qual(String mimeType, int w, int h, String encoder, int maxBFrames)
+ throws Exception {
+ doTest(mimeType, w, h, false /* isPerf */, encoder, maxBFrames);
}
/** run quality test but do not report error. */
- private void qual(String mimeType, int w, int h, String encoder, double margin)
+ private void qual(String mimeType, int w, int h, String encoder, int maxBFrames, double margin)
throws Exception {
mRmsErrorMargin = margin;
- doTest(mimeType, w, h, false /* isPerf */, encoder);
+ doTest(mimeType, w, h, false /* isPerf */, encoder, maxBFrames);
}
static void prepareParamsList(List<Object[]> testParams, String mediaType, int[] widths,
int[] heights) {
final Type[] types = {Type.Qual, Type.Perf};
String[] encoderNames = MediaUtils.getEncoderNamesForMime(mediaType);
+ int[] maxBFrames = {0, 2};
for (Type type : types) {
for (int i = 0; i < widths.length; i++) {
MediaFormat format =
@@ -230,8 +234,16 @@
continue;
}
if (MediaUtils.supports(encoder, format)) {
- testParams.add(
- new Object[]{type, mediaType, widths[i], heights[i], encoder});
+ for (int maxBFrame : maxBFrames) {
+ if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+ && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)
+ && maxBFrame != 0) {
+ continue;
+ }
+ testParams.add(
+ new Object[]{type, mediaType, widths[i], heights[i], encoder,
+ maxBFrame});
+ }
break;
}
}
@@ -239,7 +251,7 @@
}
}
- @Parameterized.Parameters(name = "{1}_{4}_{0}_{2}x{3}")
+ @Parameterized.Parameters(name = "{1}_{4}_{0}_{2}x{3}_{5}")
public static Collection<Object[]> input() throws IOException {
final List<Object[]> testParams = new ArrayList<>();
final String[] mediaTypes = {AVC, HEVC, MPEG2, MPEG4, VP8, VP9, H263};
@@ -278,12 +290,13 @@
}
public VideoEncoderDecoderTest(Type type, String mediaType, int width, int height,
- String encoderName) {
+ String encoderName, int maxBFrames) {
this.mType = type;
this.mMediaType = mediaType;
this.mWidth = width;
this.mHeight = height;
this.mEncoderName = encoderName;
+ this.mMaxBFrames = maxBFrames;
}
@Test
@@ -291,12 +304,12 @@
if (mType == Type.Qual) {
if (mMediaType == H263 && (mWidth == 704
|| mWidth == 1408)) {
- qual(mMediaType, mWidth, mHeight, mEncoderName, 25);
+ qual(mMediaType, mWidth, mHeight, mEncoderName, mMaxBFrames, 25);
} else {
- qual(mMediaType, mWidth, mHeight, mEncoderName);
+ qual(mMediaType, mWidth, mHeight, mEncoderName, mMaxBFrames);
}
} else {
- perf(mMediaType, mWidth, mHeight, mEncoderName);
+ perf(mMediaType, mWidth, mHeight, mEncoderName, mMaxBFrames);
}
}
@@ -351,8 +364,8 @@
}
}
- private void doTest(String mimeType, int w, int h, boolean isPerf, String encoderName)
- throws Exception {
+ private void doTest(String mimeType, int w, int h, boolean isPerf, String encoderName,
+ int maxBFrames) throws Exception {
if (TestArgs.shouldSkipMediaType(mimeType)) {
return;
}
@@ -433,6 +446,7 @@
format.setInteger(MediaFormat.KEY_FRAME_RATE, infoEnc.mFps);
mFrameRate = infoEnc.mFps;
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, KEY_I_FRAME_INTERVAL);
+ format.setInteger(MediaFormat.KEY_MAX_B_FRAMES, maxBFrames);
RunResult encodingResult =
runEncoder(encoderName, format, mTestConfig.mTotalFrames, i);
@@ -504,7 +518,7 @@
// allow improvements in mainline-updated google-supplied software codecs.
boolean fasterIsOk = mUpdatedSwCodec & encoderName.startsWith("c2.android.");
String error = MediaPerfUtils.verifyAchievableFrameRates(
- encoderName, mimeType, w, h, fasterIsOk, measuredFps);
+ encoderName, mimeType, w, h, fasterIsOk, maxBFrames > 0, measuredFps);
// Performance numbers only make sense on real devices, so skip on non-real devices
//
// Also ignore verification on non-preferred ABIs due to the possibility of
diff --git a/tests/videocodec/AndroidManifest.xml b/tests/videocodec/AndroidManifest.xml
index 6edbe66..14e2f31 100644
--- a/tests/videocodec/AndroidManifest.xml
+++ b/tests/videocodec/AndroidManifest.xml
@@ -23,6 +23,7 @@
<application
android:requestLegacyExternalStorage="true"
+ android:largeHeap="true"
android:usesCleartextTraffic="true">
<uses-library android:name="android.test.runner" />
</application>
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java
new file mode 100644
index 0000000..f59a450
--- /dev/null
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderMinMaxTest.java
@@ -0,0 +1,299 @@
+/*
+ * 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.videocodec.cts;
+
+import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR;
+import static android.media.MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR;
+import static android.mediav2.common.cts.CodecTestBase.ComponentClass.HARDWARE;
+import static android.mediav2.common.cts.CodecTestBase.MEDIA_CODEC_LIST_REGULAR;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.media.MediaCodecInfo;
+import android.media.MediaFormat;
+import android.mediav2.common.cts.CompareStreams;
+import android.mediav2.common.cts.EncoderConfigParams;
+import android.mediav2.common.cts.RawResource;
+
+import com.android.compatibility.common.util.ApiTest;
+
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * 1. MinMaxResolutionsTest should query the ranges of supported width and height using
+ * MediaCodecInfo.VideoCapabilities, test the min resolution and the max resolution of the encoder.
+ * <p></p>
+ * Test Params:
+ * <p>Input resolution = min/max</p>
+ * <p>Number of frames = 30</p>
+ * <p>FrameRate = 30</p>
+ * <p>Target bitrate = 10 Mbps</p>
+ * <p>Bitrate mode = VBR</p>
+ * <p>MaxBFrames = 0/1</p>
+ * <p>Codec type = AVC/HEVC</p>
+ * <p>IFrameInterval = 0/1 second</p>
+ * <p></p>
+ *
+ * 2. MinMaxBitrateTest should query the range of the supported bitrates, and test min/max of them
+ * <p></p>
+ * Test Params:
+ * <p>Input resolution = 720p30fps</p>
+ * <p>Number of frames = 300</p>
+ * <p>FrameRate = 30</p>
+ * <p>Target bitrate = min/max</p>
+ * <p>Bitrate mode = CBR/VBR</p>
+ * <p>MaxBFrames = 0/1</p>
+ * <p>Codec type = AVC/HEVC</p>
+ * <p>IFrameInterval = 0/1 second</p>
+ * <p></p>
+ *
+ * 3. MinMaxFrameRatesTest should query the range of the supported frame rates, and test min/max
+ * of them.
+ * Test Params:
+ * <p>Input resolution = 720p</p>
+ * <p>Number of frames = 300</p>
+ * <p>FrameRate = min/max</p>
+ * <p>Target bitrate = 5Mbps</p>
+ * <p>Bitrate mode = CBR/VBR</p>
+ * <p>MaxBFrames = 0/1</p>
+ * <p>Codec type = AVC/HEVC</p>
+ * <p>IFrameInterval = 0/1 second</p>
+ * <p></p>
+ */
+@RunWith(Parameterized.class)
+public class VideoEncoderMinMaxTest extends VideoEncoderValidationTestBase {
+ private static final float MIN_ACCEPTABLE_QUALITY = 20.0f; // psnr in dB
+ private static final int FRAME_LIMIT = 300;
+ private static final int FRAME_RATE = 30;
+ private static final int BIT_RATE = 10000000;
+ private static final List<Object[]> exhaustiveArgsList = new ArrayList<>();
+ private static final HashMap<String, RawResource> RES_YUV_MAP = new HashMap<>();
+
+ @BeforeClass
+ public static void decodeResourcesToYuv() {
+ ArrayList<CompressedResource> resources = new ArrayList<>();
+ for (Object[] arg : exhaustiveArgsList) {
+ resources.add((CompressedResource) arg[2]);
+ }
+ decodeStreamsToYuv(resources, RES_YUV_MAP);
+ }
+
+ @AfterClass
+ public static void cleanUpResources() {
+ for (RawResource res : RES_YUV_MAP.values()) {
+ new File(res.mFileName).delete();
+ }
+ }
+
+ private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int width,
+ int height, int maxBFrames, int intraInterval) {
+ return new EncoderConfigParams.Builder(mediaType)
+ .setWidth(width)
+ .setHeight(height)
+ .setBitRate(BIT_RATE)
+ .setMaxBFrames(maxBFrames)
+ .setKeyFrameInterval(intraInterval)
+ .setFrameRate(FRAME_RATE)
+ .build();
+ }
+
+ private static void addParams(int width, int height, CompressedResource res) {
+ final String[] mediaTypes = new String[]{MediaFormat.MIMETYPE_VIDEO_AVC,
+ MediaFormat.MIMETYPE_VIDEO_HEVC};
+ final int[] maxBFramesPerSubGop = new int[]{0, 1};
+ final int[] intraIntervals = new int[]{0, 1};
+ for (String mediaType : mediaTypes) {
+ for (int maxBFrames : maxBFramesPerSubGop) {
+ for (int intraInterval : intraIntervals) {
+ // mediaType, cfg, resource file
+ exhaustiveArgsList.add(new Object[]{mediaType,
+ getVideoEncoderCfgParams(mediaType, width, height, maxBFrames,
+ intraInterval), res});
+ }
+ }
+ }
+ }
+
+ private static List<Object> applyMinMaxRanges(MediaCodecInfo.CodecCapabilities caps,
+ Object cfgObject) throws CloneNotSupportedException {
+ int minWidth = caps.getVideoCapabilities().getSupportedWidths().getLower();
+ int maxWidth = caps.getVideoCapabilities().getSupportedWidths().getUpper();
+ int minHeight = caps.getVideoCapabilities().getSupportedHeights().getLower();
+ int maxHeight = caps.getVideoCapabilities().getSupportedHeights().getUpper();
+
+ int minBitRate = caps.getVideoCapabilities().getBitrateRange().getLower();
+ int maxBitRate = caps.getVideoCapabilities().getBitrateRange().getUpper();
+
+ int minFrameRate = caps.getVideoCapabilities().getSupportedFrameRates().getLower();
+ int maxFrameRate = caps.getVideoCapabilities().getSupportedFrameRates().getUpper();
+
+ List<Object> cfgObjects = new ArrayList<>();
+ EncoderConfigParams cfgParam = (EncoderConfigParams) cfgObject;
+
+ final int[] bitRateModes = new int[]{BITRATE_MODE_CBR, BITRATE_MODE_VBR};
+ for (int bitRateMode : bitRateModes) {
+ cfgObjects.add((Object) cfgParam.getBuilder()
+ .setWidth(minWidth)
+ .setHeight(minHeight)
+ .setBitRate(minBitRate)
+ .setBitRateMode(bitRateMode)
+ .build());
+
+ cfgObjects.add((Object) cfgParam.getBuilder()
+ .setWidth(maxWidth)
+ .setHeight(maxHeight)
+ .setBitRate(maxBitRate)
+ .setBitRateMode(bitRateMode)
+ .build());
+
+ cfgObjects.add((Object) cfgParam.getBuilder()
+ .setFrameRate(minFrameRate)
+ .setBitRate(5000000)
+ .setBitRateMode(bitRateMode)
+ .build());
+
+ cfgObjects.add((Object) cfgParam.getBuilder()
+ .setFrameRate(maxFrameRate)
+ .setBitRate(5000000)
+ .setBitRateMode(bitRateMode)
+ .build());
+ }
+
+ cfgObjects.add((Object) cfgParam.getBuilder()
+ .setWidth(minWidth)
+ .setHeight(maxHeight)
+ .setBitRateMode(BITRATE_MODE_VBR)
+ .build());
+
+ cfgObjects.add((Object) cfgParam.getBuilder()
+ .setWidth(maxWidth)
+ .setHeight(minHeight)
+ .setBitRateMode(BITRATE_MODE_VBR)
+ .build());
+
+ return cfgObjects;
+ }
+
+ private static List<Object> getMinMaxRangeCfgObjects(Object codecName, Object mediaType,
+ Object cfgObject) throws CloneNotSupportedException {
+ for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_REGULAR.getCodecInfos()) {
+ for (String type : codecInfo.getSupportedTypes()) {
+ if (codecName.equals(codecInfo.getName()) && mediaType.equals(type)) {
+ MediaCodecInfo.CodecCapabilities caps =
+ codecInfo.getCapabilitiesForType(type);
+ return applyMinMaxRanges(caps, cfgObject);
+ }
+ }
+ }
+ return null;
+ }
+
+ private static Collection<Object[]> updateParamList(Collection<Object[]> paramList)
+ throws CloneNotSupportedException {
+ Collection<Object[]> newParamList = new ArrayList<>();
+ for (Object[] arg : paramList) {
+ List<Object> cfgObjects = getMinMaxRangeCfgObjects(arg[0], arg[1], arg[2]);
+ for (Object obj : cfgObjects) {
+ Object[] argUpdate = new Object[arg.length + 1];
+ System.arraycopy(arg, 0, argUpdate, 0, arg.length);
+ argUpdate[2] = obj;
+ EncoderConfigParams cfgVar = (EncoderConfigParams) obj;
+ String label = String.format("%dkbps_%dx%d_%dfps_maxb-%d_%s_i-dist-%d",
+ cfgVar.mBitRate / 1000, cfgVar.mWidth, cfgVar.mHeight, cfgVar.mFrameRate,
+ cfgVar.mMaxBFrames, bitRateModeToString(cfgVar.mBitRateMode),
+ (int) cfgVar.mKeyFrameInterval);
+ argUpdate[arg.length - 1] = label;
+ argUpdate[arg.length] = paramToString(argUpdate);
+ newParamList.add(argUpdate);
+ }
+ }
+ return newParamList;
+ }
+
+ @Parameterized.Parameters(name = "{index}({0}_{1}_{4})")
+ public static Collection<Object[]> input() throws CloneNotSupportedException {
+ addParams(1280, 720, BIRTHDAY_FULLHD_LANDSCAPE);
+ return updateParamList(prepareParamList(exhaustiveArgsList, true, false, true, false,
+ HARDWARE));
+ }
+
+ public VideoEncoderMinMaxTest(String encoder, String mediaType, EncoderConfigParams cfgParams,
+ CompressedResource res, @SuppressWarnings("unused") String testLabel,
+ String allTestParams) {
+ super(encoder, mediaType, cfgParams, res, allTestParams);
+ }
+
+ @Before
+ public void setUp() {
+ mIsLoopBack = true;
+ }
+
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_WIDTH",
+ "android.media.MediaFormat#KEY_HEIGHT",
+ "android.media.MediaFormat#KEY_BITRATE",
+ "android.media.MediaFormat#KEY_FRAME_RATE"})
+ @Test
+ public void testMinMaxSupport() throws IOException, InterruptedException {
+ MediaFormat format = mEncCfgParams[0].getFormat();
+ ArrayList<MediaFormat> formats = new ArrayList<>();
+ formats.add(format);
+ Assume.assumeTrue("Encoder: " + mCodecName + " doesn't support format: " + format,
+ areFormatsSupported(mCodecName, mMime, formats));
+ RawResource res = RES_YUV_MAP.getOrDefault(mCRes.uniqueLabel(), null);
+ assertNotNull("no raw resource found for testing config : " + mEncCfgParams[0]
+ + mTestConfig + mTestEnv, res);
+ encodeToMemory(mCodecName, mEncCfgParams[0], res, FRAME_LIMIT, true, true);
+ CompareStreams cs = null;
+ StringBuilder msg = new StringBuilder();
+ boolean isOk = true;
+ try {
+ cs = new CompareStreams(res, mMime, mMuxedOutputFile, true, mIsLoopBack);
+ final double[] minPSNR = cs.getMinimumPSNR();
+ for (int i = 0; i < minPSNR.length; i++) {
+ if (minPSNR[i] < MIN_ACCEPTABLE_QUALITY) {
+ msg.append(String.format("For %d plane, minPSNR is less than tolerance"
+ + " threshold, Got %f, Threshold %f", i, minPSNR[i],
+ MIN_ACCEPTABLE_QUALITY));
+ isOk = false;
+ break;
+ }
+ }
+ } finally {
+ if (cs != null) cs.cleanUp();
+ }
+ new File(mMuxedOutputFile).delete();
+ assertEquals("encoder did not encode the requested number of frames \n"
+ + mTestConfig + mTestEnv, FRAME_LIMIT, mOutputCount);
+ assertTrue("Encountered frames with PSNR less than configured threshold "
+ + MIN_ACCEPTABLE_QUALITY + "dB \n" + msg + mTestConfig + mTestEnv, isOk);
+ }
+}
diff --git a/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java b/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
index 044a311..676127c 100644
--- a/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
+++ b/tests/videocodec/src/android/videocodec/cts/VideoEncoderValidationTestBase.java
@@ -27,9 +27,9 @@
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.mediav2.common.cts.BitStreamUtils;
+import android.mediav2.common.cts.CodecEncoderTestBase;
import android.mediav2.common.cts.DecodeStreamToYuv;
import android.mediav2.common.cts.EncoderConfigParams;
-import android.mediav2.common.cts.EncoderTestBase;
import android.mediav2.common.cts.RawResource;
import android.util.Log;
@@ -47,7 +47,7 @@
/**
* Wrapper class for handling and testing video encoder components.
*/
-public class VideoEncoderValidationTestBase extends EncoderTestBase {
+public class VideoEncoderValidationTestBase extends CodecEncoderTestBase {
private static final String LOG_TAG = VideoEncoderValidationTestBase.class.getSimpleName();
private static final String MEDIA_DIR = WorkDir.getMediaDirString();
diff --git a/tests/wallpapereffectsgeneration/OWNERS b/tests/wallpapereffectsgeneration/OWNERS
index 39cdd55..ab3d604 100644
--- a/tests/wallpapereffectsgeneration/OWNERS
+++ b/tests/wallpapereffectsgeneration/OWNERS
@@ -1,3 +1,4 @@
+# Bug component: 168740
susharon@google.com
shanh@google.com
huiwu@google.com
diff --git a/tools/cts-tradefed/Android.bp b/tools/cts-tradefed/Android.bp
index 0811941..e50b6b4 100644
--- a/tools/cts-tradefed/Android.bp
+++ b/tools/cts-tradefed/Android.bp
@@ -34,7 +34,7 @@
wrapper: "etc/cts-tradefed",
short_name: "CTS",
full_name: "Compatibility Test Suite",
- version: "13_r3",
+ version: "13_r4",
static_libs: ["cts-tradefed-harness"],
required: ["compatibility-host-util"],
}
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 34feac2..a37929d 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -308,4 +308,10 @@
<!-- b/260037367 -->
<option name="compatibility:exclude-filter" value="odsign_e2e_tests com.android.tests.odsign.CompOsSigningHostTest" />
-</configuration>
+
+ <!-- b/264824229 -->
+ <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.cts.VisualVoicemailServiceTest#testFilter_data" />
+ <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.cts.VisualVoicemailServiceTest#testFilter_port_match" />
+ <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.cts.VisualVoicemailServiceTest#testFilter_port_mismatch" />
+ <option name="compatibility:exclude-filter" value="CtsTelephonyTestCases android.telephony.cts.VisualVoicemailServiceTest#testFilter_port_anydata" />
+</configuration>
\ No newline at end of file
diff --git a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
index 306737f..1ccf352 100644
--- a/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
+++ b/tools/cts-tradefed/tests/src/com/android/compatibility/common/tradefed/presubmit/ValidateTestsAbi.java
@@ -103,11 +103,20 @@
BINARY_EXCEPTIONS.add("sepolicy-analyze");
BINARY_EXCEPTIONS.add("avbtool");
BINARY_EXCEPTIONS.add("img2simg");
+ BINARY_EXCEPTIONS.add("initrd_bootconfig");
BINARY_EXCEPTIONS.add("lpmake");
BINARY_EXCEPTIONS.add("lpunpack");
BINARY_EXCEPTIONS.add("mk_payload");
BINARY_EXCEPTIONS.add("sign_virt_apex");
BINARY_EXCEPTIONS.add("simg2img");
+
+ /**
+ * These binaries are testing components with no 32-bit variant, which
+ * means their dependent libraries by default will not have 32-bit
+ * variants on the device, and which gain no additional testing coverage
+ * by forcing those variants to be available.
+ */
+ BINARY_EXCEPTIONS.add("CtsInitTestCases");
}
private static final String BINARY_EXCEPTIONS_REGEX [] = {