Merge changes from topic "retailDemo" into tm-dev
* changes:
Add cts tests to cover provisioning demo devices
Add new permission PROVISION_DEMO_DEVICE
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 8516cbf..35cd382 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -253,14 +253,10 @@
# If raw is available and main camera, use it as ground truth.
ref_img_name_stem = f'{os.path.join(log_path, _NAME)}'
- if raw_avlb and (fls_physical == fls_logical):
- ref_fov, cc_ct_gt, aspect_ratio_gt = (
- image_fov_utils.find_fov_reference(
- cam, req, props, 'RAW', ref_img_name_stem))
- else:
- ref_fov, cc_ct_gt, aspect_ratio_gt = (
- image_fov_utils.find_fov_reference(
- cam, req, props, 'JPEG', ref_img_name_stem))
+ raw_bool = raw_avlb and (fls_physical == fls_logical)
+ ref_fov, cc_ct_gt, aspect_ratio_gt = (
+ image_fov_utils.find_fov_reference(
+ cam, req, props, raw_bool, ref_img_name_stem))
run_crop_test = full_or_better and raw_avlb
if run_crop_test:
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 3afd554..93e4f11 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
@@ -37,11 +37,14 @@
_ANGULAR_DIFF_THRESH_API30 = 10 # degrees
_ANGULAR_DIFF_THRESH_CALIBRATED = 1.8 # degrees (180 deg / 1000 ms * 10 ms)
_ANGULAR_MOVEMENT_THRESHOLD = 35 # degrees
+_ARDUINO_ANGLES = (0, 90)
+_ARDUINO_MOVE_TIME = 2 # seconds
+_ARDUINO_SERVO_SPEED = 20
_FRAMES_WITH_SQUARES_MIN = 20 # min number of frames with angles extracted
_NAME = os.path.basename(__file__).split('.')[0]
_NUM_CAPTURES = 100
_NUM_ROTATIONS = 10
-_ROT_INIT_WAIT_TIME = 2 # seconds
+_ROT_INIT_WAIT_TIME = 4 # seconds
_CHART_DISTANCE_SF = 25 # cm
_CM_TO_M = 1/100.0
@@ -175,7 +178,8 @@
# Start camera rotation & sleep shortly to let rotations start
p = multiprocessing.Process(
target=sensor_fusion_utils.rotation_rig,
- args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,))
+ args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,
+ _ARDUINO_ANGLES, _ARDUINO_SERVO_SPEED, _ARDUINO_MOVE_TIME,))
p.start()
time.sleep(_ROT_INIT_WAIT_TIME)
diff --git a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
index 0b2bbcc16..df1813c 100644
--- a/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
+++ b/apps/CameraITS/tests/sensor_fusion/test_sensor_fusion.py
@@ -62,6 +62,9 @@
10, 0.03)) # cv2.calcOpticalFlowPyrLK params.
_NAME = os.path.splitext(os.path.basename(__file__))[0]
+_ARDUINO_ANGLES = (0, 90)
+_ARDUINO_MOVE_TIME = 2
+_ARDUINO_SERVO_SPEED = 20
_NUM_ROTATIONS = 10
_START_FRAME = 1
_FRAME_DELTA_TOL = 1.5 # 50% margin over nominal FPS of captures
@@ -120,7 +123,8 @@
# Start camera rotation.
p = multiprocessing.Process(
target=sensor_fusion_utils.rotation_rig,
- args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,))
+ args=(rot_rig['cntl'], rot_rig['ch'], _NUM_ROTATIONS,
+ _ARDUINO_ANGLES, _ARDUINO_SERVO_SPEED, _ARDUINO_MOVE_TIME,))
p.start()
cam.start_sensor_events()
diff --git a/apps/CameraITS/utils/image_fov_utils.py b/apps/CameraITS/utils/image_fov_utils.py
index c3badf9..b9caf33 100644
--- a/apps/CameraITS/utils/image_fov_utils.py
+++ b/apps/CameraITS/utils/image_fov_utils.py
@@ -145,7 +145,7 @@
return 100 * math.pi * math.pow(radius, 2) / (img_w * img_h)
-def find_fov_reference(cam, req, props, fmt_type, ref_img_name_stem):
+def find_fov_reference(cam, req, props, raw_bool, ref_img_name_stem):
"""Determine the circle coverage of the image in reference image.
Captures a full-frame RAW or JPEG and uses its aspect ratio and circle center
@@ -166,7 +166,7 @@
cam: camera object
req: camera request
props: camera properties
- fmt_type: 'RAW' or 'JPEG'
+ raw_bool: True if RAW available
ref_img_name_stem: test _NAME + location to save data
Returns:
@@ -174,8 +174,10 @@
cc_ct_gt: circle center position relative to the center of image.
aspect_ratio_gt: aspect ratio of the detected circle in float.
"""
- logging.debug('Creating references for fov_coverage from %s', fmt_type)
- if fmt_type == 'RAW':
+ logging.debug('Creating references for fov_coverage')
+ if raw_bool:
+ logging.debug('Using RAW for reference')
+ fmt_type = 'RAW'
out_surface = {'format': 'raw'}
cap = cam.do_capture(req, out_surface)
logging.debug('Captured RAW %dx%d', cap['width'], cap['height'])
@@ -201,7 +203,9 @@
img = cv2.undistort(img, k, opencv_dist)
size = img.shape
- elif fmt_type == 'JPEG':
+ else:
+ logging.debug('Using JPEG for reference')
+ fmt_type = 'JPEG'
ref_fov = {}
fmt = capture_request_utils.get_largest_jpeg_format(props)
cap = cam.do_capture(req, fmt)
@@ -267,7 +271,7 @@
circle = {'w': 2, 'h': 1}
e_msg_stem = 'check_ar_false'
e_msg = check_ar(circle, ar_gt, w, h, e_msg_stem)
- self.assertTrue('check_ar_false' in e_msg)
+ self.assertIn('check_ar_false', e_msg)
def test_check_crop(self):
"""Unit test for crop check."""
@@ -284,7 +288,7 @@
circle = {'w': 100, 'h': 100, 'x_offset': 2, 'y_offset': 1}
e_msg_stem = 'check_crop_false'
e_msg = check_crop(circle, cc_gt, w, h, e_msg_stem, crop_thresh_factor)
- self.assertTrue('check_crop_false' in e_msg)
+ self.assertIn('check_crop_false', e_msg)
if __name__ == '__main__':
unittest.main()
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index 1087261..074399e 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -82,9 +82,12 @@
# Seconds timeout on each socket operation.
SOCK_TIMEOUT = 20.0
+ # Seconds timeout on performance measurement socket operation
+ SOCK_TIMEOUT_FOR_PERF_MEASURE = 40.0
+
# Additional timeout in seconds when ITS service is doing more complicated
# operations, for example: issuing warmup requests before actual capture.
- EXTRA_SOCK_TIMEOUT = 10.0
+ EXTRA_SOCK_TIMEOUT = 5.0
PACKAGE = 'com.android.cts.verifier.camera.its'
INTENT_START = 'com.android.cts.verifier.camera.its.START'
@@ -1144,7 +1147,7 @@
cmd['cameraId'] = self._camera_id
self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
- timeout = self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT
+ timeout = self.SOCK_TIMEOUT_FOR_PERF_MEASURE
self.sock.settimeout(timeout)
data, _ = self.__read_response_from_socket()
self.sock.settimeout(self.SOCK_TIMEOUT)
@@ -1164,7 +1167,7 @@
cmd['cameraId'] = self._camera_id
self.sock.send(json.dumps(cmd).encode() + '\n'.encode())
- timeout = self.SOCK_TIMEOUT + self.EXTRA_SOCK_TIMEOUT
+ timeout = self.SOCK_TIMEOUT_FOR_PERF_MEASURE
self.sock.settimeout(timeout)
data, _ = self.__read_response_from_socket()
self.sock.settimeout(self.SOCK_TIMEOUT)
diff --git a/apps/CameraITS/utils/sensor_fusion_utils.py b/apps/CameraITS/utils/sensor_fusion_utils.py
index 263f108..e7893fe 100644
--- a/apps/CameraITS/utils/sensor_fusion_utils.py
+++ b/apps/CameraITS/utils/sensor_fusion_utils.py
@@ -28,11 +28,9 @@
# Constants for Rotation Rig
ARDUINO_ANGLE_MAX = 180.0 # degrees
-ARDUINO_ANGLES = [0]*5 +list(range(0, 90, 3)) + [90]*5 +list(range(90, -1, -3))
ARDUINO_BAUDRATE = 9600
ARDUINO_CMD_LENGTH = 3
ARDUINO_CMD_TIME = 2.0 * ARDUINO_CMD_LENGTH / ARDUINO_BAUDRATE # round trip
-ARDUINO_MOVE_TIME = 0.06 - ARDUINO_CMD_TIME # seconds
ARDUINO_PID = 0x0043
ARDUINO_SERVO_SPEED_MAX = 255
ARDUINO_SERVO_SPEED_MIN = 1
@@ -175,14 +173,14 @@
for x in cmd]
-def arduino_rotate_servo_to_angle(ch, angle, serial_port, delay=0):
+def arduino_rotate_servo_to_angle(ch, angle, serial_port, move_time):
"""Rotate servo to the specified angle.
Args:
ch: str; servo to rotate in ARDUINO_VALID_CH
angle: int; servo angle to move to
serial_port: object; serial port
- delay: int; time in seconds
+ move_time: int; time in seconds
"""
if angle < 0 or angle > ARDUINO_ANGLE_MAX:
logging.debug('Angle must be between 0 and %d.', ARDUINO_ANGLE_MAX)
@@ -192,23 +190,31 @@
cmd = [struct.pack('B', i) for i in [ARDUINO_START_BYTE, int(ch), angle]]
arduino_send_cmd(serial_port, cmd)
- time.sleep(delay)
+ time.sleep(move_time)
-def arduino_rotate_servo(ch, serial_port):
- """Rotate servo between 0 --> 90 --> 0.
+def arduino_rotate_servo(ch, angles, servo_speed, move_time, serial_port):
+ """Rotate servo through 'angles'.
Args:
ch: str; servo to rotate
+ angles: list of ints; servo angles to move to
+ servo_speed: int; move speed between [1, 255]
+ move_time: int; time required to allow for arduino movement
serial_port: object; serial port
"""
- for angle in ARDUINO_ANGLES:
+
+ # set servo speed
+ logging.debug('Servo speed: %d', servo_speed)
+ set_servo_speed(ch, servo_speed, serial_port, delay=0)
+
+ for angle in angles:
angle_norm = int(round(angle*ARDUINO_ANGLE_MAX/HS755HB_ANGLE_MAX, 0))
- arduino_rotate_servo_to_angle(
- ch, angle_norm, serial_port, ARDUINO_MOVE_TIME)
+ arduino_rotate_servo_to_angle(ch, angle_norm, serial_port, move_time)
-def rotation_rig(rotate_cntl, rotate_ch, num_rotations):
+def rotation_rig(rotate_cntl, rotate_ch, num_rotations, angles, servo_speed,
+ move_time):
"""Rotate the phone n times using rotate_cntl and rotate_ch defined.
rotate_ch is hard wired and must be determined from physical setup.
@@ -220,6 +226,9 @@
rotate_cntl: str to identify as 'arduino' or 'canakit' controller.
rotate_ch: str to identify rotation channel number.
num_rotations: int number of rotations.
+ angles: list of ints; servo angle to move to.
+ servo_speed: int number of move speed between [1, 255].
+ move_time: int time required to allow for arduino movement.
"""
logging.debug('Controller: %s, ch: %s', rotate_cntl, rotate_ch)
@@ -244,11 +253,15 @@
logging.debug('Rotating phone %dx', num_rotations)
for _ in range(num_rotations):
if rotate_cntl == 'arduino':
- arduino_rotate_servo(rotate_ch, arduino_serial_port)
+ arduino_rotate_servo(rotate_ch, angles, servo_speed, move_time,
+ arduino_serial_port)
elif rotate_cntl == 'canakit':
canakit_set_relay_channel_state(canakit_serial_port, rotate_ch, 'ON')
canakit_set_relay_channel_state(canakit_serial_port, rotate_ch, 'OFF')
logging.debug('Finished rotations')
+ if rotate_cntl == 'arduino':
+ logging.debug('Moving servo to origin')
+ arduino_rotate_servo_to_angle(rotate_ch, 0, arduino_serial_port, 1)
def set_servo_speed(ch, servo_speed, serial_port, delay=0):
@@ -267,7 +280,8 @@
logging.debug('Servo speed must be <= %d.', ARDUINO_SERVO_SPEED_MAX)
servo_speed = ARDUINO_SERVO_SPEED_MAX
- cmd = [struct.pack('B', i) for i in [ARDUINO_SPEED_START_BYTE, int(ch), servo_speed]]
+ cmd = [struct.pack('B', i) for i in [ARDUINO_SPEED_START_BYTE,
+ int(ch), servo_speed]]
arduino_send_cmd(serial_port, cmd)
time.sleep(delay)
diff --git a/apps/CtsVerifier/OWNERS b/apps/CtsVerifier/OWNERS
new file mode 100644
index 0000000..0964da0
--- /dev/null
+++ b/apps/CtsVerifier/OWNERS
@@ -0,0 +1 @@
+per-file AndroidManifest*.xml = ape-relpgm-cls@google.com
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
index d96c0b1..f1fbf40 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/TestAppSystemServiceFactory.java
@@ -120,7 +120,7 @@
}
private static void assertHasRequiredReceiver(Context context) {
- if (!UserManager.isHeadlessSystemUserMode()) return;
+ if (!Utils.isHeadlessSystemUserMode()) return;
String packageName = context.getPackageName();
Boolean hasIt = sHasRequiredReceiver.get(packageName);
@@ -226,7 +226,7 @@
assertHasRequiredReceiver(context);
int userId = context.getUserId();
- if (userId == UserHandle.USER_SYSTEM || !UserManager.isHeadlessSystemUserMode()) {
+ if (userId == UserHandle.USER_SYSTEM || !Utils.isHeadlessSystemUserMode()) {
Log.i(TAG, "get(): returning 'pure' DevicePolicyManager for user " + userId);
return manager;
}
diff --git a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
index 03b8963..57289de 100644
--- a/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
+++ b/common/device-side/bedstead/dpmwrapper/src/main/java/com/android/bedstead/dpmwrapper/Utils.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
@@ -61,12 +62,17 @@
@GuardedBy("LOCK")
private static Handler sHandler;
+ static boolean isHeadlessSystemUserMode() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+ && UserManager.isHeadlessSystemUserMode();
+ }
+
static boolean isHeadlessSystemUser() {
- return UserManager.isHeadlessSystemUserMode() && MY_USER_ID == UserHandle.USER_SYSTEM;
+ return isHeadlessSystemUserMode() && MY_USER_ID == UserHandle.USER_SYSTEM;
}
static boolean isCurrentUserOnHeadlessSystemUser(Context context) {
- return UserManager.isHeadlessSystemUserMode()
+ return isHeadlessSystemUserMode()
&& context.getSystemService(UserManager.class).isUserForeground();
}
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
index 4b40606..24bbaee 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/DeviceOwner.java
@@ -26,6 +26,7 @@
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -121,6 +122,7 @@
Intent intent = new Intent(ACTION_DISABLE_SELF);
intent.setComponent(new ComponentName(pkg().packageName(),
"com.android.bedstead.testapp.TestAppBroadcastController"));
+ Context context = TestApis.context().androidContextAsUser(mUser);
try (PermissionContext p =
TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
@@ -130,7 +132,7 @@
BlockingBroadcastReceiver b = new BlockingBroadcastReceiver(
TestApis.context().instrumentedContext());
- TestApis.context().androidContextAsUser(mUser).sendOrderedBroadcast(
+ context.sendOrderedBroadcast(
intent, /* receiverPermission= */ null, b, /* scheduler= */
null, /* initialCode= */
Activity.RESULT_CANCELED, /* initialData= */ null, /* initialExtras= */
@@ -139,14 +141,15 @@
b.awaitForBroadcastOrFail(Duration.ofSeconds(30).toMillis());
assertThat(b.getResultCode()).isEqualTo(Activity.RESULT_OK);
}).timeout(Duration.ofMinutes(5)).runAndWrapException();
+
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+
+ Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
+ .toNotBeEqualTo(true)
+ .errorOnFail()
+ .await();
}
-// TODO(b/219894175) Expose isRemovingAdmin as a TestAPI for U.
-// DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
-//
-// Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
-// .toNotBeEqualTo(true)
-// .await();
}
@Override
diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
index f693ca1..a259203 100644
--- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
+++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/devicepolicy/ProfileOwner.java
@@ -26,6 +26,7 @@
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -113,6 +114,7 @@
Intent intent = new Intent(ACTION_DISABLE_SELF);
intent.setComponent(new ComponentName(pkg().packageName(),
"com.android.bedstead.testapp.TestAppBroadcastController"));
+ Context context = TestApis.context().androidContextAsUser(mUser);
try (PermissionContext p =
TestApis.permissions().withPermission(INTERACT_ACROSS_USERS_FULL)) {
@@ -122,7 +124,7 @@
BlockingBroadcastReceiver b = new BlockingBroadcastReceiver(
TestApis.context().instrumentedContext());
- TestApis.context().androidContextAsUser(mUser).sendOrderedBroadcast(
+ context.sendOrderedBroadcast(
intent, /* receiverPermission= */ null, b, /* scheduler= */
null, /* initialCode= */
Activity.RESULT_CANCELED, /* initialData= */ null, /* initialExtras= */
@@ -131,14 +133,15 @@
b.awaitForBroadcastOrFail(Duration.ofSeconds(30).toMillis());
assertThat(b.getResultCode()).isEqualTo(Activity.RESULT_OK);
}).timeout(Duration.ofMinutes(5)).runAndWrapException();
+
+ DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+
+ Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
+ .toNotBeEqualTo(true)
+ .errorOnFail()
+ .await();
}
-// TODO(b/219894175) Expose isRemovingAdmin as a TestAPI for U.
-// DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
-//
-// Poll.forValue(() -> dpm.isRemovingAdmin(mComponentName, mUser.id()))
-// .toNotBeEqualTo(true)
-// .await();
}
@Override
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java b/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
index 8dc2ce6..9d44cc5 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/main/java/com/android/bedstead/remoteframeworkclasses/processor/Processor.java
@@ -484,8 +484,8 @@
"public void dumpInternal(@NonNull String, @Nullable java.io.FileDescriptor, @NonNull "
+ "java.io.PrintWriter, @Nullable String[])",
- // Uses android.view.OnBackInvokedDispatcher
- "public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher()",
+ // Uses android.window.OnBackInvokedDispatcher
+ "public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher()",
// Uses android.app.Activity
"@Deprecated public void finishActivityFromChild(@NonNull android.app.Activity, int)",
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt
index 3a6fc59..a6f307a 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/current.txt
@@ -4072,7 +4072,7 @@
method @Deprecated public void onTabUnselected(android.app.ActionBar.Tab, android.app.FragmentTransaction);
}
- @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
ctor public Activity();
method public void addContentView(android.view.View, android.view.ViewGroup.LayoutParams);
method public void closeContextMenu();
@@ -4115,7 +4115,7 @@
method public int getMaxNumPictureInPictureActions();
method public final android.media.session.MediaController getMediaController();
method @NonNull public android.view.MenuInflater getMenuInflater();
- method @NonNull public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
+ method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
method public final android.app.Activity getParent();
method @Nullable public android.content.Intent getParentActivityIntent();
method public android.content.SharedPreferences getPreferences(int);
@@ -5001,7 +5001,7 @@
method public void onDateSet(android.widget.DatePicker, int, int, int);
}
- public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.view.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ public class Dialog implements android.content.DialogInterface android.view.KeyEvent.Callback android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
ctor public Dialog(@NonNull @UiContext android.content.Context);
ctor public Dialog(@NonNull @UiContext android.content.Context, @StyleRes int);
ctor protected Dialog(@NonNull @UiContext android.content.Context, boolean, @Nullable android.content.DialogInterface.OnCancelListener);
@@ -5021,7 +5021,7 @@
method @NonNull @UiContext public final android.content.Context getContext();
method @Nullable public android.view.View getCurrentFocus();
method @NonNull public android.view.LayoutInflater getLayoutInflater();
- method @NonNull public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
+ method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
method @Nullable public final android.app.Activity getOwnerActivity();
method @Nullable public final android.view.SearchEvent getSearchEvent();
method public final int getVolumeControlStream();
@@ -49026,14 +49026,14 @@
}
public interface OnBackInvokedDispatcher {
- method public void registerOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback, @IntRange(from=0) int);
- method public void unregisterOnBackInvokedCallback(@NonNull android.view.OnBackInvokedCallback);
+ method public void registerOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback, @IntRange(from=0) int);
+ method public void unregisterOnBackInvokedCallback(@NonNull android.window.OnBackInvokedCallback);
field public static final int PRIORITY_DEFAULT = 0; // 0x0
field public static final int PRIORITY_OVERLAY = 1000000; // 0xf4240
}
public interface OnBackInvokedDispatcherOwner {
- method @NonNull public android.view.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
+ method @NonNull public android.window.OnBackInvokedDispatcher getOnBackInvokedDispatcher();
}
public interface OnReceiveContentListener {
diff --git a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt
index 9757b2f..3fe2a3e 100644
--- a/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt
+++ b/common/device-side/bedstead/remoteframeworkclasses/src/processor/res/apis/test-current.txt
@@ -103,7 +103,7 @@
package android.app {
- @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
+ @UiContext public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.window.OnBackInvokedDispatcherOwner android.view.View.OnCreateContextMenuListener android.view.Window.Callback {
method public final boolean addDumpable(@NonNull android.util.Dumpable);
method public void dumpInternal(@NonNull String, @Nullable java.io.FileDescriptor, @NonNull java.io.PrintWriter, @Nullable String[]);
method public void onMovedToDisplay(int, android.content.res.Configuration);
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
index 4125ede..3ca979d 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/PropertyUtil.java
@@ -268,4 +268,33 @@
}
}
}
+
+ /** Retrieves a map of prop to value for all props with the given prefix */
+ public static Map<String, String> getPropertiesWithPrefix(String prefix) {
+ Map<String, String> result = new HashMap<>();
+ Pattern pattern = Pattern.compile("\\[(.*)\\]: \\[(.*)\\]");
+ Scanner scanner = null;
+ try {
+ Process process = new ProcessBuilder("getprop").start();
+ scanner = new Scanner(process.getInputStream());
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine().trim();
+ Matcher matcher = pattern.matcher(line);
+ if (matcher.find()) {
+ String prop = matcher.group(1);
+ String value = matcher.group(2);
+ if (prop.startsWith(prefix)) {
+ result.put(prop, value);
+ }
+ }
+ }
+ return result;
+ } catch (IOException e) {
+ return result;
+ } finally {
+ if (scanner != null) {
+ scanner.close();
+ }
+ }
+ }
}
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index b3e2cab..cff7c22 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -203,12 +203,8 @@
"Landroid/hardware/usb/gadget/V1_2/IUsbGadget;",
"Landroid/hardware/usb/gadget/V1_2/IUsbGadgetCallback;",
"Landroid/hardware/usb/gadget/V1_2/UsbSpeed;",
- "Landroid/os/BlockUntrustedTouchesMode;",
"Landroid/os/CreateAppDataArgs;",
"Landroid/os/CreateAppDataResult;",
- "Landroid/os/IInputConstants;",
- "Landroid/os/InputEventInjectionResult;",
- "Landroid/os/InputEventInjectionSync;",
"Lcom/android/internal/util/FrameworkStatsLog;"
);
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
index f61bc16..b571bba 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -21,7 +21,9 @@
<!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
to pass the build error, since tests need to use minSdkVersion 4. -->
- <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+ <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
+ androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+ androidx.test.annotation, androidx.annotation.experimental, androidx.tracing"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml
index aff6672..672b163 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/instantapp/AndroidManifest.xml
@@ -26,8 +26,9 @@
<!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
to pass the build error, since tests need to use minSdkVersion 4. -->
- <uses-sdk android:minSdkVersion="4" tools:overrideLibrary=
- "androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+ <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
+ androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+ androidx.test.annotation, androidx.annotation.experimental, androidx.tracing"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml
index 9cd26cf..7d275aa 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/needsplit/AndroidManifest.xml
@@ -23,7 +23,9 @@
<!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
to pass the build error, since tests need to use minSdkVersion 4. -->
<uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
- androidx.test.rules, androidx.test.monitor, androidx.test.services.storage" android:targetSdkVersion="27"/>
+ androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+ androidx.test.annotation, androidx.annotation.experimental androidx.tracing"
+ android:targetSdkVersion="27"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml
index 28bef9d..e2e5415 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/revision_a/AndroidManifest.xml
@@ -21,8 +21,9 @@
<!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
to pass the build error, since tests need to use minSdkVersion 4. -->
- <uses-sdk android:minSdkVersion="4" tools:overrideLibrary=
- "androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+ <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner,
+ androidx.test.rules, androidx.test.monitor, androidx.test.services.storage,
+ androidx.test.annotation, androidx.annotation.experimental, androidx.tracing"/>
<!-- Remove the CAMERA permission
<uses-permission android:name="android.permission.CAMERA"/> -->
diff --git a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
index f761e8f..0396c3b 100644
--- a/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
+++ b/hostsidetests/atrace/src/android/atrace/cts/AtraceHostTest.java
@@ -183,11 +183,12 @@
assertNotNull(result.getModel());
ThreadModel thread = findThread(result.getModel(), result.getTid());
assertNotNull(thread);
- assertEquals(2, thread.getSlices().size());
- Slice sdkSlice = thread.getSlices().get(0);
- assertEquals("AtraceDeviceTest::beginEndSection", sdkSlice.getName());
- Slice ndkSlice = thread.getSlices().get(1);
- assertEquals("ndk::beginEndSection", ndkSlice.getName());
+ Slice sdkSlice = SliceQueriesKt.selectFirst(thread,
+ slice1 -> "AtraceDeviceTest::beginEndSection".equals(slice1.getName()));
+ assertNotNull(sdkSlice);
+ Slice ndkSlice = SliceQueriesKt.selectFirst(thread,
+ slice -> "ndk::beginEndSection".equals(slice.getName()));
+ assertNotNull(ndkSlice);
}
public void testAsyncBeginEndSection() {
@@ -283,4 +284,5 @@
assertEquals("Didn't find all async sections",
0, requiredAsyncSections.size());
}
+
}
diff --git a/hostsidetests/car/Android.bp b/hostsidetests/car/Android.bp
index 337879e..caa8290 100644
--- a/hostsidetests/car/Android.bp
+++ b/hostsidetests/car/Android.bp
@@ -24,7 +24,11 @@
"src/**/*.java",
"app/src/android/car/cts/app/PowerPolicyTestCommandStatus.java",
"app/src/android/car/cts/app/PowerPolicyTestCommandType.java",
+ ":cartelemetryservice-proto-srcs",
],
+ proto: {
+ type: "lite",
+ },
libs: [
"cts-tradefed",
"tradefed",
diff --git a/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java b/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
new file mode 100644
index 0000000..779d405
--- /dev/null
+++ b/hostsidetests/car/src/android/car/cts/CarTelemetryHostTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.car.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.car.telemetry.TelemetryProto;
+import com.android.compatibility.common.util.PollingCheck;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CarTelemetryHostTest extends CarHostJUnit4TestCase {
+
+ // Publisher/subscriber listening for gear change property
+ private static final int GEAR_SELECTION_PROPERTY_ID = 287310850;
+ private static final TelemetryProto.Publisher GEAR_CHANGE_PUBLISHER =
+ TelemetryProto.Publisher.newBuilder()
+ .setVehicleProperty(
+ TelemetryProto.VehiclePropertyPublisher.newBuilder()
+ .setVehiclePropertyId(GEAR_SELECTION_PROPERTY_ID)
+ .setReadRate(0f))
+ .build();
+ private static final TelemetryProto.Subscriber GEAR_CHANGE_SUBSCRIBER =
+ TelemetryProto.Subscriber.newBuilder()
+ .setHandler("onGearChange")
+ .setPublisher(GEAR_CHANGE_PUBLISHER)
+ .setPriority(0)
+ .build();
+
+ // only produces interim result
+ private static final String LUA_SCRIPT_INTERIM = new StringBuilder()
+ .append("function onGearChange(published_data, saved_state)\n")
+ .append(" saved_state['interim_result_exists'] = true\n")
+ .append(" on_success(saved_state)\n")
+ .append("end\n")
+ .toString();
+ private static final TelemetryProto.MetricsConfig METRICS_CONFIG_1 =
+ TelemetryProto.MetricsConfig.newBuilder()
+ .setName("test_config_1")
+ .setVersion(1)
+ .setScript(LUA_SCRIPT_INTERIM)
+ .addSubscribers(GEAR_CHANGE_SUBSCRIBER)
+ .build();
+ private static final String CONFIG_NAME_1 = METRICS_CONFIG_1.getName();
+
+ // only produces final result
+ private static final String LUA_SCRIPT_FINAL = new StringBuilder()
+ .append("function onGearChange(published_data, saved_state)\n")
+ .append(" saved_state['final_result_exists'] = true\n")
+ .append(" on_script_finished(saved_state)\n")
+ .append("end\n")
+ .toString();
+ private static final TelemetryProto.MetricsConfig METRICS_CONFIG_2 =
+ TelemetryProto.MetricsConfig.newBuilder()
+ .setName("test_config_2")
+ .setVersion(1)
+ .setScript(LUA_SCRIPT_FINAL)
+ .addSubscribers(GEAR_CHANGE_SUBSCRIBER)
+ .build();
+ private static final String CONFIG_NAME_2 = METRICS_CONFIG_2.getName();
+
+ private static final long SCRIPT_EXECUTION_TIMEOUT_MILLIS = 30_000L;
+ private static final String FINAL_RESULT_DIR = "/data/system/car/telemetry/final";
+ private static final String INTERIM_RESULT_DIR = "/data/system/car/telemetry/interim";
+
+ @Before
+ public void setUp() throws Exception {
+ getDevice().enableAdbRoot();
+ String output = executeCommand("cmd car_service enable-feature car_telemetry_service");
+ if (!output.startsWith("Already enabled")) {
+ // revert the feature to its original setting
+ executeCommand("cmd car_service disable-feature car_telemetry_service");
+ assumeTrue("CarTelemetryService is not enabled, skipping test", false);
+ }
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ executeCommand("cmd car_service telemetry remove %s", CONFIG_NAME_1);
+ executeCommand("rm %s/%s", FINAL_RESULT_DIR, CONFIG_NAME_2);
+ }
+
+ @Test
+ public void testSavingResultsAcrossReboot() throws Exception {
+ // create temp files, which will be the argument to the telemetry car shell cmd
+ File config1 = createMetricsConfigTempFile(METRICS_CONFIG_1);
+ File config2 = createMetricsConfigTempFile(METRICS_CONFIG_2);
+ config1.deleteOnExit();
+ config2.deleteOnExit();
+
+ // outputs that should be produced by the Lua scripts above
+ String scriptOutput1 = "interim_result_exists";
+ String scriptOutput2 = "final_result_exists";
+
+ // add metrics configs using car shell command
+ getDevice().executeShellV2Command("cmd car_service telemetry add " + CONFIG_NAME_1,
+ config1);
+ getDevice().executeShellV2Command("cmd car_service telemetry add " + CONFIG_NAME_2,
+ config2);
+
+ // inject gear change event, should trigger script execution for both scripts
+ executeCommand("cmd car_service inject-vhal-event %d %d",
+ GEAR_SELECTION_PROPERTY_ID, 2);
+
+ // block until script execution finishes
+ PollingCheck.waitFor(SCRIPT_EXECUTION_TIMEOUT_MILLIS, () -> {
+ String dump = dumpTelemetryService();
+ return dump.contains(scriptOutput1) && dump.contains(scriptOutput2);
+ });
+
+ // verify that both results are stored in memory, not in disk
+ assertThat(executeCommand("ls %s", INTERIM_RESULT_DIR))
+ .doesNotContain(CONFIG_NAME_1);
+ assertThat(executeCommand("ls %s", FINAL_RESULT_DIR))
+ .doesNotContain(CONFIG_NAME_2);
+
+ // trigger reboot, which should save results to disk
+ getDevice().reboot();
+ waitForCarServiceReady();
+
+ // verify data is saved across reboot
+ assertThat(dumpTelemetryService()).contains(scriptOutput1);
+ String result = executeCommand("cmd car_service telemetry get-result %s", CONFIG_NAME_2);
+ assertThat(result).contains(scriptOutput2);
+ }
+
+ private String dumpTelemetryService() throws Exception {
+ return executeCommand("dumpsys car_service --services CarTelemetryService");
+ }
+
+ private File createMetricsConfigTempFile(TelemetryProto.MetricsConfig metricsConfig)
+ throws Exception {
+ File tempFile = File.createTempFile(metricsConfig.getName(), ".bin");
+ FileOutputStream os = new FileOutputStream(tempFile);
+ os.write(metricsConfig.toByteArray());
+ os.flush();
+ os.close();
+ return tempFile;
+ }
+}
diff --git a/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml b/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml
index 97f4d9a..1d5f72e 100644
--- a/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml
+++ b/hostsidetests/graphics/framerateoverride/app/AndroidManifest.xml
@@ -19,7 +19,8 @@
<!-- targetSdkVersion for this test must be below 30 -->
<uses-sdk android:targetSdkVersion="30"/>
<application
- android:debuggable="true">
+ android:debuggable="true"
+ android:appCategory="game">
<uses-library android:name="android.test.runner" />
<activity
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 3ae0e71..af0d156 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
@@ -40,6 +40,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@@ -58,6 +59,7 @@
private int mInitialMatchContentFrameRate;
private DisplayManager mDisplayManager;
+ private UiDevice mUiDevice;
@Rule
@@ -66,17 +68,17 @@
@Before
public void setUp() throws Exception {
- final UiDevice uiDevice =
- UiDevice.getInstance(
+ mUiDevice = UiDevice.getInstance(
androidx.test.platform.app.InstrumentationRegistry.getInstrumentation());
- uiDevice.wakeUp();
- uiDevice.executeShellCommand("wm dismiss-keyguard");
+ mUiDevice.wakeUp();
+ mUiDevice.executeShellCommand("wm dismiss-keyguard");
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.adoptShellPermissionIdentity(Manifest.permission.LOG_COMPAT_CHANGE,
Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
- Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS);
+ Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
+ Manifest.permission.MANAGE_GAME_MODE);
mDisplayManager = mActivityRule.getActivity().getSystemService(DisplayManager.class);
mInitialMatchContentFrameRate = toSwitchingType(
@@ -154,11 +156,23 @@
}
private void testFrameRateOverride(FrameRateObserver frameRateObserver)
- throws InterruptedException {
+ throws InterruptedException, IOException {
FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
for (Display.Mode mode : getModesToTest()) {
setMode(mode);
- activity.testFrameRateOverride(frameRateObserver, mode.getRefreshRate());
+ activity.testFrameRateOverride(activity.new SurfaceFrameRateOverrideBehavior(),
+ frameRateObserver, mode.getRefreshRate());
+ }
+ }
+
+ private void testGameModeFrameRateOverride(FrameRateObserver frameRateObserver)
+ throws InterruptedException, IOException {
+ FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+ for (Display.Mode mode : getModesToTest()) {
+ setMode(mode);
+ activity.testFrameRateOverride(
+ activity.new GameModeFrameRateOverrideBehavior(mUiDevice),
+ frameRateObserver, mode.getRefreshRate());
}
}
@@ -169,7 +183,7 @@
*/
@Test
public void testBackpressure()
- throws InterruptedException {
+ throws InterruptedException, IOException {
FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
testFrameRateOverride(activity.new BackpressureFrameRateObserver());
}
@@ -181,7 +195,7 @@
*/
@Test
public void testChoreographer()
- throws InterruptedException {
+ throws InterruptedException, IOException {
FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
testFrameRateOverride(activity.new ChoreographerFrameRateObserver());
}
@@ -196,7 +210,7 @@
*/
@Test
public void testDisplayGetRefreshRate()
- throws InterruptedException {
+ throws InterruptedException, IOException {
FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
testFrameRateOverride(activity.new DisplayGetRefreshRateFrameRateObserver());
}
@@ -208,7 +222,7 @@
*/
@Test
public void testDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
- throws InterruptedException {
+ throws InterruptedException, IOException {
FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
testFrameRateOverride(
activity.new DisplayModeGetRefreshRateFrameRateObserver(
@@ -222,10 +236,73 @@
*/
@Test
public void testDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
- throws InterruptedException {
+ throws InterruptedException, IOException {
FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
testFrameRateOverride(
activity.new DisplayModeGetRefreshRateFrameRateObserver(
/*displayModeReturnsPhysicalRefreshRateEnabled*/ false));
}
+
+ /**
+ * Test run by
+ * FrameRateOverrideHostTest
+ * .testGameModeBackpressureDisplayModeReturnsPhysicalRefreshRateEnabled
+ */
+ @Test
+ public void testGameModeBackpressure() throws InterruptedException, IOException {
+ FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+ testGameModeFrameRateOverride(activity.new BackpressureFrameRateObserver());
+ }
+
+ /**
+ * Test run by
+ * FrameRateOverrideHostTest
+ * .testGameModeChoreographerDisplayModeReturnsPhysicalRefreshRateEnabled
+ */
+ @Test
+ public void testGameModeChoreographer() throws InterruptedException, IOException {
+ FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+ testGameModeFrameRateOverride(activity.new ChoreographerFrameRateObserver());
+ }
+
+ /**
+ * Test run by
+ * FrameRateOverrideHostTest
+ * .testGameModeDisplayGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled
+ */
+ @Test
+ public void testGameModeDisplayGetRefreshRate() throws InterruptedException, IOException {
+ FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+ testGameModeFrameRateOverride(activity.new DisplayGetRefreshRateFrameRateObserver());
+ }
+
+ /**
+ * Test run by
+ * FrameRateOverrideHostTest
+ * .testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled
+ */
+ @Test
+ public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
+ throws InterruptedException, IOException {
+ FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+ testGameModeFrameRateOverride(
+ activity.new DisplayModeGetRefreshRateFrameRateObserver(
+ /*displayModeReturnsPhysicalRefreshRateEnabled*/ false));
+ }
+
+ /**
+ * Test run by
+ * FrameRateOverrideHostTest
+ * .testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled
+ */
+ @Test
+ public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
+ throws InterruptedException, IOException {
+ FrameRateOverrideTestActivity activity = mActivityRule.getActivity();
+ testGameModeFrameRateOverride(
+ activity.new DisplayModeGetRefreshRateFrameRateObserver(
+ /*displayModeReturnsPhysicalRefreshRateEnabled*/ true));
+ }
+
+
}
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 888f7f3..c54ae79 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
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.support.test.uiautomator.UiDevice;
import android.util.Log;
import android.view.Choreographer;
import android.view.Surface;
@@ -32,6 +33,7 @@
import android.view.SurfaceView;
import android.view.ViewGroup;
+import java.io.IOException;
import java.util.ArrayList;
/**
@@ -417,39 +419,80 @@
}
}
- private void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
- float initialRefreshRate) throws InterruptedException {
- Log.i(TAG, "Staring testFrameRateOverride");
- float halfFrameRate = initialRefreshRate / 2;
+ interface FrameRateOverrideBehavior{
+ void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
+ float initialRefreshRate) throws InterruptedException, IOException;
+ }
- waitForRefreshRateChange(initialRefreshRate);
- frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Initial");
+ class SurfaceFrameRateOverrideBehavior implements FrameRateOverrideBehavior {
- Log.i(TAG, String.format("Setting Frame Rate to %.2f with default compatibility",
- halfFrameRate));
- mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
- Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
- waitForRefreshRateChange(halfFrameRate);
- frameRateObserver.observe(initialRefreshRate, halfFrameRate, "setFrameRate(default)");
+ @Override
+ public void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
+ float initialRefreshRate) throws InterruptedException {
+ Log.i(TAG, "Staring testFrameRateOverride");
+ float halfFrameRate = initialRefreshRate / 2;
- Log.i(TAG, String.format("Setting Frame Rate to %.2f with fixed source compatibility",
- halfFrameRate));
- mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
- Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
- waitForRefreshRateChange(halfFrameRate);
- frameRateObserver.observe(initialRefreshRate, halfFrameRate, "setFrameRate(fixed source)");
+ waitForRefreshRateChange(initialRefreshRate);
+ frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Initial");
- Log.i(TAG, "Resetting Frame Rate setting");
- mSurface.setFrameRate(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
- Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
- waitForRefreshRateChange(initialRefreshRate);
- frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Reset");
+ Log.i(TAG, String.format("Setting Frame Rate to %.2f with default compatibility",
+ halfFrameRate));
+ mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+ Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ waitForRefreshRateChange(halfFrameRate);
+ frameRateObserver.observe(initialRefreshRate, halfFrameRate, "setFrameRate(default)");
+
+ Log.i(TAG, String.format("Setting Frame Rate to %.2f with fixed source compatibility",
+ halfFrameRate));
+ mSurface.setFrameRate(halfFrameRate, Surface.FRAME_RATE_COMPATIBILITY_FIXED_SOURCE,
+ Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ waitForRefreshRateChange(halfFrameRate);
+ frameRateObserver.observe(initialRefreshRate, halfFrameRate,
+ "setFrameRate(fixed source)");
+
+ Log.i(TAG, "Resetting Frame Rate setting");
+ mSurface.setFrameRate(0, Surface.FRAME_RATE_COMPATIBILITY_DEFAULT,
+ Surface.CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
+ waitForRefreshRateChange(initialRefreshRate);
+ frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Reset");
+ }
+ }
+
+ class GameModeFrameRateOverrideBehavior implements FrameRateOverrideBehavior {
+ private UiDevice mUiDevice;
+ GameModeFrameRateOverrideBehavior(UiDevice uiDevice) {
+ mUiDevice = uiDevice;
+ }
+ @Override
+ public void testFrameRateOverrideBehavior(FrameRateObserver frameRateObserver,
+ float initialRefreshRate) throws InterruptedException, IOException {
+ Log.i(TAG, "Starting testGameModeFrameRateOverride");
+
+ int initialRefreshRateInt = (int) initialRefreshRate;
+ for (int divisor = 1; initialRefreshRateInt / divisor >= 30; ++divisor) {
+ int overrideFrameRate = initialRefreshRateInt / divisor;
+ Log.i(TAG, String.format("Setting Frame Rate to %d using Game Mode",
+ overrideFrameRate));
+
+ mUiDevice.executeShellCommand(String.format("cmd game set --mode 2 --fps %d %s",
+ overrideFrameRate, getPackageName()));
+ waitForRefreshRateChange(overrideFrameRate);
+ frameRateObserver.observe(initialRefreshRate, overrideFrameRate,
+ String.format("Game Mode Override(%d)", overrideFrameRate));
+ }
+
+ Log.i(TAG, "Resetting Frame Rate setting");
+ mUiDevice.executeShellCommand(String.format("cmd game reset %s", getPackageName()));
+ waitForRefreshRateChange(initialRefreshRate);
+ frameRateObserver.observe(initialRefreshRate, initialRefreshRate, "Reset");
+ }
}
// The activity being intermittently paused/resumed has been observed to
// cause test failures in practice, so we run the test with retry logic.
- public void testFrameRateOverride(FrameRateObserver frameRateObserver, float initialRefreshRate)
- throws InterruptedException {
+ public void testFrameRateOverride(FrameRateOverrideBehavior frameRateOverrideBehavior,
+ FrameRateObserver frameRateObserver, float initialRefreshRate)
+ throws InterruptedException, IOException {
synchronized (mLock) {
Log.i(TAG, "testFrameRateOverride started");
int attempts = 0;
@@ -458,7 +501,8 @@
while (!testPassed) {
waitForPreconditions();
try {
- testFrameRateOverrideBehavior(frameRateObserver, initialRefreshRate);
+ frameRateOverrideBehavior.testFrameRateOverrideBehavior(frameRateObserver,
+ initialRefreshRate);
testPassed = true;
} catch (PreconditionViolatedException exc) {
// The logic below will retry if we're below max attempts.
diff --git a/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java b/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java
index 12162d9..a8d7a9e 100644
--- a/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java
+++ b/hostsidetests/graphics/framerateoverride/src/com/android/cts/graphics/framerateoverride/FrameRateOverrideHostTest.java
@@ -36,10 +36,14 @@
@Override
protected void setUp() throws Exception {
installPackage(TEST_APK, true);
+ // add device config to enable game mode
+ runCommand("device_config put game_overlay " + TEST_PKG + " mode=2:mode=3");
}
@Override
protected void tearDown() throws Exception {
+ // remove device config
+ runCommand("device_config delete game_overlay " + TEST_PKG);
uninstallPackage(TEST_PKG, true);
}
@@ -122,4 +126,84 @@
/*disabledChanges*/
ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
}
+
+ public void testGameModeBackpressureDisplayModeReturnsPhysicalRefreshRateEnabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeBackpressure",
+ /*enabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+ /*disabledChanges*/
+ ImmutableSet.of());
+ }
+
+ public void testGameModeBackpressureDisplayModeReturnsPhysicalRefreshRateDisabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeBackpressure",
+ /*enabledChanges*/
+ ImmutableSet.of(),
+ /*disabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+ }
+
+ public void testGameModeChoreographerDisplayModeReturnsPhysicalRefreshRateEnabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeChoreographer",
+ /*enabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+ /*disabledChanges*/
+ ImmutableSet.of());
+ }
+
+ public void testGameModeChoreographerDisplayModeReturnsPhysicalRefreshRateDisabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeChoreographer",
+ /*enabledChanges*/
+ ImmutableSet.of(),
+ /*disabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+ }
+
+ public void testGameModeDisplayGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeDisplayGetRefreshRate",
+ /*enabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+ /*disabledChanges*/
+ ImmutableSet.of());
+ }
+
+ public void testGameModeDisplayGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeDisplayGetRefreshRate",
+ /*enabledChanges*/
+ ImmutableSet.of(),
+ /*disabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+ }
+
+ public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateEnabled",
+ /*enabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID),
+ /*disabledChanges*/
+ ImmutableSet.of());
+ }
+
+ public void testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled()
+ throws Exception {
+ runDeviceCompatTest(TEST_PKG, ".FrameRateOverrideTest",
+ "testGameModeDisplayModeGetRefreshRateDisplayModeReturnsPhysicalRefreshRateDisabled",
+ /*enabledChanges*/
+ ImmutableSet.of(),
+ /*disabledChanges*/
+ ImmutableSet.of(DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE_CHANGEID));
+ }
}
diff --git a/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java b/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java
index 0507669..9fcd9b1 100644
--- a/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java
+++ b/hostsidetests/graphics/gpumetrics/src/com/android/cts/graphics/GpuWorkDumpsysTest.java
@@ -16,11 +16,13 @@
package com.android.cts.graphics;
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.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+import com.android.compatibility.common.util.CddTest;
import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import com.android.tradefed.util.CommandResult;
@@ -38,6 +40,8 @@
private static final String DUMPSYS_COMMAND = "dumpsys gpu --gpuwork";
private static final String TEST_PKG = "com.android.cts.framestatstestapp";
private static final int PAUSE_MILLIS = 3000;
+ private static final String GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH =
+ "/sys/kernel/tracing/events/power/gpu_work_period/format";
private CommandResult assertShellCommand(String command) throws DeviceNotAvailableException {
CommandResult commandResult = getDevice().executeShellV2Command(command);
@@ -68,16 +72,21 @@
return appUid;
}
+ @CddTest(requirement = "6.1/C-6-1")
@Test
public void testOutputFormat() throws Exception {
- // Execute dumpsys command.
- CommandResult commandResult = assertShellCommand(DUMPSYS_COMMAND);
+ CommandResult commandResult =
+ getDevice()
+ .executeShellV2Command(String.format("cat %s", GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH));
- // If the dumpsys command output indicates that the GPU information is not available then the
- // test ends here.
- assumeFalse(
- "GPU time in state information was not available.",
- commandResult.getStdout().contains("GPU time in state information is not available"));
+ // If we fail to cat the tracepoint format then the test ends here. If the tracing file system
+ // is inaccessible, then this test won't fail. We rely on VTS tests to ensure that the tracing
+ // file system is accessible.
+ assumeTrue(
+ String.format(
+ "Failed to cat the gpu_work_period tracepoint format at %s",
+ GPU_WORK_PERIOD_TRACEPOINT_FORMAT_PATH),
+ commandResult.getStatus().equals(CommandStatus.SUCCESS));
// Turn screen on.
assertShellCommand("input keyevent KEYCODE_WAKEUP");
@@ -94,30 +103,43 @@
// Get the UID of the test app.
long appUid = getTestAppUid();
- // Execute dumpsys command again.
+ // Execute dumpsys command.
commandResult = assertShellCommand(DUMPSYS_COMMAND);
- LogUtil.CLog.i("dumpsys output:\n%s", commandResult.getStdout());
+ assertFalse(
+ String.format(
+ "The command shows errors.\nCommand: %s\nOutput:\n%s\n",
+ DUMPSYS_COMMAND, commandResult.getStdout()),
+ commandResult.getStdout().contains("[errors:"));
String[] lines = commandResult.getStdout().trim().split("\n");
int i = 0;
for (; i < lines.length; ++i) {
- if (lines[i].startsWith("uid/freq: 0MHz")) {
+ if (lines[i].startsWith("gpu_id uid")) {
break;
}
}
- assertTrue("Could not find uid/freq header in output", i < lines.length);
+ assertTrue(
+ String.format(
+ "Could not find \"gpu_id uid ...\" header in output:\n%s\n", commandResult.getStdout()),
+ i < lines.length);
- Pattern uidInfoPattern = Pattern.compile(String.format("(%d): \\d+", appUid));
+ Pattern uidInfoPattern = Pattern.compile(String.format("\\d+ (%d) (\\d+) (\\d+)", appUid));
for (; i < lines.length; ++i) {
Matcher matcher = uidInfoPattern.matcher(lines[i]);
if (!matcher.lookingAt()) {
continue;
}
- if (appUid == Long.parseLong(matcher.group(1))) {
- break;
+ if (appUid == Long.parseLong(matcher.group(1))
+ && Long.parseLong(matcher.group(2)) > 0
+ && Long.parseLong(matcher.group(3)) > 0) {
+ // Success!
+ return;
}
}
- assertTrue(String.format("Could not find UID %d in output", appUid), i < lines.length);
+ fail(
+ String.format(
+ "Could not find UID %d with non-zero active and inactive GPU time in output:\n%s\n",
+ appUid, commandResult.getStdout()));
}
}
diff --git a/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java b/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
index fb37109..76bdaf7 100644
--- a/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
+++ b/hostsidetests/media/app/MediaRouterTest/src/android/media/router/cts/MediaRouter2Test.java
@@ -30,6 +30,7 @@
import static android.media.cts.MediaRouterTestConstants.ROUTE_ID_3_2;
import static android.media.cts.MediaRouterTestConstants.ROUTE_ID_3_3;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -46,6 +47,7 @@
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -53,6 +55,7 @@
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
@LargeTest
public class MediaRouter2Test {
@@ -77,14 +80,14 @@
List<String> features = new ArrayList<>();
features.add("A test feature");
RouteDiscoveryPreference preference =
- new RouteDiscoveryPreference.Builder(features, /*activeScan=*/false).build();
+ new RouteDiscoveryPreference.Builder(features, /*activeScan=*/ false).build();
mRouter2.registerRouteCallback(mExecutor, mRouterDummyCallback, preference);
}
@Test
public void dontDedupeByDefault() throws Exception {
RouteDiscoveryPreference preference =
- new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true).build();
+ new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true).build();
Map<String, MediaRoute2Info> routes =
waitAndGetRoutes(preference, Set.of(ROUTE_ID_1_1, ROUTE_ID_2_1, ROUTE_ID_3_1));
@@ -102,7 +105,7 @@
@Test
public void setDeduplicationPackageOrder1() throws Exception {
RouteDiscoveryPreference preference =
- new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+ new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
.setDeduplicationPackageOrder(
List.of(
MEDIA_ROUTER_PROVIDER_1_PACKAGE,
@@ -126,7 +129,7 @@
@Test
public void setDeduplicationPackageOrder2() throws Exception {
RouteDiscoveryPreference preference =
- new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+ new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
.setDeduplicationPackageOrder(
List.of(
MEDIA_ROUTER_PROVIDER_3_PACKAGE,
@@ -150,7 +153,7 @@
@Test
public void setDeduplicationPackageOrder3() throws Exception {
RouteDiscoveryPreference preference =
- new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/true)
+ new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
.setDeduplicationPackageOrder(
List.of(
MEDIA_ROUTER_PROVIDER_2_PACKAGE,
@@ -171,6 +174,89 @@
assertFalse(routes.containsKey(ROUTE_ID_3_3));
}
+ @Test
+ public void testRouteCallbacks() throws Exception {
+ Set<String> addedRouteIds = new HashSet<>();
+ Set<String> removedRouteIds = new HashSet<>();
+
+ AtomicReference<CountDownLatch> addLatchRef = new AtomicReference<>();
+ AtomicReference<CountDownLatch> removeLatchRef = new AtomicReference<>();
+
+ addLatchRef.set(new CountDownLatch(1));
+ removeLatchRef.set(new CountDownLatch(1));
+
+ RouteDiscoveryPreference preference =
+ new RouteDiscoveryPreference.Builder(FEATURES_ALL, /*activeScan=*/ true)
+ .setAllowedPackages(List.of(MEDIA_ROUTER_PROVIDER_1_PACKAGE))
+ .setDeduplicationPackageOrder(
+ List.of(
+ MEDIA_ROUTER_PROVIDER_2_PACKAGE,
+ MEDIA_ROUTER_PROVIDER_3_PACKAGE,
+ MEDIA_ROUTER_PROVIDER_1_PACKAGE))
+ .build();
+ MediaRouter2.RouteCallback routeCallback =
+ new MediaRouter2.RouteCallback() {
+ @Override
+ public void onRoutesAdded(List<MediaRoute2Info> routes) {
+ for (MediaRoute2Info route : routes) {
+ if (!route.isSystemRoute()) {
+ addedRouteIds.add(route.getOriginalId());
+ }
+ }
+ addLatchRef.get().countDown();
+ }
+
+ @Override
+ public void onRoutesRemoved(List<MediaRoute2Info> routes) {
+ for (MediaRoute2Info route : routes) {
+ removedRouteIds.add(route.getOriginalId());
+ }
+ removeLatchRef.get().countDown();
+ }
+ };
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, preference);
+ assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertFalse(removeLatchRef.get().await(WAIT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(Set.of(ROUTE_ID_1_1, ROUTE_ID_1_2, ROUTE_ID_1_3), addedRouteIds);
+
+ addLatchRef.set(new CountDownLatch(1));
+ removeLatchRef.set(new CountDownLatch(1));
+ RouteDiscoveryPreference preference2 =
+ new RouteDiscoveryPreference.Builder(preference)
+ .setAllowedPackages(
+ List.of(
+ MEDIA_ROUTER_PROVIDER_1_PACKAGE,
+ MEDIA_ROUTER_PROVIDER_2_PACKAGE))
+ .build();
+
+ addedRouteIds.clear();
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, preference2);
+ assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(removeLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(Set.of(ROUTE_ID_2_1, ROUTE_ID_2_2, ROUTE_ID_2_3), addedRouteIds);
+ assertEquals(Set.of(ROUTE_ID_1_2), removedRouteIds);
+
+ addLatchRef.set(new CountDownLatch(1));
+ removeLatchRef.set(new CountDownLatch(1));
+ RouteDiscoveryPreference preference3 =
+ new RouteDiscoveryPreference.Builder(preference)
+ .setAllowedPackages(
+ List.of(
+ MEDIA_ROUTER_PROVIDER_1_PACKAGE,
+ MEDIA_ROUTER_PROVIDER_2_PACKAGE,
+ MEDIA_ROUTER_PROVIDER_3_PACKAGE))
+ .build();
+
+ addedRouteIds.clear();
+ removedRouteIds.clear();
+
+ mRouter2.registerRouteCallback(mExecutor, routeCallback, preference3);
+ assertTrue(addLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertTrue(removeLatchRef.get().await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ assertEquals(Set.of(ROUTE_ID_3_1, ROUTE_ID_3_2), addedRouteIds);
+ assertEquals(Set.of(ROUTE_ID_1_3), removedRouteIds);
+ }
+
// It returns original route id -> route for convenience
private static Map<String, MediaRoute2Info> createRouteMap(List<MediaRoute2Info> routes) {
Map<String, MediaRoute2Info> routeMap = new HashMap<>();
diff --git a/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java b/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
index df6ebeb..32adb1e 100644
--- a/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
+++ b/hostsidetests/media/src/android/media/router/cts/MediaRouter2HostTest.java
@@ -66,4 +66,10 @@
runDeviceTests(
MEDIA_ROUTER_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "setDeduplicationPackageOrder3");
}
+
+ @AppModeFull
+ @RequiresDevice
+ public void testCallback() throws Exception {
+ runDeviceTests(MEDIA_ROUTER_TEST_PACKAGE, DEVICE_SIDE_TEST_CLASS, "testRouteCallbacks");
+ }
}
diff --git a/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java b/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java
index 3203793..eeabeec 100644
--- a/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java
+++ b/hostsidetests/settings/app/DeviceOwnerApp/src/com/google/android/cts/deviceowner/DeviceOwnerTest.java
@@ -76,6 +76,7 @@
}
}
+ static final String CAR_SETTING_FRAG_RESOURCE_ID_REGEX = ".*:id/fragment_container_wrapper";
static final String PACKAGE_NAME = DeviceOwnerTest.class.getPackage().getName();
static final ComponentName RECEIVER_COMPONENT =
new ComponentName(PACKAGE_NAME, BasicAdminReceiver.class.getName());
@@ -84,6 +85,7 @@
protected PackageManager mPackageManager;
protected boolean mIsDeviceOwner;
private String mWorkPolicyInfoText;
+ private boolean mIsAutomotive;
@Override
protected void setUp() throws Exception {
@@ -94,9 +96,9 @@
mDevicePolicyManager = TestAppSystemServiceFactory.getDevicePolicyManager(mContext,
BasicAdminReceiver.class, /* forDeviceOwner= */ true);
- boolean isAutomotive = mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ mIsAutomotive = mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
- mWorkPolicyInfoText = isAutomotive
+ mWorkPolicyInfoText = mIsAutomotive
? "Privacy Settings for Device Owner CTS host side app vehicle policy"
: "Your work policy info";
@@ -145,9 +147,10 @@
boolean found = null != mDevice.wait(Until.findObject(By.text(mWorkPolicyInfoText)),
TIMEOUT_MS);
- // Try to scroll the list to find the item
- if (!found) {
- UiScrollable scroller = new UiScrollable(new UiSelector().scrollable(true));
+ // For automotive UI, try to scroll the privacy list to find the item
+ if (!found && mIsAutomotive) {
+ UiScrollable scroller = new UiScrollable(new UiSelector()
+ .resourceIdMatches(CAR_SETTING_FRAG_RESOURCE_ID_REGEX));
try {
// Swipe far away from the edges to avoid triggering navigation gestures
scroller.setSwipeDeadZonePercentage(DEADZONE_PCT);
diff --git a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index c03b9b4..e356ea6 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -684,8 +684,6 @@
sleep(500);
setScreenBrightness(100);
sleep(500);
- setScreenBrightness(140);
- sleep(500);
wl.release();
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
index 8ae8d4f..33422c1 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/statsd/UidAtomTests.java
@@ -600,11 +600,9 @@
Set<Integer> screenMin = new HashSet<>(Arrays.asList(47));
Set<Integer> screen100 = new HashSet<>(Arrays.asList(100));
- Set<Integer> screen140 = new HashSet<>(Arrays.asList(140));
- // Set<Integer> screenMax = new HashSet<>(Arrays.asList(255));
// Add state sets to the list in order.
- List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100, screen140);
+ List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100);
ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
atomTag);
@@ -619,7 +617,7 @@
AtomTestUtils.popUntilFind(data, screenMin,
atom -> atom.getScreenBrightnessChanged().getLevel());
- AtomTestUtils.popUntilFindFromEnd(data, screen140,
+ AtomTestUtils.popUntilFindFromEnd(data, screen100,
atom -> atom.getScreenBrightnessChanged().getLevel());
// Assert that the events happened in the expected order.
AtomTestUtils.assertStatesOccurredInOrder(stateSet, data, AtomTestUtils.WAIT_TIME_SHORT,
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index 9836e73..a8f9132 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -29,6 +29,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertThrows;
+
import android.content.ClipData;
import android.content.ContentResolver;
import android.content.Intent;
@@ -283,8 +285,9 @@
addImage(mCloudPrimaryMediaGenerator, /* localId */ null, CLOUD_ID1);
// Notification fails because the calling cloud provider isn't enabled
- assertThat(MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
- CloudProviderPrimary.AUTHORITY)).isFalse();
+ assertThrows("Unauthorized cloud media notification", SecurityException.class,
+ () -> MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
+ CloudProviderPrimary.AUTHORITY, COLLECTION_1));
// Sleep because the notification API throttles requests with a 1s delay
Thread.sleep(1500);
@@ -298,12 +301,13 @@
setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY);
assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
CloudProviderPrimary.AUTHORITY)).isTrue();
- assertThat(MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
- CloudProviderPrimary.AUTHORITY)).isTrue();
- // Notification fails with a different provider enabled within the same app
- assertThat(MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
- CloudProviderSecondary.AUTHORITY)).isFalse();
+ MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
+ CloudProviderPrimary.AUTHORITY, COLLECTION_1);
+
+ assertThrows("Unauthorized cloud media notification", SecurityException.class,
+ () -> MediaStore.notifyCloudMediaChangedEvent(mContext.getContentResolver(),
+ CloudProviderSecondary.AUTHORITY, COLLECTION_1));
// Sleep because the notification API throttles requests with a 1s delay
Thread.sleep(1500);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
index 1b9149a..fcef908 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
@@ -33,6 +33,7 @@
import android.net.Uri;
import android.provider.MediaStore;
+import androidx.test.filters.SdkSuppress;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiSelector;
@@ -69,8 +70,13 @@
mActivity.finish();
}
+ /**
+ * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
+ * in a platform code change and is available Android T onwards.
+ */
@Test
@RequireRunOnWorkProfile
+ @SdkSuppress(minSdkVersion = 32, codeName = "T")
public void testWorkApp_canAccessPersonalProfileContents() throws Exception {
final int imageCount = 2;
createImages(imageCount, sDeviceState.primaryUser().id(), mUriList);
@@ -107,9 +113,28 @@
}
}
+ /**
+ * ACTION_PICK_IMAGES is allowlisted by default from work to personal. This got allowlisted
+ * in a platform code change and is available Android T onwards. Before that it needs to be
+ * explicitly allowlisted by the device admin.
+ */
+ @Test
+ @RequireRunOnWorkProfile
+ @SdkSuppress(maxSdkVersion = 31, codeName = "S")
+ public void testWorkApp_cannotAccessPersonalProfile_beforeT() throws Exception {
+ assertBlockedByAdmin(/* isInvokedFromWorkProfile */ true);
+ }
+
+ /**
+ * ACTION_PICK_IMAGES is allowlisted by default from work to personal only (not vice-a-versa)
+ */
@Test
@EnsureHasWorkProfile
public void testPersonalApp_cannotAccessWorkProfile_default() throws Exception {
+ assertBlockedByAdmin(/* isInvokedFromWorkProfile */ false);
+ }
+
+ private void assertBlockedByAdmin(boolean isInvokedFromWorkProfile) throws Exception {
Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
// TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
@@ -120,19 +145,22 @@
profileButton.click();
mDevice.waitForIdle();
- // By default, ACTION_PICK_IMAGES is only allowlisted to access personal
- // content from work profile, but not vice-a-versa.
- assertBlockedByAdminDialog();
+ assertBlockedByAdminDialog(isInvokedFromWorkProfile);
}
- private void assertBlockedByAdminDialog() {
+ private void assertBlockedByAdminDialog(boolean isInvokedFromWorkProfile) {
final String dialogTitle = "Blocked by your admin";
assertWithMessage("Timed out while waiting for blocked by admin dialog to appear")
.that(new UiObject(new UiSelector().textContains(dialogTitle))
.waitForExists(SHORT_TIMEOUT))
.isTrue();
- final String dialogDescription = "Accessing work data from a personal app is not permitted";
+ final String dialogDescription;
+ if (isInvokedFromWorkProfile) {
+ dialogDescription = "Accessing personal data from a work app is not permitted";
+ } else {
+ dialogDescription = "Accessing work data from a personal app is not permitted";
+ }
assertWithMessage("Blocked by admin description is not as expected")
.that(new UiObject(new UiSelector().textContains(dialogDescription)).exists())
.isTrue();
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index 0eb619c..b9f8f33 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -276,7 +276,7 @@
swipeLeftAndWait();
// Deselect one item
- clickAndWait(findPreviewSelectCheckButton());
+ clickAndWait(findPreviewSelectedCheckButton());
// Return selected items
clickAndWait(findPreviewAddButton());
@@ -556,9 +556,9 @@
REGEX_PACKAGE_NAME + ":id/button_view_selected"));
}
- private static UiObject findPreviewSelectCheckButton() {
+ private static UiObject findPreviewSelectedCheckButton() {
return new UiObject(new UiSelector().resourceIdMatches(
- REGEX_PACKAGE_NAME + ":id/preview_select_check_button"));
+ REGEX_PACKAGE_NAME + ":id/preview_selected_check_button"));
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
index fa07976..a4ec998 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/RemoteVideoPreviewTest.java
@@ -48,13 +48,13 @@
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
import org.mockito.Mockito;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -95,7 +95,7 @@
setCloudProvider(mContext, CloudProviderPrimary.AUTHORITY);
assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(mContext.getContentResolver(),
- CloudProviderPrimary.AUTHORITY)).isTrue();
+ CloudProviderPrimary.AUTHORITY)).isTrue();
mSurfaceControllerListener = CloudProviderPrimary.getMockSurfaceControllerListener();
mAssertInOrder = Mockito.inOrder(mSurfaceControllerListener);
@@ -113,7 +113,7 @@
@Test
public void testBasicVideoPreview() throws Exception {
- initCloudProviderWithVideo(Pair.create(null, CLOUD_ID1));
+ initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID1)));
launchPreviewMultiple(/* count */ 1);
@@ -121,7 +121,7 @@
verifyInitialVideoPreviewSetup(surfaceId, CLOUD_ID1);
// Remote Preview calls onMediaPlay when PLAYBACK_EVENT_READY is sent by the
// CloudMediaProvider
- verifyPlaybackEventReady(surfaceId);
+ verifyPlaybackStartedWhenPlayerReady(surfaceId);
// TODO(b/215187981): Add test for onMediaPause()
@@ -144,9 +144,9 @@
}
@Test
- @Ignore("Re-enable once b/219861183 is fixed")
public void testSwipeAdjacentVideoPreview() throws Exception {
- initCloudProviderWithVideo(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2));
+ initCloudProviderWithVideo(
+ Arrays.asList(Pair.create(null, CLOUD_ID1), Pair.create(null, CLOUD_ID2)));
launchPreviewMultiple(/* count */ 2);
@@ -154,14 +154,13 @@
verifyInitialVideoPreviewSetup(surfaceIdForFirstVideoPreview, CLOUD_ID2);
// Remote Preview calls onMediaPlay when PLAYBACK_EVENT_READY is sent by the
// CloudMediaProvider
- verifyPlaybackEventReady(surfaceIdForFirstVideoPreview);
+ verifyPlaybackStartedWhenPlayerReady(surfaceIdForFirstVideoPreview);
// Swipe left preview mode
swipeLeftAndWait();
// Remote Preview calls onSurfaceCreated with monotonically increasing surfaceIds
final int surfaceIdForSecondVideoPreview = 1;
-
verifyAdjacentVideoSwipe(surfaceIdForFirstVideoPreview, surfaceIdForSecondVideoPreview,
CLOUD_ID1);
@@ -180,10 +179,9 @@
}
@Test
- @Ignore("Re-enable once b/219861183 is fixed")
public void testSwipeImageVideoPreview() throws Exception {
- initCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
- initCloudProviderWithVideo(Pair.create(null, CLOUD_ID2));
+ initCloudProviderWithImage(Arrays.asList(Pair.create(null, CLOUD_ID1)));
+ initCloudProviderWithVideo(Arrays.asList(Pair.create(null, CLOUD_ID2)));
launchPreviewMultiple(/* count */ 2);
// Remote Preview calls onSurfaceCreated with monotonically increasing surfaceIds
@@ -191,7 +189,7 @@
verifyInitialVideoPreviewSetup(surfaceId, CLOUD_ID2);
// Remote Preview calls onMediaPlay when PLAYBACK_EVENT_READY is sent by the
// CloudMediaProvider
- verifyPlaybackEventReady(surfaceId);
+ verifyPlaybackStartedWhenPlayerReady(surfaceId);
// Swipe left preview mode
swipeLeftAndWait();
@@ -209,10 +207,7 @@
surfaceId++;
verifyInitialVideoPreviewSetup(surfaceId, CLOUD_ID2);
- // TODO (b/218871686): Remote Handler should wait for PLAYBACK_EVENT_READY to be sent.
- // Once the above bug is fixed remove the following and call
- // verifyPlaybackEventReady(surfaceId) instead
- mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(surfaceId));
+ verifyPlaybackStartedWhenPlayerReady(surfaceId);
final UiObject addButton = findPreviewAddButton();
addButton.click();
@@ -226,9 +221,10 @@
*
* @param oldSurfaceId the Surface ID which we are swiping away from
* @param newSurfaceId the Surface ID to which we are swiping
- * @param newMediaId the media ID of the video we are swiping to
+ * @param newMediaId the media ID of the video we are swiping to
*/
- private void verifyAdjacentVideoSwipe(int oldSurfaceId, int newSurfaceId, String newMediaId) {
+ private void verifyAdjacentVideoSwipe(int oldSurfaceId, int newSurfaceId, String newMediaId)
+ throws Exception {
mAssertInOrder.verify(mSurfaceControllerListener).onSurfaceCreated(eq(newSurfaceId),
any(), eq(newMediaId));
@@ -236,10 +232,7 @@
// (swipe is complete).
mAssertInOrder.verify(mSurfaceControllerListener).onSurfaceDestroyed(eq(oldSurfaceId));
- // Media plays automatically after the previous surface is destroyed (in other words the
- // previous video screen is not visible at all and the swipe has completed). This is because
- // the player is already ready.
- mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(newSurfaceId));
+ verifyPlaybackStartedWhenPlayerReady(newSurfaceId);
}
/**
@@ -249,7 +242,7 @@
* * Surface related callbacks (onSurfaceCreated and onSurfaceChanged)
*
* @param surfaceId Surface ID to set up video preview on
- * @param mediaId Media ID to set up video preview with
+ * @param mediaId Media ID to set up video preview with
*/
private void verifyInitialVideoPreviewSetup(int surfaceId, String mediaId) {
// Remote Preview calls onPlayerCreate as the first call to CloudMediaProvider
@@ -265,14 +258,16 @@
eq(VIDEO_PIXEL_FORMAT), anyInt(), anyInt());
}
- private void verifyPlaybackEventReady(int surfaceId) {
+ private void verifyPlaybackStartedWhenPlayerReady(int surfaceId) throws Exception {
CloudProviderPrimary.sendPlaybackEvent(surfaceId, PLAYBACK_EVENT_READY);
+ // Wait for photo picker to receive the event and invoke media play via binder calls.
+ MediaStore.waitForIdle(mContext.getContentResolver());
mAssertInOrder.verify(mSurfaceControllerListener).onMediaPlay(eq(surfaceId));
}
- private void initCloudProviderWithImage(Pair<String, String>... mediaPairs)
+ private void initCloudProviderWithImage(List<Pair<String, String>> mediaPairs)
throws Exception {
- for (Pair<String, String> pair: mediaPairs) {
+ for (Pair<String, String> pair : mediaPairs) {
addImage(mCloudPrimaryMediaGenerator, pair.first, pair.second);
}
@@ -286,9 +281,9 @@
R.raw.lg_g4_iso_800_jpg);
}
- private void initCloudProviderWithVideo(Pair<String, String>... mediaPairs)
+ private void initCloudProviderWithVideo(List<Pair<String, String>> mediaPairs)
throws Exception {
- for (Pair<String, String> pair: mediaPairs) {
+ for (Pair<String, String> pair : mediaPairs) {
addVideo(mCloudPrimaryMediaGenerator, pair.first, pair.second);
}
@@ -302,7 +297,7 @@
R.raw.test_video);
}
- private void launchPreviewMultiple(int count) throws Exception {
+ private void launchPreviewMultiple(int count) throws Exception {
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
// TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
@@ -313,8 +308,7 @@
assertThat(itemCount).isEqualTo(count);
- for (int i = 0; i < itemCount; i++) {
- final UiObject item = itemList.get(i);
+ for (final UiObject item : itemList) {
item.click();
mDevice.waitForIdle();
}
@@ -322,6 +316,9 @@
final UiObject viewSelectedButton = findViewSelectedButton();
viewSelectedButton.click();
mDevice.waitForIdle();
+
+ // Wait for CloudMediaProvider binder calls to finish.
+ MediaStore.waitForIdle(mContext.getContentResolver());
}
private static UiObject findViewSelectedButton() {
@@ -329,17 +326,23 @@
REGEX_PACKAGE_NAME + ":id/button_view_selected"));
}
- private void swipeLeftAndWait() {
+ private void swipeLeftAndWait() throws Exception {
final int width = mDevice.getDisplayWidth();
final int height = mDevice.getDisplayHeight();
mDevice.swipe(width / 2, height / 2, width / 4, height / 2, 10);
mDevice.waitForIdle();
+
+ // Wait for CloudMediaProvider binder calls to finish.
+ MediaStore.waitForIdle(mContext.getContentResolver());
}
- private void swipeRightAndWait() {
+ private void swipeRightAndWait() throws Exception {
final int width = mDevice.getDisplayWidth();
final int height = mDevice.getDisplayHeight();
mDevice.swipe(width / 4, height / 2, width / 2, height / 2, 10);
mDevice.waitForIdle();
+
+ // Wait for CloudMediaProvider binder calls to finish.
+ MediaStore.waitForIdle(mContext.getContentResolver());
}
}
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
index b6bb357..089aa58 100755
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityGestureDetectorTest.java
@@ -144,8 +144,8 @@
mStrokeLenPxX = (int) (GESTURE_LENGTH_INCHES * metrics.xdpi);
// The threshold is determined by xdpi.
mStrokeLenPxY = mStrokeLenPxX;
- mMaxAdjustedStrokeLenPxX = metrics.heightPixels / 2;
- mMaxAdjustedStrokeLenPxY = metrics.widthPixels / 2;
+ mMaxAdjustedStrokeLenPxX = metrics.widthPixels / 2;
+ mMaxAdjustedStrokeLenPxY = metrics.heightPixels / 2;
final boolean screenWideEnough = metrics.widthPixels / 2 > mStrokeLenPxX;
final boolean screenHighEnough = metrics.heightPixels / 2 > mStrokeLenPxY;
mScreenBigEnough = screenWideEnough && screenHighEnough;
@@ -641,14 +641,18 @@
adjustStrokeDurationForSlop(STROKE_MS, dx, slopAdjustedDx),
adjustStrokeDurationForSlop(STROKE_MS, dy, slopAdjustedDy));
+ final PointF tapLocation = new PointF(mTapLocation);
+ final float locationOffsetX = (fingerCount - 1) * fingerOffset;
+ tapLocation.offset(dx > 0 ? -locationOffsetX : locationOffsetX , 0);
for (int currentFinger = 0; currentFinger < fingerCount; ++currentFinger) {
// Make sure adjustments don't take us outside of screen boundaries.
- assertTrue(slopAdjustedDx + (fingerOffset * currentFinger) < mMaxAdjustedStrokeLenPxX);
+ assertTrue(slopAdjustedDx + (fingerOffset * currentFinger) < (mMaxAdjustedStrokeLenPxX
+ + locationOffsetX));
assertTrue(slopAdjustedDy < mMaxAdjustedStrokeLenPxY);
builder.addStroke(
GestureUtils.swipe(
- add(mTapLocation, fingerOffset * currentFinger, 0),
- add(mTapLocation, slopAdjustedDx + (fingerOffset * currentFinger),
+ add(tapLocation, fingerOffset * currentFinger, 0),
+ add(tapLocation, slopAdjustedDx + (fingerOffset * currentFinger),
slopAdjustedDy),
slopAdjustedStrokeDuration));
}
@@ -657,9 +661,9 @@
private float adjustStrokeDeltaForSlop(int fingerCount, float strokeDelta) {
if (strokeDelta > 0.0f) {
- return strokeDelta + (fingerCount * mScaledTouchSlop);
+ return Math.max(strokeDelta, fingerCount * mScaledTouchSlop + 10);
} else if (strokeDelta < 0.0f) {
- return strokeDelta - (fingerCount * mScaledTouchSlop);
+ return Math.min(strokeDelta, -(fingerCount * mScaledTouchSlop + 10));
}
return strokeDelta;
}
diff --git a/tests/app/src/android/app/cts/NearbyDeviceTest.kt b/tests/app/src/android/app/cts/NearbyDeviceTest.kt
new file mode 100644
index 0000000..07b2364
--- /dev/null
+++ b/tests/app/src/android/app/cts/NearbyDeviceTest.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.cts
+
+import android.media.NearbyDevice
+import android.os.Parcel
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Tests for [android.media.NearbyDevice]. */
+@RunWith(AndroidJUnit4::class)
+class NearbyDeviceTest {
+
+ @Test
+ fun getMediaRoute2Id_returnsIdPassedIn() {
+ val id = "testIdHere"
+ val nearbyDevice = NearbyDevice(id, NearbyDevice.RANGE_UNKNOWN)
+
+ assertThat(nearbyDevice.mediaRoute2Id).isEqualTo(id)
+ }
+
+ @Test
+ fun getRangeZone_returnsRangeZonePassedIn() {
+ val rangeZone = NearbyDevice.RANGE_WITHIN_REACH
+ val nearbyDevice = NearbyDevice("id", rangeZone)
+
+ assertThat(nearbyDevice.rangeZone).isEqualTo(rangeZone)
+ }
+
+ @Test
+ fun writeToAndCreateFromParcel_resultHasCorrectIdAndRangeZone() {
+ val id = "testIdHere"
+ val rangeZone = NearbyDevice.RANGE_WITHIN_REACH
+ val nearbyDevice = NearbyDevice(id, rangeZone)
+
+ val parcel = Parcel.obtain()
+ nearbyDevice.writeToParcel(parcel, 0)
+ parcel.setDataPosition(0)
+
+ val resultFromParcel = NearbyDevice.CREATOR.createFromParcel(parcel)
+
+ assertThat(resultFromParcel.mediaRoute2Id).isEqualTo(id)
+ assertThat(resultFromParcel.rangeZone).isEqualTo(rangeZone)
+ }
+}
diff --git a/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java b/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
index 7094e26..82000a4 100644
--- a/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerBubbleTest.java
@@ -151,7 +151,10 @@
*/
private void verifyNotificationBubbleState(int id, boolean shouldBeBubble) {
// FLAG_BUBBLE relies on notification being posted, wait for notification listener
- sleep();
+ try {
+ Thread.sleep(700);
+ } catch (InterruptedException ignored) {
+ }
for (StatusBarNotification sbn : mListener.mPosted) {
if (sbn.getId() == id) {
diff --git a/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java b/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
index 6769cf8..98b1bca 100644
--- a/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
+++ b/tests/app/src/android/app/cts/PropertyInvalidatedCacheTests.java
@@ -40,7 +40,7 @@
public class PropertyInvalidatedCacheTests {
// Configuration for creating caches
- private static final int MODULE = PropertyInvalidatedCache.MODULE_TEST;
+ private static final String MODULE = PropertyInvalidatedCache.MODULE_TEST;
private static final String API = "testApi";
// This class is a proxy for binder calls. It contains a counter that increments
@@ -216,11 +216,11 @@
this(MODULE, API);
}
- TestCache(int module, String api) {
+ TestCache(String module, String api) {
this(module, api, new TestQuery());
}
- TestCache(int module, String api, TestQuery query) {
+ TestCache(String module, String api, TestQuery query) {
super(4, module, api, "testCache7", query);
mQuery = query;
setTestMode(true);
diff --git a/tests/camera/OWNERS b/tests/camera/OWNERS
index d1d18b4..9270e30 100644
--- a/tests/camera/OWNERS
+++ b/tests/camera/OWNERS
@@ -1,2 +1,5 @@
# Bug component: 41727
include platform/frameworks/av:/camera/OWNERS
+
+per-file *ImageReader* = file:platform/frameworks/base:/graphics/java/android/graphics/OWNERS
+per-file *ImageWriter* = file:platform/frameworks/base:/graphics/java/android/graphics/OWNERS
\ No newline at end of file
diff --git a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
index cbbaea8..5db96a4 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ExtendedCameraCharacteristicsTest.java
@@ -1853,6 +1853,10 @@
mCollector.expectTrue("The recommended 10-bit dynamic range profile must " +
"not be the same as standard",
recommendedProfile != DynamicRangeProfiles.STANDARD);
+ mCollector.expectTrue("HLG10 profile must not have extra latency!",
+ !dynamicProfiles.isExtraLatencyPresent(DynamicRangeProfiles.HLG10));
+ mCollector.expectTrue("STANDARD profile must not have extra latency!",
+ !dynamicProfiles.isExtraLatencyPresent(DynamicRangeProfiles.STANDARD));
// Verify constraints validity. For example if HLG10 advertises support for HDR10, then
// there shouldn't be any HDR10 constraints related to HLG10.
diff --git a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
index 82760f0..2a65d76 100644
--- a/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/FlashlightTest.java
@@ -128,6 +128,20 @@
torchStrength = mCameraManager.getTorchStrengthLevel(id);
assertEquals(torchStrength, minLevel);
+ try {
+ mCameraManager.turnOnTorchWithStrengthLevel(id, 0);
+ fail("turnOnTorchWithStrengthLevel with strengthLevel = 0 must fail.");
+ } catch (IllegalArgumentException e) {
+ Log.v(TAG, e.getMessage());
+ }
+
+ try {
+ mCameraManager.turnOnTorchWithStrengthLevel(id, maxLevel + 1);
+ fail("turnOnTorchWithStrengthLevel with strengthLevel" + (maxLevel + 1) + " must fail.");
+ } catch (IllegalArgumentException e) {
+ Log.v(TAG, e.getMessage());
+ }
+
// Turn off the torch and verify if the strength level gets
// reset to default level.
mCameraManager.setTorchMode(id, false);
diff --git a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
index 3fd524a..1ae61a5 100644
--- a/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/ImageWriterTest.java
@@ -290,6 +290,7 @@
ImageWriter writer = new ImageWriter
.Builder(surface)
.setWidthAndHeight(imageWriterWidth, imageWriterHeight)
+ .setMaxImages(MAX_NUM_IMAGES)
.setImageFormat(ImageFormat.YV12)
.setUsage(usage)
.build();
@@ -298,8 +299,8 @@
// ImageFormat.YV12 HAL dataspace is DataSpace.DATASPACE_JFIF
assertEquals(imageWriterWidth, writer.getWidth());
assertEquals(imageWriterHeight, writer.getHeight());
+ assertEquals(MAX_NUM_IMAGES, writer.getMaxImages());
assertEquals(DataSpace.DATASPACE_JFIF, writer.getDataSpace());
- assertEquals(imageWriterHeight, writer.getHeight());
assertEquals(usage, writer.getUsage());
assertEquals(DataSpace.DATASPACE_JFIF, image.getDataSpace());
diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
index 3bc4743..44abc72 100644
--- a/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
+++ b/tests/devicepolicy/src/android/devicepolicy/cts/ResetPasswordWithTokenTest.java
@@ -27,6 +27,7 @@
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE;
+import static android.content.pm.PackageManager.FEATURE_SECURE_LOCK_SCREEN;
import static com.android.bedstead.metricsrecorder.truth.MetricQueryBuilderSubject.assertThat;
import static com.android.bedstead.remotedpc.RemoteDpc.DPC_COMPONENT_NAME;
@@ -59,6 +60,7 @@
// TODO(b/191640667): Parameterize the length limit tests with multiple limits
@RunWith(BedsteadJUnit4.class)
+@RequireFeature(FEATURE_SECURE_LOCK_SCREEN)
public final class ResetPasswordWithTokenTest {
private static final String NOT_COMPLEX_PASSWORD = "1234";
diff --git a/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java b/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java
index ac61724..032890ea 100644
--- a/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java
+++ b/tests/framework/base/windowmanager/appBackLegacy/src/android/server/wm/backlegacyapp/BackNavigationLegacyActivity.java
@@ -19,8 +19,8 @@
import android.app.Activity;
import android.os.Bundle;
import android.server.wm.TestJournalProvider;
-import android.view.OnBackInvokedCallback;
-import android.view.OnBackInvokedDispatcher;
+import android.window.OnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
import androidx.annotation.Nullable;
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
index 308d3b9..ff60f60 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
@@ -16,6 +16,7 @@
package android.server.wm.jetpack.utils;
+import static android.server.wm.jetpack.utils.ExtensionUtil.getWindowExtensions;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getMaximumActivityBounds;
import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getResumedActivityById;
@@ -39,6 +40,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.window.extensions.embedding.ActivityEmbeddingComponent;
import androidx.window.extensions.embedding.SplitInfo;
import androidx.window.extensions.embedding.SplitPairRule;
import androidx.window.extensions.embedding.SplitRule;
@@ -242,14 +244,22 @@
layoutDir = primaryActivity.getResources().getConfiguration().getLayoutDirection();
}
+ // Compute the expected bounds
final float splitRatio = splitRule.getSplitRatio();
final Rect parentBounds = getMaximumActivityBounds(primaryActivity);
final Rect expectedPrimaryActivityBounds = new Rect();
final Rect expectedSecondaryActivityBounds = new Rect();
getExpectedPrimaryAndSecondaryBounds(layoutDir, splitRatio, parentBounds,
expectedPrimaryActivityBounds, expectedSecondaryActivityBounds);
+
+ final ActivityEmbeddingComponent activityEmbeddingComponent = getWindowExtensions()
+ .getActivityEmbeddingComponent();
+
+ // Verify that both activities are embedded and that the bounds are correct
+ assertTrue(activityEmbeddingComponent.isActivityEmbedded(primaryActivity));
assertEquals(expectedPrimaryActivityBounds, getActivityBounds(primaryActivity));
if (secondaryActivity != null) {
+ assertTrue(activityEmbeddingComponent.isActivityEmbedded(secondaryActivity));
assertEquals(expectedSecondaryActivityBounds, getActivityBounds(secondaryActivity));
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java
index f4db285..326052b 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/BackNavigationTests.java
@@ -24,7 +24,7 @@
import android.platform.test.annotations.Presubmit;
import android.support.test.uiautomator.UiDevice;
import android.view.KeyEvent;
-import android.view.OnBackInvokedCallback;
+import android.window.OnBackInvokedCallback;
import androidx.lifecycle.Lifecycle;
import androidx.test.core.app.ActivityScenario;
@@ -35,6 +35,8 @@
import org.junit.Rule;
import org.junit.Test;
+import org.junit.Ignore;
+
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@@ -61,6 +63,7 @@
mInstrumentation.getUiAutomation().adoptShellPermissionIdentity();
}
+ @Ignore ("b/222208384")
@Test
public void registerCallback_initialized() {
CountDownLatch latch = registerBackCallback();
@@ -68,6 +71,7 @@
invokeBackAndAssertCallbackIsCalled(latch);
}
+ @Ignore ("b/222208384")
@Test
public void registerCallback_created() {
mScenario.moveToState(Lifecycle.State.CREATED);
@@ -77,6 +81,7 @@
invokeBackAndAssertCallbackIsCalled(latch);
}
+ @Ignore ("b/222208384")
@Test
public void registerCallback_resumed() {
mScenario.moveToState(Lifecycle.State.CREATED);
@@ -86,6 +91,7 @@
invokeBackAndAssertCallbackIsCalled(latch);
}
+ @Ignore ("b/222208384")
@Test
public void onBackPressedNotCalled() {
mScenario.moveToState(Lifecycle.State.CREATED)
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index ca997ab..0fda662 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -38,6 +38,7 @@
import android.server.wm.cts.R;
import android.view.Gravity;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
@@ -45,16 +46,20 @@
import androidx.test.filters.FlakyTest;
+import com.android.compatibility.common.util.PollingCheck;
+
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
public class KeepClearRectsTests extends WindowManagerTestBase {
+ private static final long FOCUS_VIEW_CHECK_TIMEOUT = 3000;
private static final List<Rect> TEST_KEEP_CLEAR_RECTS =
Arrays.asList(new Rect(0, 0, 25, 25),
new Rect(30, 0, 50, 25),
@@ -220,7 +225,7 @@
}
@Test
- public void testSetPreferKeepClearOverridesMultipleRects() {
+ public void testSetPreferKeepClearCombinesWithMultipleRects() {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
final ComponentName componentName = activity.getComponentName();
@@ -232,7 +237,9 @@
getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
- assertSameElements(getRectsInScreenSpace(Arrays.asList(viewBounds), componentName),
+ final List<Rect> combinedRects = new ArrayList<>(TEST_KEEP_CLEAR_RECTS);
+ combinedRects.add(viewBounds);
+ assertSameElements(getRectsInScreenSpace(combinedRects, componentName),
getKeepClearRectsForActivity(activity));
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(false));
@@ -316,6 +323,38 @@
}
@Test
+ public void testFocusedViewDeclaredAsKeepClearArea() throws Exception {
+ int preferKeepClearForFocusDelay = ViewConfiguration.get(
+ mContext).getPreferKeepClearForFocusDelay();
+
+ assumeTrue(preferKeepClearForFocusDelay >= 0);
+
+ mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
+ final TestActivity activity = mTestSession.getActivity();
+
+ final Rect viewBounds = new Rect(0, 0, 60, 60);
+ final View v = createTestViewInActivity(activity, viewBounds);
+ assertSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity));
+
+ mTestSession.runOnMainSyncAndWait(() -> {
+ v.setFocusable(true);
+ v.requestFocus();
+ });
+
+ PollingCheck.check("Expected focused view bounds as keep clear area",
+ preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
+ () -> hasSameElements(
+ getRectsInScreenSpace(Arrays.asList(viewBounds),
+ activity.getComponentName()),
+ getKeepClearRectsForActivity(activity)));
+
+ mTestSession.runOnMainSyncAndWait(() -> v.setFocusable(false));
+ PollingCheck.check("Expected no keep clear areas after clearing focus, but found some",
+ preferKeepClearForFocusDelay + FOCUS_VIEW_CHECK_TIMEOUT,
+ () -> hasSameElements(EMPTY_LIST, getKeepClearRectsForActivity(activity)));
+ }
+
+ @Test
public void testKeepClearRectsGetTranslatedToWindowSpace() {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity = mTestSession.getActivity();
@@ -350,15 +389,17 @@
v.setPreferKeepClear(false);
v.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS);
});
- assertSameElements(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName),
+ List<Rect> expectedRectsInScreenSpace =
+ getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, componentName);
+ assertSameElements(expectedRectsInScreenSpace,
getKeepClearRectsForActivity(activity));
activity.finishAndRemoveTask();
- mWmState.waitAndAssertActivityRemoved(componentName);
- assertSameElements(EMPTY_LIST, getKeepClearRectsOnDefaultDisplay());
+ assertTrue(Collections.disjoint(
+ expectedRectsInScreenSpace,
+ getKeepClearRectsOnDefaultDisplay()));
}
-
@Test
public void testKeepClearRectsOnDisplayTwoWindows() {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
@@ -371,7 +412,7 @@
assertSameElements(getRectsInScreenSpace(Arrays.asList(viewBounds), componentName),
getKeepClearRectsForActivity(activity));
- final String title = "KeepCleasrRectsTestWindow";
+ final String title = "KeepClearRectsTestWindow";
mTestSession.runOnMainSyncAndWait(() -> {
final View testView = new View(activity);
testView.setPreferKeepClear(true);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
index 6742666..4cf56b9 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java
@@ -511,12 +511,12 @@
}
@Test
- public void testLaunchFromLauncherWithEmptyIconOptions() throws Exception {
+ public void testLaunchFromLauncherWithSolidColorOptions() throws Exception {
assumeFalse(isLeanBack());
final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
TestJournalProvider.TestJournalContainer.start();
final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
- .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+ .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, intent ->
intent.putExtra(REQUEST_HANDLE_EXIT_ON_CREATE, true), noIconOptions);
mWmState.waitForActivityState(SPLASH_SCREEN_REPLACE_ICON_ACTIVITY, STATE_RESUMED);
@@ -573,9 +573,9 @@
}
@Test
- public void testLaunchActivitiesWithEmptyOptions() throws Exception {
+ public void testLaunchActivitiesWithSolidColorOptions() throws Exception {
final ActivityOptions options = ActivityOptions.makeBasic()
- .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+ .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
final Intent[] intents = new Intent[] {
new Intent().setComponent(HANDLE_SPLASH_SCREEN_EXIT_ACTIVITY)
@@ -673,7 +673,7 @@
assumeFalse(isLeanBack());
final CommandSession.ActivitySession homeActivity = prepareTestLauncher();
final ActivityOptions noIconOptions = ActivityOptions.makeBasic()
- .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_EMPTY);
+ .setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR);
startActivityFromTestLauncher(homeActivity, SPLASH_SCREEN_STYLE_THEME_ACTIVITY,
intent -> {}, noIconOptions);
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
index a611731..c1d815c 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/WindowManagerState.java
@@ -152,6 +152,7 @@
private String mInputMethodWindowAppToken = null;
private boolean mDisplayFrozen;
private boolean mSanityCheckFocusedWindow = true;
+ private boolean mWindowFramesValid;
static String appStateToString(int appState) {
switch (appState) {
@@ -322,6 +323,7 @@
retry = mRootTasks.isEmpty() || mTopFocusedTaskId == -1 || mWindowStates.isEmpty()
|| mFocusedApp == null || (mSanityCheckFocusedWindow && mFocusedWindow == null)
+ || !mWindowFramesValid
|| (mTopResumedActivityRecord == null
|| mResumedActivitiesInRootTasks.isEmpty())
&& !mKeyguardControllerState.keyguardShowing;
@@ -348,6 +350,9 @@
if (mFocusedApp == null) {
logE("No Focused App...");
}
+ if (!mWindowFramesValid) {
+ logE("Window Frames Invalid...");
+ }
}
private byte[] executeShellCommand(String cmd) {
@@ -431,6 +436,7 @@
mInputMethodWindowAppToken = Integer.toHexString(state.inputMethodWindow.hashCode);
}
mDisplayFrozen = state.displayFrozen;
+ mWindowFramesValid = state.windowFramesValid;
}
private void reset() {
@@ -452,6 +458,7 @@
mPinnedStackMovementBounds.setEmpty();
mInputMethodWindowAppToken = null;
mDisplayFrozen = false;
+ mWindowFramesValid = false;
}
public String getFocusedApp() {
diff --git a/tests/inputmethod/Android.bp b/tests/inputmethod/Android.bp
index 4902be2..268bf55 100644
--- a/tests/inputmethod/Android.bp
+++ b/tests/inputmethod/Android.bp
@@ -32,6 +32,7 @@
"androidx.test.uiautomator_uiautomator",
"compatibility-device-util-axt",
"cts-wm-util",
+ "cts-inputmethod-util",
"ctstestrunner-axt",
"CtsMockInputMethodLib",
"CtsMockSpellCheckerLib",
diff --git a/tests/inputmethod/AndroidManifest.xml b/tests/inputmethod/AndroidManifest.xml
index 6dd1836..1bb3122 100644
--- a/tests/inputmethod/AndroidManifest.xml
+++ b/tests/inputmethod/AndroidManifest.xml
@@ -19,6 +19,7 @@
package="android.view.inputmethod.cts"
android:targetSandboxVersion="2">
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:label="CtsInputMethodTestCases"
android:multiArch="true"
@@ -26,48 +27,7 @@
<uses-library android:name="android.test.runner"/>
- <activity android:name="android.view.inputmethod.cts.util.TestActivity"
- android:theme="@style/no_starting_window"
- android:label="TestActivity"
- android:configChanges="fontScale|smallestScreenSize|screenSize|screenLayout|orientation"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
- </intent-filter>
- </activity>
- <activity android:name="android.view.inputmethod.cts.util.TestActivity2"
- android:theme="@style/no_starting_window"
- android:label="TestActivity2"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
- </intent-filter>
- </activity>
-
- <activity android:name="android.view.inputmethod.cts.util.StateInitializeActivity"
- android:theme="@style/no_starting_window"
- android:label="StateInitializeActivity"
- android:configChanges="fontScale"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
- </intent-filter>
- </activity>
-
- <!--
- In order to test window-focus-stealing from other process, let this service run in a
- separate process. -->
- <service android:name="android.view.inputmethod.cts.util.WindowFocusStealerService"
- android:process=":focusstealer"
- android:exported="false">
- </service>
-
- <service android:name="android.view.inputmethod.cts.util.WindowFocusHandleService"
- android:exported="false">
- </service>
+ <!-- TestActivity etc are merged from util/AndroidManifest.xml -->
</application>
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
index a7bcdce..d03bf4b 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockIme.java
@@ -367,8 +367,15 @@
}
case "requestCursorUpdates": {
final int cursorUpdateMode = command.getExtras().getInt("cursorUpdateMode");
- return getMemorizedOrCurrentInputConnection().requestCursorUpdates(
- cursorUpdateMode);
+ final int cursorUpdateFilter =
+ command.getExtras().getInt("cursorUpdateFilter", -1);
+ if (cursorUpdateFilter == -1) {
+ return getMemorizedOrCurrentInputConnection().requestCursorUpdates(
+ cursorUpdateMode);
+ } else {
+ return getMemorizedOrCurrentInputConnection().requestCursorUpdates(
+ cursorUpdateMode, cursorUpdateFilter);
+ }
}
case "getHandler":
return getMemorizedOrCurrentInputConnection().getHandler();
diff --git a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
index 2133846..a779410 100644
--- a/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
+++ b/tests/inputmethod/mockime/src/com/android/cts/mockime/MockImeSession.java
@@ -1149,6 +1149,34 @@
}
/**
+ * Lets {@link MockIme} to call {@link InputConnection#requestCursorUpdates(int, int)} with the
+ * given parameters.
+ *
+ * <p>This triggers {@code getCurrentInputConnection().requestCursorUpdates(
+ * cursorUpdateMode, cursorUpdateFilter)}.
+ * </p>
+ *
+ * <p>Use {@link ImeEvent#getReturnBooleanValue()} for {@link ImeEvent} returned from
+ * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to see the
+ * value returned from the API.</p>
+ *
+ * <p>This can be affected by {@link #memorizeCurrentInputConnection()}.</p>
+ *
+ * @param cursorUpdateMode to be passed as the {@code cursorUpdateMode} parameter
+ * @param cursorUpdateFilter to be passed as the {@code cursorUpdateFilter} parameter
+ * @return {@link ImeCommand} object that can be passed to
+ * {@link ImeEventStreamTestUtils#expectCommand(ImeEventStream, ImeCommand, long)} to
+ * wait until this event is handled by {@link MockIme}
+ */
+ @NonNull
+ public ImeCommand callRequestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter) {
+ final Bundle params = new Bundle();
+ params.putInt("cursorUpdateMode", cursorUpdateMode);
+ params.putInt("cursorUpdateFilter", cursorUpdateFilter);
+ return callCommandInternal("requestCursorUpdates", params);
+ }
+
+ /**
* Lets {@link MockIme} to call {@link InputConnection#getHandler()} with the given parameters.
*
* <p>This triggers {@code getCurrentInputConnection().getHandler()}.</p>
diff --git a/tests/inputmethod/res/values/colors.xml b/tests/inputmethod/res/values/colors.xml
deleted file mode 100644
index 1d87ea8..0000000
--- a/tests/inputmethod/res/values/colors.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- 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.
- -->
-
-<resources>
- <drawable name="blue">#770000ff</drawable>
-</resources>
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
index 31b7a92..e8ff4f0 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/InputMethodServiceTest.java
@@ -454,6 +454,7 @@
final AtomicReference<EditText> editTextRef = new AtomicReference<>();
final AtomicInteger requestCursorUpdatesCallCount = new AtomicInteger();
+ final AtomicInteger requestCursorUpdatesWithFilterCallCount = new AtomicInteger();
TestActivity.startSync(activity -> {
final LinearLayout layout = new LinearLayout(activity);
layout.setOrientation(LinearLayout.VERTICAL);
@@ -472,6 +473,13 @@
}
return false;
}
+
+ @Override
+ public boolean requestCursorUpdates(
+ int cursorUpdateMode, int cursorUpdateFilter) {
+ requestCursorUpdatesWithFilterCallCount.incrementAndGet();
+ return requestCursorUpdates(cursorUpdateMode | cursorUpdateFilter);
+ }
};
}
};
@@ -538,6 +546,37 @@
TIMEOUT).getArguments().getParcelable("cursorAnchorInfo");
assertNotNull(receivedCursorAnchorInfo1);
assertEquals(receivedCursorAnchorInfo1, originalCursorAnchorInfo1);
+
+ requestCursorUpdatesCallCount.set(0);
+ requestCursorUpdatesWithFilterCallCount.set(0);
+ // Request Cursor updates with Mode and Filter
+ // Make sure that InputConnection#requestCursorUpdates() returns true with mode and
+ // data filter.
+ builder = new EditorBoundsInfo.Builder();
+ builder.setEditorBounds(new RectF(1f, 1f, 2f, 3f));
+ final CursorAnchorInfo originalCursorAnchorInfo2 = new CursorAnchorInfo.Builder()
+ .setMatrix(new Matrix())
+ .setEditorBoundsInfo(builder.build())
+ .build();
+ assertTrue(expectCommand(stream,
+ imeSession.callRequestCursorUpdates(
+ InputConnection.CURSOR_UPDATE_IMMEDIATE,
+ InputConnection.CURSOR_UPDATE_FILTER_EDITOR_BOUNDS
+ | InputConnection.CURSOR_UPDATE_FILTER_CHARACTER_BOUNDS
+ | InputConnection.CURSOR_UPDATE_FILTER_INSERTION_MARKER),
+ TIMEOUT).getReturnBooleanValue());
+
+ // Make sure that requestCursorUpdates() actually gets called only once.
+ assertEquals(1, requestCursorUpdatesCallCount.get());
+ assertEquals(1, requestCursorUpdatesWithFilterCallCount.get());
+ runOnMainSync(() -> editText.getContext().getSystemService(InputMethodManager.class)
+ .updateCursorAnchorInfo(editText, originalCursorAnchorInfo2));
+
+ final CursorAnchorInfo receivedCursorAnchorInfo2 = expectEvent(stream,
+ event -> "onUpdateCursorAnchorInfo".equals(event.getEventName()),
+ TIMEOUT).getArguments().getParcelable("cursorAnchorInfo");
+ assertNotNull(receivedCursorAnchorInfo2);
+ assertEquals(receivedCursorAnchorInfo2, originalCursorAnchorInfo2);
}
}
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
index c68149f..265940f2 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
+++ b/tests/inputmethod/src/android/view/inputmethod/cts/StylusHandwritingTest.java
@@ -16,6 +16,8 @@
package android.view.inputmethod.cts;
+import static android.provider.Settings.Global.STYLUS_HANDWRITING_ENABLED;
+
import static com.android.cts.mockime.ImeEventStreamTestUtils.editorMatcher;
import static com.android.cts.mockime.ImeEventStreamTestUtils.expectCommand;
import static com.android.cts.mockime.ImeEventStreamTestUtils.expectEvent;
@@ -26,8 +28,10 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import android.Manifest;
import android.content.Context;
import android.os.SystemClock;
+import android.provider.Settings;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
@@ -43,10 +47,14 @@
import androidx.test.filters.FlakyTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import com.android.cts.mockime.ImeEventStream;
import com.android.cts.mockime.ImeSettings;
import com.android.cts.mockime.MockImeSession;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import java.util.ArrayList;
@@ -61,13 +69,44 @@
public class StylusHandwritingTest extends EndToEndImeTestBase {
private static final long TIMEOUT = TimeUnit.SECONDS.toMillis(5);
private static final long NOT_EXPECT_TIMEOUT = TimeUnit.SECONDS.toMillis(1);
+ private static final int SETTING_VALUE_ON = 1;
+ private static final int SETTING_VALUE_OFF = 0;
private static final String TEST_MARKER_PREFIX =
"android.view.inputmethod.cts.StylusHandwritingTest";
+ private Context mContext;
+ private int mHwInitialState;
+ private boolean mShouldRestoreInitialHwState;
+
+ @Rule
+ public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+ InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+ Manifest.permission.WRITE_SECURE_SETTINGS);
+
+ @Before
+ public void setup() {
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ mHwInitialState = Settings.Global.getInt(mContext.getContentResolver(),
+ STYLUS_HANDWRITING_ENABLED, SETTING_VALUE_OFF);
+ if (mHwInitialState != SETTING_VALUE_ON) {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ STYLUS_HANDWRITING_ENABLED, SETTING_VALUE_ON);
+ mShouldRestoreInitialHwState = true;
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mShouldRestoreInitialHwState) {
+ mShouldRestoreInitialHwState = false;
+ Settings.Global.putInt(mContext.getContentResolver(),
+ STYLUS_HANDWRITING_ENABLED, mHwInitialState);
+ }
+ }
+
@Test
public void testHandwritingStartAndFinish() throws Exception {
- final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
- .getTargetContext().getSystemService(InputMethodManager.class);
+ final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
try (MockImeSession imeSession = MockImeSession.create(
InstrumentationRegistry.getInstrumentation().getContext(),
InstrumentationRegistry.getInstrumentation().getUiAutomation(),
@@ -120,8 +159,7 @@
*/
@Test
public void testHandwritingStylusEvents() throws Exception {
- final InputMethodManager imm = InstrumentationRegistry.getInstrumentation()
- .getTargetContext().getSystemService(InputMethodManager.class);
+ final InputMethodManager imm = mContext.getSystemService(InputMethodManager.class);
try (MockImeSession imeSession = MockImeSession.create(
InstrumentationRegistry.getInstrumentation().getContext(),
InstrumentationRegistry.getInstrumentation().getUiAutomation(),
diff --git a/tests/inputmethod/tests32/Android.bp b/tests/inputmethod/tests32/Android.bp
new file mode 100644
index 0000000..fa09833
--- /dev/null
+++ b/tests/inputmethod/tests32/Android.bp
@@ -0,0 +1,52 @@
+// 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: "CtsInputMethodTestCases32",
+ defaults: ["cts_defaults"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+ compile_multilib: "both",
+ libs: ["android.test.runner"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "compatibility-device-util-axt",
+ "cts-wm-util",
+ "cts-inputmethod-util",
+ "ctstestrunner-axt",
+ "CtsMockInputMethodLib",
+ "CtsMockSpellCheckerLib",
+ "CtsLegacyImeClientTestLib",
+ "testng",
+ "kotlin-test",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ "src/**/I*.aidl",
+ ],
+ aidl: {
+ local_include_dirs: ["src"],
+ },
+ sdk_version: "test_current",
+}
diff --git a/tests/inputmethod/tests32/AndroidManifest.xml b/tests/inputmethod/tests32/AndroidManifest.xml
new file mode 100644
index 0000000..3813e47
--- /dev/null
+++ b/tests/inputmethod/tests32/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.view.inputmethod.cts.sdk32">
+
+ <uses-sdk android:targetSdkVersion="32" />
+
+ <application android:label="CtsInputMethodSdk28TestCases" />
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.view.inputmethod.cts.sdk32" />
+
+</manifest>
diff --git a/tests/inputmethod/tests32/AndroidTest.xml b/tests/inputmethod/tests32/AndroidTest.xml
new file mode 100644
index 0000000..9c5b128
--- /dev/null
+++ b/tests/inputmethod/tests32/AndroidTest.xml
@@ -0,0 +1,79 @@
+<?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 InputMethodFramework SDK 32 compatibility test cases">
+ <option name="test-suite-tag" value="cts" />
+ <option name="config-descriptor:metadata" key="component" value="inputmethod" />
+ <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsInputMethodTestCases32.apk" />
+ </target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <!--
+ MockIME always needs to be installed as a full package, even when CTS is running
+ for instant apps.
+ -->
+ <option name="force-install-mode" value="FULL"/>
+ <option name="test-file-name" value="CtsMockInputMethod.apk" />
+ </target_preparer>
+ <!--
+ TODO(yukawa): come up with a proper way to take care of devices that do not support
+ installable IMEs. Ideally target_preparer should have an option to annotate required
+ features, e.g. android.software.input_methods so that we can conditionally install APKs
+ based on the feature supported in the target device.
+ -->
+
+ <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>
+
+ <!--
+ A (separate) standalone test app APK is needed to test implicit app-visibility from the IME
+ process to the IME target process, because if the IME target process is directly interacting
+ with MockIme process via MockImeSession, then the system would already give the MockIme an
+ implicit app-visibility back to the test app. To fully test app-visibility scenario,
+ MockImeSession cannot be used in the process where the focused Activity is hosted.
+ -->
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <!--
+ In order to simulate the scenario where the IME client process is normally
+ installed, explicitly set false here. Otherwise, the test APP will be installed under
+ force-queryable mode, which makes the test useless.
+ -->
+ <option name="force-queryable" value="false" />
+ <option name="test-file-name" value="CtsInputMethodStandaloneTestApp.apk" />
+ </target_preparer>
+
+ <!-- Enabling change id ALLOW_TEST_API_ACCESS allows that package to access @TestApi methods -->
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS com.android.cts.mockime" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS com.android.cts.mockime" />
+ <option name="run-command" value="am compat enable ALLOW_TEST_API_ACCESS android.view.inputmethod.ctstestapp" />
+ <option name="teardown-command" value="am compat reset ALLOW_TEST_API_ACCESS android.view.inputmethod.ctstestapp" />
+ </target_preparer>
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="android.view.inputmethod.cts.sdk32" />
+ <option name="runtime-hint" value="1m" />
+ </test>
+</configuration>
diff --git a/tests/inputmethod/tests32/src/android/view/inputmethod/cts/sdk32/InputMethodManagerTest.kt b/tests/inputmethod/tests32/src/android/view/inputmethod/cts/sdk32/InputMethodManagerTest.kt
new file mode 100644
index 0000000..6d1907c
--- /dev/null
+++ b/tests/inputmethod/tests32/src/android/view/inputmethod/cts/sdk32/InputMethodManagerTest.kt
@@ -0,0 +1,70 @@
+/*
+ * 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.view.inputmethod.cts.sdk32
+
+import android.content.Context
+import android.view.inputmethod.InputMethodManager
+import android.view.inputmethod.cts.util.EndToEndImeTestBase
+import android.view.inputmethod.cts.util.InputMethodVisibilityVerifier.expectImeVisible
+import android.view.inputmethod.cts.util.MockTestActivityUtil
+import androidx.test.filters.MediumTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.runner.AndroidJUnit4
+import com.android.cts.mockime.ImeSettings
+import com.android.cts.mockime.MockImeSession
+import org.junit.Assert.assertEquals
+import org.junit.AssumptionViolatedException
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.concurrent.TimeUnit
+
+@MediumTest
+@RunWith(AndroidJUnit4::class)
+class InputMethodManagerTest : EndToEndImeTestBase() {
+
+ val context: Context = InstrumentationRegistry.getInstrumentation().getContext()
+ val uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
+
+ @Test
+ fun getInputMethodWindowVisibleHeight_returnsZeroIfNotFocused() {
+ val imm = context.getSystemService(InputMethodManager::class.java)!!
+ MockImeSession.create(context, uiAutomation, ImeSettings.Builder()).use { session ->
+ MockTestActivityUtil.launchSync(false /* instant */, TIMEOUT).use {
+ session.callRequestShowSelf(0)
+ expectImeVisible(TIMEOUT)
+ assertEquals(
+ "Only IME target UID may observe the visible height of the IME",
+ 0,
+ imm.reflectivelyGetInputMethodWindowVisibleHeight()
+ )
+ }
+ }
+ }
+
+ fun InputMethodManager.reflectivelyGetInputMethodWindowVisibleHeight() =
+ try {
+ InputMethodManager::class.java
+ .getMethod("getInputMethodWindowVisibleHeight")
+ .invoke(this) as Int
+ } catch (_: NoSuchMethodError) {
+ throw AssumptionViolatedException("getInputMethodWindowVisibleHeight doesn't exist")
+ }
+
+ companion object {
+ val TIMEOUT = TimeUnit.SECONDS.toMillis(5)
+ }
+}
diff --git a/tests/inputmethod/util/Android.bp b/tests/inputmethod/util/Android.bp
new file mode 100644
index 0000000..5637f79
--- /dev/null
+++ b/tests/inputmethod/util/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_library {
+ name: "cts-inputmethod-util",
+ defaults: ["cts_defaults"],
+ static_libs: [
+ "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "compatibility-device-util-axt",
+ "cts-wm-util",
+ "ctstestrunner-axt",
+ "CtsMockInputMethodLib",
+ "CtsMockSpellCheckerLib",
+ "CtsLegacyImeClientTestLib",
+ "testng",
+ "kotlin-test",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ "src/**/I*.aidl",
+ ],
+ aidl: {
+ local_include_dirs: ["src"],
+ },
+ sdk_version: "test_current",
+}
diff --git a/tests/inputmethod/util/AndroidManifest.xml b/tests/inputmethod/util/AndroidManifest.xml
new file mode 100644
index 0000000..fecb46b
--- /dev/null
+++ b/tests/inputmethod/util/AndroidManifest.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.view.inputmethod.cts.util"
+ android:targetSandboxVersion="2">
+
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
+ <application
+ android:multiArch="true"
+ android:supportsRtl="true">
+
+ <activity android:name="android.view.inputmethod.cts.util.TestActivity"
+ android:theme="@style/no_starting_window"
+ android:label="TestActivity"
+ android:configChanges="fontScale|smallestScreenSize|screenSize|screenLayout|orientation"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+ <activity android:name="android.view.inputmethod.cts.util.TestActivity2"
+ android:theme="@style/no_starting_window"
+ android:label="TestActivity2"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+
+ <activity android:name="android.view.inputmethod.cts.util.StateInitializeActivity"
+ android:theme="@style/no_starting_window"
+ android:label="StateInitializeActivity"
+ android:configChanges="fontScale"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+
+ <!-- In order to test window-focus-stealing from other process, let this service run in a
+ separate process. -->
+ <service android:name="android.view.inputmethod.cts.util.WindowFocusStealerService"
+ android:process=":focusstealer"
+ android:exported="false">
+ </service>
+
+ <service android:name="android.view.inputmethod.cts.util.WindowFocusHandleService"
+ android:exported="false">
+ </service>
+
+ </application>
+
+</manifest>
diff --git a/tests/inputmethod/res/values/styles.xml b/tests/inputmethod/util/res/values/styles.xml
similarity index 100%
rename from tests/inputmethod/res/values/styles.xml
rename to tests/inputmethod/util/res/values/styles.xml
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/AutoCloseableWrapper.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/DisableScreenDozeRule.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/EndToEndImeTestBase.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/HandlerInputConnection.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
similarity index 96%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
index 6992015..2a673ee 100644
--- a/tests/inputmethod/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
+++ b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/HandlerInputConnection.java
@@ -168,6 +168,11 @@
return false;
}
+ @Override
+ public boolean requestCursorUpdates(int cursorUpdateMode, int cursorUpdateFilter) {
+ return false;
+ }
+
@Nullable
@Override
public Handler getHandler() {
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/IWindowFocusStealer.aidl
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputConnectionTestUtils.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/InputMethodVisibilityVerifier.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/LightNavigationBarVerifier.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/MockTestActivityUtil.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarColorVerifier.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarInfo.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarInfo.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/NavigationBarInfo.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/NavigationBarInfo.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/RequireImeCompatFlagRule.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/SimulatedVirtualDisplaySession.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/StateInitializeActivity.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/StateInitializeActivity.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/StateInitializeActivity.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/StateInitializeActivity.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity2.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity2.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestActivity2.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestActivity2.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestUtils.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestUtils.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestUtils.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestWebView.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/TestWebView.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/TestWebView.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/UnlockScreenRule.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusHandleService.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealer.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealer.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealer.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealer.java
diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java b/tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java
similarity index 100%
rename from tests/inputmethod/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java
rename to tests/inputmethod/util/src/android/view/inputmethod/cts/util/WindowFocusStealerService.java
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
index 072222b..ff5ca6d 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderTest.java
@@ -16,6 +16,7 @@
package android.mediav2.cts;
+import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaExtractor;
@@ -47,6 +48,7 @@
import static android.mediav2.cts.CodecTestBase.SupportClass.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Validate decode functionality of listed decoder components
@@ -78,22 +80,17 @@
mSupportRequirements = supportRequirements;
}
- static short[] setUpAudioReference(String file) throws IOException {
+ static ByteBuffer readAudioReferenceFile(String file) throws IOException {
File refFile = new File(file);
- short[] refData;
+ ByteBuffer refBuffer;
try (FileInputStream refStream = new FileInputStream(refFile)) {
FileChannel fileChannel = refStream.getChannel();
int length = (int) refFile.length();
- ByteBuffer refBuffer = ByteBuffer.allocate(length);
+ refBuffer = ByteBuffer.allocate(length);
refBuffer.order(ByteOrder.LITTLE_ENDIAN);
fileChannel.read(refBuffer);
- refData = new short[length / 2];
- refBuffer.position(0);
- for (int i = 0; i < length / 2; i++) {
- refData[i] = refBuffer.getShort();
- }
}
- return refData;
+ return refBuffer;
}
private ArrayList<MediaCodec.BufferInfo> createSubFrames(ByteBuffer buffer, int sfCount) {
@@ -137,13 +134,13 @@
// SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
{MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_1ch_8kHz_lame_cbr.mp3",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_lame_vbr.mp3", 91.022f, -1L,
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_lame_vbr.mp3", 91.026749f, -1L,
CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_MPEG, "bbb_2ch_44kHz_lame_cbr.mp3",
- "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_lame_vbr.mp3", 103.60f, -1L,
+ "bbb_2ch_44kHz_s16le.raw", "bbb_1ch_16kHz_lame_vbr.mp3", 103.603081f, -1L,
CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_AMR_WB, "bbb_1ch_16kHz_16kbps_amrwb.3gp",
- "bbb_1ch_16kHz_s16le.raw", "bbb_1ch_16kHz_23kbps_amrwb.3gp", 2393.598f,
+ "bbb_1ch_16kHz_s16le.raw", "bbb_1ch_16kHz_23kbps_amrwb.3gp", 2393.5979f,
-1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_AMR_NB, "bbb_1ch_8kHz_10kbps_amrnb.3gp",
"bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_8kbps_amrnb.3gp", -1.0f, -1L,
@@ -157,13 +154,13 @@
{MediaFormat.MIMETYPE_AUDIO_RAW, "bbb_2ch_44kHz.wav", "bbb_2ch_44kHz_s16le.raw",
"bbb_1ch_16kHz.wav", 0.0f, -1L, CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_G711_ALAW, "bbb_1ch_8kHz_alaw.wav",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_alaw.wav", 23.08678f, -1L,
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_alaw.wav", 23.087402f, -1L,
CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_G711_MLAW, "bbb_1ch_8kHz_mulaw.wav",
- "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_mulaw.wav", 24.4131f, -1L,
+ "bbb_1ch_8kHz_s16le.raw", "bbb_2ch_8kHz_mulaw.wav", 24.413954f, -1L,
CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_MSGSM, "bbb_1ch_8kHz_gsm.wav",
- "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_gsm.wav", 946.02698f, -1L,
+ "bbb_1ch_8kHz_s16le.raw", "bbb_1ch_8kHz_gsm.wav", 946.026978f, -1L,
CODEC_ALL},
{MediaFormat.MIMETYPE_AUDIO_VORBIS, "bbb_1ch_16kHz_vorbis.mka",
"bbb_1ch_8kHz_s16le.raw", "bbb_2ch_44kHz_vorbis.mka", -1.0f, -1L,
@@ -195,11 +192,47 @@
private native boolean nativeTestSimpleDecode(String decoder, Surface surface, String mime,
String testFile, String refFile, float rmsError, long checksum);
- static void verify(OutputManager outBuff, String refFile, float rmsError, long refCRC)
- throws IOException {
+ static void verify(OutputManager outBuff, String refFile, float rmsError, int audioFormat,
+ long refCRC) throws IOException {
if (rmsError >= 0) {
- short[] refData = setUpAudioReference(mInpPrefix + refFile);
- float currError = outBuff.getRmsError(refData);
+ int bytesPerSample = AudioFormat.getBytesPerSample(audioFormat);
+ ByteBuffer bb = readAudioReferenceFile(mInpPrefix + refFile);
+ bb.position(0);
+ int bufferSize = bb.limit();
+ assertEquals (0, bufferSize % bytesPerSample);
+ Object refObject = null;
+ int refObjectLen = bufferSize / bytesPerSample;
+ switch (audioFormat) {
+ case AudioFormat.ENCODING_PCM_8BIT:
+ refObject = new byte[refObjectLen];
+ bb.get((byte[]) refObject);
+ break;
+ case AudioFormat.ENCODING_PCM_16BIT:
+ refObject = new short[refObjectLen];
+ bb.asShortBuffer().get((short[]) refObject);
+ break;
+ case AudioFormat.ENCODING_PCM_24BIT_PACKED:
+ refObject = new int[refObjectLen];
+ int[] refArray = (int[]) refObject;
+ for (int i = 0, j = 0; i < bufferSize; i += 3, j++) {
+ int byte1 = (bb.get() & 0xff);
+ int byte2 = (bb.get() & 0xff);
+ int byte3 = (bb.get() & 0xff);
+ refArray[j] = byte1 | (byte2 << 8) | (byte3 << 16);
+ }
+ break;
+ case AudioFormat.ENCODING_PCM_32BIT:
+ refObject = new int[refObjectLen];
+ bb.asIntBuffer().get((int[]) refObject);
+ break;
+ case AudioFormat.ENCODING_PCM_FLOAT:
+ refObject = new float[refObjectLen];
+ bb.asFloatBuffer().get((float[]) refObject);
+ break;
+ default:
+ fail("unrecognized audio encoding type " + audioFormat);
+ }
+ float currError = outBuff.getRmsError(refObject, audioFormat);
float errMargin = rmsError * RMS_ERROR_TOLERANCE;
assertTrue(String.format("%s rms error too high ref/exp/got %f/%f/%f", refFile,
rmsError, errMargin, currError), currError <= errMargin);
@@ -295,7 +328,11 @@
}
}
mCodec.release();
- if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
+ if (mSaveToMem) {
+ int audioEncoding = mIsAudio ? format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_16BIT) : AudioFormat.ENCODING_INVALID;
+ verify(mOutputBuff, mRefFile, mRmsError, audioEncoding, mRefCRC);
+ }
assertTrue(nativeTestSimpleDecode(mCodecName, null, mMime, mInpPrefix + mTestFile,
mInpPrefix + mRefFile, mRmsError, ref.getCheckSumBuffer()));
}
@@ -512,7 +549,6 @@
doWork(Integer.MAX_VALUE);
queueEOS();
waitForAllOutputs();
- if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
/* TODO(b/147348711) */
if (false) mCodec.stop();
else mCodec.reset();
@@ -538,7 +574,6 @@
doWork(Integer.MAX_VALUE);
queueEOS();
waitForAllOutputs();
- if (mSaveToMem) verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
/* TODO(b/147348711) */
if (false) mCodec.stop();
else mCodec.reset();
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 4dd9923..1938b8f 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -16,6 +16,8 @@
package android.mediav2.cts;
+import android.media.AudioFormat;
+import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
@@ -32,6 +34,7 @@
import java.util.List;
import static android.mediav2.cts.CodecTestBase.SupportClass.*;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
@@ -44,21 +47,43 @@
*/
@RunWith(Parameterized.class)
public class CodecDecoderValidationTest extends CodecDecoderTestBase {
- private static final String LOG_TAG = CodecDecoderValidationTest.class.getSimpleName();
-
+ private static final String MEDIA_TYPE_RAW = MediaFormat.MIMETYPE_AUDIO_RAW;
+ private static final String MEDIA_TYPE_AMRNB = MediaFormat.MIMETYPE_AUDIO_AMR_NB;
+ private static final String MEDIA_TYPE_AMRWB = MediaFormat.MIMETYPE_AUDIO_AMR_WB;
+ private static final String MEDIA_TYPE_MP3 = MediaFormat.MIMETYPE_AUDIO_MPEG;
+ private static final String MEDIA_TYPE_AAC = MediaFormat.MIMETYPE_AUDIO_AAC;
+ private static final String MEDIA_TYPE_FLAC = MediaFormat.MIMETYPE_AUDIO_FLAC;
+ private static final String MEDIA_TYPE_VORBIS = MediaFormat.MIMETYPE_AUDIO_VORBIS;
+ private static final String MEDIA_TYPE_OPUS = MediaFormat.MIMETYPE_AUDIO_OPUS;
+ private static final String MEDIA_TYPE_MPEG2 = MediaFormat.MIMETYPE_VIDEO_MPEG2;
+ private static final String MEDIA_TYPE_MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
+ private static final String MEDIA_TYPE_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
+ private static final String MEDIA_TYPE_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
+ private static final String MEDIA_TYPE_HEVC = MediaFormat.MIMETYPE_VIDEO_HEVC;
+ private static final String MEDIA_TYPE_VP9 = MediaFormat.MIMETYPE_VIDEO_VP9;
+ private static final String MEDIA_TYPE_AV1 = MediaFormat.MIMETYPE_VIDEO_AV1;
private final String[] mSrcFiles;
private final String mRefFile;
private final float mRmsError;
private final long mRefCRC;
+ private final int mSampleRate;
+ private final int mChannelCount;
+ private final int mWidth;
+ private final int mHeight;
private final SupportClass mSupportRequirements;
public CodecDecoderValidationTest(String decoder, String mime, String[] srcFiles,
- String refFile, float rmsError, long refCRC, SupportClass supportRequirements) {
+ String refFile, float rmsError, long refCRC, int sampleRate, int channelCount,
+ int width, int height, SupportClass supportRequirements) {
super(decoder, mime, null);
mSrcFiles = srcFiles;
mRefFile = refFile;
mRmsError = rmsError;
mRefCRC = refCRC;
+ mSampleRate = sampleRate;
+ mChannelCount = channelCount;
+ mWidth = width;
+ mHeight = height;
mSupportRequirements = supportRequirements;
}
@@ -68,394 +93,485 @@
final boolean needAudio = true;
final boolean needVideo = true;
// mediaType, array list of test files (underlying elementary stream is same, except they
- // are placed in different containers), ref file, rms error, checksum, SupportClass
+ // are placed in different containers), ref file, rms error, checksum, sample rate,
+ // channel count, width, height, SupportClass
final List<Object[]> exhaustiveArgsList = Arrays.asList(new Object[][]{
// vp9 test vectors with no-show frames signalled in alternate ways
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
- "bbb_340x280_768kbps_30fps_split_non_display_frame_vp9.webm",
- "bbb_340x280_768kbps_30fps_vp9.webm"}, null, -1.0f, 4122701060L, CODEC_ALL},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
- "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm",
- "bbb_520x390_1mbps_30fps_vp9.webm"}, null, -1.0f, 1201859039L, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_340x280_768kbps_30fps_vp9.webm",
+ "bbb_340x280_768kbps_30fps_split_non_display_frame_vp9.webm"},
+ null, -1.0f, 4122701060L, -1, -1, 340, 280, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_520x390_1mbps_30fps_vp9.webm",
+ "bbb_520x390_1mbps_30fps_split_non_display_frame_vp9.webm"},
+ null, -1.0f, 1201859039L, -1, -1, 520, 390, CODEC_ALL},
// mpeg2 test vectors with interlaced fields signalled in alternate ways
- {MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
- "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_1field.ts",
- "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_2fields.mp4"}, null, -1.0f,
- -1L, CODEC_ALL},
-
- // clips with crop parameters
-// /* TODO(b/163299340) */
-// {MediaFormat.MIMETYPE_VIDEO_HEVC, new String[]{"bbb_560x280_1mbps_30fps_hevc.mkv"},
-// null, -1.0f, 26298353L, CODEC_ALL},
-// /* TODO(b/163299340) */
-// {MediaFormat.MIMETYPE_VIDEO_AVC, new String[]{"bbb_504x224_768kbps_30fps_avc.mp4"},
-// null, -1.0f, 4060874918L, CODEC_ALL},
+ {MEDIA_TYPE_MPEG2, new String[]{"bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_1field.ts",
+ "bbb_512x288_30fps_1mbps_mpeg2_interlaced_nob_2fields.mp4"},
+ null, -1.0f, -1L, -1, -1, 512, 288, CODEC_ALL},
// misc mp3 test vectors
- {MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{"bbb_1ch_16kHz_lame_vbr.mp3"},
- "bbb_1ch_16kHz_s16le.raw", 119.256f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{"bbb_2ch_44kHz_lame_vbr.mp3"},
- "bbb_2ch_44kHz_s16le.raw", 53.066f, -1L, CODEC_ALL},
+ {MEDIA_TYPE_MP3, new String[]{"bbb_1ch_16kHz_lame_vbr.mp3"},
+ "bbb_1ch_16kHz_s16le.raw", 119.256073f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_MP3, new String[]{"bbb_2ch_44kHz_lame_vbr.mp3"},
+ "bbb_2ch_44kHz_s16le.raw", 53.069080f, -1L, 44100, 2, -1, -1, CODEC_ALL},
// mp3 test vectors with CRC
- {MediaFormat.MIMETYPE_AUDIO_MPEG, new String[]{"bbb_2ch_44kHz_lame_crc.mp3"},
- "bbb_2ch_44kHz_s16le.raw", 104.09f, -1L, CODEC_ALL},
+ {MEDIA_TYPE_MP3, new String[]{"bbb_2ch_44kHz_lame_crc.mp3"},
+ "bbb_2ch_44kHz_s16le.raw", 104.089027f, -1L, 44100, 2, -1, -1, CODEC_ALL},
// vp9 test vectors with AQ mode enabled
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9" +
- ".webm"}, null, -1.0f, 1319105122L, CODEC_ALL},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9" +
- ".webm"}, null, -1.0f, 4128150660L, CODEC_ALL},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9" +
- ".webm"}, null, -1.0f, 156928091L, CODEC_ALL},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9" +
- ".webm"}, null, -1.0f, 3902485256L, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9.webm"},
+ null, -1.0f, 1319105122L, -1, -1, 1280, 720, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9.webm"},
+ null, -1.0f, 4128150660L, -1, -1, 1280, 720, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9.webm"},
+ null, -1.0f, 156928091L, -1, -1, 1280, 720, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"},
+ null, -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ALL},
// video test vectors of non standard sizes
- {MediaFormat.MIMETYPE_VIDEO_MPEG2, new String[]{
- "bbb_642x642_2mbps_30fps_mpeg2.mp4"}, null, -1.0f, -1L, CODEC_ANY},
- {MediaFormat.MIMETYPE_VIDEO_AVC, new String[]{
- "bbb_642x642_1mbps_30fps_avc.mp4"}, null, -1.0f, 3947092788L, CODEC_ANY},
- {MediaFormat.MIMETYPE_VIDEO_VP8, new String[]{
- "bbb_642x642_1mbps_30fps_vp8.webm"}, null, -1.0f, 516982978L, CODEC_ANY},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, new String[]{
- "bbb_642x642_768kbps_30fps_hevc.mp4"}, null, -1.0f, 3018465268L, CODEC_ANY},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new String[]{
- "bbb_642x642_768kbps_30fps_vp9.webm"}, null, -1.0f, 4032809269L, CODEC_ANY},
- {MediaFormat.MIMETYPE_VIDEO_AV1, new String[]{
- "bbb_642x642_768kbps_30fps_av1.mp4"}, null, -1.0f, 3684481474L, CODEC_ANY},
- {MediaFormat.MIMETYPE_VIDEO_MPEG4, new String[]{
- "bbb_130x130_192kbps_15fps_mpeg4.mp4"}, null, -1.0f, -1L, CODEC_ANY},
+ {MEDIA_TYPE_MPEG2, new String[]{"bbb_642x642_2mbps_30fps_mpeg2.mp4"},
+ null, -1.0f, -1L, -1, -1, 642, 642, CODEC_ANY},
+ {MEDIA_TYPE_AVC, new String[]{"bbb_642x642_1mbps_30fps_avc.mp4"},
+ null, -1.0f, 3947092788L, -1, -1, 642, 642, CODEC_ANY},
+ {MEDIA_TYPE_VP8, new String[]{"bbb_642x642_1mbps_30fps_vp8.webm"},
+ null, -1.0f, 516982978L, -1, -1, 642, 642, CODEC_ANY},
+ {MEDIA_TYPE_HEVC, new String[]{"bbb_642x642_768kbps_30fps_hevc.mp4"},
+ null, -1.0f, 3018465268L, -1, -1, 642, 642, CODEC_ANY},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_642x642_768kbps_30fps_vp9.webm"},
+ null, -1.0f, 4032809269L, -1, -1, 642, 642, CODEC_ANY},
+ {MEDIA_TYPE_AV1, new String[]{"bbb_642x642_768kbps_30fps_av1.mp4"},
+ null, -1.0f, 3684481474L, -1, -1, 642, 642, CODEC_ANY},
+ {MEDIA_TYPE_MPEG4, new String[]{"bbb_130x130_192kbps_15fps_mpeg4.mp4"},
+ null, -1.0f, -1L, -1, -1, 130, 130, CODEC_ANY},
- // audio test vectors covering cdd sec 5.1.3
- // amr nb
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_10.2kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_7.95kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_6.70kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_5.90kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_5.15kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_NB, new String[]{
- "audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
+ // audio test vectors covering cdd sec 5.1.3
+ // amrnb
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_10.2kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_7.95kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_7.40kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_6.70kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_5.90kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_5.15kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_4.75kbps_amrnb.3gp"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
- // amr wb
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_8.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_12.65kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_14.25kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_18.25kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_19.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_23.05kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AMR_WB, new String[]{
- "audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"}, null, -1.0f, -1L, CODEC_ALL},
-
- // flac
- // TODO(add content for 96kHz and 192kHz)
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_8kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_12kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_12kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_16kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_22kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_24kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_32kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_44kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_1ch_48kHz_lvl4_flac.mka"},
- "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_8kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_12kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_12kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_16kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_22kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_24kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_32kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_44kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_FLAC, new String[]{"audio/bbb_2ch_48kHz_lvl4_flac.mka"},
- "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
+ // amrwb
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_6.6kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_8.85kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_12.65kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_14.25kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_15.85kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_18.25kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_19.85kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_23.05kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_AMRWB, new String[]{"audio/bbb_mono_16kHz_23.85kbps_amrwb.3gp"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
// opus
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_1ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_1ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_1ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_1ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_1ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_1ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_2ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_2ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_2ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_2ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_2ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_2ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_5ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_5ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_5ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_5ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_5ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_5ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_6ch_8kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_6ch_12kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_6ch_16kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_6ch_24kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_6ch_32kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_OPUS, new String[]{
- "audio/bbb_6ch_48kHz_opus.ogg"}, null, -1.0f, -1L, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_8kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_12kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_16kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_24kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_32kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_1ch_48kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_8kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_12kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_16kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_24kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_32kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_2ch_48kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_8kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_12kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_16kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_24kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_32kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_5ch_48kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_8kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_12kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_16kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_24kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_32kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_OPUS, new String[]{"audio/bbb_6ch_48kHz_opus.ogg"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_ALL},
+
+ // vorbis
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_8kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_12kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 12000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_16kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_24kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 24000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_32kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 32000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_1ch_48kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_8kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 8000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_12kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 12000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_16kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_24kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_32kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/bbb_2ch_48kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/highres_1ch_96kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 96000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_VORBIS, new String[]{"audio/highres_2ch_96kHz_q10_vorbis.ogg"},
+ null, -1.0f, -1L, 96000, 2, -1, -1, CODEC_ALL},
+
+ // flac
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_8kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_12kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_12kHz_s16le_3s.raw", 0.0f, -1L, 12000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_16kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_22kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_24kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_32kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_44kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_1ch_48kHz_lvl4_flac.mka"},
+ "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_8kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_12kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_12kHz_s16le_3s.raw", 0.0f, -1L, 12000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_16kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_22kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_24kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_32kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_44kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/bbb_2ch_48kHz_lvl4_flac.mka"},
+ "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/highres_1ch_96kHz_lvl4_flac.mka"},
+ "audio/highres_1ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/highres_1ch_176kHz_lvl4_flac.mka"},
+ "audio/highres_1ch_176kHz_s16le_5s.raw", 0.0f, -1L, 176400, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/highres_1ch_192kHz_lvl4_flac.mka"},
+ "audio/highres_1ch_192kHz_s16le_5s.raw", 0.0f, -1L, 192000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/highres_2ch_96kHz_lvl4_flac.mka"},
+ "audio/highres_2ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/highres_2ch_176kHz_lvl4_flac.mka"},
+ "audio/highres_2ch_176kHz_s16le_5s.raw", 0.0f, -1L, 176400, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/highres_2ch_192kHz_lvl4_flac.mka"},
+ "audio/highres_2ch_192kHz_s16le_5s.raw", 0.0f, -1L, 192000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_FLAC, new String[]{"audio/sd_2ch_48kHz_lvl4_flac.mka"},
+ "audio/sd_2ch_48kHz_f32le.raw", 3.446394f, -1L, 48000, 2, -1, -1,
+ CODEC_ALL},
// raw
- // TODO: add content for larger sampling rates and float pcm
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_8kHz.wav"},
- "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_16kHz.wav"},
- "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_22kHz.wav"},
- "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_24kHz.wav"},
- "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_32kHz.wav"},
- "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_44kHz.wav"},
- "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_1ch_48kHz.wav"},
- "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_8kHz.wav"},
- "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_16kHz.wav"},
- "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_22kHz.wav"},
- "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_24kHz.wav"},
- "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_32kHz.wav"},
- "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_44kHz.wav"},
- "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_RAW, new String[]{"audio/bbb_2ch_48kHz.wav"},
- "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_8kHz.wav"},
+ "audio/bbb_1ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_16kHz.wav"},
+ "audio/bbb_1ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_22kHz.wav"},
+ "audio/bbb_1ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_24kHz.wav"},
+ "audio/bbb_1ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_32kHz.wav"},
+ "audio/bbb_1ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_44kHz.wav"},
+ "audio/bbb_1ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_1ch_48kHz.wav"},
+ "audio/bbb_1ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 1, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_8kHz.wav"},
+ "audio/bbb_2ch_8kHz_s16le_3s.raw", 0.0f, -1L, 8000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_16kHz.wav"},
+ "audio/bbb_2ch_16kHz_s16le_3s.raw", 0.0f, -1L, 16000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_22kHz.wav"},
+ "audio/bbb_2ch_22kHz_s16le_3s.raw", 0.0f, -1L, 22050, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_24kHz.wav"},
+ "audio/bbb_2ch_24kHz_s16le_3s.raw", 0.0f, -1L, 24000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_32kHz.wav"},
+ "audio/bbb_2ch_32kHz_s16le_3s.raw", 0.0f, -1L, 32000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_44kHz.wav"},
+ "audio/bbb_2ch_44kHz_s16le_3s.raw", 0.0f, -1L, 44100, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/bbb_2ch_48kHz.wav"},
+ "audio/bbb_2ch_48kHz_s16le_3s.raw", 0.0f, -1L, 48000, 2, -1, -1, CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/highres_1ch_96kHz.wav"},
+ "audio/highres_1ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_RAW, new String[]{"audio/highres_2ch_96kHz.wav"},
+ "audio/highres_2ch_96kHz_s16le_5s.raw", 0.0f, -1L, 96000, 2, -1, -1,
+ CODEC_ALL},
// aac-lc
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_8kHz_aac_lc.m4a"},
- "audio/bbb_1ch_8kHz_s16le_3s.raw", 26.907248f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_12kHz_aac_lc.m4a"},
- "audio/bbb_1ch_12kHz_s16le_3s.raw", 23.366642f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_lc.m4a"},
- "audio/bbb_1ch_16kHz_s16le_3s.raw", 21.354156f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_lc.m4a"},
- "audio/bbb_1ch_22kHz_s16le_3s.raw", 25.980762f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_lc.m4a"},
- "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.362852f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_lc.m4a"},
- "audio/bbb_1ch_32kHz_s16le_3s.raw", 28.635643f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_lc.m4a"},
- "audio/bbb_1ch_44kHz_s16le_3s.raw", 29.291637f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_lc.m4a"},
- "audio/bbb_1ch_48kHz_s16le_3s.raw", 29.325756f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_8kHz_aac_lc.m4a"},
- "audio/bbb_2ch_8kHz_s16le_3s.raw", 26.362852f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_12kHz_aac_lc.m4a"},
- "audio/bbb_2ch_12kHz_s16le_3s.raw", 21.931713f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_lc.m4a"},
- "audio/bbb_2ch_16kHz_s16le_3s.raw", 22.068077f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_lc.m4a"},
- "audio/bbb_2ch_22kHz_s16le_3s.raw", 25.317978f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_lc.m4a"},
- "audio/bbb_2ch_24kHz_s16le_3s.raw", 25.651510f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_lc.m4a"},
- "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.294687f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_lc.m4a"},
- "audio/bbb_2ch_44kHz_s16le_3s.raw", 27.313000f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_lc.m4a"},
- "audio/bbb_2ch_48kHz_s16le_3s.raw", 27.676704f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_8kHz_aac_lc.m4a"},
- "audio/bbb_5ch_8kHz_s16le_3s.raw", 43.116123f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_12kHz_aac_lc.m4a"},
- "audio/bbb_5ch_12kHz_s16le_3s.raw", 35.972210f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_16kHz_aac_lc.m4a"},
- "audio/bbb_5ch_16kHz_s16le_3s.raw", 32.710854f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_22kHz_aac_lc.m4a"},
- "audio/bbb_5ch_22kHz_s16le_3s.raw", 39.281040f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_24kHz_aac_lc.m4a"},
- "audio/bbb_5ch_24kHz_s16le_3s.raw", 40.951191f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_32kHz_aac_lc.m4a"},
- "audio/bbb_5ch_32kHz_s16le_3s.raw", 49.436829f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_44kHz_aac_lc.m4a"},
- "audio/bbb_5ch_44kHz_s16le_3s.raw", 43.886215f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_5ch_48kHz_aac_lc.m4a"},
- "audio/bbb_5ch_48kHz_s16le_3s.raw", 44.271889f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_8kHz_aac_lc.m4a"},
- "audio/bbb_6ch_8kHz_s16le_3s.raw", 39.661064f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_12kHz_aac_lc.m4a"},
- "audio/bbb_6ch_12kHz_s16le_3s.raw", 34.971416f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_16kHz_aac_lc.m4a"},
- "audio/bbb_6ch_16kHz_s16le_3s.raw", 29.068884f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_22kHz_aac_lc.m4a"},
- "audio/bbb_6ch_22kHz_s16le_3s.raw", 29.427877f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_24kHz_aac_lc.m4a"},
- "audio/bbb_6ch_24kHz_s16le_3s.raw", 30.331501f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_32kHz_aac_lc.m4a"},
- "audio/bbb_6ch_32kHz_s16le_3s.raw", 33.926392f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_44kHz_aac_lc.m4a"},
- "audio/bbb_6ch_44kHz_s16le_3s.raw", 31.733263f, -1L, CODEC_ALL},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_6ch_48kHz_aac_lc.m4a"},
- "audio/bbb_6ch_48kHz_s16le_3s.raw", 31.032242f, -1L, CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_8kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_8kHz_s16le_3s.raw", 26.910906f, -1L, 8000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_12kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_12kHz_s16le_3s.raw", 23.380817f, -1L, 12000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_16kHz_s16le_3s.raw", 21.368309f, -1L, 16000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_22kHz_s16le_3s.raw", 25.995440f, -1L, 22050, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.373266f, -1L, 24000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_32kHz_s16le_3s.raw", 28.642658f, -1L, 32000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_44kHz_s16le_3s.raw", 29.294861f, -1L, 44100, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_lc.m4a"},
+ "audio/bbb_1ch_48kHz_s16le_3s.raw", 29.335669f, -1L, 48000, 1, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_8kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_8kHz_s16le_3s.raw", 26.381552f, -1L, 8000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_12kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_12kHz_s16le_3s.raw", 21.934900f, -1L, 12000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_16kHz_s16le_3s.raw", 22.072184f, -1L, 16000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_22kHz_s16le_3s.raw", 25.334206f, -1L, 22050, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_24kHz_s16le_3s.raw", 25.653538f, -1L, 24000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.312286f, -1L, 32000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_44kHz_s16le_3s.raw", 27.316111f, -1L, 44100, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_lc.m4a"},
+ "audio/bbb_2ch_48kHz_s16le_3s.raw", 27.684767f, -1L, 48000, 2, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_8kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_8kHz_s16le_3s.raw", 43.121964f, -1L, 8000, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_12kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_12kHz_s16le_3s.raw", 35.983891f, -1L, 12000, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_16kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_16kHz_s16le_3s.raw", 32.720196f, -1L, 16000, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_22kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_22kHz_s16le_3s.raw", 39.286514f, -1L, 22050, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_24kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_24kHz_s16le_3s.raw", 40.963005f, -1L, 24000, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_32kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_32kHz_s16le_3s.raw", 49.437782f, -1L, 32000, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_44kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_44kHz_s16le_3s.raw", 43.891609f, -1L, 44100, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_48kHz_aac_lc.m4a"},
+ "audio/bbb_5ch_48kHz_s16le_3s.raw", 44.275997f, -1L, 48000, 5, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_8kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_8kHz_s16le_3s.raw", 39.666485f, -1L, 8000, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_12kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_12kHz_s16le_3s.raw", 34.979305f, -1L, 12000, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_16kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_16kHz_s16le_3s.raw", 29.069729f, -1L, 16000, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_22kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_22kHz_s16le_3s.raw", 29.440094f, -1L, 22050, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_24kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_24kHz_s16le_3s.raw", 30.333755f, -1L, 24000, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_32kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_32kHz_s16le_3s.raw", 33.927166f, -1L, 32000, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_44kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_44kHz_s16le_3s.raw", 31.733339f, -1L, 44100, 6, -1, -1,
+ CODEC_ALL},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_48kHz_aac_lc.m4a"},
+ "audio/bbb_6ch_48kHz_s16le_3s.raw", 31.033596f, -1L, 48000, 6, -1, -1,
+ CODEC_ALL},
// aac-he
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_16kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_22kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_24kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_32kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_44kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_48kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_5ch_16kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_5ch_22kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_5ch_24kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_5ch_32kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_5ch_44kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_5ch_48kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_6ch_16kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_6ch_22kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_6ch_24kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_6ch_32kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_6ch_44kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_6ch_48kHz_aac_he.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
-
- // aac-eld
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_eld.m4a"},
- "audio/bbb_1ch_16kHz_s16le_3s.raw", -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_eld.m4a"},
- "audio/bbb_1ch_22kHz_s16le_3s.raw", 24.959969f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_eld.m4a"},
- "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.495283f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_eld.m4a"},
- "audio/bbb_1ch_32kHz_s16le_3s.raw", 31.464266f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_eld.m4a"},
- "audio/bbb_1ch_44kHz_s16le_3s.raw", 33.852623f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_eld.m4a"},
- "audio/bbb_1ch_48kHz_s16le_3s.raw", 33.136082f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_eld.m4a"},
- "audio/bbb_2ch_16kHz_s16le_3s.raw", -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_eld.m4a"},
- "audio/bbb_2ch_22kHz_s16le_3s.raw", 24.959969f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_eld.m4a"},
- "audio/bbb_2ch_24kHz_s16le_3s.raw", 26.962938f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_eld.m4a"},
- "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.784887f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_eld.m4a"},
- "audio/bbb_2ch_44kHz_s16le_3s.raw", 29.223278f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_eld.m4a"},
- "audio/bbb_2ch_48kHz_s16le_3s.raw", 29.171904f, -1L, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 22050, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 44100, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_16kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 16000, 5, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_22kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 22050, 5, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_24kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 24000, 5, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_32kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 32000, 5, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_44kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 44100, 5, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_5ch_48kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 48000, 5, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_16kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 16000, 6, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_22kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 22050, 6, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_24kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 24000, 6, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_32kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 32000, 6, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_44kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 44100, 6, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_6ch_48kHz_aac_he.m4a"},
+ null, -1.0f, -1L, 48000, 6, -1, -1, CODEC_DEFAULT},
// aac-hev2
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_16kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_22kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_24kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_32kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_44kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{
- "audio/bbb_2ch_48kHz_aac_hev2.m4a"}, null, -1.0f, -1L, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_hev2.m4a"},
+ null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_hev2.m4a"},
+ null, -1.0f, -1L, 22050, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_hev2.m4a"},
+ null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_hev2.m4a"},
+ null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_hev2.m4a"},
+ null, -1.0f, -1L, 44100, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_hev2.m4a"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_DEFAULT},
+
+ // aac-eld
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_16kHz_aac_eld.m4a"},
+ "audio/bbb_1ch_16kHz_s16le_3s.raw", -1.000000f, -1L, 16000, 1, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_22kHz_aac_eld.m4a"},
+ "audio/bbb_1ch_22kHz_s16le_3s.raw", 24.969662f, -1L, 22050, 1, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_24kHz_aac_eld.m4a"},
+ "audio/bbb_1ch_24kHz_s16le_3s.raw", 26.498655f, -1L, 24000, 1, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_32kHz_aac_eld.m4a"},
+ "audio/bbb_1ch_32kHz_s16le_3s.raw", 31.468872f, -1L, 32000, 1, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_44kHz_aac_eld.m4a"},
+ "audio/bbb_1ch_44kHz_s16le_3s.raw", 33.866409f, -1L, 44100, 1, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_48kHz_aac_eld.m4a"},
+ "audio/bbb_1ch_48kHz_s16le_3s.raw", 33.148113f, -1L, 48000, 1, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_aac_eld.m4a"},
+ "audio/bbb_2ch_16kHz_s16le_3s.raw", -1.000000f, -1L, 16000, 2, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_aac_eld.m4a"},
+ "audio/bbb_2ch_22kHz_s16le_3s.raw", 24.979313f, -1L, 22050, 2, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_aac_eld.m4a"},
+ "audio/bbb_2ch_24kHz_s16le_3s.raw", 26.977774f, -1L, 24000, 2, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_aac_eld.m4a"},
+ "audio/bbb_2ch_32kHz_s16le_3s.raw", 27.790754f, -1L, 32000, 2, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_aac_eld.m4a"},
+ "audio/bbb_2ch_44kHz_s16le_3s.raw", 29.236626f, -1L, 44100, 2, -1, -1,
+ CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_aac_eld.m4a"},
+ "audio/bbb_2ch_48kHz_s16le_3s.raw", 29.183796f, -1L, 48000, 2, -1, -1,
+ CODEC_DEFAULT},
// aac-usac
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_8kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_16kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_22kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_24kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_32kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_44kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_1ch_48kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_8kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_16kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_22kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_24kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_32kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_44kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
- {MediaFormat.MIMETYPE_AUDIO_AAC, new String[]{"audio/bbb_2ch_48kHz_usac.m4a"},
- null, -1.0f, -1L, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_8kHz_usac.m4a"},
+ null, -1.0f, -1L, 8000, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_16kHz_usac.m4a"},
+ null, -1.0f, -1L, 16000, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_22kHz_usac.m4a"},
+ null, -1.0f, -1L, 22050, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_24kHz_usac.m4a"},
+ null, -1.0f, -1L, 24000, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_32kHz_usac.m4a"},
+ null, -1.0f, -1L, 32000, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_44kHz_usac.m4a"},
+ null, -1.0f, -1L, 44100, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_1ch_48kHz_usac.m4a"},
+ null, -1.0f, -1L, 48000, 1, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_8kHz_usac.m4a"},
+ null, -1.0f, -1L, 8000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_16kHz_usac.m4a"},
+ null, -1.0f, -1L, 16000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_22kHz_usac.m4a"},
+ null, -1.0f, -1L, 22050, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_24kHz_usac.m4a"},
+ null, -1.0f, -1L, 24000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_32kHz_usac.m4a"},
+ null, -1.0f, -1L, 32000, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_44kHz_usac.m4a"},
+ null, -1.0f, -1L, 44100, 2, -1, -1, CODEC_DEFAULT},
+ {MEDIA_TYPE_AAC, new String[]{"audio/bbb_2ch_48kHz_usac.m4a"},
+ null, -1.0f, -1L, 48000, 2, -1, -1, CODEC_DEFAULT},
});
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
}
@@ -472,11 +588,32 @@
mExtractor.release();
}
checkFormatSupport(mCodecName, mMime, formats, null, mSupportRequirements);
- final int mode = MediaExtractor.SEEK_TO_CLOSEST_SYNC;
{
OutputManager ref = null;
+ mSaveToMem = true;
+ int audioEncoding = AudioFormat.ENCODING_INVALID;
for (String file : mSrcFiles) {
- decodeToMemory(file, mCodecName, 0, mode, Integer.MAX_VALUE);
+ mOutputBuff = new OutputManager();
+ mCodec = MediaCodec.createByCodecName(mCodecName);
+ MediaFormat format = setUpSource(file);
+ if (mIsAudio) {
+ audioEncoding = format.getInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_16BIT);
+ }
+ configureCodec(format, false, true, false);
+ mCodec.start();
+ mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
+ doWork(Integer.MAX_VALUE);
+ queueEOS();
+ waitForAllOutputs();
+ mOutFormat = mCodec.getOutputFormat();
+ if (mIsAudio) {
+ assertEquals(mOutFormat.getInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_16BIT), audioEncoding);
+ }
+ mCodec.stop();
+ mCodec.release();
+ mExtractor.release();
String log = String.format("codec: %s, test file: %s:: ", mCodecName, file);
assertTrue(log + " unexpected error", !mAsyncHandle.hasSeenError());
assertTrue(log + "no input sent", 0 != mInputCount);
@@ -493,10 +630,16 @@
assertTrue(log + "decoder outputs are not identical",
ref.equalsInterlaced(mOutputBuff));
} else {
- assertTrue(log + "decoder outputs are not identical", ref.equals(mOutputBuff));
+ assertEquals(log + "decoder outputs are not identical", ref, mOutputBuff);
}
+ assertEquals("sample rate mismatch", mSampleRate,
+ mOutFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE, -1));
+ assertEquals("channel count mismatch", mChannelCount,
+ mOutFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT, -1));
+ assertEquals("width mismatch", mWidth, getWidth(mOutFormat));
+ assertEquals("height mismatch", mHeight, getHeight(mOutFormat));
}
- CodecDecoderTest.verify(mOutputBuff, mRefFile, mRmsError, mRefCRC);
+ CodecDecoderTest.verify(ref, mRefFile, mRmsError, audioEncoding, mRefCRC);
}
}
}
diff --git a/tests/media/src/android/mediav2/cts/CodecTestBase.java b/tests/media/src/android/mediav2/cts/CodecTestBase.java
index dacaf5b..d07a1df 100644
--- a/tests/media/src/android/mediav2/cts/CodecTestBase.java
+++ b/tests/media/src/android/mediav2/cts/CodecTestBase.java
@@ -21,6 +21,7 @@
import android.graphics.ImageFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
+import android.media.AudioFormat;
import android.media.Image;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
@@ -437,18 +438,70 @@
outPtsList.clear();
}
- float getRmsError(short[] refData) {
- long totalErrorSquared = 0;
- assertTrue(0 == (memIndex & 1));
- short[] shortData = new short[memIndex / 2];
- ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer()
- .get(shortData);
- if (refData.length != shortData.length) return Float.MAX_VALUE;
- for (int i = 0; i < shortData.length; i++) {
- int d = shortData[i] - refData[i];
- totalErrorSquared += d * d;
+ float getRmsError(Object refObject, int audioFormat) {
+ double totalErrorSquared = 0;
+ double avgErrorSquared;
+ int bytesPerSample = AudioFormat.getBytesPerSample(audioFormat);
+ if (refObject instanceof float[]) {
+ if (audioFormat != AudioFormat.ENCODING_PCM_FLOAT) return Float.MAX_VALUE;
+ float[] refData = (float[]) refObject;
+ if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+ float[] floatData = new float[refData.length];
+ ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asFloatBuffer()
+ .get(floatData);
+ for (int i = 0; i < refData.length; i++) {
+ float d = floatData[i] - refData[i];
+ totalErrorSquared += d * d;
+ }
+ avgErrorSquared = (totalErrorSquared / refData.length);
+ } else if (refObject instanceof int[]) {
+ int[] refData = (int[]) refObject;
+ int[] intData;
+ if (audioFormat == AudioFormat.ENCODING_PCM_24BIT_PACKED) {
+ if (refData.length != (memIndex / bytesPerSample)) return Float.MAX_VALUE;
+ intData = new int[refData.length];
+ for (int i = 0, j = 0; i < memIndex; i += 3, j++) {
+ intData[j] = memory[j] | (memory[j + 1] << 8) | (memory[j + 2] << 16);
+ }
+ } else if (audioFormat == AudioFormat.ENCODING_PCM_32BIT) {
+ if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+ intData = new int[refData.length];
+ ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer()
+ .get(intData);
+ } else {
+ return Float.MAX_VALUE;
+ }
+ for (int i = 0; i < intData.length; i++) {
+ float d = intData[i] - refData[i];
+ totalErrorSquared += d * d;
+ }
+ avgErrorSquared = (totalErrorSquared / refData.length);
+ } else if (refObject instanceof short[]) {
+ short[] refData = (short[]) refObject;
+ if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+ if (audioFormat != AudioFormat.ENCODING_PCM_16BIT) return Float.MAX_VALUE;
+ short[] shortData = new short[refData.length];
+ ByteBuffer.wrap(memory, 0, memIndex).order(ByteOrder.LITTLE_ENDIAN).asShortBuffer()
+ .get(shortData);
+ for (int i = 0; i < shortData.length; i++) {
+ float d = shortData[i] - refData[i];
+ totalErrorSquared += d * d;
+ }
+ avgErrorSquared = (totalErrorSquared / refData.length);
+ } else if (refObject instanceof byte[]) {
+ byte[] refData = (byte[]) refObject;
+ if (refData.length != memIndex / bytesPerSample) return Float.MAX_VALUE;
+ if (audioFormat != AudioFormat.ENCODING_PCM_8BIT) return Float.MAX_VALUE;
+ byte[] byteData = new byte[refData.length];
+ ByteBuffer.wrap(memory, 0, memIndex).get(byteData);
+ for (int i = 0; i < byteData.length; i++) {
+ float d = byteData[i] - refData[i];
+ totalErrorSquared += d * d;
+ }
+ avgErrorSquared = (totalErrorSquared / refData.length);
+ } else {
+ return Float.MAX_VALUE;
}
- long avgErrorSquared = (totalErrorSquared / shortData.length);
return (float) Math.sqrt(avgErrorSquared);
}
@@ -1201,7 +1254,17 @@
MediaFormat format = mExtractor.getTrackFormat(trackID);
if (mMime.equalsIgnoreCase(format.getString(MediaFormat.KEY_MIME))) {
mExtractor.selectTrack(trackID);
- if (!mIsAudio) {
+ if (mIsAudio) {
+ // as per cdd, pcm/wave must support PCM_{8, 16, 24, 32, float} and flac must
+ // support PCM_{16, float}. For raw media type let extractor manage the
+ // encoding type directly. For flac, basing on bits-per-sample select the type
+ if (mMime.equals(MediaFormat.MIMETYPE_AUDIO_FLAC)) {
+ if (format.getInteger("bits-per-sample", 16) > 16) {
+ format.setInteger(MediaFormat.KEY_PCM_ENCODING,
+ AudioFormat.ENCODING_PCM_FLOAT);
+ }
+ }
+ } else {
if (mSurface == null) {
// COLOR_FormatYUV420Flexible must be supported by all components
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, COLOR_FormatYUV420Flexible);
@@ -1444,8 +1507,8 @@
private static final String LOG_TAG = CodecEncoderTestBase.class.getSimpleName();
// files are in WorkDir.getMediaDirString();
- private static final String mInputAudioFile = "bbb_2ch_44kHz_s16le.raw";
- private static final String mInputVideoFile = "bbb_cif_yuv420p_30fps.yuv";
+ private static final String INPUT_AUDIO_FILE = "bbb_2ch_44kHz_s16le.raw";
+ private static final String INPUT_VIDEO_FILE = "bbb_cif_yuv420p_30fps.yuv";
private final int INP_FRM_WIDTH = 352;
private final int INP_FRM_HEIGHT = 288;
@@ -1487,7 +1550,7 @@
mSampleRate = 8000;
mAsyncHandle = new CodecAsyncHandler();
mIsAudio = mMime.startsWith("audio/");
- mInputFile = mIsAudio ? mInputAudioFile : mInputVideoFile;
+ mInputFile = mIsAudio ? INPUT_AUDIO_FILE : INPUT_VIDEO_FILE;
}
/**
diff --git a/tests/ondevicepersonalization/Android.bp b/tests/ondevicepersonalization/Android.bp
index f676d04..738effe 100644
--- a/tests/ondevicepersonalization/Android.bp
+++ b/tests/ondevicepersonalization/Android.bp
@@ -26,6 +26,7 @@
test_suites: [
"cts",
"general-tests",
+ "mts-ondevicepersonalization",
],
libs: [
"android.test.runner",
diff --git a/tests/smartspace/src/android/smartspace/cts/CarouselItemTest.java b/tests/smartspace/src/android/smartspace/cts/CarouselItemTest.java
new file mode 100644
index 0000000..a5d4101
--- /dev/null
+++ b/tests/smartspace/src/android/smartspace/cts/CarouselItemTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.smartspace.cts;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem;
+import android.app.smartspace.uitemplatedata.Text;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link CarouselItem}
+ *
+ * atest CtsSmartspaceServiceTestCases
+ */
+@RunWith(AndroidJUnit4.class)
+public class CarouselItemTest {
+
+ private static final String TAG = "CarouselItemTest";
+
+ @Test
+ public void testCreateCarouselItem() {
+ CarouselItem item = new CarouselItem.Builder()
+ .setUpperText(new Text.Builder("upper").build())
+ .setImage(SmartspaceTestUtils.createSmartspaceIcon("icon"))
+ .setLowerText(new Text.Builder("lower").build())
+ .setTapAction(
+ SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "item tap"))
+ .build();
+
+ assertThat(item.getUpperText()).isEqualTo(new Text.Builder("upper").build());
+ assertThat(item.getImage()).isEqualTo(SmartspaceTestUtils.createSmartspaceIcon("icon"));
+ assertThat(item.getLowerText()).isEqualTo(new Text.Builder("lower").build());
+ assertThat(item.getTapAction()).isEqualTo(
+ SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "item tap"));
+
+ Parcel parcel = Parcel.obtain();
+ parcel.setDataPosition(0);
+ item.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ CarouselItem copyItem = CarouselItem.CREATOR.createFromParcel(parcel);
+ assertThat(item).isEqualTo(copyItem);
+ parcel.recycle();
+ }
+}
diff --git a/tests/smartspace/src/android/smartspace/cts/IconTest.java b/tests/smartspace/src/android/smartspace/cts/IconTest.java
index 484af9f..ce9639b 100644
--- a/tests/smartspace/src/android/smartspace/cts/IconTest.java
+++ b/tests/smartspace/src/android/smartspace/cts/IconTest.java
@@ -41,10 +41,11 @@
android.graphics.drawable.Icon icon = android.graphics.drawable.Icon.createWithBitmap(
Bitmap.createBitmap(1, 1, Bitmap.Config.ALPHA_8));
Icon smartspaceIcon = new Icon.Builder(icon).setContentDescription(
- "test content").build();
+ "test content").setShouldTint(false).build();
assertThat(smartspaceIcon.getIcon()).isEqualTo(icon);
assertThat(smartspaceIcon.getContentDescription()).isEqualTo("test content");
+ assertThat(smartspaceIcon.shouldTint()).isFalse();
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
diff --git a/tests/smartspace/src/android/smartspace/cts/SubItemInfoTest.java b/tests/smartspace/src/android/smartspace/cts/SubItemInfoTest.java
new file mode 100644
index 0000000..a338abe
--- /dev/null
+++ b/tests/smartspace/src/android/smartspace/cts/SubItemInfoTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.smartspace.cts;
+
+import static androidx.test.InstrumentationRegistry.getContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo;
+import android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo;
+import android.app.smartspace.uitemplatedata.Text;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SubItemInfo}
+ *
+ * atest CtsSmartspaceServiceTestCases
+ */
+@RunWith(AndroidJUnit4.class)
+public class SubItemInfoTest {
+
+ private static final String TAG = "SubItemInfoTest";
+
+ @Test
+ public void testCreateCarouselItem() {
+ SubItemInfo itemInfo = new SubItemInfo.Builder()
+ .setText(new Text.Builder("test").build())
+ .setIcon(SmartspaceTestUtils.createSmartspaceIcon("icon"))
+ .setTapAction(
+ SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "action"))
+ .setLoggingInfo(new SubItemLoggingInfo.Builder(0, 0)
+ .setPackageName("package name").build())
+ .build();
+
+ assertThat(itemInfo.getText()).isEqualTo(new Text.Builder("test").build());
+ assertThat(itemInfo.getIcon()).isEqualTo(SmartspaceTestUtils.createSmartspaceIcon("icon"));
+ assertThat(itemInfo.getTapAction()).isEqualTo(
+ SmartspaceTestUtils.createSmartspaceTapAction(getContext(), "action"));
+ assertThat(itemInfo.getLoggingInfo()).isEqualTo(new SubItemLoggingInfo.Builder(0, 0)
+ .setPackageName("package name").build());
+
+ Parcel parcel = Parcel.obtain();
+ parcel.setDataPosition(0);
+ itemInfo.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ SubItemInfo copyItemInfo = SubItemInfo.CREATOR.createFromParcel(parcel);
+ assertThat(itemInfo).isEqualTo(copyItemInfo);
+ parcel.recycle();
+ }
+}
diff --git a/tests/smartspace/src/android/smartspace/cts/SubItemLoggingInfoTest.java b/tests/smartspace/src/android/smartspace/cts/SubItemLoggingInfoTest.java
new file mode 100644
index 0000000..e1ddafd
--- /dev/null
+++ b/tests/smartspace/src/android/smartspace/cts/SubItemLoggingInfoTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.smartspace.cts;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo;
+import android.os.Parcel;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link SubItemLoggingInfo}
+ *
+ * atest CtsSmartspaceServiceTestCases
+ */
+@RunWith(AndroidJUnit4.class)
+public class SubItemLoggingInfoTest {
+
+ private static final String TAG = "SubItemLoggingInfoTest";
+
+ @Test
+ public void testCreateSubItemLoggingInfo() {
+ SubItemLoggingInfo itemLoggingInfo = new SubItemLoggingInfo.Builder(1, 1)
+ .setPackageName("package name").build();
+
+ assertThat(itemLoggingInfo.getInstanceId()).isEqualTo(1);
+ assertThat(itemLoggingInfo.getFeatureType()).isEqualTo(1);
+ assertThat(itemLoggingInfo.getPackageName()).isEqualTo("package name");
+
+ Parcel parcel = Parcel.obtain();
+ parcel.setDataPosition(0);
+ itemLoggingInfo.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ SubItemLoggingInfo copyItemLoggingInfo = SubItemLoggingInfo.CREATOR.createFromParcel(
+ parcel);
+ assertThat(itemLoggingInfo).isEqualTo(copyItemLoggingInfo);
+ parcel.recycle();
+ }
+}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index 78868c9..2bc4128 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -104,6 +104,7 @@
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -2373,6 +2374,7 @@
actualStats = PollingCheck.waitFor(DEFAULT_TIMEOUT_MS,
() -> mUsageStatsManager.queryBroadcastResponseStats(packageName, id),
result -> compareStats(expectedStats, result));
+ actualStats.sort(Comparator.comparing(BroadcastResponseStats::getPackageName));
final String errorMsg = String.format("\nEXPECTED(%d)=%s\nACTUAL(%d)=%s\n",
1, expectedStats,
actualStats.size(), Arrays.toString(actualStats.toArray()));
@@ -2392,6 +2394,7 @@
actualStats = PollingCheck.waitFor(DEFAULT_TIMEOUT_MS,
() -> mUsageStatsManager.queryBroadcastResponseStats(null /* packageName */, id),
result -> compareStats(expectedStats, result));
+ actualStats.sort(Comparator.comparing(BroadcastResponseStats::getPackageName));
final String errorMsg = String.format("\nEXPECTED(%d)=%s\nACTUAL(%d)=%s\n",
expectedStats.size(), expectedStats,
actualStats.size(), Arrays.toString(actualStats.toArray()));
diff --git a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
index 265da81..149dcc9 100644
--- a/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
+++ b/tests/tests/assist/service/src/android/assist/service/MainInteractionSession.java
@@ -27,6 +27,7 @@
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteCallback;
import android.service.voice.VoiceInteractionSession;
@@ -36,6 +37,12 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import com.android.compatibility.common.util.PropertyUtil;
+
+import java.util.Objects;
public class MainInteractionSession extends VoiceInteractionSession {
static final String TAG = "MainInteractionSession";
@@ -125,7 +132,11 @@
mContentView.getViewTreeObserver().removeOnPreDrawListener(this);
Display d = mContentView.getDisplay();
Point displayPoint = new Point();
- d.getRealSize(displayPoint);
+ WindowManager wm = mContext.getSystemService(WindowManager.class);
+ WindowMetrics windowMetrics = wm.getCurrentWindowMetrics();
+ Rect bound = windowMetrics.getBounds();
+ displayPoint.y = bound.height();
+ displayPoint.x = bound.width();
DisplayCutout dc = d.getCutout();
if (dc != null) {
// Means the device has a cutout area
@@ -137,9 +148,16 @@
displayPoint.x -= (wi.left + wi.right);
}
}
+ int WindowInsetTop = windowMetrics.getWindowInsets().getSystemWindowInsetTop();
+ final String property = PropertyUtil.getProperty("ro.hardware.virtual_device");
+ boolean isVirtual = Objects.equals(property, "1");
Bundle bundle = new Bundle();
- bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION, Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
- bundle.putInt(Utils.EXTRA_CONTENT_VIEW_HEIGHT, mContentView.getHeight());
+ bundle.putString(Utils.EXTRA_REMOTE_CALLBACK_ACTION,
+ Utils.BROADCAST_CONTENT_VIEW_HEIGHT);
+ // TODO: find reason why virtual device don't have problem
+ bundle.putInt(Utils.EXTRA_CONTENT_VIEW_HEIGHT,
+ isVirtual ? mContentView.getHeight()
+ : mContentView.getHeight() + WindowInsetTop);
bundle.putInt(Utils.EXTRA_CONTENT_VIEW_WIDTH, mContentView.getWidth());
bundle.putParcelable(Utils.EXTRA_DISPLAY_POINT, displayPoint);
mRemoteCallback.sendResult(bundle);
diff --git a/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp b/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp
index 4b0c129..cf363c2 100644
--- a/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp
+++ b/tests/tests/binder_ndk/libbinder_ndk_test/test_ibinder.cpp
@@ -227,6 +227,10 @@
AIBinder_Weak_delete(w2);
}
+TEST_F(NdkBinderTest_AIBinder, IsHandlingTransactionFalse) {
+ EXPECT_FALSE(AIBinder_isHandlingTransaction());
+}
+
TEST_F(NdkBinderTest_AIBinder, LocalIsLocal) {
AIBinder* binder = SampleData::newBinder();
EXPECT_FALSE(AIBinder_isRemote(binder));
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
index 0b2dd82..6c7b933 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapClientTest.java
@@ -16,33 +16,47 @@
package android.bluetooth.cts;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHapClient;
import android.bluetooth.BluetoothHapPresetInfo;
-import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
+import android.content.Context;
import android.os.Build;
-import android.test.AndroidTestCase;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
-public class BluetoothHapClientTest extends AndroidTestCase {
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothHapClientTest {
private static final String TAG = BluetoothHapClientTest.class.getSimpleName();
private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
private static final String PROFILE_SUPPORTED_HAP_CLIENT = "profile_supported_hap_client";
+ private Context mContext;
private boolean mHasBluetooth;
private BluetoothAdapter mAdapter;
@@ -52,41 +66,37 @@
private Condition mConditionProfileIsConnected;
private ReentrantLock mProfileConnectedlock;
- @Override
+ @Before
public void setUp() throws Exception {
- super.setUp();
- if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
- mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_BLUETOOTH);
-
- if (!mHasBluetooth) return;
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
- BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
- mAdapter = manager.getAdapter();
- assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
-
- mProfileConnectedlock = new ReentrantLock();
- mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
- mIsProfileReady = false;
- mBluetoothHapClient = null;
-
- Resources bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
- "com.android.bluetooth");
- int hapClientSupportId = bluetoothResources.getIdentifier(
- PROFILE_SUPPORTED_HAP_CLIENT, "bool", "com.android.bluetooth");
- if (hapClientSupportId == 0) return;
- mIsHapClientSupported = bluetoothResources.getBoolean(hapClientSupportId);
- if (!mIsHapClientSupported) return;
-
- mAdapter.getProfileProxy(getContext(), new BluetoothHapClientServiceListener(),
- BluetoothProfile.HAP_CLIENT);
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
}
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+
+ mProfileConnectedlock = new ReentrantLock();
+ mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+ mIsProfileReady = false;
+ mBluetoothHapClient = null;
+
+ mIsHapClientSupported = TestUtils.getProfileConfigValueOrDie(BluetoothProfile.HAP_CLIENT);
+ if (!mIsHapClientSupported) {
+ return;
+ }
+
+ mAdapter.getProfileProxy(mContext, new BluetoothHapClientServiceListener(),
+ BluetoothProfile.HAP_CLIENT);
}
- @Override
+ @After
public void tearDown() throws Exception {
- super.tearDown();
if (mHasBluetooth) {
if (mAdapter != null && mBluetoothHapClient != null) {
mBluetoothHapClient.close();
@@ -95,14 +105,15 @@
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .dropShellPermissionIdentity();
+ TestUtils.dropPermissionAsShellUid();
}
}
+ @Test
public void testGetConnectedDevices() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -113,9 +124,11 @@
assertTrue(connectedDevices.isEmpty());
}
+ @Test
public void testGetDevicesMatchingConnectionStates() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -127,9 +140,11 @@
assertTrue(connectedDevices.isEmpty());
}
+ @Test
public void testGetConnectionState() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -146,9 +161,11 @@
mBluetoothHapClient.getConnectionState(testDevice));
}
+ @Test
public void testGetActivePresetIndex() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -160,9 +177,11 @@
assertNull(mBluetoothHapClient.getActivePresetInfo(testDevice));
}
+ @Test
public void testSelectPreset() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -173,9 +192,11 @@
mBluetoothHapClient.selectPreset(testDevice, 1);
}
+ @Test
public void testSelectPresetForGroup() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -184,8 +205,11 @@
mBluetoothHapClient.selectPresetForGroup(1, 1);
}
+ @Test
public void testGetAllPresetInfo() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -199,8 +223,11 @@
assertTrue(presets.isEmpty());
}
+ @Test
public void testSetPresetName() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -212,8 +239,11 @@
mBluetoothHapClient.setPresetName(testDevice, 1 , "New Name");
}
+ @Test
public void testSetPresetNameForGroup() {
- if (!(mHasBluetooth && mIsHapClientSupported)) return;
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothHapClient);
@@ -223,6 +253,10 @@
mBluetoothHapClient.setPresetNameForGroup(1, 1 , "New Name");
}
+ private boolean shouldSkipTest() {
+ return !(mHasBluetooth && mIsHapClientSupported);
+ }
+
private boolean waitForProfileConnect() {
mProfileConnectedlock.lock();
try {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
new file mode 100644
index 0000000..afafa39
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHapPresetInfoTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothHapPresetInfo;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothHapPresetInfoTest {
+ private static final int TEST_PRESET_INDEX = 15;
+ private static final String TEST_PRESET_NAME = "Test";
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsHapSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsHapSupported = TestUtils.getProfileConfigValueOrDie(BluetoothProfile.HAP_CLIENT);
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
+ @Test
+ public void testCreateHapPresetInfo() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothHapPresetInfo presetInfo = createBluetoothHapPresetInfoForTest(TEST_PRESET_INDEX,
+ TEST_PRESET_NAME, true /* isAvailable */, false /* isWritable */);
+ assertEquals(TEST_PRESET_INDEX, presetInfo.getIndex());
+ assertEquals(TEST_PRESET_NAME, presetInfo.getName());
+ assertTrue(presetInfo.isAvailable());
+ assertFalse(presetInfo.isWritable());
+ }
+
+ static BluetoothHapPresetInfo createBluetoothHapPresetInfoForTest(int presetIndex,
+ String presetName, boolean isAvailable, boolean isWritable) {
+ Parcel out = Parcel.obtain();
+ out.writeInt(presetIndex);
+ out.writeString(presetName);
+ out.writeBoolean(isAvailable);
+ out.writeBoolean(isWritable);
+ return BluetoothHapPresetInfo.CREATOR.createFromParcel(out);
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || !mIsHapSupported;
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
new file mode 100644
index 0000000..8536e9d
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothHeadsetTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+
+import android.app.UiAutomation;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.test.AndroidTestCase;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+public class BluetoothHeadsetTest extends AndroidTestCase {
+ private static final String TAG = BluetoothHeadsetTest.class.getSimpleName();
+
+ private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
+ private static final String PROFILE_SUPPORTED_HEADSET = "profile_supported_hs_hfp";
+
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private UiAutomation mUiAutomation;;
+
+ private BluetoothHeadset mBluetoothHeadset;
+ private boolean mIsHeadsetSupported;
+ private boolean mIsProfileReady;
+ private Condition mConditionProfileIsConnected;
+ private ReentrantLock mProfileConnectedlock;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mHasBluetooth = getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH);
+
+ if (!mHasBluetooth) return;
+ mUiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
+ mUiAutomation.adoptShellPermissionIdentity(BLUETOOTH_CONNECT);
+
+ BluetoothManager manager = getContext().getSystemService(BluetoothManager.class);
+ mAdapter = manager.getAdapter();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mProfileConnectedlock = new ReentrantLock();
+ mConditionProfileIsConnected = mProfileConnectedlock.newCondition();
+ mIsProfileReady = false;
+ mBluetoothHeadset = null;
+
+ Resources bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
+ "com.android.bluetooth");
+ int headsetSupportId = bluetoothResources.getIdentifier(
+ PROFILE_SUPPORTED_HEADSET, "bool", "com.android.bluetooth");
+ assertTrue("resource profile_supported_hs_hfp not found", headsetSupportId != 0);
+ mIsHeadsetSupported = bluetoothResources.getBoolean(headsetSupportId);
+ if (!mIsHeadsetSupported) return;
+
+ mAdapter.getProfileProxy(getContext(), new BluetoothHeadsetServiceListener(),
+ BluetoothProfile.HEADSET);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ if (mHasBluetooth) {
+ if (mAdapter != null && mBluetoothHeadset != null) {
+ mAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+ mBluetoothHeadset = null;
+ mIsProfileReady = false;
+ }
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ mUiAutomation.dropShellPermissionIdentity();
+ }
+ }
+
+ public void test_getConnectedDevices() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ assertEquals(mBluetoothHeadset.getConnectedDevices(),
+ new ArrayList<BluetoothDevice>());
+ }
+
+ public void test_getDevicesMatchingConnectionStates() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ assertEquals(mBluetoothHeadset.getDevicesMatchingConnectionStates(
+ new int[]{BluetoothProfile.STATE_CONNECTED}),
+ new ArrayList<BluetoothDevice>());
+ }
+
+ public void test_getConnectionState() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertEquals(mBluetoothHeadset.getConnectionState(testDevice),
+ BluetoothProfile.STATE_DISCONNECTED);
+ }
+
+ public void test_isAudioConnected() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertFalse(mBluetoothHeadset.isAudioConnected(testDevice));
+ assertFalse(mBluetoothHeadset.isAudioConnected(null));
+
+ // Verify the method returns false when Bluetooth is off and you supply a valid device
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertFalse(mBluetoothHeadset.isAudioConnected(testDevice));
+ }
+
+ public void test_isNoiseReductionSupported() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertFalse(mBluetoothHeadset.isNoiseReductionSupported(testDevice));
+ assertFalse(mBluetoothHeadset.isNoiseReductionSupported(null));
+
+ // Verify the method returns false when Bluetooth is off and you supply a valid device
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertFalse(mBluetoothHeadset.isNoiseReductionSupported(testDevice));
+ }
+
+ public void test_isVoiceRecognitionSupported() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ assertFalse(mBluetoothHeadset.isVoiceRecognitionSupported(testDevice));
+ assertFalse(mBluetoothHeadset.isVoiceRecognitionSupported(null));
+
+ // Verify the method returns false when Bluetooth is off and you supply a valid device
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertFalse(mBluetoothHeadset.isVoiceRecognitionSupported(testDevice));
+ }
+
+ public void test_sendVendorSpecificResultCode() {
+ if (!(mHasBluetooth && mIsHeadsetSupported)) return;
+
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothHeadset);
+
+ BluetoothDevice testDevice = mAdapter.getRemoteDevice("00:11:22:AA:BB:CC");
+
+ try {
+ mBluetoothHeadset.sendVendorSpecificResultCode(testDevice, null, null);
+ fail("sendVendorSpecificResultCode did not throw an IllegalArgumentException when the "
+ + "command was null");
+ } catch (IllegalArgumentException ignored) {
+ }
+
+ assertFalse(mBluetoothHeadset.sendVendorSpecificResultCode(testDevice, "", ""));
+ assertFalse(mBluetoothHeadset.sendVendorSpecificResultCode(null, "", ""));
+
+ // Verify the method returns false when Bluetooth is off and you supply a valid device
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ assertFalse(mBluetoothHeadset.sendVendorSpecificResultCode(testDevice, "", ""));
+ }
+
+ private boolean waitForProfileConnect() {
+ mProfileConnectedlock.lock();
+ try {
+ // Wait for the Adapter to be disabled
+ while (!mIsProfileReady) {
+ if (!mConditionProfileIsConnected.await(
+ PROXY_CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ // Timeout
+ Log.e(TAG, "Timeout while waiting for Profile Connect");
+ break;
+ } // else spurious wakeups
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "waitForProfileConnect: interrrupted");
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ return mIsProfileReady;
+ }
+
+ private final class BluetoothHeadsetServiceListener implements
+ BluetoothProfile.ServiceListener {
+
+ @Override
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ mProfileConnectedlock.lock();
+ mBluetoothHeadset = (BluetoothHeadset) proxy;
+ mIsProfileReady = true;
+ try {
+ mConditionProfileIsConnected.signal();
+ } finally {
+ mProfileConnectedlock.unlock();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(int profile) {
+ }
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
new file mode 100644
index 0000000..af30292
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioCodecConfigMetadataTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeAudioCodecConfigMetadata;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeAudioCodecConfigMetadataTest {
+ private static final long TEST_AUDIO_LOCATION_FRONT_LEFT = 0x01;
+ // See Page 5 of Generic Audio assigned number specification
+ private static final byte[] TEST_METADATA_BYTES = {
+ // length = 0x05, type = 0x03, value = 0x00000001 (front left)
+ 0x05, 0x03, 0x00, 0x00, 0x00, 0x01
+ };
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsBroadcastSourceSupported;
+ private boolean mIsBroadcastAssistantSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
+ }
+
+ mIsBroadcastSourceSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (!mIsBroadcastSourceSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
+ @Test
+ public void testCreateCodecConfigMetadataFromBuilder() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothLeAudioCodecConfigMetadata codecMetadata =
+ new BluetoothLeAudioCodecConfigMetadata.Builder()
+ .setAudioLocation(TEST_AUDIO_LOCATION_FRONT_LEFT).build();
+ assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadata.getAudioLocation());
+ // TODO: Implement implicit LTV byte conversion in the API class
+ // assertArrayEquals(TEST_METADATA_BYTES, codecMetadata.getRawMetadata());
+ }
+
+ @Test
+ public void testCreateCodecConfigMetadataFromBytes() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothLeAudioCodecConfigMetadata codecMetadata =
+ BluetoothLeAudioCodecConfigMetadata.fromRawBytes(TEST_METADATA_BYTES);
+ byte[] metadataBytes = codecMetadata.getRawMetadata();
+ assertNotNull(metadataBytes);
+ assertArrayEquals(TEST_METADATA_BYTES, metadataBytes);
+ // TODO: Implement implicit LTV byte conversion in the API class
+ // assertEquals(TEST_AUDIO_LOCATION_FRONT_LEFT, codecMetadata.getAudioLocation());
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
new file mode 100644
index 0000000..6c32580
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeAudioContentMetadataTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeAudioContentMetadataTest {
+ // "Test" in UTF-8 is "54 65 73 74"
+ private static final String TEST_PROGRAM_INFO = "Test";
+ // German language code in ISO 639-3
+ // In byte it is ASCII, 0x64, 0x65, 0x75
+ private static final String TEST_LANGUAGE = "deu";
+ // See Page 6 of Generic Audio assigned number specification
+ private static final byte[] TEST_METADATA_BYTES = {
+ // length is 0x05, type is 0x03, data is "Test" in UTF-8 "54 65 73 74" hex
+ 0x05, 0x03, 0x54, 0x65, 0x73, 0x74,
+ // length is 0x04, type is 0x04, data is "deu" in ASCII "64 65 75" hex
+ 0x04, 0x04, 0x64, 0x65, 0x75
+ };
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsBroadcastSourceSupported;
+ private boolean mIsBroadcastAssistantSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
+ }
+
+ mIsBroadcastSourceSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (!mIsBroadcastSourceSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
+ @Test
+ public void testCreateCodecConfigMetadataFromBuilder() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothLeAudioContentMetadata contentMetadata =
+ new BluetoothLeAudioContentMetadata.Builder()
+ .setProgramInfo(TEST_PROGRAM_INFO).setLanguage(TEST_LANGUAGE).build();
+ assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
+ assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
+ // TODO: Implement implicit LTV byte conversion in the API class
+ // assertArrayEquals(TEST_METADATA_BYTES, contentMetadata.getRawMetadata());
+ }
+
+ @Test
+ public void testCreateCodecConfigMetadataFromBytes() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothLeAudioContentMetadata contentMetadata =
+ BluetoothLeAudioContentMetadata.fromRawBytes(TEST_METADATA_BYTES);
+ byte[] metadataBytes = contentMetadata.getRawMetadata();
+ assertNotNull(metadataBytes);
+ assertArrayEquals(TEST_METADATA_BYTES, metadataBytes);
+ // TODO: Implement implicit LTV byte conversion in the API class
+ // assertEquals(TEST_PROGRAM_INFO, contentMetadata.getProgramInfo());
+ // assertEquals(TEST_LANGUAGE, contentMetadata.getLanguage());
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
index 1118fd8..667aa52 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastAssistantTest.java
@@ -16,26 +16,29 @@
package android.bluetooth.cts;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastAssistant;
-import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.Build;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
@@ -44,7 +47,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
@@ -56,15 +61,13 @@
private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
- private static final String PROFILE_SUPPORTED_LE_BROADCAST_ASSISTANT = "profile_supported_bass";
- private static final int LE_AUDIO_PROFILE_CONSTANT = 22;
private Context mContext;
private boolean mHasBluetooth;
private BluetoothAdapter mAdapter;
private BluetoothLeBroadcastAssistant mBluetoothLeBroadcastAssistant;
- private boolean mIsLeBroadcastAssistantSupported;
+ private boolean mIsBroadcastAssistantSupported;
private boolean mIsProfileReady;
private Condition mConditionProfileIsConnected;
private ReentrantLock mProfileConnectedlock;
@@ -75,16 +78,12 @@
if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
return;
}
- mHasBluetooth = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_BLUETOOTH);
-
+ mHasBluetooth = TestUtils.hasBluetooth();
if (!mHasBluetooth) {
return;
}
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .adoptShellPermissionIdentity(android.Manifest.permission.BLUETOOTH_CONNECT);
- BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
- mAdapter = manager.getAdapter();
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
mProfileConnectedlock = new ReentrantLock();
@@ -92,22 +91,14 @@
mIsProfileReady = false;
mBluetoothLeBroadcastAssistant = null;
- Resources bluetoothResources = null;
- try {
- bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
- "com.android.bluetooth");
- } catch (PackageManager.NameNotFoundException e) {
- return;
- }
- int leBroadcastAssistantSupportId = bluetoothResources.getIdentifier(
- PROFILE_SUPPORTED_LE_BROADCAST_ASSISTANT, "bool", "com.android.bluetooth");
- if (leBroadcastAssistantSupportId == 0) {
- return;
- }
- mIsLeBroadcastAssistantSupported = bluetoothResources.getBoolean(
- leBroadcastAssistantSupportId);
- if (!mIsLeBroadcastAssistantSupported) {
- return;
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
}
mAdapter.getProfileProxy(mContext, new ServiceListener(),
@@ -125,15 +116,186 @@
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
- InstrumentationRegistry.getInstrumentation().getUiAutomation()
- .dropShellPermissionIdentity();
+ TestUtils.dropPermissionAsShellUid();
}
}
@Test
- public void testGetConnectedDevices() {
- if (!(mHasBluetooth && mIsLeBroadcastAssistantSupported)) return;
+ public void test_addSource() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+ // TODO When implemented
+ assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+ .addSource(null, null, true));
+
+ mBluetoothLeBroadcastAssistant.removeSource(null, 0);
+ }
+
+ @Test
+ public void test_getAllSources() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ // TODO When implemented
+
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ // Verify returns empty list if bluetooth is not enabled
+ assertTrue(mBluetoothLeBroadcastAssistant.getAllSources(null).isEmpty());
+ }
+
+ @Test
+ public void test_setConnectionPolicy() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ // TODO When implemented
+ assertFalse(mBluetoothLeBroadcastAssistant.setConnectionPolicy(null,
+ BluetoothProfile.CONNECTION_POLICY_FORBIDDEN));
+ assertEquals(mBluetoothLeBroadcastAssistant.getConnectionPolicy(null),
+ BluetoothProfile.CONNECTION_POLICY_FORBIDDEN);
+ }
+
+ @Test
+ public void test_getMaximumSourceCapacity() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ // TODO When implemented
+ assertEquals(mBluetoothLeBroadcastAssistant.getMaximumSourceCapacity(null), 0);
+ }
+
+ @Test
+ public void test_isSearchInProgress() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ // TODO When implemented
+ assertFalse(mBluetoothLeBroadcastAssistant.isSearchInProgress());
+ }
+
+ @Test
+ public void test_modifySource() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ // TODO When implemented
+ assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+ .modifySource(null, 0, null));
+ }
+
+ @Test
+ public void test_registerCallback() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ Executor executor = mContext.getMainExecutor();
+ BluetoothLeBroadcastAssistant.Callback callback =
+ new BluetoothLeBroadcastAssistant.Callback() {
+ @Override
+ public void onSearchStarted(int reason) {}
+ @Override
+ public void onSearchStartFailed(int reason) {}
+ @Override
+ public void onSearchStopped(int reason) {}
+ @Override
+ public void onSearchStopFailed(int reason) {}
+ @Override
+ public void onSourceFound(BluetoothLeBroadcastMetadata source) {}
+ @Override
+ public void onSourceAdded(BluetoothDevice sink, int sourceId, int reason) {}
+ @Override
+ public void onSourceAddFailed(BluetoothDevice sink,
+ BluetoothLeBroadcastMetadata source, int reason) {}
+ @Override
+ public void onSourceModified(BluetoothDevice sink, int sourceId, int reason) {}
+ @Override
+ public void onSourceModifyFailed(
+ BluetoothDevice sink, int sourceId, int reason) {}
+ @Override
+ public void onSourceRemoved(BluetoothDevice sink, int sourceId, int reason) {}
+ @Override
+ public void onSourceRemoveFailed(
+ BluetoothDevice sink, int sourceId, int reason) {}
+ @Override
+ public void onReceiveStateChanged(BluetoothDevice sink, int sourceId,
+ BluetoothLeBroadcastReceiveState state) {}
+ };
+ // empty calls to callback override
+ callback.onSearchStarted(0);
+ callback.onSearchStartFailed(0);
+ callback.onSearchStopped(0);
+ callback.onSearchStopFailed(0);
+ callback.onSourceFound(null);
+ callback.onSourceAdded(null, 0, 0);
+ callback.onSourceAddFailed(null, null, 0);
+ callback.onSourceModified(null, 0, 0);
+ callback.onSourceModifyFailed(null, 0, 0);
+ callback.onSourceRemoved(null, 0, 0);
+ callback.onSourceRemoveFailed(null, 0, 0);
+ callback.onReceiveStateChanged(null, 0, null);
+
+ // Verify parameter
+ assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+ .registerCallback(null, callback));
+ assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+ .registerCallback(executor, null));
+ assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+ .unregisterCallback(null));
+
+
+ // TODO When implemented
+ assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+ .registerCallback(executor, callback));
+ assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+ .unregisterCallback(callback));
+ }
+
+ @Test
+ public void test_startSearchingForSources() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ assertTrue(waitForProfileConnect());
+ assertNotNull(mBluetoothLeBroadcastAssistant);
+
+ // Verify parameter
+ assertThrows(IllegalArgumentException.class, () -> mBluetoothLeBroadcastAssistant
+ .startSearchingForSources(null));
+
+ // TODO When implemented
+ assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+ .startSearchingForSources(new ArrayList<>()));
+ assertThrows(UnsupportedOperationException.class, () -> mBluetoothLeBroadcastAssistant
+ .stopSearchingForSources());
+ }
+
+ @Test
+ public void testGetConnectedDevices() {
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothLeBroadcastAssistant);
@@ -147,8 +309,9 @@
@Test
public void testGetDevicesMatchingConnectionStates() {
- if (!(mHasBluetooth && mIsLeBroadcastAssistantSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothLeBroadcastAssistant);
@@ -162,7 +325,9 @@
@Test
public void testGetConnectionState() {
- if (!(mHasBluetooth && mIsLeBroadcastAssistantSupported)) return;
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothLeBroadcastAssistant);
@@ -187,10 +352,14 @@
}
if (mAdapter.isLeAudioBroadcastAssistantSupported()
== BluetoothStatusCodes.FEATURE_NOT_SUPPORTED) {
- assertFalse(mIsLeBroadcastAssistantSupported);
+ assertFalse(mIsBroadcastAssistantSupported);
return;
}
- assertTrue(mIsLeBroadcastAssistantSupported);
+ assertTrue(mIsBroadcastAssistantSupported);
+ }
+
+ private boolean shouldSkipTest() {
+ return !(mHasBluetooth && mIsBroadcastAssistantSupported);
}
private boolean waitForProfileConnect() {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
new file mode 100644
index 0000000..7390b82
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastChannelTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeBroadcastChannel;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeBroadcastChannelTest {
+ private static final int TEST_CHANNEL_INDEX = 42;
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsBroadcastSourceSupported;
+ private boolean mIsBroadcastAssistantSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
+ }
+
+ mIsBroadcastSourceSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (!mIsBroadcastSourceSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
+ @Test
+ public void testCreateBroadcastChannelFromBuilder() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothLeBroadcastChannel channel =
+ new BluetoothLeBroadcastChannel.Builder()
+ .setSelected(true)
+ .setChannelIndex(TEST_CHANNEL_INDEX)
+ .setCodecMetadata(null)
+ .build();
+ assertTrue(channel.isSelected());
+ assertEquals(TEST_CHANNEL_INDEX, channel.getChannelIndex());
+ assertNull(channel.getCodecMetadata());
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
index c03ad8e..5651320 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastMetadataTest.java
@@ -16,30 +16,116 @@
package android.bluetooth.cts;
-import static org.junit.Assert.assertEquals;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcastMetadata;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class BluetoothLeBroadcastMetadataTest {
+ private static final String TEST_MAC_ADDRESS = "00:11:22:33:44:55";
+ private static final int TEST_BROADCAST_ID = 42;
+ private static final int TEST_ADVERTISER_SID = 1234;
+ private static final int TEST_PA_SYNC_INTERVAL = 100;
+ private static final int TEST_PRESENTATION_DELAY_MS = 345;
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsBroadcastSourceSupported;
+ private boolean mIsBroadcastAssistantSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
+ }
+
+ mIsBroadcastSourceSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (!mIsBroadcastSourceSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
@Test
public void testCreateMetadataFromBuilder() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothDevice testDevice =
+ mAdapter.getRemoteLeDevice(TEST_MAC_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM);
BluetoothLeBroadcastMetadata.Builder builder = new BluetoothLeBroadcastMetadata.Builder();
BluetoothLeBroadcastMetadata metadata =
- builder.setEncrypted(false).setBroadcastCode(null)
- .setPaSyncInterval(1)
- .setPresentationDelayMicros(2)
- .setBroadcastId(3)
+ builder.setEncrypted(false)
+ .setSourceDevice(testDevice, BluetoothDevice.ADDRESS_TYPE_RANDOM)
+ .setSourceAdvertisingSid(TEST_ADVERTISER_SID)
+ .setBroadcastId(TEST_BROADCAST_ID)
+ .setBroadcastCode(null)
+ .setPaSyncInterval(TEST_PA_SYNC_INTERVAL)
+ .setPresentationDelayMicros(TEST_PRESENTATION_DELAY_MS)
.build();
- assertEquals(1, metadata.getPaSyncInterval());
- assertEquals(2, metadata.getPresentationDelayMicros());
- assertEquals(3, metadata.getBroadcastId());
+ assertEquals(testDevice, metadata.getSourceDevice());
+ assertEquals(BluetoothDevice.ADDRESS_TYPE_RANDOM, metadata.getSourceAddressType());
+ assertEquals(TEST_BROADCAST_ID, metadata.getBroadcastId());
+ assertNull(metadata.getBroadcastCode());
+ assertEquals(TEST_PA_SYNC_INTERVAL, metadata.getPaSyncInterval());
+ assertEquals(TEST_PRESENTATION_DELAY_MS, metadata.getPresentationDelayMicros());
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
}
}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
new file mode 100644
index 0000000..cc28740
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastReceiveStateTest.java
@@ -0,0 +1,180 @@
+/*
+ * 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.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothLeAudioContentMetadata;
+import android.bluetooth.BluetoothLeBroadcastReceiveState;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+import android.os.Parcel;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeBroadcastReceiveStateTest {
+ private static final int TEST_SOURCE_ID = 42;
+ private static final int TEST_SOURCE_ADDRESS_TYPE = BluetoothDevice.ADDRESS_TYPE_RANDOM;
+ private static final String TEST_MAC_ADDRESS = "00:11:22:33:44:55";
+ private static final int TEST_ADVERTISER_SID = 1234;
+ private static final int TEST_BROADCAST_ID = 45;
+ private static final int TEST_PA_SYNC_STATE =
+ BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED;
+ private static final int TEST_BIG_ENCRYPTION_STATE =
+ BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED;
+ private static final int TEST_NUM_SUBGROUPS = 1;
+ private static final Long[] TEST_BIS_SYNC_STATE = {1L};
+ private static final BluetoothLeAudioContentMetadata[] TEST_SUBGROUP_METADATA = {null};
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsBroadcastSourceSupported;
+ private boolean mIsBroadcastAssistantSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
+ }
+
+ mIsBroadcastSourceSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (!mIsBroadcastSourceSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
+ @Test
+ public void testCreateBroadcastReceiveState() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothDevice testDevice =
+ mAdapter.getRemoteLeDevice(TEST_MAC_ADDRESS, TEST_SOURCE_ADDRESS_TYPE);
+ BluetoothLeBroadcastReceiveState state = createBroadcastReceiveStateForTest(
+ TEST_SOURCE_ID,
+ TEST_SOURCE_ADDRESS_TYPE,
+ testDevice,
+ TEST_ADVERTISER_SID,
+ TEST_BROADCAST_ID,
+ TEST_PA_SYNC_STATE,
+ TEST_BIG_ENCRYPTION_STATE,
+ null /* badCode */,
+ TEST_NUM_SUBGROUPS,
+ Arrays.asList(TEST_BIS_SYNC_STATE),
+ Arrays.asList(TEST_SUBGROUP_METADATA));
+ assertEquals(TEST_SOURCE_ID, state.getSourceId());
+ assertEquals(TEST_SOURCE_ADDRESS_TYPE, state.getSourceAddressType());
+ assertEquals(testDevice, state.getSourceDevice());
+ assertEquals(TEST_ADVERTISER_SID, state.getSourceAdvertisingSid());
+ assertEquals(TEST_BROADCAST_ID, state.getBroadcastId());
+ assertEquals(TEST_PA_SYNC_STATE, state.getPaSyncState());
+ assertEquals(TEST_BIG_ENCRYPTION_STATE, state.getBigEncryptionState());
+ assertNull(state.getBadCode());
+ assertEquals(TEST_NUM_SUBGROUPS, state.getNumSubgroups());
+ assertArrayEquals(TEST_BIS_SYNC_STATE, state.getBisSyncState().toArray(new Long[0]));
+ assertArrayEquals(TEST_SUBGROUP_METADATA,
+ state.getSubgroupMetadata().toArray(new BluetoothLeAudioContentMetadata[0]));
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+ }
+
+ static BluetoothLeBroadcastReceiveState createBroadcastReceiveStateForTest(
+ int sourceId, int sourceAddressType,
+ BluetoothDevice sourceDevice, int sourceAdvertisingSid, int broadcastId,
+ int paSyncState, int bigEncryptionState, byte[] badCode, int numSubgroups,
+ List<Long> bisSyncState,
+ List<BluetoothLeAudioContentMetadata> subgroupMetadata) {
+ Parcel out = Parcel.obtain();
+ out.writeInt(sourceId);
+ out.writeInt(sourceAddressType);
+ out.writeTypedObject(sourceDevice, 0);
+ out.writeInt(sourceAdvertisingSid);
+ out.writeInt(broadcastId);
+ out.writeInt(paSyncState);
+ out.writeInt(bigEncryptionState);
+
+ if (badCode != null) {
+ out.writeInt(badCode.length);
+ out.writeByteArray(badCode);
+ } else {
+ // -1 indicates that there is no "bad broadcast code"
+ out.writeInt(-1);
+ }
+ out.writeInt(numSubgroups);
+ out.writeList(bisSyncState);
+ out.writeTypedList(subgroupMetadata);
+ return BluetoothLeBroadcastReceiveState.CREATOR.createFromParcel(out);
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
new file mode 100644
index 0000000..3ad73c7
--- /dev/null
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastSubgroupTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.bluetooth.cts;
+
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothLeBroadcastChannel;
+import android.bluetooth.BluetoothLeBroadcastSubgroup;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.ApiLevelUtil;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class BluetoothLeBroadcastSubgroupTest {
+ private static final int TEST_CODEC_ID = 42;
+ private static final BluetoothLeBroadcastChannel[] TEST_CHANNELS = {null};
+
+ private Context mContext;
+ private boolean mHasBluetooth;
+ private BluetoothAdapter mAdapter;
+ private boolean mIsBroadcastSourceSupported;
+ private boolean mIsBroadcastAssistantSupported;
+
+ @Before
+ public void setUp() {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
+ return;
+ }
+ mHasBluetooth = TestUtils.hasBluetooth();
+ if (!mHasBluetooth) {
+ return;
+ }
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
+ assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
+
+ mIsBroadcastAssistantSupported =
+ mAdapter.isLeAudioBroadcastAssistantSupported() == FEATURE_SUPPORTED;
+ if (mIsBroadcastAssistantSupported) {
+ boolean isBroadcastAssistantEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastAssistantEnabledInConfig);
+ }
+
+ mIsBroadcastSourceSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (!mIsBroadcastSourceSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(
+ BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
+ }
+ }
+
+ @After
+ public void tearDown() {
+ if (mHasBluetooth) {
+ assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
+ mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
+ }
+ }
+
+ @Test
+ public void testCreateBroadcastSubgroupFromBuilder() {
+ if (shouldSkipTest()) {
+ return;
+ }
+ BluetoothLeBroadcastSubgroup.Builder builder = new BluetoothLeBroadcastSubgroup.Builder()
+ .setCodecId(TEST_CODEC_ID)
+ .setCodecSpecificConfig(null)
+ .setContentMetadata(null)
+ .setNoChannelPreference(true);
+ for (BluetoothLeBroadcastChannel channel : TEST_CHANNELS) {
+ builder.addChannel(channel);
+ }
+ BluetoothLeBroadcastSubgroup subgroup = builder.build();
+ assertEquals(TEST_CODEC_ID, subgroup.getCodecId());
+ assertArrayEquals(TEST_CHANNELS,
+ subgroup.getChannels().toArray(new BluetoothLeBroadcastChannel[0]));
+ }
+
+ private boolean shouldSkipTest() {
+ return !mHasBluetooth || (!mIsBroadcastSourceSupported && !mIsBroadcastAssistantSupported);
+ }
+}
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
index 1ad8e3b..d73f721 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BluetoothLeBroadcastTest.java
@@ -16,6 +16,9 @@
package android.bluetooth.cts;
+import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -24,12 +27,9 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothLeBroadcast;
-import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
import android.os.Build;
import android.util.Log;
@@ -73,14 +73,12 @@
if (!ApiLevelUtil.isAtLeast(Build.VERSION_CODES.TIRAMISU)) {
return;
}
- mHasBluetooth = mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_BLUETOOTH);
-
+ mHasBluetooth = TestUtils.hasBluetooth();
if (!mHasBluetooth) {
return;
}
- BluetoothManager manager = mContext.getSystemService(BluetoothManager.class);
- mAdapter = manager.getAdapter();
+ TestUtils.adoptPermissionAsShellUid(BLUETOOTH_CONNECT);
+ mAdapter = TestUtils.getBluetoothAdapterOrDie();
assertTrue(BTAdapterUtils.enableAdapter(mAdapter, mContext));
mProfileConnectedlock = new ReentrantLock();
@@ -88,20 +86,14 @@
mIsProfileReady = false;
mBluetoothLeBroadcast = null;
- Resources bluetoothResources = null;
- try {
- bluetoothResources = mContext.getPackageManager().getResourcesForApplication(
- "com.android.bluetooth");
- } catch (PackageManager.NameNotFoundException e) {
- return;
+ mIsLeBroadcastSupported =
+ mAdapter.isLeAudioBroadcastSourceSupported() == FEATURE_SUPPORTED;
+ if (mIsLeBroadcastSupported) {
+ boolean isBroadcastSourceEnabledInConfig =
+ TestUtils.getProfileConfigValueOrDie(BluetoothProfile.LE_AUDIO_BROADCAST);
+ assertTrue("Config must be true when profile is supported",
+ isBroadcastSourceEnabledInConfig);
}
- int leBroadcastSupportId = bluetoothResources.getIdentifier(
- PROFILE_SUPPORTED_LE_BROADCAST, "bool", "com.android.bluetooth");
- if (leBroadcastSupportId == 0) {
- return;
- }
- mIsLeBroadcastSupported = bluetoothResources.getBoolean(
- leBroadcastSupportId);
if (!mIsLeBroadcastSupported) {
return;
}
@@ -121,13 +113,15 @@
}
assertTrue(BTAdapterUtils.disableAdapter(mAdapter, mContext));
mAdapter = null;
+ TestUtils.dropPermissionAsShellUid();
}
}
@Test
public void testGetConnectedDevices() {
- if (!(mHasBluetooth && mIsLeBroadcastSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothLeBroadcast);
@@ -140,8 +134,9 @@
@Test
public void testGetDevicesMatchingConnectionStates() {
- if (!(mHasBluetooth && mIsLeBroadcastSupported)) return;
-
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothLeBroadcast);
@@ -155,7 +150,9 @@
@Test
public void testGetConnectionState() {
- if (!(mHasBluetooth && mIsLeBroadcastSupported)) return;
+ if (shouldSkipTest()) {
+ return;
+ }
assertTrue(waitForProfileConnect());
assertNotNull(mBluetoothLeBroadcast);
@@ -186,6 +183,10 @@
assertTrue(mIsLeBroadcastSupported);
}
+ private boolean shouldSkipTest() {
+ return !(mHasBluetooth && mIsLeBroadcastSupported);
+ }
+
private boolean waitForProfileConnect() {
mProfileConnectedlock.lock();
try {
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java b/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java
index 7c4c454..6da32e3 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/TestUtils.java
@@ -16,30 +16,168 @@
package android.bluetooth.cts;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.ScanRecord;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.provider.Settings;
import android.util.Log;
+import androidx.test.platform.app.InstrumentationRegistry;
+
import junit.framework.Assert;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.ReentrantLock;
/**
* Utility class for Bluetooth CTS test.
*/
class TestUtils {
/**
+ * Bluetooth package name
+ */
+ static final String BLUETOOTH_PACKAGE_NAME = "com.android.bluetooth";
+
+ /**
+ * Get the Config.xml name tag for a particular Bluetooth profile
+ * @param profile profile id from {@link BluetoothProfile}
+ * @return config name tag, or null if the tag name is not available
+ */
+ @Nullable static String profileIdToConfigTag(int profile) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ return "profile_supported_a2dp";
+ case BluetoothProfile.A2DP_SINK:
+ return "profile_supported_a2dp_sink";
+ case BluetoothProfile.HEADSET:
+ return "profile_supported_hs_hfp";
+ case BluetoothProfile.HEADSET_CLIENT:
+ return "profile_supported_hfpclient";
+ case BluetoothProfile.HID_HOST:
+ return "profile_supported_hid_host";
+ case BluetoothProfile.OPP:
+ return "profile_supported_opp";
+ case BluetoothProfile.PAN:
+ return "profile_supported_pan";
+ case BluetoothProfile.PBAP:
+ return "profile_supported_pbap";
+ case BluetoothProfile.GATT:
+ return "profile_supported_gatt";
+ case BluetoothProfile.MAP:
+ return "profile_supported_map";
+ // Hidden profile
+ // case BluetoothProfile.AVRCP:
+ // return "profile_supported_avrcp_target";
+ case BluetoothProfile.AVRCP_CONTROLLER:
+ return "profile_supported_avrcp_controller";
+ case BluetoothProfile.SAP:
+ return "profile_supported_sap";
+ case BluetoothProfile.PBAP_CLIENT:
+ return "profile_supported_pbapclient";
+ case BluetoothProfile.MAP_CLIENT:
+ return "profile_supported_mapmce";
+ case BluetoothProfile.HID_DEVICE:
+ return "profile_supported_hid_device";
+ case BluetoothProfile.LE_AUDIO:
+ return "profile_supported_le_audio";
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ return "profile_supported_le_audio_broadcast";
+ case BluetoothProfile.VOLUME_CONTROL:
+ return "profile_supported_vc";
+ // Hidden profile
+ // case BluetoothProfile.MCP_SERVER:
+ // return "profile_supported_mcp_server";
+ case BluetoothProfile.CSIP_SET_COORDINATOR:
+ return "profile_supported_csip_set_coordinator";
+ // Hidden profile
+ // case BluetoothProfile.LE_CALL_CONTROL:
+ // return "profile_supported_le_call_control";
+ case BluetoothProfile.HAP_CLIENT:
+ return "profile_supported_hap_client";
+ case BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT:
+ return "profile_supported_bass_client";
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Checks if a particular Bluetooth profile is configured for this device
+ * Fail the test if profile config status cannot be obtained
+ */
+ static boolean getProfileConfigValueOrDie(int profile) {
+ String profileConfigValueTag = profileIdToConfigTag(profile);
+ assertNotNull(profileConfigValueTag);
+ assertNotEquals("profile tag cannot be empty", 0, profileConfigValueTag.length());
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ Resources bluetoothResources = null;
+ try {
+ bluetoothResources = context.getPackageManager().getResourcesForApplication(
+ BLUETOOTH_PACKAGE_NAME);
+ } catch (PackageManager.NameNotFoundException e) {
+ fail("Cannot get Bluetooth package resource");
+ }
+ int resourceId = bluetoothResources.getIdentifier(
+ profileConfigValueTag, "bool", BLUETOOTH_PACKAGE_NAME);
+ if (resourceId == 0) {
+ return false;
+ }
+ return bluetoothResources.getBoolean(resourceId);
+ }
+
+ /**
+ * Checks whether this device has Bluetooth feature
+ * @return true if this device has Bluetooth feature
+ */
+ static boolean hasBluetooth() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ return context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_BLUETOOTH);
+ }
+
+ /**
+ * Adopt shell UID's permission via {@link android.app.UiAutomation}
+ * @param permission permission to adopt
+ */
+ static void adoptPermissionAsShellUid(@NonNull String permission) {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .adoptShellPermissionIdentity(permission);
+ }
+
+ /**
+ * Drop all permissions adopted as shell UID
+ */
+ static void dropPermissionAsShellUid() {
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ .dropShellPermissionIdentity();
+ }
+
+ /**
+ * Get {@link BluetoothAdapter} via {@link android.bluetooth.BluetoothManager}
+ * Fail the test if {@link BluetoothAdapter} is null
+ * @return instance of {@link BluetoothAdapter}
+ */
+ @NonNull static BluetoothAdapter getBluetoothAdapterOrDie() {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ BluetoothManager manager = context.getSystemService(BluetoothManager.class);
+ assertNotNull(manager);
+ BluetoothAdapter adapter = manager.getAdapter();
+ assertNotNull(adapter);
+ return adapter;
+ }
+
+ /**
* Utility method to call hidden ScanRecord.parseFromBytes method.
*/
static ScanRecord parseScanRecord(byte[] bytes) {
diff --git a/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java b/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
index 6c706be..0b744d8 100644
--- a/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
+++ b/tests/tests/car/src/android/car/cts/CarServiceHelperServiceUpdatableTest.java
@@ -35,6 +35,7 @@
import android.os.UserManager;
import android.util.Log;
+import androidx.test.filters.FlakyTest;
import androidx.test.InstrumentationRegistry;
import com.android.compatibility.common.util.SystemUtil;
@@ -99,6 +100,7 @@
.contains("dumpServiceStacks ANR file path=/data/anr/anr_");
}
+ @FlakyTest(bugId = 222167696)
@Test
public void testSendUserLifecycleEventAndOnUserRemoved() throws Exception {
// Add listener to check if user started
@@ -129,7 +131,9 @@
// check the dump stack
assertLastUserRemoved(userId);
} finally {
- if (!userRemoved) userManager.removeUser(response.getUser());
+ if (!userRemoved && response != null && response.isSuccessful()) {
+ userManager.removeUser(response.getUser());
+ }
carUserManager.removeListener(listener);
InstrumentationRegistry.getInstrumentation().getUiAutomation()
.dropShellPermissionIdentity();
diff --git a/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java b/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
index d0d9b04..0c62806 100644
--- a/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarTelemetryManagerTest.java
@@ -48,7 +48,7 @@
@RunWith(AndroidJUnit4.class)
public class CarTelemetryManagerTest extends CarApiTestBase {
- /* Test MetricsConfig that does nothing. */
+ /** Test MetricsConfig that does nothing. */
private static final TelemetryProto.MetricsConfig TEST_CONFIG =
TelemetryProto.MetricsConfig.newBuilder()
.setName("test_config")
@@ -57,7 +57,7 @@
.build();
private static final String TEST_CONFIG_NAME = TEST_CONFIG.getName();
- /* MetricsConfig with simple script that listens for parking brake change. */
+ /** MetricsConfig with simple script that listens for parking brake change. */
private static final String PARKING_BRAKE_CHANGE_SCRIPT = new StringBuilder()
.append("function onParkingBrakeChange(published_data, saved_state)\n")
.append(" result = {data = \"Hello World!\"}\n")
@@ -86,7 +86,7 @@
.build();
private static final String PARKING_BRAKE_CONFIG_NAME = PARKING_BRAKE_CONFIG.getName();
- /*
+ /**
* MetricsConfig with a bad script that listens for parking brake change, will produce error.
*/
private static final TelemetryProto.MetricsConfig ERROR_CONFIG =
diff --git a/tests/tests/car_builtin/AndroidManifest.xml b/tests/tests/car_builtin/AndroidManifest.xml
index ef09db3..d86153d 100644
--- a/tests/tests/car_builtin/AndroidManifest.xml
+++ b/tests/tests/car_builtin/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="android.car.cts.builtin">
<uses-feature android:name="android.hardware.type.automotive" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
<application android:description="@string/app_description">
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
index f5012b5..bc3fc04 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/app/ActivityManagerHelperTest.java
@@ -43,11 +43,6 @@
private static final int OWNING_UID = -1;
@Test
- public void testGetInstance() throws Exception {
- assertThat(ActivityManagerHelper.getInstance()).isNotNull();
- }
-
- @Test
public void testCheckComponentPermission() throws Exception {
// not requested from Manifest
assertComponentPermissionNotGranted(NOT_REQUESTED_PERMISSION_CAR_MILEAGE);
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
index 42e5968..2c2e3f1 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/content/pm/PackageManagerHelperTest.java
@@ -16,7 +16,10 @@
package android.car.cts.builtin.content.pm;
+import static android.car.builtin.content.pm.PackageManagerHelper.PROPERTY_CAR_SERVICE_PACKAGE_NAME;
+
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import android.car.builtin.content.pm.PackageManagerHelper;
import android.car.cts.builtin.R;
@@ -26,6 +29,7 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
+import android.os.SystemProperties;
import android.os.UserHandle;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -119,6 +123,21 @@
// builtin API
}
+ @Test
+ public void testCarServicePackageName() throws Exception {
+ // The property must exist.
+ String packageName = SystemProperties.get(
+ PROPERTY_CAR_SERVICE_PACKAGE_NAME, /* def= */null);
+
+ assertWithMessage("Property %s not defined", PROPERTY_CAR_SERVICE_PACKAGE_NAME).that(
+ packageName).isNotNull();
+
+ // The package must exist.
+ PackageInfo info = mPackageManager.getPackageInfo(packageName, /* flags= */ 0);
+
+ assertWithMessage("Package %s not found", packageName).that(info).isNotNull();
+ }
+
private boolean hasActivity(String activityName, ActivityInfo[] activities) {
return Arrays.stream(activities).anyMatch(a -> activityName.equals(a.name));
}
diff --git a/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java b/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java
index af5a0a2..9217465 100644
--- a/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java
+++ b/tests/tests/car_builtin/src/android/car/cts/builtin/power/PowerManagerHelperTest.java
@@ -38,20 +38,20 @@
public void testSetDisplayState() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
Context context = instrumentation.getContext();
- PowerManagerHelper helper = new PowerManagerHelper(context);
PowerManager powerManager = context.getSystemService(PowerManager.class);
UiAutomation uiAutomation = instrumentation.getUiAutomation();
uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.DEVICE_POWER);
try {
- helper.setDisplayState(/* on= */ true, SystemClock.uptimeMillis());
+ PowerManagerHelper.setDisplayState(context, /* on= */ true, SystemClock.uptimeMillis());
assertWithMessage("Screen on").that(powerManager.isInteractive()).isTrue();
- helper.setDisplayState(/* on= */ false, SystemClock.uptimeMillis());
+ PowerManagerHelper.setDisplayState(context, /* on= */ false,
+ SystemClock.uptimeMillis());
assertWithMessage("Screen on").that(powerManager.isInteractive()).isFalse();
- helper.setDisplayState(/* on= */ true, SystemClock.uptimeMillis());
+ PowerManagerHelper.setDisplayState(context, /* on= */ true, SystemClock.uptimeMillis());
assertWithMessage("Screen on").that(powerManager.isInteractive()).isTrue();
} finally {
uiAutomation.dropShellPermissionIdentity();
diff --git a/tests/tests/companion/Android.bp b/tests/tests/companion/Android.bp
index 22a45e8..6d465ce 100644
--- a/tests/tests/companion/Android.bp
+++ b/tests/tests/companion/Android.bp
@@ -76,6 +76,38 @@
}
android_test {
+ name: "CtsCompanionDeviceManagerNoCompanionServicesTestCases",
+ srcs: [
+ "noservices/src/**/*.kt",
+ ],
+ manifest: "noservices/AndroidManifest.xml",
+ test_config: "noservices/AndroidTest.xml",
+
+ platform_apis: true,
+ static_libs: [
+ "androidx.test.ext.junit",
+ "cts-companion-common",
+ "junit",
+ "kotlin-test",
+ ],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ ],
+
+ defaults: ["cts_defaults"],
+ // Tag this module as a cts test artifact
+ test_suites: [
+ "cts",
+ "general-tests",
+ ],
+
+ // TODO(b/211264986) Change both SDK versions to T (33) once it's formally defined.
+ min_sdk_version: "current",
+ target_sdk_version: "current",
+}
+
+android_test {
name: "CtsCompanionDeviceManagerUiAutomationTestCases",
srcs: [
"uiautomation/src/**/*.kt",
diff --git a/tests/tests/companion/common/AndroidManifest.xml b/tests/tests/companion/common/AndroidManifest.xml
index bf91897..febd8a0 100644
--- a/tests/tests/companion/common/AndroidManifest.xml
+++ b/tests/tests/companion/common/AndroidManifest.xml
@@ -34,7 +34,6 @@
<property android:name="android.companion.PROPERTY_PRIMARY_COMPANION_DEVICE_SERVICE"
android:value="true" />
-
</service>
<service
@@ -47,6 +46,26 @@
</intent-filter>
</service>
+ <!-- Service does not require BIND_COMPANION_DEVICE_SERVICE -->
+ <service
+ android:name=".MissingPermissionCompanionService"
+ android:exported="true"
+ android:label="Secondary Companion Service">
+ <intent-filter>
+ <action android:name="android.companion.CompanionDeviceService" />
+ </intent-filter>
+ </service>
+
+ <!--
+ Service does not declare an intent-filter for "android.companion.CompanionDeviceService"
+ action
+ -->
+ <service
+ android:name=".MissingIntentFilterActionCompanionService"
+ android:exported="true"
+ android:label="Primary Companion Service"
+ android:permission="android.permission.BIND_COMPANION_DEVICE_SERVICE"/>
+
<activity
android:name=".CompanionActivity"
android:exported="false"
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt b/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
index 4c16478..4d09333 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/CompanionService.kt
@@ -135,4 +135,14 @@
class SecondaryCompanionService : CompanionService<SecondaryCompanionService>(Companion) {
companion object : InstanceHolder<SecondaryCompanionService>()
+}
+
+class MissingPermissionCompanionService
+ : CompanionService<MissingPermissionCompanionService>(Companion) {
+ companion object : InstanceHolder<MissingPermissionCompanionService>()
+}
+
+class MissingIntentFilterActionCompanionService
+ : CompanionService<MissingIntentFilterActionCompanionService>(Companion) {
+ companion object : InstanceHolder<MissingIntentFilterActionCompanionService>()
}
\ No newline at end of file
diff --git a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
index 812238d..b650324 100644
--- a/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
+++ b/tests/tests/companion/common/src/android/companion/cts/common/TestBase.kt
@@ -16,10 +16,12 @@
package android.companion.cts.common
+import android.Manifest
import android.annotation.CallSuper
import android.app.Instrumentation
import android.app.UiAutomation
import android.companion.AssociationInfo
+import android.companion.AssociationRequest
import android.companion.CompanionDeviceManager
import android.content.Context
import android.content.pm.PackageManager
@@ -36,6 +38,7 @@
import java.io.IOException
import kotlin.test.assertEquals
import kotlin.test.assertFalse
+import kotlin.test.assertIs
import kotlin.test.assertTrue
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
@@ -112,6 +115,23 @@
}
}
+ protected fun createSelfManagedAssociation(displayName: String): Int {
+ val callback = RecordingCallback()
+ val request: AssociationRequest = AssociationRequest.Builder()
+ .setSelfManaged(true)
+ .setDisplayName(displayName)
+ .build()
+ callback.assertInvokedByActions {
+ withShellPermissionIdentity(Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) {
+ cdm.associate(request, SIMPLE_EXECUTOR, callback)
+ }
+ }
+
+ val callbackInvocation = callback.invocations.first()
+ assertIs<RecordingCallback.OnAssociationCreated>(callbackInvocation)
+ return callbackInvocation.associationInfo.id
+ }
+
private fun CompanionDeviceManager.disassociateAll() =
allAssociations.forEach { disassociate(it.id) }
}
diff --git a/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt b/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
index 15202bd..54cc1e6 100644
--- a/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
+++ b/tests/tests/companion/core/src/android/companion/cts/core/SelfPresenceReportingTest.kt
@@ -17,14 +17,12 @@
package android.companion.cts.core
import android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED
-import android.companion.AssociationRequest
import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
import android.companion.cts.common.DEVICE_DISPLAY_NAME_B
import android.companion.cts.common.MAC_ADDRESS_A
+import android.companion.cts.common.MissingIntentFilterActionCompanionService
+import android.companion.cts.common.MissingPermissionCompanionService
import android.companion.cts.common.PrimaryCompanionService
-import android.companion.cts.common.RecordingCallback
-import android.companion.cts.common.RecordingCallback.OnAssociationCreated
-import android.companion.cts.common.SIMPLE_EXECUTOR
import android.companion.cts.common.SecondaryCompanionService
import android.companion.cts.common.assertEmpty
import android.companion.cts.common.waitFor
@@ -36,7 +34,6 @@
import kotlin.test.assertContentEquals
import kotlin.test.assertFailsWith
import kotlin.test.assertFalse
-import kotlin.test.assertIs
import kotlin.test.assertTrue
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@@ -63,23 +60,35 @@
cdm.notifyDeviceAppeared(associationId)
- assertTrue("Both Services - Primary and Secondary - should be bound now") {
+ assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
+ "now") {
waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
}
}
+ assertFalse("CompanionDeviceServices that do not require " +
+ "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
+ "\"android.companion.CompanionDeviceService\" action should not be bound") {
+ MissingPermissionCompanionService.isBound ||
+ MissingIntentFilterActionCompanionService.isBound
+ }
- // Check that only the primary services has received the onDeviceAppeared() callback...
+ // Check that only the primary CompanionDeviceService has received the onDeviceAppeared()
+ // callback...
PrimaryCompanionService.waitAssociationToAppear(associationId)
assertContentEquals(
actual = PrimaryCompanionService.associationIdsForConnectedDevices,
expected = setOf(associationId)
)
- // ... while the non-primary service - has NOT. (Give it 1 more second.)
+ // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
+ // have NOT. (Give it 1 more second.)
sleep(1000)
assertEmpty(SecondaryCompanionService.connectedDevices)
+ assertEmpty(MissingPermissionCompanionService.connectedDevices)
+ assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
- assertFalse("Both Services - Primary and Secondary - should stay bound") {
+ assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
+ "bound ") {
waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
!PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
}
@@ -105,11 +114,18 @@
cdm.notifyDeviceAppeared(idA)
- assertTrue("Both Services - Primary and Secondary - should be bound now") {
+ assertTrue("Both valid CompanionDeviceServices - Primary and Secondary - should be bound " +
+ "now") {
waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
PrimaryCompanionService.isBound && SecondaryCompanionService.isBound
}
}
+ assertFalse("CompanionDeviceServices that do not require " +
+ "BIND_COMPANION_DEVICE_SERVICE permission or do not declare an intent-filter for " +
+ "\"android.companion.CompanionDeviceService\" action should not be bound") {
+ MissingPermissionCompanionService.isBound ||
+ MissingIntentFilterActionCompanionService.isBound
+ }
// Check that only the primary services has received the onDeviceAppeared() callback...
PrimaryCompanionService.waitAssociationToAppear(idA)
@@ -117,9 +133,12 @@
actual = PrimaryCompanionService.associationIdsForConnectedDevices,
expected = setOf(idA)
)
- // ... while the non-primary service - has NOT. (Give it 1 more second.)
+ // ... while neither the non-primary nor incorrectly defined CompanionDeviceServices -
+ // have NOT. (Give it 1 more second.)
sleep(1000)
assertEmpty(SecondaryCompanionService.connectedDevices)
+ assertEmpty(MissingPermissionCompanionService.connectedDevices)
+ assertEmpty(MissingIntentFilterActionCompanionService.connectedDevices)
cdm.notifyDeviceAppeared(idB)
@@ -130,8 +149,9 @@
expected = setOf(idA, idB)
)
- // Make sure both services stay bound.
- assertFalse("Both Services - Primary and Secondary - should stay bound") {
+ // Make sure both valid services stay bound.
+ assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
+ "bound ") {
waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
!PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
}
@@ -141,10 +161,11 @@
cdm.notifyDeviceDisappeared(idA)
PrimaryCompanionService.waitAssociationToDisappear(idA)
- // Both services should stay bound for as long as there is at least
- // one connected device - device B in this case.
- assertFalse("Both Services - Primary and Secondary - should stay bound") {
- waitFor(timeout = 3.seconds, interval = 1.seconds) {
+ // Both valid services should stay bound for as long as there is at least one connected
+ // device - device B in this case.
+ assertFalse("Both valid CompanionDeviceServices - Primary and Secondary - should stay " +
+ "bound ") {
+ waitFor(timeout = 3.seconds, interval = 1.milliseconds) {
!PrimaryCompanionService.isBound || !SecondaryCompanionService.isBound
}
}
@@ -183,21 +204,4 @@
cdm.notifyDeviceAppeared(id)
}
}
-
- private fun createSelfManagedAssociation(displayName: String): Int {
- val callback = RecordingCallback()
- val request: AssociationRequest = AssociationRequest.Builder()
- .setSelfManaged(true)
- .setDisplayName(displayName)
- .build()
- callback.assertInvokedByActions {
- withShellPermissionIdentity(REQUEST_COMPANION_SELF_MANAGED) {
- cdm.associate(request, SIMPLE_EXECUTOR, callback)
- }
- }
-
- val callbackInvocation = callback.invocations.first()
- assertIs<OnAssociationCreated>(callbackInvocation)
- return callbackInvocation.associationInfo.id
- }
}
\ No newline at end of file
diff --git a/tests/tests/companion/noservices/AndroidManifest.xml b/tests/tests/companion/noservices/AndroidManifest.xml
new file mode 100644
index 0000000..a851ff4
--- /dev/null
+++ b/tests/tests/companion/noservices/AndroidManifest.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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.companion.cts.noservices">
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.companion.cts.noservices"
+ android:label="CompanionDeviceManager No-CompanionDeviceServices CTS tests">
+
+ <meta-data
+ android:name="listener"
+ android:value="com.android.cts.runner.CtsTestRunListener" />
+ </instrumentation>
+
+ <application>
+ <!--
+ "Re-define" PrimaryCompanionService and SecondaryCompanionService services defined in
+ common/AndroidManifest.xml. This should leave the package without any valid
+ CompanionDeviceServices.
+ -->
+ <service
+ android:name="android.companion.cts.common.PrimaryCompanionService"
+ android:enabled="false" />
+ <service
+ android:name="android.companion.cts.common.SecondaryCompanionService"
+ android:enabled="false" />
+ </application>
+
+</manifest>
+
diff --git a/tests/tests/companion/noservices/AndroidTest.xml b/tests/tests/companion/noservices/AndroidTest.xml
new file mode 100644
index 0000000..fd7a954
--- /dev/null
+++ b/tests/tests/companion/noservices/AndroidTest.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.
+-->
+<configuration description="Configuration for No-Companion-Devices-Services CTS tests for CompanionDeviceManager">
+ <option name="config-descriptor:metadata" key="component" value="framework" />
+ <option name="config-descriptor:metadata" key="parameter" value="instant_app" />
+ <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+ <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+ <option name="not-shardable" value="true" />
+ <option name="test-suite-tag" value="cts" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="CtsCompanionDeviceManagerNoCompanionServicesTestCases.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="android.companion.cts.noservices" />
+ <option name="runtime-hint" value="1s" />
+ </test>
+
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="am wait-for-broadcast-idle" />
+ </target_preparer>
+</configuration>
diff --git a/tests/tests/companion/noservices/src/android/companion/cts/noservices/NoCompanionDeviceServiceTest.kt b/tests/tests/companion/noservices/src/android/companion/cts/noservices/NoCompanionDeviceServiceTest.kt
new file mode 100644
index 0000000..92d468c
--- /dev/null
+++ b/tests/tests/companion/noservices/src/android/companion/cts/noservices/NoCompanionDeviceServiceTest.kt
@@ -0,0 +1,84 @@
+/*
+ * 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.companion.cts.noservices
+
+import android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED
+import android.companion.cts.common.DEVICE_DISPLAY_NAME_A
+import android.companion.cts.common.MissingIntentFilterActionCompanionService
+import android.companion.cts.common.MissingPermissionCompanionService
+import android.companion.cts.common.PrimaryCompanionService
+import android.companion.cts.common.SecondaryCompanionService
+import android.companion.cts.common.TestBase
+import android.companion.cts.common.waitFor
+import android.platform.test.annotations.AppModeFull
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertFalse
+import kotlin.time.Duration.Companion.milliseconds
+import kotlin.time.Duration.Companion.seconds
+
+/**
+ * Tests CDM handling the case when the companion application does not define a valid
+ * [CompanionDeviceService][android.companion.CompanionDeviceService].
+ *
+ * Build/Install/Run:
+ * atest CtsCompanionDeviceManagerNoCompanionServicesTestCases:NoCompanionDeviceServiceTest
+ */
+@AppModeFull(reason = "CompanionDeviceManager APIs are not available to the instant apps.")
+@RunWith(AndroidJUnit4::class)
+class NoCompanionDeviceServiceTest : TestBase() {
+
+ /**
+ * Ensures that CDM service DOES NOT try to bind
+ * [CompanionDeviceServices][android.companion.CompanionDeviceService] that do not meet all the
+ * requirements, as well as that the system's stability in case when the companion applications
+ * do not define any valid CompanionDeviceServices.
+ */
+ @Test
+ fun test_noService() =
+ withShellPermissionIdentity(REQUEST_COMPANION_SELF_MANAGED) {
+ val associationId = createSelfManagedAssociation(DEVICE_DISPLAY_NAME_A)
+
+ // This should neither throw an Exception nor cause system to crash, even when the
+ // companion application does not define any valid CompanionDeviceServices.
+ // (If the system crashes this instrumentation test won't complete).
+ cdm.notifyDeviceAppeared(associationId)
+
+ // Every 100ms check if any of the services is bound or received a callback.
+ assertFalse("None of the services should be bound or receive a callback") {
+ waitFor(timeout = 1.seconds, interval = 100.milliseconds) {
+ val isBound = PrimaryCompanionService.isBound ||
+ SecondaryCompanionService.isBound ||
+ MissingPermissionCompanionService.isBound ||
+ MissingIntentFilterActionCompanionService.isBound
+ val receivedCallback =
+ PrimaryCompanionService.connectedDevices.isNotEmpty() ||
+ SecondaryCompanionService.connectedDevices.isNotEmpty() ||
+ MissingPermissionCompanionService.connectedDevices.isNotEmpty() ||
+ MissingIntentFilterActionCompanionService.connectedDevices
+ .isNotEmpty()
+ return@waitFor isBound || receivedCallback
+ }
+ }
+
+ // This should neither throw an Exception nor cause system to crash, even when the
+ // companion application does not define any valid CompanionDeviceServices.
+ // (If the system crashes this instrumentation test won't complete).
+ cdm.notifyDeviceDisappeared(associationId)
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
index 7736065..da8a7ab 100644
--- a/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/PackageManagerShellCommandTest.java
@@ -44,8 +44,11 @@
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.IIntentReceiver;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
import android.content.pm.ApkChecksum;
import android.content.pm.ApplicationInfo;
import android.content.pm.DataLoaderParams;
@@ -57,9 +60,12 @@
import android.content.pm.Signature;
import android.content.pm.SigningInfo;
import android.content.pm.cts.util.AbandonAllPackageSessionsRule;
+import android.os.Bundle;
import android.os.ConditionVariable;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.AppModeFull;
import android.util.PackageUtils;
@@ -73,6 +79,7 @@
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;
@@ -93,6 +100,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Random;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
@@ -235,6 +243,15 @@
}
}
+ private static void writeFileToSession(PackageInstaller.Session session, String name,
+ String apk) throws IOException {
+ File file = new File(createApkPath(apk));
+ try (OutputStream os = session.openWrite(name, 0, file.length());
+ InputStream is = new FileInputStream(file)) {
+ writeFullStream(is, os, file.length());
+ }
+ }
+
@Before
public void onBefore() throws Exception {
// Check if Incremental is allowed and revert to non-dataloader installation.
@@ -597,6 +614,78 @@
}
@Test
+ public void testDontKillWithSplit() throws Exception {
+ installPackage(TEST_HW5);
+
+ getUiAutomation().adoptShellPermissionIdentity();
+ try {
+ final PackageInstaller installer = getPackageInstaller();
+ final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+ params.setAppPackageName(TEST_APP_PACKAGE);
+ params.setDontKillApp(true);
+
+ final int sessionId = installer.createSession(params);
+ PackageInstaller.Session session = installer.openSession(sessionId);
+ assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
+
+ writeFileToSession(session, "hw5_split0", TEST_HW5_SPLIT0);
+
+ final CompletableFuture<Boolean> result = new CompletableFuture<>();
+ session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder whitelistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) throws RemoteException {
+ boolean dontKillApp =
+ (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+ result.complete(dontKillApp);
+ }
+ }));
+
+ // We are adding split. OK to have the flag.
+ assertTrue(result.get());
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
+ public void testDontKillRemovedWithBaseApk() throws Exception {
+ installPackage(TEST_HW5);
+
+ getUiAutomation().adoptShellPermissionIdentity();
+ try {
+ final PackageInstaller installer = getPackageInstaller();
+ final SessionParams params = new SessionParams(SessionParams.MODE_INHERIT_EXISTING);
+ params.setAppPackageName(TEST_APP_PACKAGE);
+ params.setDontKillApp(true);
+
+ final int sessionId = installer.createSession(params);
+ PackageInstaller.Session session = installer.openSession(sessionId);
+ assertTrue((session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0);
+
+ writeFileToSession(session, "hw7", TEST_HW7);
+
+ final CompletableFuture<Boolean> result = new CompletableFuture<>();
+ session.commit(new IntentSender((IIntentSender) new IIntentSender.Stub() {
+ @Override
+ public void send(int code, Intent intent, String resolvedType,
+ IBinder whitelistToken, IIntentReceiver finishedReceiver,
+ String requiredPermission, Bundle options) throws RemoteException {
+ boolean dontKillApp =
+ (session.getInstallFlags() & PackageManager.INSTALL_DONT_KILL_APP) != 0;
+ result.complete(dontKillApp);
+ }
+ }));
+
+ // We are updating base.apk. Flag to be removed.
+ assertFalse(result.get());
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ @Test
public void testDataLoaderParamsApiV1() throws Exception {
if (!mStreaming) {
return;
@@ -1309,6 +1398,7 @@
}
}
+ @Ignore
@Test
public void testGetFirstInstallTime() throws Exception {
final int currentUser = getContext().getUserId();
@@ -1433,6 +1523,7 @@
assertTrue(isAppInstalled(TEST_APP_PACKAGE));
}
+ @Ignore
@Test
public void testPackageFullyRemovedBroadcastAfterUninstall() throws IOException {
final int currentUser = getContext().getUserId();
@@ -1483,7 +1574,7 @@
final ApplicationInfo info = pm.getApplicationInfo(
name, PackageManager.ApplicationInfoFlags.of(PackageManager.MATCH_SYSTEM_ONLY));
assertEquals(ApplicationInfo.FLAG_SYSTEM, info.flags & ApplicationInfo.FLAG_SYSTEM);
- assertTrue(info.sourceDir.startsWith("/apex/com.android.supplementalprocess"));
+ assertTrue(info.sourceDir.startsWith("/apex/com.android.adservices"));
}
@Test
@@ -1606,8 +1697,9 @@
private boolean isAppInstalled(String packageName) throws IOException {
final String commandResult = executeShellCommand("pm list packages");
final int prefixLength = "package:".length();
- return Arrays.stream(commandResult.split("\\r?\\n"))
- .anyMatch(line -> line.substring(prefixLength).equals(packageName));
+ return Arrays.stream(commandResult.split("\\r?\\n")).anyMatch(
+ line -> line.length() > prefixLength && line.substring(prefixLength).equals(
+ packageName));
}
private boolean isAppInstalledForUser(String packageName, int userId) throws IOException {
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java
index eb51afa..e2346c4 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteOpenHelperTest.java
@@ -28,6 +28,7 @@
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteDebug;
+import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteGlobal;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQuery;
@@ -289,6 +290,59 @@
}
}
+ /**
+ * Tests a scenario in WAL mode with multiple connections, when a connection should see schema
+ * changes made from another connection.
+ */
+ public void testWalSchemaChangeVisibilityOnDowngrade() {
+ File dbPath = mContext.getDatabasePath(TEST_DATABASE_NAME);
+ SQLiteDatabase.deleteDatabase(dbPath);
+ SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbPath, null);
+ db.execSQL("CREATE TABLE test_table (_id INTEGER PRIMARY KEY AUTOINCREMENT"
+ + ", _key INTEGER DEFAULT 1234)");
+ db.execSQL("CREATE TABLE test_table2 (_id INTEGER PRIMARY KEY AUTOINCREMENT)");
+ db.setVersion(2);
+ try (Cursor cursor = db.rawQuery("select * from test_table", null)) {
+ assertEquals(2, cursor.getColumnCount());
+ }
+ try (Cursor cursor = db.rawQuery("select * from test_table2", null)) {
+ assertEquals(1, cursor.getColumnCount());
+ }
+ db.close();
+ mOpenHelper = new MockOpenHelper(mContext, TEST_DATABASE_NAME, null, 1) {
+ {
+ setWriteAheadLoggingEnabled(true);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ }
+
+ @Override
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ if (newVersion == 1) {
+ // Drop all tables
+ db.execSQL("DROP TABLE IF EXISTS test_table");
+ db.execSQL("DROP TABLE IF EXISTS test_table2");
+
+ // Recreate test_table with one column _id
+ db.execSQL("CREATE TABLE test_table"
+ + " (_id INTEGER PRIMARY KEY AUTOINCREMENT)");
+ }
+ }
+ };
+ // Check if the test_table has only one column.
+ try (Cursor cursor = mOpenHelper.getReadableDatabase()
+ .rawQuery("select * from test_table", null)) {
+ assertEquals(1, cursor.getColumnCount());
+ }
+ // Check if the test_table2 has been dropped.
+ try (Cursor cursor = mOpenHelper.getReadableDatabase().rawQuery(
+ "select name from sqlite_master where type='table' and name='test_table2'", null)) {
+ assertEquals(0, cursor.getCount());
+ }
+ }
+
public void testSetWriteAheadLoggingDisablesCompatibilityWal() {
// Verify that compatibility WAL is not enabled, if an application explicitly disables WAL
diff --git a/tests/tests/gamemanager/Android.bp b/tests/tests/gamemanager/Android.bp
index 827d41f..4e8b4b7 100644
--- a/tests/tests/gamemanager/Android.bp
+++ b/tests/tests/gamemanager/Android.bp
@@ -28,6 +28,8 @@
data: [
":CtsGameTestApp",
+ ":CtsGameTestAppWithBatteryMode",
+ ":CtsGameTestAppWithPerformanceMode",
":CtsLegacyGameTestApp",
":CtsNotGameTestApp",
],
diff --git a/tests/tests/gamemanager/AndroidTest.xml b/tests/tests/gamemanager/AndroidTest.xml
index be17c48..fb23c6c 100644
--- a/tests/tests/gamemanager/AndroidTest.xml
+++ b/tests/tests/gamemanager/AndroidTest.xml
@@ -30,6 +30,8 @@
<option name="push" value="CtsLegacyGameTestApp.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsLegacyGameTestApp.apk" />
<option name="push" value="CtsNotGameTestApp.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsNotGameTestApp.apk" />
<option name="push" value="CtsGameTestApp.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsGameTestApp.apk" />
+ <option name="push" value="CtsGameTestAppWithBatteryMode.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsGameTestAppWithBatteryMode.apk" />
+ <option name="push" value="CtsGameTestAppWithPerformanceMode.apk->/data/local/tmp/cts/gamemanager/test/apps/CtsGameTestAppWithPerformanceMode.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/Android.bp b/tests/tests/gamemanager/GameTestAppWithBatteryMode/Android.bp
new file mode 100644
index 0000000..b428860
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsGameTestAppWithBatteryMode",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "guava",
+ ],
+ defaults: ["cts_support_defaults"],
+ min_sdk_version: "current",
+}
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/AndroidManifest.xml b/tests/tests/gamemanager/GameTestAppWithBatteryMode/AndroidManifest.xml
new file mode 100644
index 0000000..9834584
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.gamemanager.cts.app.gametestapp.battery">
+
+ <application android:appCategory="game">
+ <uses-library android:name="android.test.runner"/>
+ <meta-data android:name="android.game_mode_config"
+ android:resource="@xml/game_mode_config" />
+ <activity android:name=".GameTestAppMainActivity"
+ android:label="GameTestAppMainActivity"
+ android:visibleToInstantApps="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/res/xml/game_mode_config.xml b/tests/tests/gamemanager/GameTestAppWithBatteryMode/res/xml/game_mode_config.xml
new file mode 100644
index 0000000..a1991a1
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/res/xml/game_mode_config.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<game-mode-config
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:supportsBatteryGameMode="true"
+ android:supportsPerformanceGameMode="false"
+ android:allowGameAngleDriver="true"
+ android:allowGameDownscaling="true"
+/>
diff --git a/tests/tests/gamemanager/GameTestAppWithBatteryMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java b/tests/tests/gamemanager/GameTestAppWithBatteryMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
new file mode 100644
index 0000000..7e2536c
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithBatteryMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.gamemanager.cts.app;
+
+import android.app.Activity;
+import android.app.GameManager;
+import android.content.Context;
+import android.os.Bundle;
+
+public class GameTestAppMainActivity extends Activity {
+
+ private static final String TAG = "GameTestAppMainActivity";
+
+ Context mContext;
+ GameManager mGameManager;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = getApplicationContext();
+ mGameManager = mContext.getSystemService(GameManager.class);
+ }
+
+ public String getPackageName() {
+ return mContext.getPackageName();
+ }
+
+ public int getGameMode() {
+ return mGameManager.getGameMode();
+ }
+}
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/Android.bp b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/Android.bp
new file mode 100644
index 0000000..b783a75
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/Android.bp
@@ -0,0 +1,30 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsGameTestAppWithPerformanceMode",
+ srcs: [
+ "src/**/*.java",
+ ],
+ static_libs: [
+ "androidx.annotation_annotation",
+ "guava",
+ ],
+ defaults: ["cts_support_defaults"],
+ min_sdk_version: "current",
+}
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/AndroidManifest.xml b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/AndroidManifest.xml
new file mode 100644
index 0000000..a6174b9
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.gamemanager.cts.app.gametestapp.performance">
+
+ <application android:appCategory="game">
+ <uses-library android:name="android.test.runner"/>
+ <meta-data android:name="android.game_mode_config"
+ android:resource="@xml/game_mode_config" />
+ <activity android:name=".GameTestAppMainActivity"
+ android:label="GameTestAppMainActivity"
+ android:visibleToInstantApps="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
\ No newline at end of file
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/res/xml/game_mode_config.xml b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/res/xml/game_mode_config.xml
new file mode 100644
index 0000000..492075c9
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/res/xml/game_mode_config.xml
@@ -0,0 +1,25 @@
+<?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.
+ -->
+
+<game-mode-config
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:supportsBatteryGameMode="false"
+ android:supportsPerformanceGameMode="true"
+ android:allowGameAngleDriver="true"
+ android:allowGameDownscaling="true"
+/>
diff --git a/tests/tests/gamemanager/GameTestAppWithPerformanceMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
new file mode 100644
index 0000000..7e2536c
--- /dev/null
+++ b/tests/tests/gamemanager/GameTestAppWithPerformanceMode/src/android/gamemanager/cts/app/GameTestAppMainActivity.java
@@ -0,0 +1,45 @@
+/*
+ * 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.gamemanager.cts.app;
+
+import android.app.Activity;
+import android.app.GameManager;
+import android.content.Context;
+import android.os.Bundle;
+
+public class GameTestAppMainActivity extends Activity {
+
+ private static final String TAG = "GameTestAppMainActivity";
+
+ Context mContext;
+ GameManager mGameManager;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mContext = getApplicationContext();
+ mGameManager = mContext.getSystemService(GameManager.class);
+ }
+
+ public String getPackageName() {
+ return mContext.getPackageName();
+ }
+
+ public int getGameMode() {
+ return mGameManager.getGameMode();
+ }
+}
diff --git a/tests/tests/gamemanager/OWNERS b/tests/tests/gamemanager/OWNERS
index 986180d..d0186b0 100644
--- a/tests/tests/gamemanager/OWNERS
+++ b/tests/tests/gamemanager/OWNERS
@@ -1,3 +1,3 @@
# Bug component: 878256
lpy@google.com
-timvp@google.com
+xwxw@google.com
diff --git a/tests/tests/gamemanager/res/xml/game_mode_config.xml b/tests/tests/gamemanager/res/xml/game_mode_config.xml
index 492075c9..e013590 100644
--- a/tests/tests/gamemanager/res/xml/game_mode_config.xml
+++ b/tests/tests/gamemanager/res/xml/game_mode_config.xml
@@ -18,7 +18,7 @@
<game-mode-config
xmlns:android="http://schemas.android.com/apk/res/android"
- android:supportsBatteryGameMode="false"
+ android:supportsBatteryGameMode="true"
android:supportsPerformanceGameMode="true"
android:allowGameAngleDriver="true"
android:allowGameDownscaling="true"
diff --git a/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java b/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java
index 7c47072..f6c14be 100644
--- a/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java
+++ b/tests/tests/gamemanager/src/android/gamemanager/cts/GameManagerTest.java
@@ -54,14 +54,27 @@
private static final Pattern GAME_LOADING_REGEX =
Pattern.compile("^GAME_LOADING\\t(\\d*)\\t\\d*$", Pattern.MULTILINE);
private static final String APK_DIRECTORY = "/data/local/tmp/cts/gamemanager/test/apps/";
+
private static final String NOT_GAME_TEST_APP_APK_PATH =
APK_DIRECTORY + "CtsNotGameTestApp.apk";
private static final String NOT_GAME_TEST_APP_PACKAGE_NAME =
"android.gamemanager.cts.app.notgametestapp";
+
private static final String GAME_TEST_APP_APK_PATH =
APK_DIRECTORY + "CtsGameTestApp.apk";
private static final String GAME_TEST_APP_PACKAGE_NAME =
"android.gamemanager.cts.app.gametestapp";
+
+ private static final String GAME_TEST_APP_WITH_BATTERY_APK_PATH =
+ APK_DIRECTORY + "CtsGameTestAppWithBatteryMode.apk";
+ private static final String GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME =
+ "android.gamemanager.cts.app.gametestapp.battery";
+
+ private static final String GAME_TEST_APP_WITH_PERFORMANCE_APK_PATH =
+ APK_DIRECTORY + "CtsGameTestAppWithPerformanceMode.apk";
+ private static final String GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME =
+ "android.gamemanager.cts.app.gametestapp.performance";
+
private static final int TEST_LABEL = 1;
private static final int TEST_QUALITY = 2;
@@ -78,6 +91,8 @@
public void setUp() {
TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
+ TestUtil.uninstallPackage(GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME);
+ TestUtil.uninstallPackage(GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME);
mActivityRule.getScenario().onActivity(activity -> {
mActivity = activity;
@@ -93,21 +108,35 @@
public void tearDown() throws Exception {
TestUtil.uninstallPackage(NOT_GAME_TEST_APP_PACKAGE_NAME);
TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
+ TestUtil.uninstallPackage(GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME);
+ TestUtil.uninstallPackage(GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME);
}
@Test
public void testIsAngleEnabled() throws Exception {
+ final String packageName = GAME_TEST_APP_WITH_PERFORMANCE_PACKAGE_NAME;
+ assertTrue(TestUtil.installPackage(GAME_TEST_APP_WITH_PERFORMANCE_APK_PATH));
+ Thread.sleep(500);
+
// enable Angle for BATTERY mode.
- runShellCommand("device_config put game_overlay " + mActivity.getPackageName()
+ runShellCommand("device_config put game_overlay " + packageName
+ " mode=3,useAngle=true");
+ Thread.sleep(500);
+
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
- (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
- GameManager.GAME_MODE_BATTERY));
- assertTrue(mGameManager.isAngleEnabled(mActivity.getPackageName()));
+ (gameManager) -> gameManager.setGameMode(packageName,
+ GameManager.GAME_MODE_BATTERY), "android.permission.MANAGE_GAME_MODE");
+ assertTrue(ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+ (gameManager) -> gameManager.isAngleEnabled(packageName),
+ "android.permission.MANAGE_GAME_MODE"));
ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
- (gameManager) -> gameManager.setGameMode(mActivity.getPackageName(),
- GameManager.GAME_MODE_PERFORMANCE));
- assertFalse(mGameManager.isAngleEnabled(mActivity.getPackageName()));
+ (gameManager) -> gameManager.setGameMode(packageName,
+ GameManager.GAME_MODE_PERFORMANCE), "android.permission.MANAGE_GAME_MODE");
+ assertFalse(ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+ (gameManager) -> gameManager.isAngleEnabled(packageName),
+ "android.permission.MANAGE_GAME_MODE"));
+
+ TestUtil.uninstallPackage(packageName);
}
/**
@@ -340,4 +369,40 @@
TestUtil.uninstallPackage(GAME_TEST_APP_PACKAGE_NAME);
}
+
+ /**
+ * Test that GameManager::getGameModeInfo() returns correct values for a game when it only
+ * supports battery mode.
+ */
+ @Test
+ public void testGetGameModeInfoWithBatteryMode() throws InterruptedException {
+ final String packageName = GAME_TEST_APP_WITH_BATTERY_PACKAGE_NAME;
+ assertTrue(TestUtil.installPackage(GAME_TEST_APP_WITH_BATTERY_APK_PATH));
+ // When an app is installed, some propagation work for the configuration will
+ // be set up asynchronously, hence wait for 500ms here.
+ Thread.sleep(500);
+
+ GameModeInfo gameModeInfo =
+ ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+ (gameManager) -> gameManager.getGameModeInfo(packageName),
+ "android.permission.MANAGE_GAME_MODE");
+ assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
+ 2, gameModeInfo.getAvailableGameModes().length);
+ assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
+ GameManager.GAME_MODE_STANDARD, gameModeInfo.getActiveGameMode());
+
+ // Attempt to set the game mode to battery.
+ ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(mGameManager,
+ (gameManager) -> gameManager.setGameMode(packageName,
+ GameManager.GAME_MODE_BATTERY));
+ gameModeInfo = ShellIdentityUtils.invokeMethodWithShellPermissions(mGameManager,
+ (gameManager) -> gameManager.getGameModeInfo(packageName),
+ "android.permission.MANAGE_GAME_MODE");
+ assertEquals("GameManager#getGameModeInfo returned incorrect available game modes.",
+ 2, gameModeInfo.getAvailableGameModes().length);
+ assertEquals("GameManager#getGameModeInfo returned incorrect active game mode.",
+ GameManager.GAME_MODE_BATTERY, gameModeInfo.getActiveGameMode());
+
+ TestUtil.uninstallPackage(packageName);
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java b/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java
index 436c1dc..9247ab0 100644
--- a/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java
+++ b/tests/tests/graphics/src/android/graphics/fonts/SystemEmojiTest.java
@@ -18,6 +18,9 @@
import static com.google.common.truth.Truth.assertThat;
+import android.graphics.Paint;
+import android.graphics.text.PositionedGlyphs;
+import android.graphics.text.TextRunShaper;
import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -46,4 +49,23 @@
assertThat(FontFileTestUtil.containsEmojiCompatMetadata(emojiFont)).isTrue();
}
+
+ public String getFontName(String chars) {
+ Paint paint = new Paint();
+
+ PositionedGlyphs glyphs = TextRunShaper.shapeTextRun(
+ chars, 0, chars.length(), 0, chars.length(), 0f, 0f, false, paint);
+ assertThat(glyphs.glyphCount()).isEqualTo(1);
+ assertThat(glyphs.getFont(0)).isNotNull();
+ File file = glyphs.getFont(0).getFile();
+ assertThat(file).isNotNull();
+ assertThat(file.getParent()).isEqualTo("/system/fonts");
+
+ return file.getName();
+ }
+
+ @Test
+ public void doNotDrawLegacy() {
+ assertThat(getFontName("\u263A")).isNotEqualTo("NotoColorEmojiLegacy.ttf");
+ }
}
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
index 80a7983..ca8d1ec 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/AudioManagerTest.java
@@ -2022,6 +2022,10 @@
}
}
+ public void testGetHalVersion() {
+ assertNotEquals(null, AudioManager.getHalVersion());
+ }
+
private void assertStreamVolumeEquals(int stream, int expectedVolume) throws Exception {
assertStreamVolumeEquals(stream, expectedVolume,
"Unexpected stream volume for stream=" + stream);
diff --git a/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java b/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java
index 5c1821b..af4dc75 100644
--- a/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java
+++ b/tests/tests/media/audio/src/android/media/audio/cts/CallAudioInterceptionTest.java
@@ -57,7 +57,6 @@
@Before
public void setUp() throws Exception {
Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
- assumeTrue(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
mAudioManager = context.getSystemService(AudioManager.class);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
@@ -66,6 +65,8 @@
.getUiAutomation()
.adoptShellPermissionIdentity(Manifest.permission.CALL_AUDIO_INTERCEPTION,
Manifest.permission.MODIFY_PHONE_STATE);
+
+ assumeTrue(context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY));
}
/** Test teardown */
diff --git a/tests/tests/media/drm/Android.bp b/tests/tests/media/drmframework/Android.bp
similarity index 90%
rename from tests/tests/media/drm/Android.bp
rename to tests/tests/media/drmframework/Android.bp
index 05545db..e7ebf7a 100644
--- a/tests/tests/media/drm/Android.bp
+++ b/tests/tests/media/drmframework/Android.bp
@@ -21,7 +21,7 @@
}
android_test {
- name: "CtsMediaDrmTestCases",
+ name: "CtsMediaDrmFrameworkTestCases",
defaults: ["cts_defaults"],
// include both the 32 and 64 bit versions
compile_multilib: "both",
@@ -33,8 +33,8 @@
],
aaptflags: [
"--auto-add-overlay",
- // Give com.android.media.drm.cts Java files access to the R class
- "--extra-packages com.android.media.drm.cts",
+ // Give com.android.media.drmframework.cts Java files access to the R class
+ "--extra-packages com.android.media.drmframework.cts",
// Do not compress these files:
"-0 .vp9",
diff --git a/tests/tests/media/drm/AndroidManifest.xml b/tests/tests/media/drmframework/AndroidManifest.xml
similarity index 93%
rename from tests/tests/media/drm/AndroidManifest.xml
rename to tests/tests/media/drmframework/AndroidManifest.xml
index e7aa4cd..fd146bd 100644
--- a/tests/tests/media/drm/AndroidManifest.xml
+++ b/tests/tests/media/drmframework/AndroidManifest.xml
@@ -15,7 +15,7 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.media.drm.cts"
+ package="android.media.drmframework.cts"
android:targetSandboxVersion="2">
<uses-sdk android:minSdkVersion="29"
@@ -36,7 +36,7 @@
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="android.media.drm.cts"
+ android:targetPackage="android.media.drmframework.cts"
android:label="CTS tests of android MediaDrm">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener"/>
diff --git a/tests/tests/media/drm/AndroidTest.xml b/tests/tests/media/drmframework/AndroidTest.xml
similarity index 82%
rename from tests/tests/media/drm/AndroidTest.xml
rename to tests/tests/media/drmframework/AndroidTest.xml
index 6a4fb73..01639e5 100644
--- a/tests/tests/media/drm/AndroidTest.xml
+++ b/tests/tests/media/drmframework/AndroidTest.xml
@@ -22,30 +22,30 @@
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
<option name="target" value="host" />
- <option name="config-filename" value="CtsMediaDrmTestCases" />
- <option name="dynamic-config-name" value="CtsMediaDrmTestCases" />
+ <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
+ <option name="dynamic-config-name" value="CtsMediaDrmFrameworkTestCases" />
<option name="version" value="9.0_r1"/>
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer">
<option name="push-all" value="true" />
- <option name="media-folder-name" value="CtsMediaDrmTestCases-1.4" />
- <option name="dynamic-config-module" value="CtsMediaDrmTestCases" />
+ <option name="media-folder-name" value="CtsMediaDrmFrameworkTestCases-1.0" />
+ <option name="dynamic-config-module" value="CtsMediaDrmFrameworkTestCases" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="CtsMediaDrmTestCases.apk" />
+ <option name="test-file-name" value="CtsMediaDrmFrameworkTestCases.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<!-- MediaProjectionTest needs this one to not be granted, SuiteApkInstaller grants all of them by default.-->
- <option name="run-command" value="pm revoke android.media.drm.cts android.permission.SYSTEM_ALERT_WINDOW"/>
+ <option name="run-command" value="pm revoke android.media.drmframework.cts android.permission.SYSTEM_ALERT_WINDOW"/>
</target_preparer>
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.DynamicConfigPusher">
<option name="target" value="device" />
- <option name="config-filename" value="CtsMediaDrmTestCases" />
+ <option name="config-filename" value="CtsMediaDrmFrameworkTestCases" />
<option name="version" value="7.0"/>
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="android.media.drm.cts" />
+ <option name="package" value="android.media.drmframework.cts" />
<!-- setup can be expensive so limit the number of shards -->
<option name="ajur-max-shard" value="5" />
<!-- test-timeout unit is ms, value = 30 min -->
diff --git a/tests/tests/media/drm/DynamicConfig.xml b/tests/tests/media/drmframework/DynamicConfig.xml
similarity index 98%
rename from tests/tests/media/drm/DynamicConfig.xml
rename to tests/tests/media/drmframework/DynamicConfig.xml
index 942ab80..0795037 100644
--- a/tests/tests/media/drm/DynamicConfig.xml
+++ b/tests/tests/media/drmframework/DynamicConfig.xml
@@ -45,6 +45,6 @@
<value>http://redirector.gvt1.com/videoplayback?id=c80658495af60617&itag=17&source=youtube&ip=0.0.0.0&ipbits=0&expire=19000000000&sparams=ip,ipbits,expire,id,itag,source&signature=70E979A621001201BC18622BDBF914FA870BDA40.6E78890B80F4A33A18835F775B1FF64F0A4D0003&key=ik0&user=android-device-test</value>
</entry>
<entry key="media_files_url">
- <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/CtsMediaTestCases-1.4.zip</value>
+ <value>https://storage.googleapis.com/android_media/cts/tests/tests/media/drmframework/CtsMediaDrmFrameworkTestCases-1.0.zip</value>
</entry>
</dynamicConfig>
diff --git a/tests/tests/media/drm/OWNERS b/tests/tests/media/drmframework/OWNERS
similarity index 92%
rename from tests/tests/media/drm/OWNERS
rename to tests/tests/media/drmframework/OWNERS
index 09b0051..f20d2d9 100644
--- a/tests/tests/media/drm/OWNERS
+++ b/tests/tests/media/drmframework/OWNERS
@@ -3,7 +3,6 @@
conglin@google.com
edwinwong@google.com
fredgc@google.com
-jtinker@google.com
juce@google.com
kylealexander@google.com
mattfedd@google.com
diff --git a/tests/tests/media/drm/jni/AMediaObjects.h b/tests/tests/media/drmframework/jni/AMediaObjects.h
similarity index 100%
rename from tests/tests/media/drm/jni/AMediaObjects.h
rename to tests/tests/media/drmframework/jni/AMediaObjects.h
diff --git a/tests/tests/media/drm/jni/Android.bp b/tests/tests/media/drmframework/jni/Android.bp
similarity index 100%
rename from tests/tests/media/drm/jni/Android.bp
rename to tests/tests/media/drmframework/jni/Android.bp
diff --git a/tests/tests/media/drm/jni/CtsMediaDrmJniOnLoad.cpp b/tests/tests/media/drmframework/jni/CtsMediaDrmJniOnLoad.cpp
similarity index 85%
rename from tests/tests/media/drm/jni/CtsMediaDrmJniOnLoad.cpp
rename to tests/tests/media/drmframework/jni/CtsMediaDrmJniOnLoad.cpp
index 54b2dd5..935e8a6 100644
--- a/tests/tests/media/drm/jni/CtsMediaDrmJniOnLoad.cpp
+++ b/tests/tests/media/drmframework/jni/CtsMediaDrmJniOnLoad.cpp
@@ -17,7 +17,7 @@
#include <jni.h>
#include <stdio.h>
-extern int register_android_mediadrm_cts_NativeMediaDrmClearkeyTest(JNIEnv*);
+extern int registerNativeMediaDrmClearkeyTest(JNIEnv*);
jint JNI_OnLoad(JavaVM *vm, void */*reserved*/) {
JNIEnv *env = NULL;
@@ -26,7 +26,7 @@
return JNI_ERR;
}
- if (register_android_mediadrm_cts_NativeMediaDrmClearkeyTest(env)) {
+ if (registerNativeMediaDrmClearkeyTest(env)) {
return JNI_ERR;
}
diff --git a/tests/tests/media/drm/jni/native-mediadrm-jni.cpp b/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
similarity index 94%
rename from tests/tests/media/drm/jni/native-mediadrm-jni.cpp
rename to tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
index 441d17a..40584b6 100644
--- a/tests/tests/media/drm/jni/native-mediadrm-jni.cpp
+++ b/tests/tests/media/drmframework/jni/native-mediadrm-jni.cpp
@@ -173,7 +173,7 @@
return status;
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_isCryptoSchemeSupportedNative(
+extern "C" jboolean isCryptoSchemeSupportedNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
if (NULL == uuid) {
@@ -205,7 +205,7 @@
playbackParams, gFieldIds.videoUrl));
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetPropertyStringNative(
+extern "C" jboolean testGetPropertyStringNative(
JNIEnv* env, jclass clazz, jbyteArray uuid,
jstring name, jobject outValue) {
@@ -250,7 +250,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPropertyByteArrayNative(
+extern "C" jboolean testPropertyByteArrayNative(
JNIEnv* env, jclass /* clazz */, jbyteArray uuid) {
if (NULL == uuid) {
@@ -301,7 +301,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPsshNative(
+extern "C" jboolean testPsshNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jstring videoUrl) {
if (NULL == uuid || NULL == videoUrl) {
@@ -686,7 +686,7 @@
jniThrowExceptionFmt(env, "java/lang/RuntimeException", errorMessage.c_str(), status);
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testClearKeyPlaybackNative(
+extern "C" jboolean testClearKeyPlaybackNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jobject playbackParams) {
if (NULL == uuid || NULL == playbackParams) {
jniThrowException(env, "java/lang/NullPointerException",
@@ -826,7 +826,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testQueryKeyStatusNative(
+extern "C" jboolean testQueryKeyStatusNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
if (NULL == uuid) {
@@ -919,7 +919,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testFindSessionIdNative(
+extern "C" jboolean testFindSessionIdNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid) {
if (NULL == uuid) {
@@ -975,7 +975,7 @@
return JNI_TRUE;
}
-extern "C" jboolean Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetKeyRequestNative(
+extern "C" jboolean testGetKeyRequestNative(
JNIEnv* env, jclass /*clazz*/, jbyteArray uuid, jobject playbackParams) {
if (NULL == uuid || NULL == playbackParams) {
@@ -1058,41 +1058,41 @@
static JNINativeMethod gMethods[] = {
{ "isCryptoSchemeSupportedNative", "([B)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_isCryptoSchemeSupportedNative },
+ (void *)isCryptoSchemeSupportedNative },
{ "testClearKeyPlaybackNative",
- "([BLandroid/media/drm/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testClearKeyPlaybackNative },
+ "([BLandroid/media/drmframework/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
+ (void *)testClearKeyPlaybackNative },
{ "testGetPropertyStringNative",
"([BLjava/lang/String;Ljava/lang/StringBuffer;)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetPropertyStringNative },
+ (void *)testGetPropertyStringNative },
{ "testPropertyByteArrayNative",
"([B)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPropertyByteArrayNative },
+ (void *)testPropertyByteArrayNative },
{ "testPsshNative", "([BLjava/lang/String;)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testPsshNative },
+ (void *)testPsshNative },
{ "testQueryKeyStatusNative", "([B)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testQueryKeyStatusNative },
+ (void *)testQueryKeyStatusNative },
{ "testFindSessionIdNative", "([B)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testFindSessionIdNative },
+ (void *)testFindSessionIdNative },
{ "testGetKeyRequestNative",
- "([BLandroid/media/drm/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
- (void *)Java_android_mediadrm_cts_NativeMediaDrmClearkeyTest_testGetKeyRequestNative},
+ "([BLandroid/media/drmframework/cts/NativeMediaDrmClearkeyTest$PlaybackParams;)Z",
+ (void *)testGetKeyRequestNative},
};
-int register_android_mediadrm_cts_NativeMediaDrmClearkeyTest(JNIEnv* env) {
+int registerNativeMediaDrmClearkeyTest(JNIEnv* env) {
jint result = JNI_ERR;
jclass testClass =
- env->FindClass("android/media/drm/cts/NativeMediaDrmClearkeyTest");
+ env->FindClass("android/media/drmframework/cts/NativeMediaDrmClearkeyTest");
if (testClass) {
jclass playbackParamsClass = env->FindClass(
- "android/media/drm/cts/NativeMediaDrmClearkeyTest$PlaybackParams");
+ "android/media/drmframework/cts/NativeMediaDrmClearkeyTest$PlaybackParams");
if (playbackParamsClass) {
jclass surfaceClass =
env->FindClass("android/view/Surface");
diff --git a/tests/tests/media/drm/res/raw/segment000001.ts b/tests/tests/media/drmframework/res/raw/segment000001.ts
similarity index 100%
rename from tests/tests/media/drm/res/raw/segment000001.ts
rename to tests/tests/media/drmframework/res/raw/segment000001.ts
Binary files differ
diff --git a/tests/tests/media/drm/res/raw/segment000001_scrambled.ts b/tests/tests/media/drmframework/res/raw/segment000001_scrambled.ts
similarity index 100%
rename from tests/tests/media/drm/res/raw/segment000001_scrambled.ts
rename to tests/tests/media/drmframework/res/raw/segment000001_scrambled.ts
Binary files differ
diff --git a/tests/tests/media/drm/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm b/tests/tests/media/drmframework/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm
similarity index 100%
rename from tests/tests/media/drm/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm
rename to tests/tests/media/drmframework/res/raw/video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt.webm
Binary files differ
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/DrmInitDataTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/DrmInitDataTest.java
similarity index 96%
rename from tests/tests/media/drm/src/android/media/drm/cts/DrmInitDataTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/DrmInitDataTest.java
index db6ec49..915d561 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/DrmInitDataTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/DrmInitDataTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.DrmInitData;
import android.media.cts.NonMediaMainlineTest;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmClearkeyTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
index 1fc248f..1a1a46f 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmClearkeyTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.MediaCodecInfo.CodecCapabilities;
import android.media.MediaDrm;
@@ -107,11 +107,11 @@
private static final String CENC_AUDIO_PATH = "/clear/h264/llama/llama_aac_audio.mp4";
private static final String CENC_VIDEO_PATH = "/clearkey/llama_h264_main_720p_8000.mp4";
private static final Uri WEBM_URL = Uri.parse(
- "android.resource://android.media.drm.cts/" + R.raw.video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt);
+ "android.resource://android.media.drmframework.cts/" + R.raw.video_320x240_webm_vp8_800kbps_30fps_vorbis_stereo_128kbps_44100hz_crypt);
private static final Uri MPEG2TS_SCRAMBLED_URL = Uri.parse(
- "android.resource://android.media.drm.cts/" + R.raw.segment000001_scrambled);
+ "android.resource://android.media.drmframework.cts/" + R.raw.segment000001_scrambled);
private static final Uri MPEG2TS_CLEAR_URL = Uri.parse(
- "android.resource://android.media.drm.cts/" + R.raw.segment000001);
+ "android.resource://android.media.drmframework.cts/" + R.raw.segment000001);
private static final UUID COMMON_PSSH_SCHEME_UUID =
new UUID(0x1077efecc0b24d02L, 0xace33c1e52e2fb4bL);
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecBlockModelTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecBlockModelTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecBlockModelTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecBlockModelTest.java
index ebb6629..2555bff 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecBlockModelTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecBlockModelTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.content.res.AssetFileDescriptor;
import android.media.MediaDrm;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecTest.java
index 2fb107e..38b1d37 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmCodecTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmCodecTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.MediaCodec;
import android.media.MediaCodec.CryptoException;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmExtractorTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmExtractorTest.java
similarity index 98%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmExtractorTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmExtractorTest.java
index eca036b..e7ac382 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmExtractorTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmExtractorTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.DrmInitData;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMetricsTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMetricsTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMetricsTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMetricsTest.java
index 3f8de70..c9494aa 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMetricsTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMetricsTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsInAnyOrder;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMockTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMockTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMockTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMockTest.java
index 35130aa..4e4a4eb 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmMockTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmMockTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.MediaDrm;
import android.media.MediaDrm.CryptoSession;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaDrmTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmTest.java
index 5dacfee..1bb5646 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaDrmTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaDrmTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.MediaCrypto;
import android.media.MediaCryptoException;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTest.java
similarity index 98%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTest.java
index deaef06..944595a 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.content.Context;
import android.content.pm.PackageManager;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTestBase.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTestBase.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTestBase.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTestBase.java
index c2bce4f..45bcd3e 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/MediaPlayerDrmTestBase.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/MediaPlayerDrmTestBase.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.app.DownloadManager;
import android.app.DownloadManager.Request;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/NativeMediaDrmClearkeyTest.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/NativeMediaDrmClearkeyTest.java
similarity index 99%
rename from tests/tests/media/drm/src/android/media/drm/cts/NativeMediaDrmClearkeyTest.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/NativeMediaDrmClearkeyTest.java
index f80ebda..0bb09ca 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/NativeMediaDrmClearkeyTest.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/NativeMediaDrmClearkeyTest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.content.pm.PackageManager;
import android.media.MediaDrm;
diff --git a/tests/tests/media/drm/src/android/media/drm/cts/WorkDir.java b/tests/tests/media/drmframework/src/android/media/drmframework/cts/WorkDir.java
similarity index 86%
rename from tests/tests/media/drm/src/android/media/drm/cts/WorkDir.java
rename to tests/tests/media/drmframework/src/android/media/drmframework/cts/WorkDir.java
index 7f6a1b8..5636d63 100644
--- a/tests/tests/media/drm/src/android/media/drm/cts/WorkDir.java
+++ b/tests/tests/media/drmframework/src/android/media/drmframework/cts/WorkDir.java
@@ -14,12 +14,12 @@
* limitations under the License.
*/
-package android.media.drm.cts;
+package android.media.drmframework.cts;
import android.media.cts.WorkDirBase;
class WorkDir extends WorkDirBase {
public static final String getMediaDirString() {
- return getMediaDirString("CtsMediaDrmTestCases-1.4");
+ return getMediaDirString("CtsMediaDrmFrameworkTestCases-1.0");
}
}
diff --git a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
index c76d150..d38f767 100644
--- a/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
+++ b/tests/tests/media/misc/src/android/media/misc/cts/MediaRouter2Test.java
@@ -198,7 +198,7 @@
public void testAllowedPackages() throws Exception {
RouteDiscoveryPreference preference =
new RouteDiscoveryPreference.Builder(FEATURES_ALL, true)
- .setAllowedPackages(List.of("android.media.cts"))
+ .setAllowedPackages(List.of("android.media.misc.cts"))
.build();
Map<String, MediaRoute2Info> routes = waitAndGetRoutes(preference);
@@ -591,11 +591,11 @@
try {
mRouter2.registerTransferCallback(mExecutor, transferCallback);
- mRouter2.transferTo(route);
-
// Unregisters transfer callback
mRouter2.unregisterTransferCallback(transferCallback);
+ mRouter2.transferTo(route);
+
// No transfer callback methods should be called.
assertFalse(successLatch.await(WAIT_MS, TimeUnit.MILLISECONDS));
assertFalse(failureLatch.await(WAIT_MS, TimeUnit.MILLISECONDS));
diff --git a/tests/tests/os/src/android/os/cts/ProcessTest.java b/tests/tests/os/src/android/os/cts/ProcessTest.java
index ebffb79..8ca7811 100644
--- a/tests/tests/os/src/android/os/cts/ProcessTest.java
+++ b/tests/tests/os/src/android/os/cts/ProcessTest.java
@@ -16,7 +16,11 @@
package android.os.cts;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import android.content.ComponentName;
import android.content.Context;
@@ -24,15 +28,24 @@
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.Process;
-import android.test.AndroidTestCase;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+
/**
* CTS for {@link android.os.Process}.
*
* We have more test in cts/tests/process/ too.
*/
-public class ProcessTest extends AndroidTestCase {
+@RunWith(JUnit4.class)
+public class ProcessTest {
public static final int THREAD_PRIORITY_HIGHEST = -20;
private static final String NONE_EXISITENT_NAME = "abcdefcg";
@@ -40,6 +53,8 @@
private static final String PROCESS_SHELL= "shell";
private static final String PROCESS_CACHE= "cache";
private static final String REMOTE_SERVICE = "android.app.REMOTESERVICE";
+ private static final int APP_UID = 10001;
+ private static final int SANDBOX_SDK_UID = 20001;
private static final String TAG = "ProcessTest";
private ISecondary mSecondaryService = null;
private Intent mIntent;
@@ -47,10 +62,11 @@
private boolean mHasConnected;
private boolean mHasDisconnected;
private ServiceConnection mSecondaryConnection;
+ private Context mContext;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getContext();
mSync = new Object();
mSecondaryConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className,
@@ -74,12 +90,12 @@
}
};
mIntent = new Intent(REMOTE_SERVICE);
- mIntent.setPackage(getContext().getPackageName());
- getContext().startService(mIntent);
+ mIntent.setPackage(mContext.getPackageName());
+ mContext.startService(mIntent);
Intent secondaryIntent = new Intent(ISecondary.class.getName());
- secondaryIntent.setPackage(getContext().getPackageName());
- getContext().bindService(secondaryIntent, mSecondaryConnection,
+ secondaryIntent.setPackage(mContext.getPackageName());
+ mContext.bindService(secondaryIntent, mSecondaryConnection,
Context.BIND_AUTO_CREATE);
synchronized (mSync) {
if (!mHasConnected) {
@@ -91,17 +107,17 @@
}
}
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
+ @After
+ public void tearDown() throws Exception {
if (mIntent != null) {
- getContext().stopService(mIntent);
+ mContext.stopService(mIntent);
}
if (mSecondaryConnection != null) {
- getContext().unbindService(mSecondaryConnection);
+ mContext.unbindService(mSecondaryConnection);
}
}
+ @Test
public void testMiscMethods() {
/*
* Test setThreadPriority(int) and setThreadPriority(int, int)
@@ -163,6 +179,7 @@
* Only the process running the caller's packages/application
* and any additional processes created by that app be able to kill each other's processes.
*/
+ @Test
public void testKillProcess() throws Exception {
long time = 0;
int servicePid = 0;
@@ -170,7 +187,7 @@
servicePid = mSecondaryService.getPid();
time = mSecondaryService.getElapsedCpuTime();
} finally {
- getContext().stopService(mIntent);
+ mContext.stopService(mIntent);
mIntent = null;
}
@@ -196,12 +213,13 @@
* Test sendSignal(int) point.
* Send a signal to the given process.
*/
+ @Test
public void testSendSignal() throws Exception {
int servicePid = 0;
try {
servicePid = mSecondaryService.getPid();
} finally {
- getContext().stopService(mIntent);
+ mContext.stopService(mIntent);
mIntent = null;
}
assertTrue(servicePid != 0);
@@ -217,4 +235,18 @@
}
assertTrue(mHasDisconnected);
}
+
+ /**
+ * Tests APIs related to sdk sandbox uids.
+ */
+ @Test
+ public void testSdkSandboxUids() {
+ assertEquals(SANDBOX_SDK_UID, Process.toSdkSandboxUid(APP_UID));
+ assertEquals(APP_UID, Process.sdkSandboxToAppUid(SANDBOX_SDK_UID));
+
+ assertFalse(Process.isSdkSandboxUid(APP_UID));
+ assertTrue(Process.isSdkSandboxUid(SANDBOX_SDK_UID));
+
+ assertFalse(Process.isSdkSandbox());
+ }
}
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 28ffcd3..c26ab8d 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -6862,10 +6862,6 @@
android:resource="@xml/autofill_compat_accessibility_service" />
</service>
- <service android:name="com.google.android.startop.iorap.IorapForwardingService$IorapdJobServiceProxy"
- android:permission="android.permission.BIND_JOB_SERVICE" >
- </service>
-
<service android:name="com.android.server.blob.BlobStoreIdleJobService"
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
diff --git a/tests/tests/permission2/res/raw/automotive_android_manifest.xml b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
index 4117a78..d37ff8b 100644
--- a/tests/tests/permission2/res/raw/automotive_android_manifest.xml
+++ b/tests/tests/permission2/res/raw/automotive_android_manifest.xml
@@ -16,20 +16,26 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- package="com.android.car"
- coreApp="true"
- android:sharedUserId="android.uid.system">
+ package="com.android.car.updatable" >
- <original-package android:name="com.android.car"/>
- <permission-group android:name="android.car.permission-group.CAR_MONITORING"
- android:icon="@drawable/perm_group_car"
- android:description="@string/car_permission_desc"
- android:label="@string/car_permission_label"/>
+ <permission-group android:name="android.car.permission-group.CAR_MONITORING"
+ android:icon="@drawable/perm_group_car"
+ android:description="@string/car_permission_desc"
+ android:label="@string/car_permission_label"/>
<permission android:name="android.car.permission.CAR_ENERGY"
android:permissionGroup="android.car.permission-group.CAR_MONITORING"
android:protectionLevel="dangerous"
android:label="@string/car_permission_label_energy"
android:description="@string/car_permission_desc_energy"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_ENERGY"
+ android:permissionGroup="android.car.permission-group.CAR_MONITORING"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_energy"
+ android:description="@string/car_permission_desc_control_car_energy"/>
+ <permission android:name="android.car.permission.ADJUST_RANGE_REMAINING"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_adjust_range_remaining"
+ android:description="@string/car_permission_desc_adjust_range_remaining"/>
<permission android:name="android.car.permission.CAR_IDENTIFICATION"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_car_identification"
@@ -83,6 +89,10 @@
android:protectionLevel="normal"
android:label="@string/car_permission_label_car_energy_ports"
android:description="@string/car_permission_desc_car_energy_ports"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_ENERGY_PORTS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_energy_ports"
+ android:description="@string/car_permission_desc_control_car_energy_ports"/>
<permission android:name="android.car.permission.CAR_ENGINE_DETAILED"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_car_engine_detailed"
@@ -115,10 +125,31 @@
android:protectionLevel="normal"
android:label="@string/car_permission_label_car_info"
android:description="@string/car_permission_desc_car_info"/>
+ <permission android:name="android.car.permission.PRIVILEGED_CAR_INFO"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_privileged_car_info"
+ android:description="@string/car_permission_desc_privileged_car_info"/>
+ <permission android:name="android.car.permission.READ_CAR_VENDOR_PERMISSION_INFO"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_vendor_permission_info"
+ android:description="@string/car_permission_desc_vendor_permission_info"/>
+
+ <!-- Allows an application to read the vehicle exterior environment information. For example,
+ it allows an application to read the vehicle exterior temperature and night mode status.
+ <p>Protection level: normal
+ -->
<permission android:name="android.car.permission.CAR_EXTERIOR_ENVIRONMENT"
android:protectionLevel="normal"
android:label="@string/car_permission_label_car_exterior_environment"
android:description="@string/car_permission_desc_car_exterior_environment"/>
+ <permission android:name="android.car.permission.CAR_EPOCH_TIME"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_car_epoch_time"
+ android:description="@string/car_permission_desc_car_epoch_time"/>
+ <permission android:name="android.car.permission.STORAGE_ENCRYPTION_BINDING_SEED"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_encryption_binding_seed"
+ android:description="@string/car_permission_desc_encryption_binding_seed"/>
<permission android:name="android.car.permission.CAR_EXTERIOR_LIGHTS"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_car_exterior_lights"
@@ -171,385 +202,276 @@
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_driving_state"
android:description="@string/car_permission_desc_driving_state"/>
- <!-- may replace this with system permission if proper one is defined. -->
+ <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_use_telemetry_service"
+ android:description="@string/car_permission_desc_use_telemetry_service"/>
+ <permission android:name="android.car.permission.REQUEST_CAR_EVS_ACTIVITY"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_request_evs_activity"
+ android:description="@string/car_permission_desc_request_evs_activity"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_evs_activity"
+ android:description="@string/car_permission_desc_control_evs_activity"/>
+ <permission android:name="android.car.permission.USE_CAR_EVS_CAMERA"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_use_evs_camera"
+ android:description="@string/car_permission_desc_use_evs_camera"/>
+ <permission android:name="android.car.permission.MONITOR_CAR_EVS_STATUS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_monitor_evs_status"
+ android:description="@string/car_permission_desc_monitor_evs_status"/>
<permission android:name="android.car.permission.CONTROL_APP_BLOCKING"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_control_app_blocking"
android:description="@string/car_permission_desc_control_app_blocking"/>
- <permission android:name="android.car.permission.ADJUST_RANGE_REMAINING"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_adjust_range_remaining"
- android:description="@string/car_permission_desc_adjust_range_remaining"/>
- <permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_read_car_occupant_awareness_state"
- android:description="@string/car_permission_desc_read_car_occupant_awareness_state"/>
- <permission android:name="android.car.permission.CONTROL_CAR_ENERGY_PORTS"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_control_car_energy_ports"
- android:description="@string/car_permission_desc_control_car_energy_ports"/>
- <permission android:name="android.car.permission.CONTROL_CAR_OCCUPANT_AWARENESS_SYSTEM"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_control_car_occupant_awareness_system"
- android:description="@string/car_permission_desc_control_car_occupant_awareness_system"/>
- <permission android:name="android.car.permission.CONTROL_CAR_FEATURES"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_control_car_features"
- android:description="@string/car_permission_desc_control_car_features"/>
- <permission android:name="android.car.permission.USE_CAR_WATCHDOG"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_use_car_watchdog"
- android:description="@string/car_permission_desc_use_car_watchdog"/>
- <permission android:name="android.car.permission.READ_CAR_VENDOR_PERMISSION_INFO"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_vendor_permission_info"
- android:description="@string/car_permission_desc_vendor_permission_info"/>
- <!-- Permission for vendor properties -->
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_WINDOW"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_window"
- android:description="@string/car_permission_desc_get_car_vendor_category_window"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_WINDOW"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_window"
- android:description="@string/car_permission_desc_set_car_vendor_category_window"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_DOOR"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_door"
- android:description="@string/car_permission_desc_get_car_vendor_category_door"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_DOOR"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_door"
- android:description="@string/car_permission_desc_set_car_vendor_category_door"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_seat"
- android:description="@string/car_permission_desc_get_car_vendor_category_seat"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_SEAT"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_seat"
- android:description="@string/car_permission_desc_set_car_vendor_category_seat"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_MIRROR"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_mirror"
- android:description="@string/car_permission_desc_get_car_vendor_category_mirror"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_MIRROR"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_mirror"
- android:description="@string/car_permission_desc_set_car_vendor_category_mirror"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_info"
- android:description="@string/car_permission_desc_get_car_vendor_category_info"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_info"
- android:description="@string/car_permission_desc_set_car_vendor_category_info"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_ENGINE"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_engine"
- android:description="@string/car_permission_desc_get_car_vendor_category_engine"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_ENGINE"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_engine"
- android:description="@string/car_permission_desc_set_car_vendor_category_engine"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_HVAC"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_hvac"
- android:description="@string/car_permission_desc_get_car_vendor_category_hvac"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_HVAC"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_hvac"
- android:description="@string/car_permission_desc_set_car_vendor_category_hvac"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_LIGHT"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_light"
- android:description="@string/car_permission_desc_get_car_vendor_category_light"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_LIGHT"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_light"
- android:description="@string/car_permission_desc_set_car_vendor_category_light"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_1"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_1"
- android:description="@string/car_permission_desc_get_car_vendor_category_1"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_1"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_1"
- android:description="@string/car_permission_desc_set_car_vendor_category_1"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_2"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_2"
- android:description="@string/car_permission_desc_get_car_vendor_category_2"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_2"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_2"
- android:description="@string/car_permission_desc_set_car_vendor_category_2"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_3"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_3"
- android:description="@string/car_permission_desc_get_car_vendor_category_3"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_3"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_3"
- android:description="@string/car_permission_desc_set_car_vendor_category_3"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_4"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_4"
- android:description="@string/car_permission_desc_get_car_vendor_category_4"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_4"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_4"
- android:description="@string/car_permission_desc_set_car_vendor_category_4"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_5"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_5"
- android:description="@string/car_permission_desc_get_car_vendor_category_5"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_5"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_5"
- android:description="@string/car_permission_desc_set_car_vendor_category_5"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_6"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_6"
- android:description="@string/car_permission_desc_get_car_vendor_category_6"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_6"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_6"
- android:description="@string/car_permission_desc_set_car_vendor_category_6"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_7"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_7"
- android:description="@string/car_permission_desc_get_car_vendor_category_7"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_7"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_7"
- android:description="@string/car_permission_desc_set_car_vendor_category_7"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_8"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_8"
- android:description="@string/car_permission_desc_get_car_vendor_category_8"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_8"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_8"
- android:description="@string/car_permission_desc_set_car_vendor_category_8"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_9"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_9"
- android:description="@string/car_permission_desc_get_car_vendor_category_9"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_9"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_9"
- android:description="@string/car_permission_desc_set_car_vendor_category_9"/>
- <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_10"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_get_car_vendor_category_10"
- android:description="@string/car_permission_desc_get_car_vendor_category_10"/>
- <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_10"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_set_car_vendor_category_10"
- android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
-
<permission android:name="android.car.permission.CAR_CONTROL_AUDIO_VOLUME"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_audio_volume"
android:description="@string/car_permission_desc_audio_volume"/>
-
<permission android:name="android.car.permission.CAR_CONTROL_AUDIO_SETTINGS"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_audio_settings"
android:description="@string/car_permission_desc_audio_settings"/>
-
<permission android:name="android.car.permission.RECEIVE_CAR_AUDIO_DUCKING_EVENTS"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_receive_ducking"
android:description="@string/car_permission_desc_receive_ducking"/>
-
<permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"
android:protectionLevel="signature"
android:label="@string/car_permission_label_bind_instrument_cluster_rendering"
android:description="@string/car_permission_desc_bind_instrument_cluster_rendering"/>
-
<permission android:name="android.car.permission.BIND_CAR_INPUT_SERVICE"
android:protectionLevel="signature"
android:label="@string/car_permission_label_bind_input_service"
android:description="@string/car_permission_desc_bind_input_service"/>
-
<permission android:name="android.car.permission.CAR_DISPLAY_IN_CLUSTER"
android:protectionLevel="system|signature"
android:label="@string/car_permission_car_display_in_cluster"
android:description="@string/car_permission_desc_car_display_in_cluster"/>
-
<permission android:name="android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL"
android:protectionLevel="system|signature"
android:label="@string/car_permission_car_cluster_control"
android:description="@string/car_permission_desc_car_cluster_control"/>
-
<permission android:name="android.car.permission.CAR_MONITOR_CLUSTER_NAVIGATION_STATE"
- android:protectionLevel="signature|privileged"
+ android:protectionLevel="system|signature"
android:label="@string/car_permission_car_monitor_cluster_navigation_state"
android:description="@string/car_permission_desc_car_monitor_cluster_navigation_state"/>
-
<permission android:name="android.car.permission.CAR_HANDLE_USB_AOAP_DEVICE"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_car_handle_usb_aoap_device"
android:description="@string/car_permission_desc_car_handle_usb_aoap_device"/>
-
<permission android:name="android.car.permission.CAR_UX_RESTRICTIONS_CONFIGURATION"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_car_ux_restrictions_configuration"
android:description="@string/car_permission_desc_car_ux_restrictions_configuration"/>
-
+ <permission android:name="android.car.permission.READ_CAR_OCCUPANT_AWARENESS_STATE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_read_car_occupant_awareness_state"
+ android:description="@string/car_permission_desc_read_car_occupant_awareness_state"/>
+ <permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_access_private_display_id"
+ android:description="@string/car_permission_desc_access_private_display_id"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_OCCUPANT_AWARENESS_SYSTEM"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_occupant_awareness_system"
+ android:description="@string/car_permission_desc_control_car_occupant_awareness_system"/>
<permission android:name="android.car.permission.STORAGE_MONITORING"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_storage_monitoring"
android:description="@string/car_permission_desc_storage_monitoring"/>
-
<permission android:name="android.car.permission.CAR_ENROLL_TRUST"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_enroll_trust"
android:description="@string/car_permission_desc_enroll_trust"/>
-
<permission android:name="android.car.permission.CAR_TEST_SERVICE"
android:protectionLevel="system|signature"
android:label="@string/car_permission_label_car_test_service"
android:description="@string/car_permission_desc_car_test_service"/>
-
- <permission android:name="android.car.permission.ACCESS_PRIVATE_DISPLAY_ID"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_access_private_display_id"
- android:description="@string/car_permission_desc_access_private_display_id"/>
-
- <permission android:name="android.car.permission.MONITOR_CAR_EVS_STATUS"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_monitor_evs_status"
- android:description="@string/car_permission_desc_monitor_evs_status"/>
-
- <permission android:name="android.car.permission.CONTROL_CAR_POWER_POLICY"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_control_car_power_policy"
- android:description="@string/car_permission_desc_control_car_power_policy"/>
-
- <permission android:name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_collect_car_watchdog_metrics"
- android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
-
- <permission android:name="android.car.permission.USE_CAR_TELEMETRY_SERVICE"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_use_telemetry_service"
- android:description="@string/car_permission_desc_use_telemetry_service"/>
-
- <permission android:name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_control_evs_activity"
- android:description="@string/car_permission_desc_control_evs_activity"/>
-
- <permission android:name="android.car.permission.REQUEST_CAR_EVS_ACTIVITY"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_request_evs_activity"
- android:description="@string/car_permission_desc_request_evs_activity"/>
-
- <permission android:name="android.car.permission.USE_CAR_EVS_CAMERA"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_use_evs_camera"
- android:description="@string/car_permission_desc_use_evs_camera"/>
-
- <permission android:name="android.car.permission.STORAGE_ENCRYPTION_BINDING_SEED"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_encryption_binding_seed"
- android:description="@string/car_permission_desc_encryption_binding_seed"/>
-
- <permission android:name="android.car.permission.READ_CAR_POWER_POLICY"
- android:protectionLevel="normal"
- android:label="@string/car_permission_label_read_car_power_policy"
- android:description="@string/car_permission_desc_read_car_power_policy"/>
-
- <permission android:name="android.car.permission.CAR_EPOCH_TIME"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_car_epoch_time"
- android:description="@string/car_permission_desc_car_epoch_time"/>
-
+ <permission android:name="android.car.permission.CONTROL_CAR_FEATURES"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_features"
+ android:description="@string/car_permission_desc_control_car_features"/>
+ <permission android:name="android.car.permission.USE_CAR_WATCHDOG"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_use_car_watchdog"
+ android:description="@string/car_permission_desc_use_car_watchdog"/>
<permission android:name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_control_car_watchdog_config"
- android:description="@string/car_permission_desc_control_car_watchdog_config"/>
-
- <permission android:name="android.car.permission.TEMPLATE_RENDERER"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_template_renderer"
- android:description="@string/car_permission_desc_template_renderer"/>
-
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_watchdog_config"
+ android:description="@string/car_permission_desc_control_car_watchdog_config"/>
+ <permission android:name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_collect_car_watchdog_metrics"
+ android:description="@string/car_permission_desc_collect_car_watchdog_metrics"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_WINDOW"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_window"
+ android:description="@string/car_permission_desc_get_car_vendor_category_window"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_WINDOW"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_window"
+ android:description="@string/car_permission_desc_set_car_vendor_category_window"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_DOOR"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_door"
+ android:description="@string/car_permission_desc_get_car_vendor_category_door"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_DOOR"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_door"
+ android:description="@string/car_permission_desc_set_car_vendor_category_door"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_SEAT"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_seat"
+ android:description="@string/car_permission_desc_get_car_vendor_category_seat"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_SEAT"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_seat"
+ android:description="@string/car_permission_desc_set_car_vendor_category_seat"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_MIRROR"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_mirror"
+ android:description="@string/car_permission_desc_get_car_vendor_category_mirror"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_MIRROR"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_mirror"
+ android:description="@string/car_permission_desc_set_car_vendor_category_mirror"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_INFO"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_info"
+ android:description="@string/car_permission_desc_get_car_vendor_category_info"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_INFO"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_info"
+ android:description="@string/car_permission_desc_set_car_vendor_category_info"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_ENGINE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_engine"
+ android:description="@string/car_permission_desc_get_car_vendor_category_engine"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_ENGINE"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_engine"
+ android:description="@string/car_permission_desc_set_car_vendor_category_engine"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_HVAC"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_hvac"
+ android:description="@string/car_permission_desc_get_car_vendor_category_hvac"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_HVAC"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_hvac"
+ android:description="@string/car_permission_desc_set_car_vendor_category_hvac"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_LIGHT"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_light"
+ android:description="@string/car_permission_desc_get_car_vendor_category_light"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_LIGHT"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_light"
+ android:description="@string/car_permission_desc_set_car_vendor_category_light"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_1"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_1"
+ android:description="@string/car_permission_desc_get_car_vendor_category_1"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_1"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_1"
+ android:description="@string/car_permission_desc_set_car_vendor_category_1"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_2"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_2"
+ android:description="@string/car_permission_desc_get_car_vendor_category_2"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_2"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_2"
+ android:description="@string/car_permission_desc_set_car_vendor_category_2"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_3"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_3"
+ android:description="@string/car_permission_desc_get_car_vendor_category_3"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_3"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_3"
+ android:description="@string/car_permission_desc_set_car_vendor_category_3"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_4"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_4"
+ android:description="@string/car_permission_desc_get_car_vendor_category_4"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_4"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_4"
+ android:description="@string/car_permission_desc_set_car_vendor_category_4"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_5"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_5"
+ android:description="@string/car_permission_desc_get_car_vendor_category_5"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_5"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_5"
+ android:description="@string/car_permission_desc_set_car_vendor_category_5"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_6"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_6"
+ android:description="@string/car_permission_desc_get_car_vendor_category_6"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_6"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_6"
+ android:description="@string/car_permission_desc_set_car_vendor_category_6"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_7"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_7"
+ android:description="@string/car_permission_desc_get_car_vendor_category_7"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_7"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_7"
+ android:description="@string/car_permission_desc_set_car_vendor_category_7"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_8"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_8"
+ android:description="@string/car_permission_desc_get_car_vendor_category_8"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_8"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_8"
+ android:description="@string/car_permission_desc_set_car_vendor_category_8"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_9"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_9"
+ android:description="@string/car_permission_desc_get_car_vendor_category_9"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_9"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_9"
+ android:description="@string/car_permission_desc_set_car_vendor_category_9"/>
+ <permission android:name="android.car.permission.GET_CAR_VENDOR_CATEGORY_10"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_get_car_vendor_category_10"
+ android:description="@string/car_permission_desc_get_car_vendor_category_10"/>
+ <permission android:name="android.car.permission.SET_CAR_VENDOR_CATEGORY_10"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_set_car_vendor_category_10"
+ android:description="@string/car_permission_desc_set_car_vendor_category_10"/>
<permission android:name="android.car.permission.CAR_MONITOR_INPUT"
- android:protectionLevel="signature|privileged"
- android:label="@string/car_permission_label_monitor_input"
- android:description="@string/car_permission_desc_monitor_input"/>
-
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_monitor_input"
+ android:description="@string/car_permission_desc_monitor_input"/>
+ <permission android:name="android.car.permission.READ_CAR_POWER_POLICY"
+ android:protectionLevel="normal"
+ android:label="@string/car_permission_label_read_car_power_policy"
+ android:description="@string/car_permission_desc_read_car_power_policy"/>
+ <permission android:name="android.car.permission.CONTROL_CAR_POWER_POLICY"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_control_car_power_policy"
+ android:description="@string/car_permission_desc_control_car_power_policy"/>
+ <permission android:name="android.car.permission.CONTROL_SHUTDOWN_PROCESS"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_adjust_shutdown_process"
+ android:description="@string/car_permission_desc_adjust_shutdown_process"/>
+ <permission android:name="android.car.permission.TEMPLATE_RENDERER"
+ android:protectionLevel="system|signature"
+ android:label="@string/car_permission_label_template_renderer"
+ android:description="@string/car_permission_desc_template_renderer"/>
<permission android:name="android.car.permission.CONTROL_CAR_APP_LAUNCH"
- android:protectionLevel="signature|privileged"
+ android:protectionLevel="system|signature"
android:label="@string/car_permission_label_control_car_app_launch"
android:description="@string/car_permission_desc_control_car_app_launch"/>
-
- <uses-permission android:name="android.permission.CALL_PHONE"/>
- <uses-permission android:name="android.permission.DEVICE_POWER"/>
- <uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"/>
- <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/>
- <uses-permission android:name="android.permission.MANAGE_ACTIVITY_TASKS"/>
- <uses-permission android:name="android.permission.MODIFY_AUDIO_ROUTING"/>
- <uses-permission android:name="android.permission.MODIFY_DAY_NIGHT_MODE"/>
- <uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>
- <uses-permission android:name="android.permission.READ_CALL_LOG"/>
- <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
- <uses-permission android:name="android.permission.REAL_GET_TASKS"/>
- <uses-permission android:name="android.permission.REBOOT"/>
- <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
- <uses-permission android:name="android.permission.REMOVE_TASKS"/>
- <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
- <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
- <uses-permission android:name="android.permission.BLUETOOTH"/>
- <uses-permission android:name="android.permission.MANAGE_USERS"/>
- <uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT"/>
-
- <application android:label="@string/app_title"
- android:directBootAware="true"
- android:allowBackup="false"
- android:persistent="true">
-
- <uses-library android:name="android.test.runner"/>
- <service android:name=".CarService"
- android:singleUser="true"
- android:exported="true">
- <intent-filter>
- <action android:name="android.car.ICar"/>
- </intent-filter>
- </service>
- <service android:name=".PerUserCarService"
- android:exported="false"/>
-
- <service android:name="com.android.car.trust.CarBleTrustAgent"
- android:permission="android.permission.BIND_TRUST_AGENT"
- android:singleUser="true"
- android:exported="true">
- <intent-filter>
- <action android:name="android.service.trust.TrustAgentService"/>
- <category android:name="android.intent.category.DEFAULT"/>
- </intent-filter>
- <!-- Warning: the meta data must be included if the service is direct boot aware.
- If not included, the device will crash before boot completes. Rendering the
- device unusable. -->
- <meta-data android:name="android.service.trust.trustagent"
- android:resource="@xml/car_trust_agent"/>
- </service>
- <activity android:name="com.android.car.pm.ActivityBlockingActivity"
- android:excludeFromRecents="true"
- android:theme="@android:style/Theme.Translucent.NoTitleBar"
- android:exported="false"
- android:launchMode="singleTask">
- <intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- </intent-filter>
- </activity>
- </application>
</manifest>
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index a7c46f1..edfcf3a 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -30,6 +30,7 @@
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.os.Process;
+import android.os.SystemProperties;
import android.platform.test.annotations.AppModeFull;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -76,8 +77,6 @@
private static final String PLATFORM_ROOT_NAMESPACE = "android.";
- private static final String AUTOMOTIVE_SERVICE_PACKAGE_NAME = "com.android.car";
-
private static final String TAG_PERMISSION = "permission";
private static final String TAG_PERMISSION_GROUP = "permission-group";
@@ -123,8 +122,14 @@
if (sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
expectedPermissions.addAll(loadExpectedPermissions(R.raw.automotive_android_manifest));
+ String carServicePackageName = SystemProperties.get("ro.android.car.carservice.package",
+ null);
+
+ assertWithMessage("Car service package not defined").that(
+ carServicePackageName).isNotNull();
+
declaredPermissionsMap.putAll(
- getPermissionsForPackage(sContext, AUTOMOTIVE_SERVICE_PACKAGE_NAME));
+ getPermissionsForPackage(sContext, carServicePackageName));
}
for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
diff --git a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
index 9e09ad1..457549f 100644
--- a/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
+++ b/tests/tests/permission3/CreateNotificationChannelsApp31/src/android/permission3/cts/usepermission/CreateNotificationChannelsActivity.kt
@@ -28,8 +28,9 @@
const val EXTRA_DELETE_CHANNELS_ON_CLOSE = "extra_delete_channels_on_close"
const val EXTRA_CREATE_CHANNELS = "extra_create"
const val EXTRA_CREATE_CHANNELS_DELAYED = "extra_create_delayed"
-const val EXTRA_REQUEST_PERMISSIONS = "extra_request_permissions"
-const val EXTRA_REQUEST_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
+const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
const val CHANNEL_ID = "channel_id"
const val BROADCAST_ACTION = "usepermission.createchannels.BROADCAST"
const val DELAY_MS = 1000L
@@ -53,13 +54,17 @@
}, DELAY_MS)
}
- if (intent.getBooleanExtra(EXTRA_REQUEST_PERMISSIONS, false)) {
+ if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
- } else if (intent.getBooleanExtra(EXTRA_REQUEST_PERMISSIONS_DELAYED, false)) {
+ } else if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED, false)) {
handler.postDelayed({
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
}, DELAY_MS)
}
+
+ if (intent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
+ requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
+ }
super.onStart()
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index dc83cd2..ebdc507 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -22,6 +22,7 @@
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
+import android.os.Build
import android.provider.Settings
import android.support.test.uiautomator.By
import android.support.test.uiautomator.BySelector
@@ -31,6 +32,7 @@
import android.text.style.ClickableSpan
import android.view.View
import com.android.compatibility.common.util.SystemUtil.eventually
+import com.android.modules.utils.build.SdkLevel
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
@@ -96,11 +98,21 @@
const val ASK_BUTTON_TEXT = "app_permission_button_ask"
const val ALLOW_ONE_TIME_BUTTON_TEXT = "grant_dialog_button_allow_one_time"
const val DENY_BUTTON_TEXT = "grant_dialog_button_deny"
+ const val DENY_ANYWAY_BUTTON_TEXT = "grant_dialog_button_deny_anyway"
const val DENY_AND_DONT_ASK_AGAIN_BUTTON_TEXT =
"grant_dialog_button_deny_and_dont_ask_again"
const val NO_UPGRADE_AND_DONT_ASK_AGAIN_BUTTON_TEXT = "grant_dialog_button_no_upgrade"
const val REQUEST_LOCATION_MESSAGE = "permgrouprequest_location"
+
+ val STORAGE_AND_MEDIA_PERMISSIONS = setOf(
+ android.Manifest.permission.READ_EXTERNAL_STORAGE,
+ android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ android.Manifest.permission.ACCESS_MEDIA_LOCATION,
+ android.Manifest.permission.READ_MEDIA_AUDIO,
+ android.Manifest.permission.READ_MEDIA_IMAGE,
+ android.Manifest.permission.READ_MEDIA_VIDEO
+ )
}
enum class PermissionState {
@@ -165,7 +177,15 @@
android.Manifest.permission.BLUETOOTH_CONNECT to
"@android:string/permgrouplab_nearby_devices",
android.Manifest.permission.BLUETOOTH_SCAN to
- "@android:string/permgrouplab_nearby_devices"
+ "@android:string/permgrouplab_nearby_devices",
+ // Aural
+ android.Manifest.permission.READ_MEDIA_AUDIO to
+ "@android:string/permgrouplab_readMediaAural",
+ // Visual
+ android.Manifest.permission.READ_MEDIA_IMAGE to
+ "@android:string/permgrouplab_readMediaVisual",
+ android.Manifest.permission.READ_MEDIA_VIDEO to
+ "@android:string/permgrouplab_readMediaVisual"
)
@Before
@@ -315,8 +335,8 @@
*/
protected fun clickNotificationPermissionRequestAllowButton() {
if (waitFindObjectOrNull(By.text(getPermissionControllerString(
- NOTIF_CONTINUE_TEXT, APP_PACKAGE_NAME)), 1000) != null
- || waitFindObjectOrNull(By.text(getPermissionControllerString(
+ NOTIF_CONTINUE_TEXT, APP_PACKAGE_NAME)), 1000) != null ||
+ waitFindObjectOrNull(By.text(getPermissionControllerString(
NOTIF_TEXT, APP_PACKAGE_NAME)), 1000) != null) {
if (isAutomotive) {
click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
@@ -558,7 +578,15 @@
if (!alreadyChecked) {
button.click()
}
- if (!alreadyChecked && isLegacyApp && wasGranted) {
+
+ val shouldShowStorageWarning = !isTv && !isWatch &&
+ SdkLevel.isAtLeastT() && targetSdk <= Build.VERSION_CODES.S_V2 &&
+ permission in STORAGE_AND_MEDIA_PERMISSIONS
+ if (shouldShowStorageWarning && state == PermissionState.ALLOWED) {
+ click(By.text(getPermissionControllerString(ALLOW_BUTTON_TEXT)))
+ } else if (shouldShowStorageWarning && state == PermissionState.DENIED) {
+ click(By.text(getPermissionControllerString(DENY_ANYWAY_BUTTON_TEXT)))
+ } else if (!alreadyChecked && isLegacyApp && wasGranted) {
if (!isTv) {
scrollToBottom()
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index 853bc10..2e5baf5 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -45,7 +45,8 @@
const val EXTRA_DELETE_CHANNELS_ON_CLOSE = "extra_delete_channels_on_close"
const val EXTRA_CREATE_CHANNELS = "extra_create"
const val EXTRA_CREATE_CHANNELS_DELAYED = "extra_create_delayed"
-const val EXTRA_REQUEST_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_OTHER_PERMISSIONS = "extra_request_permissions"
+const val EXTRA_REQUEST_NOTIF_PERMISSION = "extra_request_notif_permission"
const val EXTRA_REQUEST_PERMISSIONS_DELAYED = "extra_request_permissions_delayed"
const val ACTIVITY_NAME = "CreateNotificationChannelsActivity"
const val ACTIVITY_LABEL = "CreateNotif"
@@ -337,6 +338,18 @@
waitFindObject(By.textContains(ALLOW))
}
+ @Test
+ fun legacyAppCannotExplicitlyRequestNotifications() {
+ installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
+ launchApp(createChannels = false, requestNotificationPermission = true)
+ try {
+ clickPermissionRequestAllowButton()
+ Assert.fail("Expected not to find permission request dialog")
+ } catch (expected: RuntimeException) {
+ // Do nothing
+ }
+ }
+
private fun assertAppPermissionGrantedState(permission: String, granted: Boolean) {
SystemUtil.eventually {
runWithShellPermissionIdentity {
@@ -371,6 +384,7 @@
createChannels: Boolean = true,
createChannelsDelayed: Boolean = false,
deleteChannels: Boolean = false,
+ requestNotificationPermission: Boolean = false,
requestPermissions: Boolean = false,
requestPermissionsDelayed: Boolean = false,
launcherCategory: Boolean = true,
@@ -391,10 +405,11 @@
intent.putExtra(EXTRA_CREATE_CHANNELS_DELAYED, createChannelsDelayed)
}
intent.putExtra(EXTRA_DELETE_CHANNELS_ON_CLOSE, deleteChannels)
- intent.putExtra(EXTRA_REQUEST_PERMISSIONS, requestPermissions)
+ intent.putExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, requestPermissions)
if (!requestPermissions) {
intent.putExtra(EXTRA_REQUEST_PERMISSIONS_DELAYED, requestPermissionsDelayed)
}
+ intent.putExtra(EXTRA_REQUEST_NOTIF_PERMISSION, requestNotificationPermission)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
val options = ActivityOptions.makeBasic()
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTestMediaPermissions.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTestMediaPermissions.kt
new file mode 100644
index 0000000..86dd1e8
--- /dev/null
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTestMediaPermissions.kt
@@ -0,0 +1,112 @@
+/*
+ * 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.permission3.cts
+
+import android.os.Build
+import androidx.test.filters.SdkSuppress
+import org.junit.Assume.assumeFalse
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * Tests media storage supergroup behavior. I.e., on a T+ platform, for legacy (targetSdk<T) apps,
+ * the storage permission groups (STORAGE, AURAL, and VISUAL) form a supergroup, which effectively
+ * treats them as one group and therefore their permission state must always be equal.
+ */
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class PermissionTestMediaPermissions : BaseUsePermissionTest() {
+ private fun assertAllPermissionState(state: Boolean) {
+ for (permission in STORAGE_AND_MEDIA_PERMISSIONS) {
+ assertAppHasPermission(permission, state)
+ }
+ }
+
+ @Before
+ fun assumeNotTvOrWatch() {
+ assumeFalse(isTv)
+ assumeFalse(isWatch)
+ }
+
+ @Before
+ fun installApp23() {
+ installPackage(APP_APK_PATH_23)
+ }
+
+ @Before
+ fun assertAppStartsWithNoPermissions() {
+ assertAllPermissionState(false)
+ }
+
+ @Test
+ fun testWhenRESIsGrantedFromGrantDialogThenShouldGrantAllPermissions() {
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.READ_EXTERNAL_STORAGE to true
+ ) {
+ clickPermissionRequestAllowButton()
+ }
+ assertAllPermissionState(true)
+ }
+
+ @Test
+ fun testWhenRESIsGrantedManuallyThenShouldGrantAllPermissions() {
+ grantAppPermissions(android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23)
+ assertAllPermissionState(true)
+ }
+
+ @Test
+ fun testWhenAuralIsGrantedManuallyThenShouldGrantAllPermissions() {
+ grantAppPermissions(android.Manifest.permission.READ_MEDIA_AUDIO, targetSdk = 23)
+ assertAllPermissionState(true)
+ }
+
+ @Test
+ fun testWhenVisualIsGrantedManuallyThenShouldGrantAllPermissions() {
+ grantAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
+ assertAllPermissionState(true)
+ }
+
+ @Test
+ fun testWhenRESIsDeniedFromGrantDialogThenShouldDenyAllPermissions() {
+ requestAppPermissionsAndAssertResult(
+ android.Manifest.permission.READ_EXTERNAL_STORAGE to false
+ ) {
+ clickPermissionRequestDenyButton()
+ }
+ assertAllPermissionState(false)
+ }
+
+ @Test
+ fun testWhenRESIsDeniedManuallyThenShouldDenyAllPermissions() {
+ grantAppPermissions(android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23)
+ revokeAppPermissions(android.Manifest.permission.READ_EXTERNAL_STORAGE, targetSdk = 23)
+ assertAllPermissionState(false)
+ }
+
+ @Test
+ fun testWhenAuralIsDeniedManuallyThenShouldDenyAllPermissions() {
+ grantAppPermissions(android.Manifest.permission.READ_MEDIA_AUDIO, targetSdk = 23)
+ revokeAppPermissions(android.Manifest.permission.READ_MEDIA_AUDIO, targetSdk = 23)
+ assertAllPermissionState(false)
+ }
+
+ @Test
+ fun testWhenVisualIsDeniedManuallyThenShouldDenyAllPermissions() {
+ grantAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
+ revokeAppPermissions(android.Manifest.permission.READ_MEDIA_VIDEO, targetSdk = 23)
+ assertAllPermissionState(false)
+ }
+}
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
index 37e9d41..72f1de1 100644
--- a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -21,9 +21,11 @@
import android.hardware.SensorPrivacyManager.Sensors.CAMERA
import android.hardware.SensorPrivacyManager.Sensors.MICROPHONE
import android.location.LocationManager
+import android.Manifest.permission_group.CAMERA as CAMERA_PERMISSION_GROUP
+import android.Manifest.permission_group.LOCATION as LOCATION_PERMISSION_GROUP
+import android.Manifest.permission_group.MICROPHONE as MICROPHONE_PERMISSION_GROUP
import android.os.Build
import android.provider.DeviceConfig
-import android.provider.Settings
import android.support.test.uiautomator.By
import androidx.test.filters.SdkSuppress
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
@@ -31,6 +33,7 @@
import org.junit.After
import org.junit.Assume
import org.junit.Before
+import org.junit.Ignore
import org.junit.Test
/**
@@ -50,9 +53,9 @@
WARNING_BANNER_ENABLED, false.toString())
}
- private val permToLabel = mapOf(CAMERA to "privdash_label_camera",
- MICROPHONE to "privdash_label_microphone",
- LOCATION to "privdash_label_location")
+ private val sensorToPermissionGroup = mapOf(CAMERA to CAMERA_PERMISSION_GROUP,
+ MICROPHONE to MICROPHONE_PERMISSION_GROUP,
+ LOCATION to LOCATION_PERMISSION_GROUP)
private val permToTitle = mapOf(CAMERA to "blocked_camera_title",
MICROPHONE to "blocked_microphone_title",
@@ -80,17 +83,16 @@
}
private fun navigateAndTest(sensor: Int) {
- val permLabel = permToLabel.getOrDefault(sensor, "Break")
- val intent = Intent(Settings.ACTION_PRIVACY_SETTINGS)
+ val permissionGroup = sensorToPermissionGroup.getOrDefault(sensor, "Break")
+ val intent = Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
+ .putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroup)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- context.startActivity(intent)
- click(By.text(getPermissionControllerString("app_permission_manager")))
- click(By.text(getPermissionControllerString(permLabel)))
+ runWithShellPermissionIdentity {
+ context.startActivity(intent)
+ }
val bannerTitle = permToTitle.getOrDefault(sensor, "Break")
waitFindObject(By.text(getPermissionControllerString(bannerTitle)))
pressBack()
- pressBack()
- pressBack()
}
private fun runSensorTest(sensor: Int) {
@@ -117,6 +119,7 @@
}
@Test
+ @Ignore
fun testLocationCardDisplayed() {
runSensorTest(LOCATION)
}
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
index 019832d..090554b 100644
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
+++ b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_logging.xml
@@ -10,7 +10,7 @@
summary="@string/reference"
intentAction="intent"
profile="primary_profile_only"
- allowLogging="false"/>
+ loggingAllowed="false"/>
</safety-sources-group>
</safety-sources-config>
</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
index 5e46a44..caaeee6 100644
--- a/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
+++ b/tests/tests/safetycenter/res/xml/config_static_safety_source_with_refresh.xml
@@ -10,7 +10,7 @@
summary="@string/reference"
intentAction="intent"
profile="primary_profile_only"
- allowRefreshOnPageOpen="true"/>
+ refreshOnPageOpenAllowed="true"/>
</safety-sources-group>
</safety-sources-config>
</safety-center-config>
diff --git a/tests/tests/safetycenter/res/xml/config_valid.xml b/tests/tests/safetycenter/res/xml/config_valid.xml
index dfb0469..e2f9e77 100644
--- a/tests/tests/safetycenter/res/xml/config_valid.xml
+++ b/tests/tests/safetycenter/res/xml/config_valid.xml
@@ -24,8 +24,8 @@
maxSeverityLevel="300"
searchTerms="@string/reference"
broadcastReceiverClassName="broadcast"
- allowLogging="false"
- allowRefreshOnPageOpen="true"/>
+ loggingAllowed="false"
+ refreshOnPageOpenAllowed="true"/>
<dynamic-safety-source
id="dynamic_disabled"
packageName="package"
@@ -69,8 +69,8 @@
profile="all_profiles"
maxSeverityLevel="300"
broadcastReceiverClassName="broadcast"
- allowLogging="false"
- allowRefreshOnPageOpen="true"/>
+ loggingAllowed="false"
+ refreshOnPageOpenAllowed="true"/>
</safety-sources-group>
<safety-sources-group
id="mixed"
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
index c9ffb66..d276865 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigInvalidTest.kt
@@ -17,7 +17,8 @@
package android.safetycenter.config.cts
import android.content.Context
-import android.safetycenter.config.Parser
+import android.safetycenter.config.ParseException
+import android.safetycenter.config.SafetyCenterConfig
import android.safetycenter.cts.R
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import com.google.common.truth.Truth.assertThat
@@ -45,8 +46,8 @@
@Test
fun invalidConfig_throws() {
val parser = context.resources.getXml(params.configResourceId)
- val thrown = assertThrows(Parser.ParseException::class.java) {
- Parser.parseXmlResource(parser)
+ val thrown = assertThrows(ParseException::class.java) {
+ SafetyCenterConfig.fromXml(parser)
}
assertThat(thrown).hasMessageThat().isEqualTo(params.errorMessage)
if (params.causeErrorMessage != null) {
@@ -350,7 +351,7 @@
"ConfigStaticSafetySourceWithLogging",
R.xml.config_static_safety_source_with_logging,
"Element static-safety-source invalid",
- "Prohibited attribute allowLogging present"
+ "Prohibited attribute loggingAllowed present"
),
Params(
"ConfigStaticSafetySourceWithPackage",
@@ -368,7 +369,7 @@
"ConfigStaticSafetySourceWithRefresh",
R.xml.config_static_safety_source_with_refresh,
"Element static-safety-source invalid",
- "Prohibited attribute allowRefreshOnPageOpen present"
+ "Prohibited attribute refreshOnPageOpenAllowed present"
),
Params(
"ConfigStaticSafetySourceWithSeverity",
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
index 17d1cde..9190b6d 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/config/cts/ParserConfigValidTest.kt
@@ -17,7 +17,6 @@
package android.safetycenter.config.cts
import android.content.Context
-import android.safetycenter.config.Parser
import android.safetycenter.config.SafetyCenterConfig
import android.safetycenter.config.SafetySource
import android.safetycenter.config.SafetySourcesGroup
@@ -61,8 +60,8 @@
.setMaxSeverityLevel(300)
.setSearchTermsResId(R.string.reference)
.setBroadcastReceiverClassName("broadcast")
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build())
.addSafetySource(SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
.setId("dynamic_disabled")
@@ -112,8 +111,8 @@
.setProfile(SafetySource.PROFILE_ALL)
.setMaxSeverityLevel(300)
.setBroadcastReceiverClassName("broadcast")
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build())
.build())
.addSafetySourcesGroup(SafetySourcesGroup.Builder()
@@ -141,6 +140,6 @@
.build())
.build())
.build()
- assertEquals(expected, Parser.parseXmlResource(parser))
+ assertEquals(expected, SafetyCenterConfig.fromXml(parser))
}
}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
index 3c794ad..f2a96df 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/config/cts/SafetySourceTest.kt
@@ -230,35 +230,35 @@
}
@Test
- fun isAllowLogging_returnsAllowLoggingOrThrows() {
- assertThat(DYNAMIC_BAREBONE.isAllowLogging).isEqualTo(true)
- assertThat(DYNAMIC_ALL_OPTIONAL.isAllowLogging).isEqualTo(false)
- assertThat(DYNAMIC_DISABLED.isAllowLogging).isEqualTo(true)
- assertThat(DYNAMIC_HIDDEN.isAllowLogging).isEqualTo(true)
+ fun isLoggingAllowed_returnsLoggingAllowedOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.isLoggingAllowed).isEqualTo(true)
+ assertThat(DYNAMIC_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
+ assertThat(DYNAMIC_DISABLED.isLoggingAllowed).isEqualTo(true)
+ assertThat(DYNAMIC_HIDDEN.isLoggingAllowed).isEqualTo(true)
assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.isAllowLogging
+ STATIC_BAREBONE.isLoggingAllowed
}
assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.isAllowLogging
+ STATIC_ALL_OPTIONAL.isLoggingAllowed
}
- assertThat(ISSUE_ONLY_BAREBONE.isAllowLogging).isEqualTo(true)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.isAllowLogging).isEqualTo(false)
+ assertThat(ISSUE_ONLY_BAREBONE.isLoggingAllowed).isEqualTo(true)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.isLoggingAllowed).isEqualTo(false)
}
@Test
- fun isAllowRefreshOnPageOpen_returnsAllowRefreshOnPageOpenOrThrows() {
- assertThat(DYNAMIC_BAREBONE.isAllowRefreshOnPageOpen).isEqualTo(false)
- assertThat(DYNAMIC_ALL_OPTIONAL.isAllowRefreshOnPageOpen).isEqualTo(true)
- assertThat(DYNAMIC_DISABLED.isAllowRefreshOnPageOpen).isEqualTo(false)
- assertThat(DYNAMIC_HIDDEN.isAllowRefreshOnPageOpen).isEqualTo(false)
+ fun isRefreshOnPageOpenAllowed_returnsRefreshOnPageOpenAllowedOrThrows() {
+ assertThat(DYNAMIC_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThat(DYNAMIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
+ assertThat(DYNAMIC_DISABLED.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThat(DYNAMIC_HIDDEN.isRefreshOnPageOpenAllowed).isEqualTo(false)
assertThrows(UnsupportedOperationException::class.java) {
- STATIC_BAREBONE.isAllowRefreshOnPageOpen
+ STATIC_BAREBONE.isRefreshOnPageOpenAllowed
}
assertThrows(UnsupportedOperationException::class.java) {
- STATIC_ALL_OPTIONAL.isAllowRefreshOnPageOpen
+ STATIC_ALL_OPTIONAL.isRefreshOnPageOpenAllowed
}
- assertThat(ISSUE_ONLY_BAREBONE.isAllowRefreshOnPageOpen).isEqualTo(false)
- assertThat(ISSUE_ONLY_ALL_OPTIONAL.isAllowRefreshOnPageOpen).isEqualTo(true)
+ assertThat(ISSUE_ONLY_BAREBONE.isRefreshOnPageOpenAllowed).isEqualTo(false)
+ assertThat(ISSUE_ONLY_ALL_OPTIONAL.isRefreshOnPageOpenAllowed).isEqualTo(true)
}
@Test
@@ -327,8 +327,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalCopy)
}
@@ -360,8 +360,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -380,8 +380,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -400,8 +400,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -420,8 +420,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -440,8 +440,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -460,8 +460,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -491,8 +491,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -511,8 +511,8 @@
.setMaxSeverityLevel(-1)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -531,8 +531,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(-1)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -551,14 +551,14 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName("other")
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@Test
- fun hashCode_equals_toString_withDifferentAllowLoggings_areNotEqual() {
+ fun hashCode_equals_toString_withDifferentLoggingAlloweds_areNotEqual() {
val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
.setId(DYNAMIC_ALL_OPTIONAL_ID)
.setPackageName(PACKAGE_NAME)
@@ -571,14 +571,14 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(true)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(true)
+ .setRefreshOnPageOpenAllowed(true)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@Test
- fun hashCode_equals_toString_withDifferentAllowRefreshOnPageOpens_areNotEqual() {
+ fun hashCode_equals_toString_withDifferentRefreshOnPageOpenAlloweds_areNotEqual() {
val dynamicAllOptionalAlt = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
.setId(DYNAMIC_ALL_OPTIONAL_ID)
.setPackageName(PACKAGE_NAME)
@@ -591,8 +591,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(false)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(false)
.build()
AnyTester.assertThatRepresentationsAreNotEqual(DYNAMIC_ALL_OPTIONAL, dynamicAllOptionalAlt)
}
@@ -636,8 +636,8 @@
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setSearchTermsResId(REFERENCE_RES_ID)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
private val DYNAMIC_DISABLED =
@@ -692,8 +692,8 @@
.setProfile(SafetySource.PROFILE_ALL)
.setMaxSeverityLevel(MAX_SEVERITY_LEVEL)
.setBroadcastReceiverClassName(BROADCAST_RECEIVER_CLASS_NAME)
- .setAllowLogging(false)
- .setAllowRefreshOnPageOpen(true)
+ .setLoggingAllowed(false)
+ .setRefreshOnPageOpenAllowed(true)
.build()
}
}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
index a6a9f0a..c3c7e726 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterApisWithShellPermissions.kt
@@ -22,26 +22,32 @@
import android.safetycenter.SafetyCenterManager
import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetyEvent
+import android.safetycenter.config.SafetyCenterConfig
import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import java.util.concurrent.Executor
/**
- * Call {@link SafetyCenterManager#sendSafetyCenterUpdate} adopting Shell's
+ * Call {@link SafetyCenterManager#setSafetySourceData} adopting Shell's
* {@link SEND_SAFETY_CENTER_UPDATE} permission.
*/
-fun SafetyCenterManager.sendUpdateWithPermission(safetySourceData: SafetySourceData) =
+fun SafetyCenterManager.setSafetySourceDataWithPermission(
+ safetySourceId: String,
+ safetySourceData: SafetySourceData,
+ safetyEvent: SafetyEvent
+) =
runWithShellPermissionIdentity({
- sendSafetyCenterUpdate(safetySourceData)
+ setSafetySourceData(safetySourceId, safetySourceData, safetyEvent)
}, SEND_SAFETY_CENTER_UPDATE)
/**
- * Call {@link SafetyCenterManager#getLastSafetyCenterUpdate} adopting Shell's
+ * Call {@link SafetyCenterManager#getSafetySourceData} adopting Shell's
* {@link SEND_SAFETY_CENTER_UPDATE} permission.
*/
-fun SafetyCenterManager.getLastUpdateWithPermission(id: String): SafetySourceData? =
+fun SafetyCenterManager.getSafetySourceDataWithPermission(id: String): SafetySourceData? =
callWithShellPermissionIdentity({
- getLastSafetyCenterUpdate(id)
+ getSafetySourceData(id)
}, SEND_SAFETY_CENTER_UPDATE)
/**
@@ -82,24 +88,22 @@
}, MANAGE_SAFETY_CENTER)
/**
- * Call {@link SafetyCenterManager#clearSafetyCenterData} adopting Shell's
+ * Call {@link SafetyCenterManager#clearAllSafetySourceData} adopting Shell's
* {@link MANAGE_SAFETY_CENTER} permission.
*/
-fun SafetyCenterManager.clearDataWithPermission() =
+fun SafetyCenterManager.clearAllSafetySourceDataWithPermission() =
runWithShellPermissionIdentity({
- clearSafetyCenterData()
+ clearAllSafetySourceData()
}, MANAGE_SAFETY_CENTER)
-fun SafetyCenterManager.addAdditionalSafetySourceWithPermission(
- sourceId: String,
- packageName: String,
- broadcastReceiverName: String
+fun SafetyCenterManager.setSafetyCenterConfigOverrideWithPermission(
+ safetyCenterConfig: SafetyCenterConfig
) =
runWithShellPermissionIdentity({
- addAdditionalSafetySource(sourceId, packageName, broadcastReceiverName)
+ setSafetyCenterConfigOverride(safetyCenterConfig)
}, MANAGE_SAFETY_CENTER)
-fun SafetyCenterManager.clearAdditionalSafetySourcesWithPermission() =
+fun SafetyCenterManager.clearSafetyCenterConfigOverrideWithPermission() =
runWithShellPermissionIdentity({
- clearAdditionalSafetySources()
+ clearSafetyCenterConfigOverride()
}, MANAGE_SAFETY_CENTER)
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
index f86ce84..bd58849 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyCenterManagerTest.kt
@@ -34,9 +34,14 @@
import android.safetycenter.SafetyCenterManager.OnSafetyCenterDataChangedListener
import android.safetycenter.SafetySourceData
import android.safetycenter.SafetySourceIssue
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
import android.safetycenter.SafetySourceIssue.SEVERITY_LEVEL_CRITICAL_WARNING
import android.safetycenter.SafetySourceStatus
import android.safetycenter.SafetySourceStatus.STATUS_LEVEL_CRITICAL_WARNING
+import android.safetycenter.config.SafetyCenterConfig
+import android.safetycenter.config.SafetySource
+import android.safetycenter.config.SafetySourcesGroup
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
@@ -59,13 +64,12 @@
class SafetyCenterManagerTest {
private val context: Context = getApplicationContext()
private val safetyCenterManager = context.getSystemService(SafetyCenterManager::class.java)!!
- private val sourceId = "source_id"
private val somePendingIntent = PendingIntent.getActivity(
context, 0 /* requestCode */,
Intent(ACTION_SAFETY_CENTER).addFlags(FLAG_ACTIVITY_NEW_TASK),
FLAG_IMMUTABLE
)
- private val safetySourceDataOnPageOpen = SafetySourceData.Builder(sourceId)
+ private val safetySourceDataOnPageOpen = SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder(
"safetySourceDataOnPageOpen status title",
@@ -76,7 +80,7 @@
.build()
)
.build()
- private val safetySourceDataOnRescanClick = SafetySourceData.Builder(sourceId)
+ private val safetySourceDataOnRescanClick = SafetySourceData.Builder()
.setStatus(
SafetySourceStatus.Builder(
"safetySourceDataOnRescanClick status title",
@@ -100,51 +104,57 @@
@After
fun clearDataBetweenTest() {
safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
- safetyCenterManager.clearDataWithPermission()
+ safetyCenterManager.clearAllSafetySourceDataWithPermission()
SafetySourceBroadcastReceiver.reset()
}
@Before
- fun addAdditionalSafetySourcesBeforeTest() {
- safetyCenterManager.clearAdditionalSafetySourcesWithPermission()
- safetyCenterManager.addAdditionalSafetySourceWithPermission(
- sourceId, CTS_PACKAGE_NAME,
- CTS_BROADCAST_RECEIVER_NAME
- )
+ fun setSafetyCenterConfigOverrideBeforeTest() {
+ safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
+ // TODO(b/217944317): When the test API impl is finalized to override XML config, only
+ // override config in select test cases that require it. This is to ensure that we do have
+ // some test cases running with the XML config.
+ safetyCenterManager.setSafetyCenterConfigOverrideWithPermission(CTS_ONLY_CONFIG)
}
@After
- fun clearAdditionalSafetySourcesAfterTest() {
- safetyCenterManager.clearAdditionalSafetySourcesWithPermission()
+ fun clearSafetyCenterConfigOverrideAfterTest() {
+ safetyCenterManager.clearSafetyCenterConfigOverrideWithPermission()
}
@Test
- fun getLastSafetyCenterUpdate_noUpdate_returnsNull() {
- val lastSafetyCenterUpdate =
- safetyCenterManager.getLastUpdateWithPermission("some_unknown_id")
+ fun getSafetySourceData_notSet_returnsNull() {
+ val safetySourceData =
+ safetyCenterManager.getSafetySourceDataWithPermission("some_unknown_id")
- assertThat(lastSafetyCenterUpdate).isNull()
+ assertThat(safetySourceData).isNull()
}
@Test
- fun sendSafetyCenterUpdate_getLastSafetyCenterUpdateReturnsNewValue() {
- val id = "some_known_id"
- val safetyCenterUpdate = SafetySourceData.Builder(id).build()
- safetyCenterManager.sendUpdateWithPermission(safetyCenterUpdate)
+ fun setSafetySourceData_getSafetySourceDataReturnsNewValue() {
+ val safetySourceData = SafetySourceData.Builder().build()
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ CTS_SOURCE_ID,
+ safetySourceData,
+ EVENT_SOURCE_STATE_CHANGED
+ )
- val lastSafetyCenterUpdate =
- safetyCenterManager.getLastUpdateWithPermission(id)
+ val safetySourceDataResult =
+ safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
- assertThat(lastSafetyCenterUpdate).isEqualTo(safetyCenterUpdate)
+ assertThat(safetySourceDataResult).isEqualTo(safetySourceData)
}
@Test
- fun sendSafetyCenterUpdate_withSameId_replacesValue() {
- val id = "some_known_id"
- val firstSafetyCenterUpdate = SafetySourceData.Builder(id).build()
- safetyCenterManager.sendUpdateWithPermission(firstSafetyCenterUpdate)
+ fun setSafetySourceData_withSameId_replacesValue() {
+ val firstSafetySourceData = SafetySourceData.Builder().build()
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ CTS_SOURCE_ID,
+ firstSafetySourceData,
+ EVENT_SOURCE_STATE_CHANGED
+ )
- val secondSafetyCenterUpdate = SafetySourceData.Builder(id).setStatus(
+ val secondSafetySourceData = SafetySourceData.Builder().setStatus(
SafetySourceStatus.Builder(
"Status title", "Summary of the status", STATUS_LEVEL_CRITICAL_WARNING,
somePendingIntent
@@ -163,12 +173,15 @@
).build()
).build()
).build()
- safetyCenterManager.sendUpdateWithPermission(secondSafetyCenterUpdate)
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ CTS_SOURCE_ID,
+ secondSafetySourceData,
+ EVENT_SOURCE_STATE_CHANGED
+ )
- val lastSafetyCenterUpdate =
- safetyCenterManager.getLastUpdateWithPermission(id)
+ val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
- assertThat(lastSafetyCenterUpdate).isEqualTo(secondSafetyCenterUpdate)
+ assertThat(safetySourceData).isEqualTo(secondSafetySourceData)
}
@Test
@@ -186,8 +199,7 @@
)
}
- val isSafetyCenterEnabled =
- safetyCenterManager.isSafetyCenterEnabledWithPermission()
+ val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
assertThat(isSafetyCenterEnabled).isTrue()
}
@@ -207,8 +219,7 @@
)
}
- val isSafetyCenterEnabled =
- safetyCenterManager.isSafetyCenterEnabledWithPermission()
+ val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
assertThat(isSafetyCenterEnabled).isFalse()
}
@@ -228,8 +239,7 @@
)
}
- val isSafetyCenterEnabled =
- safetyCenterManager.isSafetyCenterEnabledWithPermission()
+ val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
assertThat(isSafetyCenterEnabled).isFalse()
}
@@ -249,8 +259,7 @@
)
}
- val isSafetyCenterEnabled =
- safetyCenterManager.isSafetyCenterEnabledWithPermission()
+ val isSafetyCenterEnabled = safetyCenterManager.isSafetyCenterEnabledWithPermission()
assertThat(isSafetyCenterEnabled).isFalse()
}
@@ -271,6 +280,7 @@
@Test
fun refreshSafetySources_whenReceiverDoesNotHaveSendingPermission_sourceDoesNotSendData() {
+ SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
safetyCenterManager.refreshSafetySourcesWithPermission(
@@ -280,39 +290,40 @@
assertFailsWith(TimeoutCancellationException::class) {
SafetySourceBroadcastReceiver.waitTillOnReceiveComplete(TIMEOUT_SHORT)
}
- val lastSafetyCenterUpdate =
- safetyCenterManager.getLastUpdateWithPermission(sourceId)
- assertThat(lastSafetyCenterUpdate).isNull()
+ val safetySourceData =
+ safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
+ assertThat(safetySourceData).isNull()
}
@Test
fun refreshSafetySources_withRefreshReasonRescanButtonClick_sourceSendsRescanData() {
+ SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_RESCAN_BUTTON_CLICK
)
- val lastSafetyCenterUpdate =
- safetyCenterManager.getLastUpdateWithPermission(sourceId)
- assertThat(lastSafetyCenterUpdate).isEqualTo(safetySourceDataOnRescanClick)
+ val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
+ assertThat(safetySourceData).isEqualTo(safetySourceDataOnRescanClick)
}
@Test
fun refreshSafetySources_withRefreshReasonPageOpen_sourceSendsPageOpenData() {
+ SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOnPageOpen
safetyCenterManager.refreshSafetySourcesWithReceiverPermissionAndWait(
REFRESH_REASON_PAGE_OPEN
)
- val lastSafetyCenterUpdate =
- safetyCenterManager.getLastUpdateWithPermission(sourceId)
- assertThat(lastSafetyCenterUpdate).isEqualTo(safetySourceDataOnPageOpen)
+ val safetySourceData = safetyCenterManager.getSafetySourceDataWithPermission(CTS_SOURCE_ID)
+ assertThat(safetySourceData).isEqualTo(safetySourceDataOnPageOpen)
}
@Test
fun refreshSafetySources_withInvalidRefreshSeason_throwsIllegalArgumentException() {
+ SafetySourceBroadcastReceiver.safetySourceId = CTS_SOURCE_ID
SafetySourceBroadcastReceiver.safetySourceDataOnPageOpen = safetySourceDataOnPageOpen
SafetySourceBroadcastReceiver.safetySourceDataOnRescanClick = safetySourceDataOnRescanClick
@@ -348,16 +359,19 @@
}
@Test
- fun addOnSafetyCenterDataChangedListener_listenerCalledOnSafetyCenterUpdate() {
+ fun addOnSafetyCenterDataChangedListener_listenerCalledOnSafetySourceData() {
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(), listener
)
// Receive initial data.
receiveListenerUpdate()
- val id = "some_known_id"
- val safetyCenterUpdate = SafetySourceData.Builder(id).build()
- safetyCenterManager.sendUpdateWithPermission(safetyCenterUpdate)
+ val safetySourceData = SafetySourceData.Builder().build()
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ CTS_SOURCE_ID,
+ safetySourceData,
+ EVENT_SOURCE_STATE_CHANGED
+ )
val safetyCenterDataFromListener = receiveListenerUpdate()
// TODO(b/218830137): Assert on content.
@@ -365,7 +379,7 @@
}
@Test
- fun removeOnSafetyCenterDataChangedListener_listenerNotCalledOnSafetyCenterUpdate() {
+ fun removeOnSafetyCenterDataChangedListener_listenerNotCalledOnSafetySourceData() {
safetyCenterManager.addOnSafetyCenterDataChangedListenerWithPermission(
directExecutor(), listener
)
@@ -373,9 +387,12 @@
receiveListenerUpdate()
safetyCenterManager.removeOnSafetyCenterDataChangedListenerWithPermission(listener)
- val id = "some_known_id"
- val safetyCenterUpdate = SafetySourceData.Builder(id).build()
- safetyCenterManager.sendUpdateWithPermission(safetyCenterUpdate)
+ val safetySourceData = SafetySourceData.Builder().build()
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ CTS_SOURCE_ID,
+ safetySourceData,
+ EVENT_SOURCE_STATE_CHANGED
+ )
assertFailsWith(TimeoutCancellationException::class) {
receiveListenerUpdate(TIMEOUT_SHORT)
@@ -454,5 +471,28 @@
"android.safetycenter.cts.SafetySourceBroadcastReceiver"
private val TIMEOUT_LONG: Duration = Duration.ofMillis(5000)
private val TIMEOUT_SHORT: Duration = Duration.ofMillis(1000)
+ private val EVENT_SOURCE_STATE_CHANGED =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
+ private const val CTS_SOURCE_ID = "cts_source_id"
+ // TODO(b/217944317): Consider moving the following to a file where they can be used by
+ // other tests.
+ private val CTS_SOURCE = SafetySource.Builder(SafetySource.SAFETY_SOURCE_TYPE_DYNAMIC)
+ .setId(CTS_SOURCE_ID)
+ .setPackageName(CTS_PACKAGE_NAME)
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .setIntentAction("SafetyCenterManagerTest.INTENT_ACTION")
+ .setBroadcastReceiverClassName(CTS_BROADCAST_RECEIVER_NAME)
+ .setProfile(SafetySource.PROFILE_PRIMARY)
+ .build()
+ private val CTS_SOURCE_GROUP = SafetySourcesGroup.Builder()
+ .setId("cts_source_group")
+ .setTitleResId(R.string.reference)
+ .setSummaryResId(R.string.reference)
+ .addSafetySource(CTS_SOURCE)
+ .build()
+ private val CTS_ONLY_CONFIG = SafetyCenterConfig.Builder()
+ .addSafetySourcesGroup(CTS_SOURCE_GROUP)
+ .build()
}
}
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
new file mode 100644
index 0000000..bc9d538
--- /dev/null
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetyEventTest.kt
@@ -0,0 +1,189 @@
+/*
+ * 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.safetycenter.cts
+
+import android.os.Build
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreEqual
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreNotEqual
+import android.safetycenter.testers.ParcelableTester.assertThatRoundTripReturnsOriginal
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** CTS tests for [SafetyEvent]. */
+@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+class SafetyEventTest {
+ @Test
+ fun getSafetyEventType_returnsSafetyEventType() {
+ val safetyEvent = SafetyEvent.Builder(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
+
+ assertThat(safetyEvent.safetyEventType).isEqualTo(SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED)
+ }
+
+ @Test
+ fun getRefreshBroadcastId_returnsRefreshBroadcastId() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+ .build()
+
+ assertThat(safetyEvent.refreshBroadcastId).isEqualTo(REFRESH_BROADCAST_ID)
+ }
+
+ @Test
+ fun getSafetySourceIssueId_returnsSafetySourceIssueId() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .build()
+
+ assertThat(safetyEvent.safetySourceIssueId).isEqualTo(SAFETY_SOURCE_ISSUE_ID)
+ }
+
+ @Test
+ fun getSafetySourceIssueActionId_returnsSafetySourceIssueActionId() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+
+ assertThat(safetyEvent.safetySourceIssueActionId).isEqualTo(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ }
+
+ @Test
+ fun describeContents_returns0() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+
+ assertThat(safetyEvent.describeContents()).isEqualTo(0)
+ }
+
+ @Test
+ fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+
+ assertThatRoundTripReturnsOriginal(safetyEvent, SafetyEvent.CREATOR)
+ }
+
+ // TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
+ @Test
+ fun hashCode_equals_toString_withEqualByReference_areEqual() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+ .build()
+ val otherSafetyEvent = safetyEvent
+
+ assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
+ }
+
+ @Test
+ fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+ val otherSafetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+
+ assertThatRepresentationsAreEqual(safetyEvent, otherSafetyEvent)
+ }
+
+ @Test
+ fun hashCode_equals_toString_withDifferentSafetyEventTypes_areNotEqual() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .build()
+ val otherSafetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_DEVICE_REBOOTED)
+ .build()
+
+ assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+ }
+
+ @Test
+ fun hashCode_equals_toString_withDifferentRefreshBroadcastIds_areNotEqual() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(REFRESH_BROADCAST_ID)
+ .build()
+ val otherSafetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId(OTHER_REFRESH_BROADCAST_ID)
+ .build()
+
+ assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+ }
+
+ @Test
+ fun hashCode_equals_toString_withDifferentIssueIds_areNotEqual() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .build()
+ val otherSafetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(OTHER_SAFETY_SOURCE_ISSUE_ID)
+ .build()
+
+ assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+ }
+
+ @Test
+ fun hashCode_equals_toString_withDifferentActionIds_areNotEqual() {
+ val safetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+ val otherSafetyEvent =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_RESOLVING_ACTION_FAILED)
+ .setSafetySourceIssueId(SAFETY_SOURCE_ISSUE_ID)
+ .setSafetySourceIssueActionId(OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID)
+ .build()
+
+ assertThatRepresentationsAreNotEqual(safetyEvent, otherSafetyEvent)
+ }
+
+ companion object {
+ const val REFRESH_BROADCAST_ID = "refresh_broadcast_id"
+ const val OTHER_REFRESH_BROADCAST_ID = "other_refresh_broadcast_id"
+ const val SAFETY_SOURCE_ISSUE_ID = "safety_source_issue_id"
+ const val OTHER_SAFETY_SOURCE_ISSUE_ID = "other_safety_source_issue_id"
+ const val SAFETY_SOURCE_ISSUE_ACTION_ID = "safety_source_issue_action_id"
+ const val OTHER_SAFETY_SOURCE_ISSUE_ACTION_ID = "other_safety_source_issue_action_id"
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
index 4924c94..5f8e8b8 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceBroadcastReceiver.kt
@@ -25,6 +25,8 @@
import android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE
import android.safetycenter.SafetyCenterManager
import android.safetycenter.SafetySourceData
+import android.safetycenter.SafetyEvent
+import android.safetycenter.SafetyEvent.SAFETY_EVENT_TYPE_REFRESH_REQUESTED
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
@@ -45,9 +47,17 @@
when (intent.getIntExtra(EXTRA_REFRESH_SAFETY_SOURCES_REQUEST_TYPE, -1)) {
EXTRA_REFRESH_REQUEST_TYPE_GET_DATA ->
- safetyCenterManager.sendUpdateWithPermission(safetySourceDataOnPageOpen!!)
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ safetySourceId!!,
+ safetySourceDataOnPageOpen!!,
+ EVENT_REFRESH_REQUESTED
+ )
EXTRA_REFRESH_REQUEST_TYPE_FETCH_FRESH_DATA ->
- safetyCenterManager.sendUpdateWithPermission(safetySourceDataOnRescanClick!!)
+ safetyCenterManager.setSafetySourceDataWithPermission(
+ safetySourceId!!,
+ safetySourceDataOnRescanClick!!,
+ EVENT_REFRESH_REQUESTED
+ )
}
runBlocking {
@@ -57,10 +67,16 @@
companion object {
private var updateChannel = Channel<Unit>()
+ private val EVENT_REFRESH_REQUESTED =
+ SafetyEvent.Builder(SAFETY_EVENT_TYPE_REFRESH_REQUESTED)
+ .setRefreshBroadcastId("refresh_id")
+ .build()
+ var safetySourceId: String? = null
var safetySourceDataOnPageOpen: SafetySourceData? = null
var safetySourceDataOnRescanClick: SafetySourceData? = null
fun reset() {
+ safetySourceId = null
safetySourceDataOnRescanClick = null
safetySourceDataOnPageOpen = null
updateChannel = Channel()
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
index 5706434..76090bf 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceDataTest.kt
@@ -104,22 +104,15 @@
.build()
@Test
- fun getId_returnsId() {
- val safetySourceData = SafetySourceData.Builder("Safety source id").build()
-
- assertThat(safetySourceData.id).isEqualTo("Safety source id")
- }
-
- @Test
fun getStatus_withDefaultBuilder_returnsNull() {
- val safetySourceData = SafetySourceData.Builder("Safety source id").build()
+ val safetySourceData = SafetySourceData.Builder().build()
assertThat(safetySourceData.status).isNull()
}
@Test
fun getStatus_whenSetExplicitly_returnsStatus() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.build()
@@ -128,14 +121,14 @@
@Test
fun getIssues_withDefaultBuilder_returnsEmptyList() {
- val safetySourceData = SafetySourceData.Builder("Safety source id").build()
+ val safetySourceData = SafetySourceData.Builder().build()
assertThat(safetySourceData.issues).isEmpty()
}
@Test
fun getIssues_whenSetExplicitly_returnsIssues() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.addIssue(issue1)
.addIssue(issue2)
.build()
@@ -145,7 +138,7 @@
@Test
fun clearIssues_removesAllIssues() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.addIssue(issue1)
.addIssue(issue2)
.clearIssues()
@@ -156,7 +149,7 @@
@Test
fun describeContents_returns0() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
@@ -167,7 +160,7 @@
@Test
fun createFromParcel_withWriteToParcel_returnsOriginalSafetySourceData() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
@@ -186,7 +179,7 @@
// TODO(b/208473675): Use `EqualsTester` for testing `hashcode` and `equals`.
@Test
fun hashCode_equals_toString_withEqualByReference_withoutStatusAndIssues_areEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id").build()
+ val safetySourceData = SafetySourceData.Builder().build()
val otherSafetySourceData = safetySourceData
assertThat(safetySourceData.hashCode()).isEqualTo(otherSafetySourceData.hashCode())
@@ -196,7 +189,7 @@
@Test
fun hashCode_equals_toString_withEqualByReference_withoutIssues_areEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.build()
val otherSafetySourceData = safetySourceData
@@ -208,7 +201,7 @@
@Test
fun hashCode_equals_toString_withEqualByReference_areEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
@@ -222,12 +215,12 @@
@Test
fun hashCode_equals_toString_withAllFieldsEqual_areEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
.build()
- val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+ val otherSafetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
@@ -239,27 +232,13 @@
}
@Test
- fun hashCode_equals_toString_withDifferentIds_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
- .setStatus(status1)
- .build()
- val otherSafetySourceData = SafetySourceData.Builder("Safety source id 2")
- .setStatus(status1)
- .build()
-
- assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
- assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
- assertThat(safetySourceData.toString()).isNotEqualTo(otherSafetySourceData.toString())
- }
-
- @Test
fun hashCode_equals_toString_withDifferentIssues_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
.build()
- val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+ val otherSafetySourceData = SafetySourceData.Builder()
.setStatus(status2)
.addIssue(issue1)
.addIssue(issue2)
@@ -272,12 +251,12 @@
@Test
fun hashCode_equals_toString_withDifferentStatuses_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
.build()
- val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+ val otherSafetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.build()
@@ -289,10 +268,10 @@
@Test
fun hashCode_equals_toString_withStatusSetInOneAndNotOther_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.build()
- val otherSafetySourceData = SafetySourceData.Builder("Safety source id").build()
+ val otherSafetySourceData = SafetySourceData.Builder().build()
assertThat(safetySourceData.hashCode()).isNotEqualTo(otherSafetySourceData.hashCode())
assertThat(safetySourceData).isNotEqualTo(otherSafetySourceData)
@@ -301,12 +280,12 @@
@Test
fun hashCode_equals_toString_withIssuesSetInOneAndNotOther_areNotEqual() {
- val safetySourceData = SafetySourceData.Builder("Safety source id")
+ val safetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.addIssue(issue1)
.addIssue(issue2)
.build()
- val otherSafetySourceData = SafetySourceData.Builder("Safety source id")
+ val otherSafetySourceData = SafetySourceData.Builder()
.setStatus(status1)
.build()
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
index 2dba3c0..0d69f2c 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/SafetySourceErrorTest.kt
@@ -16,107 +16,63 @@
package android.safetycenter.cts
-import android.os.Parcel
+import android.os.Build
+import android.safetycenter.SafetyEvent
import android.safetycenter.SafetySourceError
-import android.safetycenter.SafetySourceError.SOURCE_ERROR_TYPE_ACTION_ERROR
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreEqual
+import android.safetycenter.testers.AnyTester.assertThatRepresentationsAreNotEqual
+import android.safetycenter.testers.ParcelableTester.assertThatRoundTripReturnsOriginal
import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SdkSuppress
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
+/** CTS tests for [SafetySourceError]. */
@RunWith(AndroidJUnit4::class)
+@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
class SafetySourceErrorTest {
-
- val actionError1 = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_1")
- .setActionId("action_id_1")
- .build()
- val actionError2 = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_2")
- .setActionId("action_id_2")
- .build()
-
@Test
- fun getType_returnsType() {
- assertThat(actionError1.type).isEqualTo(SOURCE_ERROR_TYPE_ACTION_ERROR)
- assertThat(actionError2.type).isEqualTo(SOURCE_ERROR_TYPE_ACTION_ERROR)
- }
+ fun getSafetyEvent_returnsSafetyEvent() {
+ val safetySourceError = SafetySourceError(SAFETY_EVENT)
- @Test
- fun getIssueId_returnsIssueId() {
- assertThat(actionError1.issueId).isEqualTo("issue_id_1")
- assertThat(actionError2.issueId).isEqualTo("issue_id_2")
- }
-
- @Test
- fun getActionId_returnsActionId() {
- assertThat(actionError1.actionId).isEqualTo("action_id_1")
- assertThat(actionError2.actionId).isEqualTo("action_id_2")
+ assertThat(safetySourceError.safetyEvent).isEqualTo(SAFETY_EVENT)
}
@Test
fun createFromParcel_withWriteToParcel_returnsEquivalentObject() {
- val parcel = Parcel.obtain()
+ val safetySourceError = SafetySourceError(SAFETY_EVENT)
- actionError1.writeToParcel(parcel, /* flags= */ 0)
- parcel.setDataPosition(0)
-
- val fromParcel = SafetySourceError.CREATOR.createFromParcel(parcel)
- parcel.recycle()
-
- assertThat(fromParcel).isEqualTo(actionError1)
+ assertThatRoundTripReturnsOriginal(safetySourceError, SafetySourceError.CREATOR)
}
@Test
fun equals_hashCode_toString_equalByReference_areEqual() {
- assertThat(actionError1).isEqualTo(actionError1)
- assertThat(actionError1.hashCode()).isEqualTo(actionError1.hashCode())
- assertThat(actionError1.toString()).isEqualTo(actionError1.toString())
+ val safetySourceError = SafetySourceError(SAFETY_EVENT)
+
+ assertThatRepresentationsAreEqual(safetySourceError, safetySourceError)
}
@Test
- fun equals_hashCode_toString_actionErrors_equalByValue_areEqual() {
- val actionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_1")
- .setActionId("action_id_1")
- .build()
- val equivalentActionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_1")
- .setActionId("action_id_1")
- .build()
+ fun equals_hashCode_toString_equalByValue_areEqual() {
+ val safetySourceError = SafetySourceError(SAFETY_EVENT)
+ val equivalentSafetySourceError = SafetySourceError(SAFETY_EVENT)
- assertThat(actionError).isEqualTo(equivalentActionError)
- assertThat(actionError.hashCode()).isEqualTo(equivalentActionError.hashCode())
- assertThat(actionError.toString()).isEqualTo(equivalentActionError.toString())
+ assertThatRepresentationsAreEqual(safetySourceError, equivalentSafetySourceError)
}
@Test
- fun equals_toString_withDifferentIssueIds_areNotEqual() {
- val actionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_1")
- .setActionId("action_id_1")
- .build()
- val differentActionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_2")
- .setActionId("action_id_1")
- .build()
+ fun equals_toString_withDifferentSafetyEvents_areNotEqual() {
+ val safetySourceError = SafetySourceError(
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build())
+ val otherSafetySourceError = SafetySourceError(
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_DEVICE_REBOOTED).build())
- assertThat(actionError).isNotEqualTo(differentActionError)
- assertThat(actionError.toString()).isNotEqualTo(differentActionError.toString())
+ assertThatRepresentationsAreNotEqual(safetySourceError, otherSafetySourceError)
}
- @Test
- fun equals_toString_withDifferentActionIds_areNotEqual() {
- val actionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_1")
- .setActionId("action_id_1")
- .build()
- val differentActionError = SafetySourceError.Builder(SOURCE_ERROR_TYPE_ACTION_ERROR)
- .setIssueId("issue_id_1")
- .setActionId("action_id_2")
- .build()
-
- assertThat(actionError).isNotEqualTo(differentActionError)
- assertThat(actionError.toString()).isNotEqualTo(differentActionError.toString())
+ companion object {
+ private val SAFETY_EVENT =
+ SafetyEvent.Builder(SafetyEvent.SAFETY_EVENT_TYPE_SOURCE_STATE_CHANGED).build()
}
}
\ No newline at end of file
diff --git a/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt b/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
index 461dc69..9b77e99 100644
--- a/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
+++ b/tests/tests/safetycenter/src/android/safetycenter/cts/XmlConfigTest.kt
@@ -17,7 +17,7 @@
package android.safetycenter.cts
import android.os.Build.VERSION_CODES.TIRAMISU
-import android.safetycenter.config.Parser
+import android.safetycenter.config.SafetyCenterConfig
import androidx.test.core.app.ApplicationProvider.getApplicationContext
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SdkSuppress
@@ -34,6 +34,6 @@
@Test
fun safetyCenterConfigResource_validConfig() {
// Assert that the parser validates the Safety Center config without throwing any exception
- assertThat(Parser.parseXmlResource(safetyCenterContext.safetyCenterConfig!!)).isNotNull()
+ assertThat(SafetyCenterConfig.fromXml(safetyCenterContext.safetyCenterConfig!!)).isNotNull()
}
}
diff --git a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
index 391f9c4..484438b 100644
--- a/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
+++ b/tests/tests/secure_element/omapi/src/android/omapi/cts/OmapiTest.java
@@ -694,6 +694,38 @@
}
}
+ /** Tests closeChannels API */
+ @Test
+ public void testCloseChannels() {
+ assumeTrue(supportOMAPIReaders());
+ try {
+ waitForConnection();
+ Reader[] readers = seService.getReaders();
+
+ for (Reader reader : readers) {
+ Session session = null;
+ Channel channelA = null;
+ Channel channelB = null;
+ try {
+ assertTrue(reader.isSecureElementPresent());
+ session = reader.openSession();
+ assertNotNull("null session", session);
+ channelA = session.openLogicalChannel(SELECTABLE_AID, (byte) 0x00);
+ assertNotNull("Null Channel", channelA);
+ channelB = session.openLogicalChannel(LONG_SELECT_RESPONSE_AID, (byte) 0x00);
+ assertNotNull("Null Channel", channelB);
+ session.closeChannels();
+ assertFalse("channel is still open", channelA.isOpen());
+ assertFalse("channel is still open", channelB.isOpen());
+ } finally {
+ if (session != null) session.close();
+ }
+ }
+ } catch (Exception e) {
+ fail("unexpected exception " + e);
+ }
+ }
+
/**
* Verifies TLV data
* @param tlv
diff --git a/tests/tests/security/src/android/security/cts/AttributionSourceTest.java b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
index 80ffd60..e36fa49 100644
--- a/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
+++ b/tests/tests/security/src/android/security/cts/AttributionSourceTest.java
@@ -16,44 +16,39 @@
package android.security.cts;
+import static org.junit.Assert.assertThrows;
+
+import java.lang.reflect.Field;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import android.content.AttributionSource;
import android.content.Context;
import android.platform.test.annotations.AsbSecurityTest;
-
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
-import org.junit.Assume;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.Assert;
-
-import java.lang.reflect.Field;
-
@RunWith(AndroidJUnit4.class)
public class AttributionSourceTest {
@AsbSecurityTest(cveBugId = 200288596)
@Test
- public void testPidCheck()
- throws Exception {
+ public void testPidCheck() throws Exception {
Context context = ApplicationProvider.getApplicationContext();
- AttributionSource attributionSource = null;
- Field attSourceStateField = null;
- try {
- attributionSource = (AttributionSource) Context.class.getMethod(
- "getAttributionSource").invoke(context);
- attSourceStateField = attributionSource.getClass().getDeclaredField(
- "mAttributionSourceState");
- attSourceStateField.setAccessible(true);
- } catch (Exception e) {
- Assume.assumeFalse(true);
- }
+ AttributionSource attributionSource =
+ new AttributionSource(
+ (AttributionSource)
+ Context.class.getMethod("getAttributionSource").invoke(context),
+ null);
+
+ Field attSourceStateField =
+ attributionSource.getClass().getDeclaredField("mAttributionSourceState");
+ attSourceStateField.setAccessible(true);
Object attSourceState = attSourceStateField.get(attributionSource);
attSourceState.getClass().getField("pid").setInt(attSourceState, 0);
final AttributionSource attributionSourceFinal = attributionSource;
- Assert.assertThrows(SecurityException.class,
- () -> attributionSourceFinal.enforceCallingPid());
+ assertThrows(SecurityException.class, () -> attributionSourceFinal.enforceCallingPid());
}
}
+
diff --git a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
index 52eca56..65eb132 100644
--- a/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaMetadataRetrieverTest.java
@@ -40,13 +40,13 @@
protected MediaMetadataRetriever mRetriever;
@Before
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
mResources = getContext().getResources();
mRetriever = new MediaMetadataRetriever();
}
@After
- protected void tearDown() throws Exception {
+ public void tearDown() throws Exception {
mRetriever.release();
}
diff --git a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
index 953fbb9..83ce8ff 100644
--- a/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
+++ b/tests/tests/security/src/android/security/cts/MediaServerCrashTest.java
@@ -59,7 +59,7 @@
private final ConditionVariable mOnCompletionCalled = new ConditionVariable();
@Before
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
mFlFilePath = new File(getContext().getFilesDir(), "temp.fl").getAbsolutePath();
mOnPrepareCalled.close();
@@ -92,7 +92,7 @@
}
@After
- protected void tearDown() throws Exception {
+ public void tearDown() throws Exception {
new File(mFlFilePath).delete();
}
diff --git a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
index 9d1dc42..135d493 100644
--- a/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
+++ b/tests/tests/security/src/android/security/cts/NanoAppBundleTest.java
@@ -83,7 +83,7 @@
};
@Before
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
mContext = getInstrumentation().getContext();
Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
mContext.startService(serviceIntent);
@@ -91,7 +91,7 @@
}
@After
- protected void tearDown() throws Exception {
+ public void tearDown() throws Exception {
if (mContext != null) {
Intent serviceIntent = new Intent(mContext, AuthenticatorService.class);
mContext.stopService(serviceIntent);
diff --git a/tests/tests/security/src/android/security/cts/SQLiteTest.java b/tests/tests/security/src/android/security/cts/SQLiteTest.java
index 9aa69ad..84d36fa 100644
--- a/tests/tests/security/src/android/security/cts/SQLiteTest.java
+++ b/tests/tests/security/src/android/security/cts/SQLiteTest.java
@@ -52,7 +52,7 @@
private SQLiteDatabase mDatabase;
@Before
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
mResolver = getContext().getContentResolver();
mContext = InstrumentationRegistry.getTargetContext();
mPackageName = mContext.getPackageName();
diff --git a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
index e5366ae..2765de4 100644
--- a/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
+++ b/tests/tests/security/src/android/security/cts/STKFrameworkTest.java
@@ -33,7 +33,7 @@
private boolean mHasTelephony;
@Before
- protected void setUp() throws Exception {
+ public void setUp() throws Exception {
mHasTelephony = getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY);
}
diff --git a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
index 079f576d..d277a43 100644
--- a/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
+++ b/tests/tests/security/src/android/security/cts/WallpaperManagerTest.java
@@ -32,11 +32,14 @@
import android.view.Display;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import java.io.BufferedInputStream;
import java.io.File;
@@ -46,7 +49,8 @@
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
-public class WallpaperManagerTest {
+@RunWith(AndroidJUnit4.class)
+public class WallpaperManagerTest extends StsExtraBusinessLogicTestCase {
private static final String TAG = "WallpaperManagerSTS";
private static final long PNG_SIZE = 7503368920L;
diff --git a/tests/tests/settings/src/android/settings/cts/TetherProvisioningCarrierDialogActivityTest.java b/tests/tests/settings/src/android/settings/cts/TetherProvisioningCarrierDialogActivityTest.java
new file mode 100644
index 0000000..51664ea
--- /dev/null
+++ b/tests/tests/settings/src/android/settings/cts/TetherProvisioningCarrierDialogActivityTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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.settings.cts;
+
+import static org.junit.Assert.assertTrue;
+
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests to ensure the Activity to handle
+ * {@link Settings#ACTION_TETHER_PROVISIONING_CARRIER_UI}
+ */
+@RunWith(AndroidJUnit4.class)
+public class TetherProvisioningCarrierDialogActivityTest {
+ @Test
+ public void testTetheringProvisioningCarrierUiExisted() throws RemoteException {
+ final Intent intent = new Intent(Settings.ACTION_TETHER_UNSUPPORTED_CARRIER_UI);
+ final ResolveInfo ri = InstrumentationRegistry.getTargetContext()
+ .getPackageManager().resolveActivity(
+ intent, PackageManager.MATCH_DEFAULT_ONLY);
+ assertTrue(ri != null);
+ }
+}
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
index 7377132..740020c 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallDetailsTest.java
@@ -18,12 +18,12 @@
import static android.telecom.Connection.PROPERTY_HIGH_DEF_AUDIO;
import static android.telecom.Connection.PROPERTY_WIFI;
-import static android.telecom.cts.TestUtils.InvokeCounter;
-import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE;
-import static android.telecom.cts.TestUtils.TEST_PHONE_ACCOUNT_HANDLE_2;
-import static android.telecom.cts.TestUtils.WAIT_FOR_STATE_CHANGE_TIMEOUT_MS;
+import static android.telecom.cts.TestUtils.*;
+
+import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import android.content.Context;
@@ -299,9 +299,6 @@
mConnection.setConnectionProperties(Connection.PROPERTY_CROSS_SIM);
assertCallProperties(mCall, Call.Details.PROPERTY_CROSS_SIM);
-
- mConnection.setConnectionProperties(Connection.PROPERTY_TETHERED_CALL);
- assertCallProperties(mCall, Call.Details.PROPERTY_TETHERED_CALL);
}
/**
diff --git a/tests/tests/telecom/src/android/telecom/cts/CallTest.java b/tests/tests/telecom/src/android/telecom/cts/CallTest.java
index 1659c12..f7bad4e 100644
--- a/tests/tests/telecom/src/android/telecom/cts/CallTest.java
+++ b/tests/tests/telecom/src/android/telecom/cts/CallTest.java
@@ -125,11 +125,4 @@
assertTrue(cas.getSupportedBluetoothDevices().contains(TestUtils.BLUETOOTH_DEVICE1));
assertTrue(cas.getSupportedBluetoothDevices().contains(TestUtils.BLUETOOTH_DEVICE2));
}
-
- public void testExternalCallAudioState() {
- CallAudioState cas = new CallAudioState(false, CallAudioState.ROUTE_EXTERNAL,
- CallAudioState.ROUTE_BLUETOOTH + CallAudioState.ROUTE_SPEAKER
- + CallAudioState.ROUTE_EARPIECE);
- assertEquals(CallAudioState.ROUTE_EXTERNAL, cas.getSupportedRouteMask());
- }
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
index 5d76420..f87ccd6 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/ServiceStateTest.java
@@ -35,6 +35,7 @@
import android.os.Build;
import android.os.Parcel;
import android.telephony.AccessNetworkConstants;
+import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.LteVopsSupportInfo;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.NrVopsSupportInfo;
@@ -371,9 +372,12 @@
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE,
LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE);
- NetworkRegistrationInfo wwanDataRegState = new NetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
- 0, 0, 0, true, null, null, "", 0, false, false, false, vopsSupportInfo);
+ NetworkRegistrationInfo wwanDataRegState = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setDataSpecificInfo(new DataSpecificRegistrationInfo(
+ 0, false, false, false, vopsSupportInfo))
+ .setEmergencyOnly(true).build();
ServiceState ss = new ServiceState();
@@ -386,9 +390,12 @@
new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED,
LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED);
- wwanDataRegState = new NetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
- 0, 0, 0, true, null, null, "", 0, false, false, false, vopsSupportInfo);
+ wwanDataRegState = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setDataSpecificInfo(new DataSpecificRegistrationInfo(
+ 0, false, false, false, vopsSupportInfo))
+ .setEmergencyOnly(true).build();
ss.addNetworkRegistrationInfo(wwanDataRegState);
assertEquals(ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN), wwanDataRegState);
@@ -402,9 +409,12 @@
vopsSupportInfo = new NrVopsSupportInfo(NrVopsSupportInfo.NR_STATUS_VOPS_NOT_SUPPORTED,
NrVopsSupportInfo.NR_STATUS_EMC_NOT_SUPPORTED,
NrVopsSupportInfo.NR_STATUS_EMF_NOT_SUPPORTED);
- wwanDataRegState = new NetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
- 0, 0, 0, true, null, null, "", 0, false, false, false, vopsSupportInfo);
+ wwanDataRegState = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .setDataSpecificInfo(new DataSpecificRegistrationInfo(
+ 0, false, false, false, vopsSupportInfo))
+ .setEmergencyOnly(true).build();
ss.addNetworkRegistrationInfo(wwanDataRegState);
assertEquals(ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN), wwanDataRegState);
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
index b4d4986..140a704 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTestOnMockModem.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -33,6 +34,7 @@
import com.android.compatibility.common.util.ShellIdentityUtils;
import org.junit.AfterClass;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@@ -47,12 +49,9 @@
@BeforeClass
public static void beforeAllTests() throws Exception {
-
Log.d(TAG, "TelephonyManagerTestOnMockModem#beforeAllTests()");
- final PackageManager pm = getContext().getPackageManager();
- if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
- Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+ if (!hasTelephonyFeature()) {
return;
}
@@ -68,16 +67,34 @@
public static void afterAllTests() throws Exception {
Log.d(TAG, "TelephonyManagerTestOnMockModem#afterAllTests()");
+ if (!hasTelephonyFeature()) {
+ return;
+ }
+
// Rebind all interfaces which is binding to MockModemService to default.
assertNotNull(sMockModemManager);
assertTrue(sMockModemManager.disconnectMockModemService());
sMockModemManager = null;
}
+ @Before
+ public void beforeTest() {
+ assumeTrue(hasTelephonyFeature());
+ }
+
private static Context getContext() {
return InstrumentationRegistry.getInstrumentation().getContext();
}
+ private static boolean hasTelephonyFeature() {
+ final PackageManager pm = getContext().getPackageManager();
+ if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.d(TAG, "Skipping test that requires FEATURE_TELEPHONY");
+ return false;
+ }
+ return true;
+ }
+
@Test
public void testSimStateChange() throws Throwable {
Log.d(TAG, "TelephonyManagerTestOnMockModem#testSimStateChange");
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
index 1ce51e3..d8381fd 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/SharedFilterTestService.java
@@ -106,7 +106,13 @@
Log.e(TAG, "Failed to flush SharedFilter");
return false;
}
- f.read(new byte[3], 0, 3);
+ int size = f.read(new byte[3], 0, 3);
+ if (size < 0 || size > 3) {
+ f.close();
+ f = null;
+ Log.e(TAG, "Failed to read from SharedFilter");
+ return false;
+ }
if (f.stop() != Tuner.RESULT_SUCCESS) {
f.close();
f = null;
diff --git a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
index d633eef..626f08d 100644
--- a/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
+++ b/tests/tests/tv/src/android/media/tv/tuner/cts/TunerTest.java
@@ -2242,7 +2242,8 @@
assertEquals(f.start(), Tuner.RESULT_SUCCESS);
assertEquals(f.flush(), Tuner.RESULT_SUCCESS);
- assertTrue(f.read(new byte[3], 0, 3) != 0);
+ int size = f.read(new byte[3], 0, 3);
+ assertTrue(size >= 0 && size <= 3);
assertEquals(f.stop(), Tuner.RESULT_SUCCESS);
mLockLatch = new CountDownLatch(1);
@@ -2273,7 +2274,8 @@
assertEquals(f.start(), Tuner.RESULT_SUCCESS);
assertEquals(f.flush(), Tuner.RESULT_SUCCESS);
- assertTrue(f.read(new byte[3], 0, 3) != 0);
+ int size = f.read(new byte[3], 0, 3);
+ assertTrue(size >= 0 && size <= 3);
assertEquals(f.stop(), Tuner.RESULT_SUCCESS);
mLockLatch = new CountDownLatch(1);
@@ -2303,7 +2305,8 @@
assertEquals(f.start(), Tuner.RESULT_SUCCESS);
assertEquals(f.flush(), Tuner.RESULT_SUCCESS);
- assertTrue(f.read(new byte[3], 0, 3) != 0);
+ int size = f.read(new byte[3], 0, 3);
+ assertTrue(size >= 0 && size <= 3);
assertEquals(f.stop(), Tuner.RESULT_SUCCESS);
mLockLatch = new CountDownLatch(1);
diff --git a/tests/tests/uidmigration/Android.bp b/tests/tests/uidmigration/Android.bp
index 92db2e1..4f98ae6 100644
--- a/tests/tests/uidmigration/Android.bp
+++ b/tests/tests/uidmigration/Android.bp
@@ -24,6 +24,7 @@
"androidx.test.rules",
"ctstestrunner-axt",
"permission-test-util-lib",
+ "services.core",
"CtsSharedUserMigrationTestLibs",
],
libs: [
@@ -36,5 +37,5 @@
"cts",
"general-tests",
],
- sdk_version: "test_current",
+ platform_apis: true,
}
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
new file mode 100644
index 0000000..ec3c206
--- /dev/null
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/AppIdMigrationTest.kt
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.uidmigration.cts
+
+import android.Manifest.permission.INTERNET
+import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.PackageInfoFlags
+import android.permission.cts.PermissionUtils
+import android.permission.cts.PermissionUtils.isPermissionGranted
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.server.pm.SharedUidMigration.LIVE_TRANSITION
+import org.junit.After
+import org.junit.Assert.assertArrayEquals
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotEquals
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.io.ByteArrayInputStream
+import java.nio.charset.StandardCharsets.UTF_8
+import java.security.Signature
+import java.security.cert.CertificateFactory
+import java.security.cert.X509Certificate
+import java.util.UUID
+import java.util.concurrent.ArrayBlockingQueue
+import java.util.concurrent.BlockingQueue
+import java.util.concurrent.TimeUnit
+
+// All tests ignored: appId migration is disabled (http://b/220015249)
+@RunWith(AndroidJUnit4::class)
+class AppIdMigrationTest {
+
+ companion object {
+ private const val RESULT_KEY = "result"
+ private val NOT_AN_ERROR = Throwable()
+ }
+
+ private lateinit var mContext: Context
+ private lateinit var mPm: PackageManager
+
+ @Before
+ fun setup() {
+ mContext = ApplicationProvider.getApplicationContext<Context>()
+ mPm = mContext.packageManager
+ }
+
+ @After
+ fun tearDown() {
+ uninstallPackage(Const.INSTALL_TEST_PKG)
+ uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+ uninstallPackage(Const.PERM_TEST_PKG)
+ uninstallPackage(Const.PERM_TEST_PKG + ".secondary")
+ uninstallPackage(Const.DATA_TEST_PKG)
+ }
+
+ @Ignore
+ @Test
+ fun testAppInstall() = withStrategy(LIVE_TRANSITION) {
+ assertTrue(installPackage(InstallTest.APK))
+ assertTrue(installPackage(InstallTest.APK2))
+
+ // Both app should share the same UID.
+ val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, PackageInfoFlags.of(0))
+ var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ assertEquals(2, pkgs.size)
+
+ // Should not allow upgrading to an APK that directly removes sharedUserId.
+ assertFalse(installPackage(InstallTest.APK3))
+
+ // Leave shared UID.
+ assertTrue(installPackage(InstallTest.APK4))
+ pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ assertEquals(1, pkgs.size)
+
+ uninstallPackage(Const.INSTALL_TEST_PKG)
+ uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+ }
+
+ @Ignore
+ @Test
+ fun testPermissionMigration() = withStrategy(LIVE_TRANSITION) {
+ val apk = "$TMP_APK_PATH/PermissionTestApp"
+ assertTrue(installPackage(apk + "1.apk"))
+ assertTrue(installPackage(apk + "2.apk"))
+ val secondaryPkg = Const.PERM_TEST_PKG + ".secondary"
+
+ // Runtime permissions are not granted by default.
+ assertFalse(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+
+ // Grant a runtime permission.
+ PermissionUtils.grantPermission(secondaryPkg, WRITE_EXTERNAL_STORAGE)
+
+ // All apps in the UID group should have the same permissions.
+ assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
+ assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
+ assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
+ assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+
+ // Upgrade and leave shared UID.
+ assertTrue(installPackage(apk + "3.apk"))
+
+ // The app in the original UID group should no longer have the permissions.
+ assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
+ assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
+
+ // The upgraded app should still have the permissions.
+ assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
+ assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+ uninstallPackage(Const.PERM_TEST_PKG)
+ uninstallPackage(secondaryPkg)
+ }
+
+ @Ignore
+ @Test
+ fun testDataMigration() = withStrategy(LIVE_TRANSITION) {
+ val apk = "$TMP_APK_PATH/DataTestApp"
+ assertTrue(installPackage(apk + "1.apk"))
+ val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+ val authority = Const.DATA_TEST_PKG + ".provider"
+ val resolver = mContext.contentResolver
+
+ // Ask the app to generate a new random UUID and persist in data.
+ var result = resolver.call(authority, "data", null, null).assertNotNull()
+ val oldUUID = result.getString(RESULT_KEY).assertNotNull()
+
+ val receiver = PackageBroadcastReceiver(oldUid)
+ IntentFilter().apply {
+ addAction(Intent.ACTION_PACKAGE_REMOVED)
+ addAction(Intent.ACTION_PACKAGE_ADDED)
+ addAction(Intent.ACTION_PACKAGE_REPLACED)
+ addDataScheme("package")
+ mContext.registerReceiver(receiver, this)
+ }
+ IntentFilter().apply {
+ addAction(Intent.ACTION_UID_REMOVED)
+ addAction(Const.ACTION_UPDATE_ACK)
+ mContext.registerReceiver(receiver, this)
+ }
+
+ // Update the data test APK and make sure UID changed.
+ assertTrue(installPackage(apk + "2.apk"))
+ val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+ assertNotEquals(oldUid, newUid)
+
+ // Ensure system broadcasts are delivered properly.
+ try {
+ val e = receiver.poll(30, TimeUnit.SECONDS)
+ if (e !== NOT_AN_ERROR) {
+ throw AssertionError(e)
+ }
+ } catch (e: InterruptedException) {
+ fail(e.message)
+ }
+ assertEquals(newUid, receiver.newUid)
+ mContext.unregisterReceiver(receiver)
+
+ // Ask the app again for a UUID. If data migration is working, it shall be the same.
+ result = resolver.call(authority, "data", null, null).assertNotNull()
+ val newUUID = result.getString(RESULT_KEY)
+ assertEquals(oldUUID, newUUID)
+ uninstallPackage(Const.DATA_TEST_PKG)
+ }
+
+ @Ignore
+ @Test
+ fun testKeyMigration() = withStrategy(LIVE_TRANSITION) {
+ val apk = "$TMP_APK_PATH/DataTestApp"
+ assertTrue(installPackage(apk + "1.apk"))
+ val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+ val authority = Const.DATA_TEST_PKG + ".provider"
+ val resolver = mContext.contentResolver
+ val secret = UUID.randomUUID().toString()
+
+ // Ask the app to encrypt secret with AES.
+ var result = resolver.call(authority, "encryptAES", secret, null).assertNotNull()
+ assertNotNull(result[RESULT_KEY])
+ assertNotNull(result["iv"])
+ val encResult = result
+
+ // Ask the app to generate a new EC keypair and sign our data.
+ result = resolver.call(authority, "signEC", secret, null).assertNotNull()
+ val signature = result.getByteArray(RESULT_KEY).assertNotNull()
+ val oldCertChain = result.getByteArray("certChain").assertNotNull()
+
+ // Update the data test APK and make sure UID changed.
+ assertTrue(installPackage(apk + "2.apk"))
+ val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
+ assertNotEquals(oldUid, newUid)
+
+ // Ask the app to decrypt our secret.
+ result = resolver.call(authority, "decryptAES", null, encResult).assertNotNull()
+ val decSecret = result.getString(RESULT_KEY)
+ assertEquals(secret, decSecret)
+
+ // Ask the app to return the previously generated EC certificate.
+ result = resolver.call(authority, "getECCert", null, null).assertNotNull()
+ val rawCert = result.getByteArray(RESULT_KEY).assertNotNull()
+ val newCertChain = result.getByteArray("certChain").assertNotNull()
+ val cf = CertificateFactory.getInstance("X.509")
+ val cert = cf.generateCertificate(ByteArrayInputStream(rawCert)) as X509Certificate
+
+ // Verify the signature and cert.
+ assertArrayEquals(oldCertChain, newCertChain)
+ val s = Signature.getInstance("SHA256withECDSA")
+ s.initVerify(cert)
+ s.update(secret.toByteArray(UTF_8))
+ assertTrue(s.verify(signature))
+ uninstallPackage(Const.DATA_TEST_PKG)
+ }
+
+ class PackageBroadcastReceiver(
+ private val mPreviousUid: Int
+ ) : BroadcastReceiver(), BlockingQueue<Throwable?> by ArrayBlockingQueue<Throwable?>(1) {
+
+ var newUid = -1
+ private set
+ private var mCounter = 0
+
+ override fun onReceive(context: Context?, intent: Intent) {
+ try {
+ verifyInternal(intent)
+ } catch (e: Throwable) {
+ offer(e)
+ }
+ }
+
+ private fun verifyInternal(intent: Intent) {
+ val action = intent.action
+ assertNotNull(action)
+ if (action == Intent.ACTION_UID_REMOVED) {
+ // Not the test package, none of our business.
+ if (intent.getIntExtra(Intent.EXTRA_UID, -1) != mPreviousUid) {
+ return
+ }
+ }
+ val data = intent.data
+ if (data != null) {
+ assertEquals("package", data.scheme)
+ val pkg = data.schemeSpecificPart
+ assertNotNull(pkg)
+ // Not the test package, none of our business.
+ if (Const.DATA_TEST_PKG != pkg) {
+ return
+ }
+ }
+
+ // Broadcasts must come in the following order:
+ // ACTION_PACKAGE_REMOVED -> ACTION_UID_REMOVED
+ // -> ACTION_PACKAGE_ADDED -> ACTION_UPDATE_ACK
+ mCounter++
+ when (action) {
+ Intent.ACTION_PACKAGE_REMOVED -> {
+ assertEquals(1, mCounter)
+ assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
+ assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
+ assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_UID, -1))
+ newUid = intent.getIntExtra(Intent.EXTRA_NEW_UID, -1)
+ assertNotEquals(mPreviousUid, newUid)
+ }
+ Intent.ACTION_UID_REMOVED -> {
+ assertEquals(2, mCounter)
+ assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
+ assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
+ assertEquals(
+ Const.DATA_TEST_PKG,
+ intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
+ )
+ }
+ Intent.ACTION_PACKAGE_ADDED -> {
+ assertEquals(3, mCounter)
+ assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
+ assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
+ assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, mPreviousUid))
+ assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_PREVIOUS_UID, -1))
+ }
+ Const.ACTION_UPDATE_ACK -> {
+ assertEquals(4, mCounter)
+ assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, -2))
+ // End of actions
+ offer(NOT_AN_ERROR)
+ }
+ Intent.ACTION_PACKAGE_REPLACED -> fail("PACKAGE_REPLACED should not be called!")
+ else -> fail("Unknown action received")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
new file mode 100644
index 0000000..a525ff8
--- /dev/null
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/Common.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.uidmigration.cts
+
+import android.content.pm.PackageManager
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.server.pm.SharedUidMigration
+import com.android.server.pm.SharedUidMigration.PROPERTY_KEY
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNotNull
+
+const val TMP_APK_PATH = "/data/local/tmp/cts/uidmigration"
+
+val FLAG_ZERO = PackageManager.PackageInfoFlags.of(0)
+
+// What each APK meant
+// APK : pkg , with sharedUserId
+// APK2: pkg2, with sharedUserId
+// APK3: pkg , with sharedUserId removed
+// APK4: pkg , with sharedUserMaxSdkVersion="32"
+
+object InstallTest {
+ const val APK = "$TMP_APK_PATH/InstallTestApp.apk"
+ const val APK2 = "$TMP_APK_PATH/InstallTestApp2.apk"
+ const val APK3 = "$TMP_APK_PATH/InstallTestApp3.apk"
+ const val APK4 = "$TMP_APK_PATH/InstallTestApp4.apk"
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline fun <T> T?.assertNotNull(): T {
+ assertNotNull(this)
+ return this!!
+}
+
+@Suppress("NOTHING_TO_INLINE")
+inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
+
+fun installPackage(apkPath: String): Boolean {
+ return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
+}
+
+fun uninstallPackage(packageName: String) {
+ runShellCommand("pm uninstall $packageName")
+}
+
+@SharedUidMigration.Strategy
+var migrationStrategy: Int
+ get() = SharedUidMigration.getCurrentStrategy()
+ set(value) { runShellCommand("setprop $PROPERTY_KEY $value") }
+
+inline fun withStrategy(strategy: Int? = null, body: () -> Unit) {
+ if (SharedUidMigration.isDisabled()) {
+ // Nothing to test if shared UID migration is disabled
+ return
+ }
+
+ val backup = migrationStrategy
+ strategy?.let { migrationStrategy = it }
+ try {
+ body.invoke()
+ } finally {
+ // Always restore the device state no matter what happened
+ migrationStrategy = backup
+ }
+}
\ No newline at end of file
diff --git a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
index 911758f..3958a12 100644
--- a/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
+++ b/tests/tests/uidmigration/src/android/uidmigration/cts/SharedUserMigrationTest.kt
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,63 +13,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package android.uidmigration.cts
-import android.Manifest.permission.INTERNET
-import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
-import android.content.BroadcastReceiver
import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
import android.content.pm.PackageManager
-import android.content.pm.PackageManager.PackageInfoFlags
-import android.permission.cts.PermissionUtils
-import android.permission.cts.PermissionUtils.isPermissionGranted
+import android.os.Build
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
-import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.server.pm.SharedUidMigration.BEST_EFFORT
+import com.android.server.pm.SharedUidMigration.NEW_INSTALL_ONLY
import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import java.io.ByteArrayInputStream
-import java.nio.charset.StandardCharsets.UTF_8
-import java.security.Signature
-import java.security.cert.CertificateFactory
-import java.security.cert.X509Certificate
-import java.util.UUID
-import java.util.concurrent.ArrayBlockingQueue
-import java.util.concurrent.BlockingQueue
-import java.util.concurrent.TimeUnit
-import org.junit.Assert.assertArrayEquals
-import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
-import org.junit.Assert.fail
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class SharedUserMigrationTest {
- companion object {
- private const val TMP_APK_PATH = "/data/local/tmp/cts/uidmigration"
- private const val RESULT_KEY = "result"
- private val NOT_AN_ERROR = Throwable()
- }
-
private lateinit var mContext: Context
private lateinit var mPm: PackageManager
- @Suppress("NOTHING_TO_INLINE")
- private inline fun <T> T?.assertNotNull(): T {
- assertNotNull(this)
- return this!!
- }
-
- @Suppress("NOTHING_TO_INLINE")
- private inline fun assertEquals(a: Int, b: Int) = assertEquals(a.toLong(), b.toLong())
-
@Before
fun setup() {
mContext = ApplicationProvider.getApplicationContext<Context>()
@@ -80,248 +49,97 @@
fun tearDown() {
uninstallPackage(Const.INSTALL_TEST_PKG)
uninstallPackage(Const.INSTALL_TEST_PKG + "2")
- uninstallPackage(Const.PERM_TEST_PKG)
- uninstallPackage(Const.PERM_TEST_PKG + ".secondary")
- uninstallPackage(Const.DATA_TEST_PKG)
}
- @Test
- fun testAppInstall() {
- val apk = "$TMP_APK_PATH/InstallTestApp"
- assertTrue(installPackage("$apk.apk"))
- assertTrue(installPackage(apk + "2.apk"))
-
- // Both app should share the same UID.
- val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, PackageInfoFlags.of(0))
- var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ // Restore and ensure both test apps are sharing UID.
+ private fun reset(uid: Int) {
+ uninstallPackage(Const.INSTALL_TEST_PKG)
+ assertTrue(installPackage(InstallTest.APK))
+ val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
assertEquals(2, pkgs.size)
+ }
- // Should not allow directly removing sharedUserId.
- assertFalse(installPackage(apk + "3.apk"))
+ private fun testNewInstallOnly(uid: Int) {
+ migrationStrategy = NEW_INSTALL_ONLY
- // Leave shared UID.
- assertTrue(installPackage(apk + "4.apk"))
+ // Should not allow upgrading to an APK that directly removes sharedUserId.
+ assertFalse(installPackage(InstallTest.APK3))
+
+ // Directly parsing APK4 should return no sharedUserId.
+ var pkgInfo = mPm.getPackageArchiveInfo(InstallTest.APK4, FLAG_ZERO).assertNotNull()
+ assertNull(pkgInfo.sharedUserId)
+
+ assertTrue(installPackage(InstallTest.APK4))
+ var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ // With NEW_INSTALL_ONLY, upgrades should not change appId.
+ assertEquals(2, pkgs.size)
+ pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+ assertNotNull(pkgInfo.sharedUserId)
+
+ // Should not allow re-joining sharedUserId.
+ assertFalse(installPackage(InstallTest.APK))
+
+ // Uninstall and install a new pkg leaving shared UID
+ uninstallPackage(Const.INSTALL_TEST_PKG)
+ assertTrue(installPackage(InstallTest.APK4))
+ pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ // Newly installed apps with sharedUserMaxSdkVersion set should not join shared UID.
+ assertEquals(1, pkgs.size)
+ pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+ assertNull(pkgInfo.sharedUserId)
+ }
+
+ private fun testBestEffort(uid: Int) {
+ migrationStrategy = BEST_EFFORT
+
+ assertTrue(installPackage(InstallTest.APK4))
+ var pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ // With BEST_EFFORT, upgrades should also not change appId.
+ assertEquals(2, pkgs.size)
+ var pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+ assertNotNull(pkgInfo.sharedUserId)
+
+ val oldUidName = mPm.getNameForUid(uid)
+ uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+
+ // There should be only 1 package left in the shared UID group.
+ // This should trigger the transparent shared UID migration.
pkgs = mPm.getPackagesForUid(uid).assertNotNull()
assertEquals(1, pkgs.size)
- // Should not allow re-joining sharedUserId.
- assertFalse(installPackage("$apk.apk"))
+ // Confirm that the internal PackageSetting is actually migrated.
+ val newUidName = mPm.getNameForUid(uid)
+ assertNotEquals(oldUidName, newUidName)
+ pkgInfo = mPm.getPackageInfo(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+ assertNull(pkgInfo.sharedUserId)
- uninstallPackage(Const.INSTALL_TEST_PKG)
- uninstallPackage(Const.INSTALL_TEST_PKG + "2")
+ // Even installing another shared UID app, the appId shall not be reused.
+ assertTrue(installPackage(InstallTest.APK2))
+ pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ assertEquals(1, pkgs.size)
}
@Test
- fun testPermissionMigration() {
- val apk = "$TMP_APK_PATH/PermissionTestApp"
- assertTrue(installPackage(apk + "1.apk"))
- assertTrue(installPackage(apk + "2.apk"))
- val secondaryPkg = Const.PERM_TEST_PKG + ".secondary"
+ fun testAppInstall() = withStrategy {
+ assertTrue(installPackage(InstallTest.APK))
+ assertTrue(installPackage(InstallTest.APK2))
- // Runtime permissions are not granted by default.
- assertFalse(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
+ // Both app should share the same UID.
+ val uid = mPm.getPackageUid(Const.INSTALL_TEST_PKG, FLAG_ZERO)
+ val pkgs = mPm.getPackagesForUid(uid).assertNotNull()
+ assertEquals(2, pkgs.size)
- // Grant a runtime permission.
- PermissionUtils.grantPermission(secondaryPkg, WRITE_EXTERNAL_STORAGE)
-
- // All apps in the UID group should have the same permissions.
- assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
- assertTrue(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
- assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
- assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
-
- // Upgrade and leave shared UID.
- assertTrue(installPackage(apk + "3.apk"))
-
- // The app in the original UID group should no longer have the permissions.
- assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, INTERNET))
- assertFalse(isPermissionGranted(Const.PERM_TEST_PKG, WRITE_EXTERNAL_STORAGE))
-
- // The upgraded app should still have the permissions.
- assertTrue(isPermissionGranted(secondaryPkg, INTERNET))
- assertTrue(isPermissionGranted(secondaryPkg, WRITE_EXTERNAL_STORAGE))
- uninstallPackage(Const.PERM_TEST_PKG)
- uninstallPackage(secondaryPkg)
- }
-
- @Test
- fun testDataMigration() {
- val apk = "$TMP_APK_PATH/DataTestApp"
- assertTrue(installPackage(apk + "1.apk"))
- val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
- val authority = Const.DATA_TEST_PKG + ".provider"
- val resolver = mContext.contentResolver
-
- // Ask the app to generate a new random UUID and persist in data.
- var result = resolver.call(authority, "data", null, null).assertNotNull()
- val oldUUID = result.getString(RESULT_KEY).assertNotNull()
-
- val receiver = PackageBroadcastReceiver(oldUid)
- IntentFilter().apply {
- addAction(Intent.ACTION_PACKAGE_REMOVED)
- addAction(Intent.ACTION_PACKAGE_ADDED)
- addAction(Intent.ACTION_PACKAGE_REPLACED)
- addDataScheme("package")
- mContext.registerReceiver(receiver, this)
- }
- IntentFilter().apply {
- addAction(Intent.ACTION_UID_REMOVED)
- addAction(Const.ACTION_UPDATE_ACK)
- mContext.registerReceiver(receiver, this)
- }
-
- // Update the data test APK and make sure UID changed.
- assertTrue(installPackage(apk + "2.apk"))
- val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
- assertNotEquals(oldUid, newUid)
-
- // Ensure system broadcasts are delivered properly.
- try {
- val e = receiver.poll(5, TimeUnit.SECONDS)
- if (e !== NOT_AN_ERROR) {
- throw AssertionError(e)
- }
- } catch (e: InterruptedException) {
- fail(e.message)
- }
- assertEquals(newUid, receiver.newUid)
- mContext.unregisterReceiver(receiver)
-
- // Ask the app again for a UUID. If data migration is working, it shall be the same.
- result = resolver.call(authority, "data", null, null).assertNotNull()
- val newUUID = result.getString(RESULT_KEY)
- assertEquals(oldUUID, newUUID)
- uninstallPackage(Const.DATA_TEST_PKG)
- }
-
- @Test
- fun testKeyMigration() {
- val apk = "$TMP_APK_PATH/DataTestApp"
- assertTrue(installPackage(apk + "1.apk"))
- val oldUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
- val authority = Const.DATA_TEST_PKG + ".provider"
- val resolver = mContext.contentResolver
- val secret = UUID.randomUUID().toString()
-
- // Ask the app to encrypt secret with AES.
- var result = resolver.call(authority, "encryptAES", secret, null).assertNotNull()
- assertNotNull(result[RESULT_KEY])
- assertNotNull(result["iv"])
- val encResult = result
-
- // Ask the app to generate a new EC keypair and sign our data.
- result = resolver.call(authority, "signEC", secret, null).assertNotNull()
- val signature = result.getByteArray(RESULT_KEY).assertNotNull()
- val oldCertChain = result.getByteArray("certChain").assertNotNull()
-
- // Update the data test APK and make sure UID changed.
- assertTrue(installPackage(apk + "2.apk"))
- val newUid = mPm.getPackageUid(Const.DATA_TEST_PKG, PackageInfoFlags.of(0))
- assertNotEquals(oldUid, newUid)
-
- // Ask the app to decrypt our secret.
- result = resolver.call(authority, "decryptAES", null, encResult).assertNotNull()
- val decSecret = result.getString(RESULT_KEY)
- assertEquals(secret, decSecret)
-
- // Ask the app to return the previously generated EC certificate.
- result = resolver.call(authority, "getECCert", null, null).assertNotNull()
- val rawCert = result.getByteArray(RESULT_KEY).assertNotNull()
- val newCertChain = result.getByteArray("certChain").assertNotNull()
- val cf = CertificateFactory.getInstance("X.509")
- val cert = cf.generateCertificate(ByteArrayInputStream(rawCert)) as X509Certificate
-
- // Verify the signature and cert.
- assertArrayEquals(oldCertChain, newCertChain)
- val s = Signature.getInstance("SHA256withECDSA")
- s.initVerify(cert)
- s.update(secret.toByteArray(UTF_8))
- assertTrue(s.verify(signature))
- uninstallPackage(Const.DATA_TEST_PKG)
- }
-
- private fun installPackage(apkPath: String): Boolean {
- return runShellCommand("pm install --force-queryable -t $apkPath") == "Success\n"
- }
-
- private fun uninstallPackage(packageName: String) {
- runShellCommand("pm uninstall $packageName")
- }
-
- class PackageBroadcastReceiver(
- private val mPreviousUid: Int
- ) : BroadcastReceiver(), BlockingQueue<Throwable?> by ArrayBlockingQueue<Throwable?>(1) {
-
- var newUid = -1
- private set
- private var mCounter = 0
-
- override fun onReceive(context: Context?, intent: Intent) {
- try {
- verifyInternal(intent)
- } catch (e: Throwable) {
- offer(e)
+ if (Build.IS_USERDEBUG) {
+ testNewInstallOnly(uid)
+ reset(uid)
+ testBestEffort(uid)
+ } else {
+ when (migrationStrategy) {
+ NEW_INSTALL_ONLY -> testNewInstallOnly(uid)
+ BEST_EFFORT -> testBestEffort(uid)
}
}
- private fun verifyInternal(intent: Intent) {
- val action = intent.action
- assertNotNull(action)
- if (action == Intent.ACTION_UID_REMOVED) {
- // Not the test package, none of our business.
- if (intent.getIntExtra(Intent.EXTRA_UID, -1) != mPreviousUid) {
- return
- }
- }
- val data = intent.data
- if (data != null) {
- assertEquals("package", data.scheme)
- val pkg = data.schemeSpecificPart
- assertNotNull(pkg)
- // Not the test package, none of our business.
- if (Const.DATA_TEST_PKG != pkg) {
- return
- }
- }
-
- // Broadcasts must come in the following order:
- // ACTION_PACKAGE_REMOVED -> ACTION_UID_REMOVED
- // -> ACTION_PACKAGE_ADDED -> ACTION_UPDATE_ACK
- mCounter++
- when (action) {
- Intent.ACTION_PACKAGE_REMOVED -> {
- assertEquals(1, mCounter)
- assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
- assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
- assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_UID, -1))
- newUid = intent.getIntExtra(Intent.EXTRA_NEW_UID, -1)
- assertNotEquals(mPreviousUid, newUid)
- }
- Intent.ACTION_UID_REMOVED -> {
- assertEquals(2, mCounter)
- assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
- assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
- assertEquals(
- Const.DATA_TEST_PKG,
- intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME)
- )
- }
- Intent.ACTION_PACKAGE_ADDED -> {
- assertEquals(3, mCounter)
- assertFalse(intent.hasExtra(Intent.EXTRA_REPLACING))
- assertTrue(intent.getBooleanExtra(Intent.EXTRA_UID_CHANGING, false))
- assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, mPreviousUid))
- assertEquals(mPreviousUid, intent.getIntExtra(Intent.EXTRA_PREVIOUS_UID, -1))
- }
- Const.ACTION_UPDATE_ACK -> {
- assertEquals(4, mCounter)
- assertEquals(newUid, intent.getIntExtra(Intent.EXTRA_UID, -2))
- // End of actions
- offer(NOT_AN_ERROR)
- }
- Intent.ACTION_PACKAGE_REPLACED -> fail("PACKAGE_REPLACED should not be called!")
- else -> fail("Unknown action received")
- }
- }
+ tearDown()
}
}
\ No newline at end of file
diff --git a/tests/tests/view/jni/ChoreographerTestUtils.h b/tests/tests/view/jni/ChoreographerTestUtils.h
index 83a23b7..58866a0 100644
--- a/tests/tests/view/jni/ChoreographerTestUtils.h
+++ b/tests/tests/view/jni/ChoreographerTestUtils.h
@@ -61,8 +61,8 @@
std::chrono::nanoseconds frameTime{0LL};
};
-struct ExtendedCallback : Callback {
- ExtendedCallback(const char* name, JNIEnv* env) : Callback(name), env(env) {}
+struct VsyncCallback : Callback {
+ VsyncCallback(const char* name, JNIEnv* env) : Callback(name), env(env) {}
struct FrameTime {
FrameTime(const AChoreographerFrameCallbackData* callbackData, int index)
@@ -105,30 +105,30 @@
std::vector<FrameTime> timeline;
};
-static void extendedFrameCallback(int64_t frameTimeNanos, void* data) {
+static void vsyncCallback(int64_t frameTimeNanos, void* data) {
std::lock_guard<std::mutex> _l(gLock);
- ATrace_beginSection("extendedFrameCallback base");
+ ATrace_beginSection("vsyncCallback base");
Callback* cb = static_cast<Callback*>(data);
cb->count++;
cb->frameTime = std::chrono::nanoseconds{frameTimeNanos};
ATrace_endSection();
}
-static void extendedFrameCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
- ATrace_beginSection("extendedFrameCallback");
- extendedFrameCallback(AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData), data);
+static void vsyncCallback(const AChoreographerFrameCallbackData* callbackData, void* data) {
+ ATrace_beginSection("vsyncCallback");
+ vsyncCallback(AChoreographerFrameCallbackData_getFrameTimeNanos(callbackData), data);
- ExtendedCallback* cb = static_cast<ExtendedCallback*>(data);
+ VsyncCallback* cb = static_cast<VsyncCallback*>(data);
cb->populate(callbackData);
ATrace_endSection();
}
static void frameCallback64(int64_t frameTimeNanos, void* data) {
- extendedFrameCallback(frameTimeNanos, data);
+ vsyncCallback(frameTimeNanos, data);
}
static void frameCallback(long frameTimeNanos, void* data) {
- extendedFrameCallback((int64_t)frameTimeNanos, data);
+ vsyncCallback((int64_t)frameTimeNanos, data);
}
static std::chrono::nanoseconds now() {
diff --git a/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp b/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
index 5104b58..1ffa4ca 100644
--- a/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
+++ b/tests/tests/view/jni/android_view_cts_ASurfaceControlTest.cpp
@@ -596,10 +596,10 @@
ATrace_endSection();
verifyChoreographer(env, choreographer);
- ExtendedCallback cb1("cb1", env);
+ VsyncCallback cb1("cb1", env);
auto start = now();
ATrace_beginSection("postVsyncCallback");
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
ATrace_endSection();
auto delayPeriod = std::chrono::duration_cast<std::chrono::milliseconds>(DELAY_PERIOD).count();
ATrace_beginSection("ALooper_pollOnce");
@@ -621,7 +621,7 @@
return NULL;
}
for (int i = 0; i < cb1.getTimeline().size(); i++) {
- ExtendedCallback::FrameTime frameTimeline = cb1.getTimeline()[i];
+ VsyncCallback::FrameTime frameTimeline = cb1.getTimeline()[i];
jobject frameTimelineObj =
env->NewObject(gFrameTimelineClassInfo.clazz, gFrameTimelineClassInfo.constructor,
frameTimeline.vsyncId, frameTimeline.expectedPresentTime,
diff --git a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
index 80f0759..f1e81ff 100644
--- a/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
+++ b/tests/tests/view/jni/android_view_cts_ChoreographerNativeTest.cpp
@@ -136,15 +136,15 @@
}
static void
-android_view_cts_ChoreographerNativeTest_testPostExtendedCallbackWithoutDelayEventuallyRunsCallback(
+android_view_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback(
JNIEnv* env, jclass, jlong choreographerPtr) {
AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
- ExtendedCallback cb1("cb1", env);
- ExtendedCallback cb2("cb2", env);
+ VsyncCallback cb1("cb1", env);
+ VsyncCallback cb2("cb2", env);
auto start = now();
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb2);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb2);
std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -156,7 +156,7 @@
"Callback 1 and 2 have frame times too large of a delta in frame times");
}
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
start = now();
std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
verifyCallback(env, cb1, 2, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -166,19 +166,19 @@
static void android_view_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid(
JNIEnv* env, jclass, jlong choreographerPtr) {
AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
- ExtendedCallback cb1("cb1", env);
+ VsyncCallback cb1("cb1", env);
auto start = now();
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
std::lock_guard<std::mutex> _l{gLock};
- for (const ExtendedCallback::FrameTime& frameTime : cb1.getTimeline()) {
+ for (const VsyncCallback::FrameTime& frameTime : cb1.getTimeline()) {
int64_t vsyncId = frameTime.vsyncId;
ASSERT(vsyncId >= 0, "Invalid vsync ID");
ASSERT(std::count_if(cb1.getTimeline().begin(), cb1.getTimeline().end(),
- [vsyncId](const ExtendedCallback::FrameTime& ft) {
+ [vsyncId](const VsyncCallback::FrameTime& ft) {
return ft.vsyncId == vsyncId;
}) == 1,
"Vsync ID is not unique");
@@ -188,10 +188,10 @@
static void android_view_cts_ChoreographerNativeTest_testFrameCallbackDataDeadlineInFuture(
JNIEnv* env, jclass, jlong choreographerPtr) {
AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
- ExtendedCallback cb1("cb1", env);
+ VsyncCallback cb1("cb1", env);
auto start = now();
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -209,10 +209,10 @@
android_view_cts_ChoreographerNativeTest_testFrameCallbackDataExpectedPresentTimeInFuture(
JNIEnv* env, jclass, jlong choreographerPtr) {
AChoreographer* choreographer = reinterpret_cast<AChoreographer*>(choreographerPtr);
- ExtendedCallback cb1("cb1", env);
+ VsyncCallback cb1("cb1", env);
auto start = now();
- AChoreographer_postVsyncCallback(choreographer, extendedFrameCallback, &cb1);
+ AChoreographer_postVsyncCallback(choreographer, vsyncCallback, &cb1);
std::this_thread::sleep_for(NOMINAL_VSYNC_PERIOD * 3);
verifyCallback(env, cb1, 1, start, NOMINAL_VSYNC_PERIOD * 3);
@@ -550,8 +550,8 @@
(void*)android_view_cts_ChoreographerNativeTest_getChoreographer},
{"nativePrepareChoreographerTests", "(J[J)Z",
(void*)android_view_cts_ChoreographerNativeTest_prepareChoreographerTests},
- {"nativeTestPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
- (void*)android_view_cts_ChoreographerNativeTest_testPostExtendedCallbackWithoutDelayEventuallyRunsCallback},
+ {"nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks", "(J)V",
+ (void*)android_view_cts_ChoreographerNativeTest_testPostVsyncCallbackWithoutDelayEventuallyRunsCallback},
{"nativeTestFrameCallbackDataVsyncIdValid", "(J)V",
(void*)android_view_cts_ChoreographerNativeTest_testFrameCallbackDataVsyncIdValid},
{"nativeTestFrameCallbackDataDeadlineInFuture", "(J)V",
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
index 261895d..b9e7f11 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerNativeTest.java
@@ -75,7 +75,7 @@
private static native void nativeTestPostCallback64WithoutDelayEventuallyRunsCallbacks(
long ptr);
private static native void nativeTestPostCallback64WithDelayEventuallyRunsCallbacks(long ptr);
- private static native void nativeTestPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks(
+ private static native void nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks(
long ptr);
private static native void nativeTestFrameCallbackDataVsyncIdValid(
long ptr);
@@ -130,8 +130,8 @@
@MediumTest
@Test
- public void testPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks() {
- nativeTestPostExtendedCallbackWithoutDelayEventuallyRunsCallbacks(mChoreographerPtr);
+ public void testPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks() {
+ nativeTestPostVsyncCallbackWithoutDelayEventuallyRunsCallbacks(mChoreographerPtr);
}
@MediumTest
diff --git a/tests/tests/view/src/android/view/cts/ChoreographerTest.java b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
index c74b4a1..6d2933a 100644
--- a/tests/tests/view/src/android/view/cts/ChoreographerTest.java
+++ b/tests/tests/view/src/android/view/cts/ChoreographerTest.java
@@ -38,6 +38,7 @@
import org.mockito.ArgumentCaptor;
import java.util.HashSet;
+import java.util.Set;
@MediumTest
@RunWith(AndroidJUnit4.class)
@@ -337,6 +338,26 @@
}
@Test
+ public void testPostVsyncCallbackFrameDataPreferredFrameTimelineValid() {
+ final Choreographer.VsyncCallback addedCallback = mock(
+ Choreographer.VsyncCallback.class);
+ long postTimeNanos = System.nanoTime();
+ mChoreographer.postVsyncCallback(addedCallback);
+
+ ArgumentCaptor<Choreographer.FrameData> captor = ArgumentCaptor.forClass(
+ Choreographer.FrameData.class);
+ verify(addedCallback, timeout(NOMINAL_VSYNC_PERIOD * 10).times(1)).onVsync(
+ captor.capture());
+
+ Choreographer.FrameData frameData = captor.getValue();
+ assertTrue("Number of frame timelines should be greater than 0",
+ frameData.getFrameTimelines().length > 0);
+ Set<Choreographer.FrameTimeline> frameTimelines = Set.of(frameData.getFrameTimelines());
+ assertTrue("Preferred frame timeline is not included in frame timelines",
+ frameTimelines.contains(frameData.getPreferredFrameTimeline()));
+ }
+
+ @Test
public void testPostVsyncCallbackFrameDataVsyncIdValid() {
final Choreographer.VsyncCallback addedCallback = mock(
Choreographer.VsyncCallback.class);
diff --git a/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java b/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
index def377d..afca7b0 100644
--- a/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
+++ b/tests/tests/view/src/android/view/cts/OnBackInvokedDispatcherTest.java
@@ -19,8 +19,8 @@
import static org.junit.Assert.assertNotNull;
import android.app.Dialog;
-import android.view.OnBackInvokedCallback;
-import android.view.OnBackInvokedDispatcher;
+import android.window.OnBackInvokedCallback;
+import android.window.OnBackInvokedDispatcher;
import androidx.lifecycle.Lifecycle;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java
index 0f2b760..7e81b08 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityBlockingTest.java
@@ -238,7 +238,7 @@
mVirtualDeviceManager.createVirtualDevice(
mFakeAssociationRule.getAssociationInfo().getId(),
new VirtualDeviceParams.Builder()
- .setBlockedActivities(Set.of())
+ .setBlockedActivities(Set.of(TestAppHelper.MAIN_ACTIVITY_COMPONENT))
.build());
VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
/* width= */ 100,
@@ -259,7 +259,8 @@
EmptyActivity.Callback callback = mock(EmptyActivity.Callback.class);
emptyActivity.setCallback(callback);
final int requestCode = 1;
- emptyActivity.startActivityForResult(TestAppHelper.createNoActionIntent(), requestCode);
+ emptyActivity.startActivityForResult(
+ TestAppHelper.createActivityLaunchedReceiverIntent(mResultReceiver), requestCode);
verify(mOnReceiveResultListener, after(3000).never()).onReceiveResult(
eq(Activity.RESULT_OK),
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
index 423007a..789e63b 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/ActivityManagementTest.java
@@ -137,7 +137,7 @@
DEFAULT_VIRTUAL_DEVICE_PARAMS);
ActivityListener activityListener = mock(ActivityListener.class);
Executor mockExecutor = mock(Executor.class);
- mVirtualDevice.addActivityListener(activityListener, mockExecutor);
+ mVirtualDevice.addActivityListener(mockExecutor, activityListener);
VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
/* width= */ 100,
/* height= */ 100,
@@ -175,7 +175,7 @@
mFakeAssociationRule.getAssociationInfo().getId(),
DEFAULT_VIRTUAL_DEVICE_PARAMS);
ActivityListener activityListener = mock(ActivityListener.class);
- mVirtualDevice.addActivityListener(activityListener);
+ mVirtualDevice.addActivityListener(context.getMainExecutor(), activityListener);
VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
/* width= */ 100,
/* height= */ 100,
@@ -210,7 +210,7 @@
mFakeAssociationRule.getAssociationInfo().getId(),
DEFAULT_VIRTUAL_DEVICE_PARAMS);
ActivityListener activityListener = mock(ActivityListener.class);
- mVirtualDevice.addActivityListener(activityListener);
+ mVirtualDevice.addActivityListener(context.getMainExecutor(), activityListener);
VirtualDisplay virtualDisplay = mVirtualDevice.createVirtualDisplay(
/* width= */ 100,
/* height= */ 100,
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java
index 5db7500..205daae 100644
--- a/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/StreamedAppBehaviorTest.java
@@ -26,8 +26,8 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.TruthJUnit.assume;
-import static org.junit.Assume.assumeNotNull;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
@@ -91,6 +91,8 @@
private Context mContext;
@Mock
private VirtualDisplay.Callback mVirtualDisplayCallback;
+ @Mock
+ private ActivityListener mActivityListener;
@Before
public void setUp() throws Exception {
@@ -101,6 +103,7 @@
mVirtualDeviceManager.createVirtualDevice(
mFakeAssociationRule.getAssociationInfo().getId(),
DEFAULT_VIRTUAL_DEVICE_PARAMS);
+ mVirtualDevice.addActivityListener(mContext.getMainExecutor(), mActivityListener);
mVirtualDisplay = mVirtualDevice.createVirtualDisplay(
/* width= */ 100,
/* height= */ 100,
@@ -123,8 +126,6 @@
@Test
public void appsInVirtualDevice_shouldNotHaveAccessToClipboard() {
- ActivityListener activityListener = mock(ActivityListener.class);
- mVirtualDevice.addActivityListener(activityListener);
ClipboardManager clipboardManager = mContext.getSystemService(ClipboardManager.class);
clipboardManager.setPrimaryClip(
new ClipData(
@@ -158,7 +159,7 @@
assertThat(resultData).isNotNull();
ClipData appReadClipData = resultData.getParcelableExtra("readClip");
assertThat(appReadClipData).isNull();
- verify(activityListener, timeout(3000))
+ verify(mActivityListener, timeout(3000))
.onDisplayEmpty(eq(mVirtualDisplay.getDisplay().getDisplayId()));
assertThat(clipboardManager.getPrimaryClip().getItemAt(0).getText().toString())
.isEqualTo("clipboard content from test");
@@ -168,7 +169,7 @@
public void appsInVirtualDevice_shouldNotHaveAccessToCamera() throws CameraAccessException {
CameraManager manager = mContext.getSystemService(CameraManager.class);
String[] cameras = manager.getCameraIdList();
- assumeNotNull(cameras);
+ assume().that(cameras).isNotNull();
for (String cameraId : cameras) {
EmptyActivity activity =
diff --git a/tests/tests/widget/AndroidManifest.xml b/tests/tests/widget/AndroidManifest.xml
index a703814..f3dbee4 100644
--- a/tests/tests/widget/AndroidManifest.xml
+++ b/tests/tests/widget/AndroidManifest.xml
@@ -20,7 +20,6 @@
android:targetSandboxVersion="2">
<uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>
- <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<application android:label="Android TestCase"
diff --git a/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml b/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml
index 4a3b211..1bad59c 100644
--- a/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml
+++ b/tests/tests/widget/res/layout-watch/magnifier_activity_centered_view_layout.xml
@@ -23,7 +23,7 @@
android:gravity="center" >
<FrameLayout
android:id="@+id/magnifier_centered_view"
- android:layout_width="40dp"
- android:layout_height="16dp"
+ android:layout_width="80dp"
+ android:layout_height="56dp"
android:background="@android:color/holo_blue_bright" />
</LinearLayout>
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 6857891..c3a16f3 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -266,7 +266,7 @@
assertNull(view.getParent());
assertEquals(View.VISIBLE, view.getVisibility());
- runOnMainAndDrawSync(view, mToast::show);
+ runOnMainAndDrawSync(view, () -> showToastWithNotificationPermission(mToast));
// view will be attached to screen when show it
assertEquals(View.VISIBLE, view.getVisibility());
@@ -277,7 +277,7 @@
public void testShow_whenTextToast() throws Throwable {
makeTextToast();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertTextToastShownAndHidden();
}
@@ -288,7 +288,7 @@
// Measure the length of a long toast.
makeTextToast();
long start1 = SystemClock.uptimeMillis();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
assertTextToastShownAndHidden();
long longDurationMs = SystemClock.uptimeMillis() - start1;
@@ -296,10 +296,10 @@
// Call show in the middle of the toast duration.
makeTextToast();
long start2 = SystemClock.uptimeMillis();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
SystemClock.sleep(longDurationMs / 2);
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertTextToastShownAndHidden();
long repeatCallDurationMs = SystemClock.uptimeMillis() - start2;
@@ -315,7 +315,7 @@
// Measure the length of a long toast.
makeCustomToast();
long start1 = SystemClock.uptimeMillis();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
assertCustomToastShownAndHidden(mToast.getView());
long longDurationMs = SystemClock.uptimeMillis() - start1;
@@ -323,10 +323,10 @@
// Call show in the middle of the toast duration.
makeCustomToast();
long start2 = SystemClock.uptimeMillis();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
SystemClock.sleep(longDurationMs / 2);
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertCustomToastShownAndHidden(mToast.getView());
long repeatCallDurationMs = SystemClock.uptimeMillis() - start2;
@@ -342,7 +342,7 @@
Toast toast = new Toast(mContext);
// do not have any views or text
assertNull(toast.getView());
- toast.show();
+ showToastWithNotificationPermission(mToast);
}
@Test
@@ -354,7 +354,7 @@
// view has not been attached to screen yet
assertNull(view.getParent());
mActivityRule.runOnUiThread(() -> {
- mToast.show();
+ showToastWithNotificationPermission(mToast);
mToast.cancel();
});
@@ -372,7 +372,7 @@
runOnMainAndDrawSync(imageView, () -> {
mToast.setView(imageView);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
});
assertSame(imageView, mToast.getView());
assertCustomToastShownAndHidden(imageView);
@@ -382,7 +382,8 @@
public void testAccessDuration_whenCustomToast() throws Throwable {
long start = SystemClock.uptimeMillis();
makeCustomToast();
- runOnMainAndDrawSync(mToast.getView(), mToast::show);
+ runOnMainAndDrawSync(mToast.getView(),
+ () -> showToastWithNotificationPermission(mToast));
assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
View view = mToast.getView();
@@ -392,7 +393,7 @@
start = SystemClock.uptimeMillis();
runOnMainAndDrawSync(mToast.getView(), () -> {
mToast.setDuration(Toast.LENGTH_SHORT);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
});
assertEquals(Toast.LENGTH_SHORT, mToast.getDuration());
@@ -407,7 +408,7 @@
public void testAccessDuration_whenTextToast() throws Throwable {
long start = SystemClock.uptimeMillis();
makeTextToast();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToast(mToast, true));
assertEquals(Toast.LENGTH_LONG, mToast.getDuration());
assertTextToastShownAndHidden();
@@ -417,7 +418,7 @@
makeTextToast();
mActivityRule.runOnUiThread(() -> {
mToast.setDuration(Toast.LENGTH_SHORT);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
});
assertEquals(Toast.LENGTH_SHORT, mToast.getDuration());
@@ -432,7 +433,7 @@
makeCustomToast();
final Runnable showToast = () -> {
mToast.setDuration(Toast.LENGTH_SHORT);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
};
long start = SystemClock.uptimeMillis();
runOnMainAndDrawSync(mToast.getView(), showToast);
@@ -463,7 +464,7 @@
makeTextToast();
final Runnable showToast = () -> {
mToast.setDuration(Toast.LENGTH_SHORT);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
};
long start = SystemClock.uptimeMillis();
mActivityRule.runOnUiThread(showToast);
@@ -536,7 +537,7 @@
final float vertical1 = 1.0f;
runOnMainAndDrawSync(view, () -> {
mToast.setMargin(horizontal1, vertical1);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
registerLayoutListener(mToast.getView());
});
assertCustomToastShown(view);
@@ -556,7 +557,7 @@
final float vertical2 = 0.1f;
runOnMainAndDrawSync(view, () -> {
mToast.setMargin(horizontal2, vertical2);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
registerLayoutListener(mToast.getView());
});
assertCustomToastShown(view);
@@ -594,7 +595,7 @@
makeCustomToast();
runOnMainAndDrawSync(mToast.getView(), () -> {
mToast.setGravity(Gravity.CENTER, 0, 0);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
registerLayoutListener(mToast.getView());
});
View view = mToast.getView();
@@ -609,7 +610,7 @@
runOnMainAndDrawSync(mToast.getView(), () -> {
mToast.setGravity(Gravity.BOTTOM, 0, 0);
- mToast.show();
+ showToastWithNotificationPermission(mToast);
registerLayoutListener(mToast.getView());
});
view = mToast.getView();
@@ -765,7 +766,7 @@
mToast.removeCallback(testCallback);
});
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertTextToastShownAndHidden();
assertFalse(toastShown.isDone());
@@ -788,7 +789,7 @@
mToast.addCallback(new ConditionCallback(toastShown, toastHidden));
});
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertTrue(toastShown.block(TIME_OUT));
assertTrue(toastHidden.block(TIME_OUT));
@@ -802,17 +803,20 @@
mActivityRule.runOnUiThread(
() -> mToast.addCallback(new ConditionCallback(toastShown, toastHidden)));
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertTrue(toastShown.block(TIME_OUT));
assertTrue(toastHidden.block(TIME_OUT));
}
@Test
- public void testTextToastAllowed_whenInTheForeground() throws Throwable {
+ public void testTextToastAllowed_whenInTheForeground()
+ throws Throwable {
makeTextToast();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(
+ () -> showToastWithoutNotificationPermission(mToast)
+ );
assertTextToastShownAndHidden();
}
@@ -824,24 +828,43 @@
// View has not been attached to screen yet
assertNull(view.getParent());
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(
+ () -> showToastWithoutNotificationPermission(mToast)
+ );
assertCustomToastShownAndHidden(view);
}
@Test
- public void testTextToastAllowed_whenInTheBackground() throws Throwable {
+ public void testTextToastAllowed_whenInTheBackground_withNotificationPermission()
+ throws Throwable {
assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
// Make it background
mActivityRule.finishActivity();
makeTextToast();
- mActivityRule.runOnUiThread(mToast::show);
-
+ mActivityRule.runOnUiThread(
+ () -> showToastWithNotificationPermission(mToast)
+ );
assertTextToastShownAndHidden();
}
@Test
+ public void testTextToastNotAllowed_whenInTheBackground_withoutNotificationPermission()
+ throws Throwable {
+ assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
+ // Make it background
+ mActivityRule.finishActivity();
+ List<TextToastInfo> toastInfoList = createTextToasts(1, "Text", Toast.LENGTH_SHORT);
+
+ mActivityRule.runOnUiThread(
+ () -> showToastWithoutNotificationPermission(toastInfoList.get(0).getToast())
+ );
+
+ assertTextToastNotShown(toastInfoList.get(0));
+ }
+
+ @Test
public void testCustomToastBlocked_whenInTheBackground() throws Throwable {
// Make it background
mActivityRule.finishActivity();
@@ -850,7 +873,7 @@
// View has not been attached to screen yet
assertNull(view.getParent());
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertCustomToastNotShown(view);
}
@@ -870,7 +893,7 @@
makeCustomToast();
View view = mToast.getView();
- mActivityRule.runOnUiThread(mToast::show);
+ mActivityRule.runOnUiThread(() -> showToastWithNotificationPermission(mToast));
assertCustomToastNotShown(view);
@@ -906,8 +929,10 @@
event -> event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
AccessibilityEvent event = mUiAutomation.executeAndWaitForEvent(
- () -> uncheck(() -> mActivityRule.runOnUiThread(mToast::show)), filter, TIME_OUT);
-
+ () -> uncheck(() -> mActivityRule.runOnUiThread(
+ () -> showToastWithNotificationPermission(mToast))),
+ filter,
+ TIME_OUT);
assertThat(event.getEventType()).isEqualTo(
AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
assertThat(event.getClassName()).isEqualTo(Toast.class.getCanonicalName());
@@ -922,7 +947,10 @@
event -> event.getEventType() == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
AccessibilityEvent event = mUiAutomation.executeAndWaitForEvent(
- () -> uncheck(() -> mActivityRule.runOnUiThread(mToast::show)), filter, TIME_OUT);
+ () -> uncheck(() -> mActivityRule.runOnUiThread(
+ () -> showToastWithNotificationPermission(mToast))),
+ filter,
+ TIME_OUT);
assertThat(event.getEventType()).isEqualTo(
AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
@@ -1063,14 +1091,14 @@
private void showToasts(List<? extends ToastInfo> toasts) throws Throwable {
mActivityRule.runOnUiThread(() -> {
for (ToastInfo t : toasts) {
- t.getToast().show();
+ showToast(t.getToast(), /* run with POST_NOTIFICATION permission */true);
}
});
}
private void showToast(ToastInfo toast) throws Throwable {
mActivityRule.runOnUiThread(() -> {
- toast.getToast().show();
+ showToast(toast.getToast(), /* run with POST_NOTIFICATION permission */true);
});
}
@@ -1144,6 +1172,22 @@
}
}
+ private static void showToastWithNotificationPermission(Toast toast) {
+ showToast(toast, true);
+ }
+
+ private static void showToastWithoutNotificationPermission(Toast toast) {
+ showToast(toast, false);
+ }
+
+ private static void showToast(Toast toast, boolean runWithPostNotificationPermission) {
+ if (runWithPostNotificationPermission) {
+ SystemUtil.runWithShellPermissionIdentity(() -> toast.show());
+ } else {
+ toast.show();
+ }
+ }
+
private interface ThrowingRunnable {
void run() throws Throwable;
}
diff --git a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
index 5a3b86e..711e098 100644
--- a/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/aware/cts/SingleDeviceTest.java
@@ -540,10 +540,12 @@
assertTrue("Max number of Subscribe sessions",
characteristics.getNumberOfSupportedSubscribeSessions() > 0);
if (ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)) {
- mWifiAwareManager.enableInstantCommunicationMode(true);
+ ShellIdentityUtils.invokeWithShellPermissions(() ->
+ mWifiAwareManager.enableInstantCommunicationMode(true));
assertEquals(mWifiAwareManager.isInstantCommunicationModeEnabled(),
characteristics.isInstantCommunicationModeSupported());
- mWifiAwareManager.enableInstantCommunicationMode(false);
+ ShellIdentityUtils.invokeWithShellPermissions(() ->
+ mWifiAwareManager.enableInstantCommunicationMode(false));
}
}
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
index d1f750d..ed2342d 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -134,6 +134,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiConsumer;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@@ -4699,6 +4700,57 @@
}
/**
+ * Verify the invalid and valid usages of {@code WifiManager#getAutojoinGlobal}.
+ */
+ @SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
+ public void testGetAutojoinGlobal() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
+ AtomicBoolean enabled = new AtomicBoolean(false);
+ Consumer<Boolean> listener = new Consumer<Boolean>() {
+ @Override
+ public void accept(Boolean value) {
+ synchronized (mLock) {
+ enabled.set(value);
+ mLock.notify();
+ }
+ }
+ };
+ // Test invalid inputs trigger IllegalArgumentException
+ assertThrows("null executor should trigger exception", NullPointerException.class,
+ () -> mWifiManager.getAutojoinGlobal(null, listener));
+ assertThrows("null listener should trigger exception", NullPointerException.class,
+ () -> mWifiManager.getAutojoinGlobal(mExecutor, null));
+
+ // Test caller with no permission triggers SecurityException.
+ assertThrows("No permission should trigger SecurityException", SecurityException.class,
+ () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+
+ // Test get/set autojoin global enabled
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.allowAutojoinGlobal(true));
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+ synchronized (mLock) {
+ mLock.wait(TEST_WAIT_DURATION_MS);
+ }
+ assertTrue(enabled.get());
+
+ // Test get/set autojoin global disabled
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.allowAutojoinGlobal(false));
+ ShellIdentityUtils.invokeWithShellPermissions(
+ () -> mWifiManager.getAutojoinGlobal(mExecutor, listener));
+ synchronized (mLock) {
+ mLock.wait(TEST_WAIT_DURATION_MS);
+ }
+ assertFalse(enabled.get());
+ }
+
+ /**
* Tests {@link WifiManager#isWapiSupported()} does not crash.
*/
public void testIsWapiSupported() throws Exception {
@@ -5502,7 +5554,7 @@
/**
* Tests
- * {@link WifiManager#reportImpactToCreateIfaceRequest(int, boolean, Executor, BiConsumer)}.
+ * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}.
*/
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.TIRAMISU, codeName = "Tiramisu")
public void testIsItPossibleToCreateInterface() throws Exception {
@@ -5513,7 +5565,7 @@
AtomicBoolean called = new AtomicBoolean(false);
AtomicBoolean canBeCreated = new AtomicBoolean(false);
- assertThrows(SecurityException.class, () -> mWifiManager.reportImpactToCreateIfaceRequest(
+ assertThrows(SecurityException.class, () -> mWifiManager.reportCreateInterfaceImpact(
WifiManager.WIFI_INTERFACE_TYPE_AP, false, mExecutor,
(canBeCreatedLocal, interfacesWhichWillBeDeleted) -> {
synchronized (mLock) {
diff --git a/tests/translation/src/android/translation/cts/TranslationManagerTest.java b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
index fa21041..67fa455 100644
--- a/tests/translation/src/android/translation/cts/TranslationManagerTest.java
+++ b/tests/translation/src/android/translation/cts/TranslationManagerTest.java
@@ -21,6 +21,7 @@
import static com.android.compatibility.common.util.ActivitiesWatcher.ActivityLifecycle.RESUMED;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Application;
import android.app.PendingIntent;
@@ -42,6 +43,7 @@
import android.view.translation.TranslationSpec;
import android.view.translation.Translator;
+import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
@@ -120,7 +122,7 @@
}
@Test
- public void testTranslationCapabilityUpdateListener() throws Exception{
+ public void testTranslationCapabilityUpdateListener() throws Exception {
// enable cts translation service
enableCtsTranslationService();
@@ -128,9 +130,9 @@
// text to text capability
final TranslationCapability updatedText2TextCapability =
new TranslationCapability(TranslationCapability.STATE_ON_DEVICE,
- new TranslationSpec(ULocale.ENGLISH, DATA_FORMAT_TEXT),
- new TranslationSpec(ULocale.FRENCH, DATA_FORMAT_TEXT),
- true, 0);
+ new TranslationSpec(ULocale.ENGLISH, DATA_FORMAT_TEXT),
+ new TranslationSpec(ULocale.FRENCH, DATA_FORMAT_TEXT),
+ true, 0);
// text to image capability
final TranslationCapability updatedText2ImageCapability =
new TranslationCapability(TranslationCapability.STATE_ON_DEVICE,
@@ -198,7 +200,7 @@
}
@Test
- public void testSingleTranslation() throws Exception{
+ public void testSingleTranslation() throws Exception {
enableCtsTranslationService();
final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -211,26 +213,7 @@
.build())
.build());
- final TranslationContext translationContext = new TranslationContext.Builder(
- new TranslationSpec(ULocale.ENGLISH,
- TranslationSpec.DATA_FORMAT_TEXT),
- new TranslationSpec(ULocale.FRENCH,
- TranslationSpec.DATA_FORMAT_TEXT))
- .build();
-
- final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
- final AtomicReference<Translator> translatorRef = new AtomicReference<>();
- manager.createOnDeviceTranslator(translationContext, r -> r.run(),
- new Consumer<Translator>() {
- @Override
- public void accept(Translator translator) {
- createTranslatorLatch.countDown();
- translatorRef.set(translator);
- }
- });
-
- createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
- final Translator translator = translatorRef.get();
+ final Translator translator = createTranslator(manager, createTranslationContext());
try {
mServiceWatcher.waitOnConnected();
@@ -246,13 +229,10 @@
values.add(TranslationRequestValue.forText("hello world"));
translator.translate(new TranslationRequest.Builder()
.setTranslationRequestValues(values)
- .build(), new CancellationSignal(), (r) -> r.run(),
- new Consumer<TranslationResponse>() {
- @Override
- public void accept(TranslationResponse translationResponse) {
- responseRef.set(translationResponse);
- translationLatch.countDown();
- }
+ .build(), new CancellationSignal(), Runnable::run,
+ translationResponse -> {
+ responseRef.set(translationResponse);
+ translationLatch.countDown();
});
sTranslationReplier.getNextTranslationRequest();
@@ -293,7 +273,7 @@
}
@Test
- public void testTranslation_partialResponses() throws Exception{
+ public void testTranslation_partialResponses() throws Exception {
enableCtsTranslationService();
final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -314,23 +294,7 @@
.setFinalResponse(true)
.build());
- final TranslationContext translationContext = new TranslationContext.Builder(
- new TranslationSpec(ULocale.ENGLISH,
- TranslationSpec.DATA_FORMAT_TEXT),
- new TranslationSpec(ULocale.FRENCH,
- TranslationSpec.DATA_FORMAT_TEXT))
- .build();
-
- final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
- final AtomicReference<Translator> translatorRef = new AtomicReference<>();
- manager.createOnDeviceTranslator(translationContext, r -> r.run(),
- translator -> {
- createTranslatorLatch.countDown();
- translatorRef.set(translator);
- });
-
- createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
- final Translator translator = translatorRef.get();
+ final Translator translator = createTranslator(manager, createTranslationContext());
try {
mServiceWatcher.waitOnConnected();
@@ -343,13 +307,13 @@
final CountDownLatch translationLatch = new CountDownLatch(2);
final AtomicReference<List<TranslationResponse>> responsesRef = new AtomicReference<>();
- responsesRef.set(new ArrayList<TranslationResponse>());
+ responsesRef.set(new ArrayList<>());
final ArrayList<TranslationRequestValue> values = new ArrayList<>();
values.add(TranslationRequestValue.forText("hello world"));
translator.translate(new TranslationRequest.Builder()
.setTranslationRequestValues(values)
.setFlags(TranslationRequest.FLAG_PARTIAL_RESPONSES)
- .build(), new CancellationSignal(), (r) -> r.run(),
+ .build(), new CancellationSignal(), Runnable::run,
translationResponse -> {
responsesRef.getAndUpdate(responses -> {
responses.add(translationResponse);
@@ -406,7 +370,7 @@
}
@Test
- public void testTranslationCancelled() throws Exception{
+ public void testTranslationCancelled() throws Exception {
enableCtsTranslationService();
final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -419,27 +383,7 @@
.build())
.build());
- final CountDownLatch translationLatch = new CountDownLatch(1);
- final AtomicReference<TranslationResponse> responseRef = new AtomicReference<>();
-
- final TranslationContext translationContext = new TranslationContext.Builder(
- new TranslationSpec(ULocale.ENGLISH, TranslationSpec.DATA_FORMAT_TEXT),
- new TranslationSpec(ULocale.FRENCH, TranslationSpec.DATA_FORMAT_TEXT))
- .build();
-
- final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
- final AtomicReference<Translator> translatorRef = new AtomicReference<>();
- manager.createOnDeviceTranslator(translationContext, r -> r.run(),
- new Consumer<Translator>() {
- @Override
- public void accept(Translator translator) {
- createTranslatorLatch.countDown();
- translatorRef.set(translator);
- }
- });
-
- createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
- final Translator translator = translatorRef.get();
+ final Translator translator = createTranslator(manager, createTranslationContext());
try {
mServiceWatcher.waitOnConnected();
@@ -449,21 +393,19 @@
assertThat(translator.isDestroyed()).isFalse();
- final Consumer<TranslationResponse> callback = new Consumer<TranslationResponse>() {
- @Override
- public void accept(TranslationResponse translationResponse) {
- responseRef.set(translationResponse);
- translationLatch.countDown();
- }
- };
-
final CancellationSignal cancellationSignal = new CancellationSignal();
+ final CountDownLatch translationLatch = new CountDownLatch(1);
+ final AtomicReference<TranslationResponse> responseRef = new AtomicReference<>();
final ArrayList<TranslationRequestValue> values = new ArrayList<>();
values.add(TranslationRequestValue.forText("hello world"));
translator.translate(new TranslationRequest.Builder()
- .setTranslationRequestValues(values)
- .build(), cancellationSignal, (r) -> r.run(), callback);
+ .setTranslationRequestValues(values)
+ .build(), cancellationSignal, Runnable::run,
+ translationResponse -> {
+ responseRef.set(translationResponse);
+ translationLatch.countDown();
+ });
// TODO: implement with cancellation signal listener
// cancel translation request
@@ -481,7 +423,7 @@
}
@Test
- public void testGetTranslationCapabilities() throws Exception{
+ public void testGetTranslationCapabilities() throws Exception {
enableCtsTranslationService();
final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -513,7 +455,7 @@
}
@Test
- public void testGetTranslationSettingsActivityIntent() throws Exception{
+ public void testGetTranslationSettingsActivityIntent() throws Exception {
enableCtsTranslationService();
final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
@@ -533,6 +475,41 @@
watcher.waitFor(RESUMED);
}
+ @Test
+ public void testTranslatorsAreNotCached() throws Exception {
+ enableCtsTranslationService();
+
+ final TranslationManager manager = sContext.getSystemService(TranslationManager.class);
+
+ final TranslationContext translationContext = createTranslationContext();
+ final Translator translator1 = createTranslator(manager, translationContext);
+ final Translator translator2 = createTranslator(manager, translationContext);
+
+ assertWithMessage("The same Translator was returned for the same TranslationContext")
+ .that(translator1).isNotEqualTo(translator2);
+ }
+
+ private TranslationContext createTranslationContext() {
+ return new TranslationContext.Builder(
+ new TranslationSpec(ULocale.ENGLISH, TranslationSpec.DATA_FORMAT_TEXT),
+ new TranslationSpec(ULocale.FRENCH, TranslationSpec.DATA_FORMAT_TEXT))
+ .build();
+ }
+
+ private Translator createTranslator(@NonNull TranslationManager manager,
+ @NonNull TranslationContext translationContext) throws Exception {
+ final CountDownLatch createTranslatorLatch = new CountDownLatch(1);
+ final AtomicReference<Translator> translatorRef = new AtomicReference<>();
+ manager.createOnDeviceTranslator(translationContext, Runnable::run,
+ translator -> {
+ createTranslatorLatch.countDown();
+ translatorRef.set(translator);
+ });
+
+ createTranslatorLatch.await(5_000, TimeUnit.MILLISECONDS);
+ return translatorRef.get();
+ }
+
//TODO(183605243): add test for cancelling translation.
protected void enableCtsTranslationService() {