Merge "CTS-V: Skip Audio Descriptor Test if HDMI feature is not supported" into android13-tests-dev
diff --git a/apps/CameraITS/tests/its_base_test.py b/apps/CameraITS/tests/its_base_test.py
index 60e0b38..c0b8665 100644
--- a/apps/CameraITS/tests/its_base_test.py
+++ b/apps/CameraITS/tests/its_base_test.py
@@ -103,6 +103,13 @@
try:
self.tablet = devices[1]
self.tablet_screen_brightness = self.user_params['brightness']
+ tablet_name_unencoded = self.tablet.adb.shell(
+ ['getprop', 'ro.build.product']
+ )
+ tablet_name = str(tablet_name_unencoded.decode('utf-8')).strip()
+ logging.debug('tablet name: %s', tablet_name)
+ its_session_utils.validate_tablet_brightness(
+ tablet_name, self.tablet_screen_brightness)
except KeyError:
logging.debug('Not all tablet arguments set.')
else: # sensor_fusion or manual run
@@ -251,9 +258,11 @@
# edit root_output_path and summary_writer path
# to add test name to output directory
logging.debug('summary_writer._path: %s', self.summary_writer._path)
- logging.debug('root_output_path: %s', self.root_output_path)
summary_head, summary_tail = os.path.split(self.summary_writer._path)
self.summary_writer._path = os.path.join(
f'{summary_head}_{self.__class__.__name__}', summary_tail)
os.rename(self.root_output_path,
f'{self.root_output_path}_{self.__class__.__name__}')
+ # print root_output_path so that it can be written to report log.
+ # Note: Do not replace print with logging.debug here.
+ print('root_output_path:', f'{self.root_output_path}_{self.__class__.__name__}')
\ No newline at end of file
diff --git a/apps/CameraITS/tests/scene6/test_zoom.py b/apps/CameraITS/tests/scene6/test_zoom.py
index fbc882e..2b211ba 100644
--- a/apps/CameraITS/tests/scene6/test_zoom.py
+++ b/apps/CameraITS/tests/scene6/test_zoom.py
@@ -38,7 +38,7 @@
MIN_FOCUS_DIST_TOL = 0.80 # allow charts a little closer than min
NAME = os.path.splitext(os.path.basename(__file__))[0]
NUM_STEPS = 10
-OFFSET_LOW_VAL = 10 # number of pixels
+OFFSET_ATOL = 10 # number of pixels
OFFSET_RTOL = 0.15
OFFSET_RTOL_LOW_OFFSET = 0.20
OFFSET_RTOL_MIN_FD = 0.30
@@ -207,6 +207,7 @@
def test_zoom(self):
test_data = {}
+ test_failed = False
with its_session_utils.ItsSession(
device_id=self.dut.serial,
camera_id=self.camera_id,
@@ -310,10 +311,10 @@
for i, data in test_data.items():
logging.debug('Zoom: %.2f, fl: %.2f', data['z'], data['fl'])
- offset_abs = [(data['circle'][0] - size[0] // 2),
- (data['circle'][1] - size[1] // 2)]
+ offset_xy = [(data['circle'][0] - size[0] // 2),
+ (data['circle'][1] - size[1] // 2)]
logging.debug('Circle r: %.1f, center offset x, y: %d, %d',
- data['circle'][2], offset_abs[0], offset_abs[1])
+ data['circle'][2], offset_xy[0], offset_xy[1])
z_ratio = data['z'] / z_0
# check relative size against zoom[0]
@@ -326,20 +327,24 @@
# check relative offset against init vals w/ no focal length change
if i == 0 or test_data[i-1]['fl'] != data['fl']: # set init values
z_init = float(data['z'])
- offset_init = [(data['circle'][0] - size[0] // 2),
- (data['circle'][1] - size[1] // 2)]
+ offset_hypot_init = math.hypot(offset_xy[0], offset_xy[1])
+ logging.debug('offset_hypot_init: %.3f', offset_hypot_init)
else: # check
z_ratio = data['z'] / z_init
- offset_rel = (distance(offset_abs[0], offset_abs[1]) / z_ratio /
- distance(offset_init[0], offset_init[1]))
- logging.debug('offset_rel: %.3f', offset_rel)
+ offset_hypot_rel = math.hypot(offset_xy[0], offset_xy[1]) / z_ratio
+ logging.debug('offset_hypot_rel: %.3f', offset_hypot_rel)
rel_tol = data['o_tol']
- if (np.linalg.norm(offset_init) < OFFSET_LOW_VAL and
- rel_tol == OFFSET_RTOL):
- rel_tol = OFFSET_RTOL_LOW_OFFSET
- if not math.isclose(offset_rel, 1.0, rel_tol=rel_tol):
- raise AssertionError(f"zoom: {data['z']:.2f}, offset(rel to 1): "
- f'{offset_rel:.4f}, RTOL: {rel_tol}')
+ if not math.isclose(offset_hypot_init, offset_hypot_rel,
+ rel_tol=rel_tol, abs_tol=OFFSET_ATOL):
+ test_failed = True
+ e_msg = (f"zoom: {data['z']:.2f}, "
+ f'offset init: {offset_hypot_init:.4f}, '
+ f'offset rel: {offset_hypot_rel:.4f}, '
+ f'RTOL: {rel_tol}, ATOL: {OFFSET_ATOL}')
+ logging.error(e_msg)
+
+ if test_failed:
+ raise AssertionError(f'{NAME} failed! Check test_log.DEBUG for errors')
if __name__ == '__main__':
test_runner.main()
diff --git a/apps/CameraITS/tools/run_all_tests.py b/apps/CameraITS/tools/run_all_tests.py
index a75ce5e..ed3d50d 100755
--- a/apps/CameraITS/tools/run_all_tests.py
+++ b/apps/CameraITS/tools/run_all_tests.py
@@ -475,6 +475,13 @@
config_file_test_key = config_file_contents['TestBeds'][0]['Name'].lower()
if TEST_KEY_TABLET in config_file_test_key:
tablet_id = get_device_serial_number('tablet', config_file_contents)
+ tablet_name_cmd = f'adb -s {tablet_id} shell getprop ro.build.product'
+ raw_output = subprocess.check_output(
+ tablet_name_cmd, stderr=subprocess.STDOUT, shell=True)
+ tablet_name = str(raw_output.decode('utf-8')).strip()
+ logging.debug('Tablet name: %s', tablet_name)
+ brightness = test_params_content['brightness']
+ its_session_utils.validate_tablet_brightness(tablet_name, brightness)
else:
tablet_id = None
diff --git a/apps/CameraITS/tools/run_sensor_fusion.py b/apps/CameraITS/tools/run_sensor_fusion.py
index c000562..daf822f 100644
--- a/apps/CameraITS/tools/run_sensor_fusion.py
+++ b/apps/CameraITS/tools/run_sensor_fusion.py
@@ -168,17 +168,26 @@
else:
return_string = 'FAIL'
+ with open(run_all_tests.MOBLY_TEST_SUMMARY_TXT_FILE, 'r') as file:
+ content = file.read()
+ lines = content.splitlines()
+ for one_line in lines:
+ if 'root_output_path:' in one_line:
+ root_output_path = one_line.split(':')[1].strip()
+ file.close()
+
os.remove(run_all_tests.MOBLY_TEST_SUMMARY_TXT_FILE)
- file_name = os.path.join(
- mobly_scene_output_logs_path, _TEST_BED_SENSOR_FUSION, 'latest',
- 'test_log.DEBUG')
+ file_name = os.path.join(root_output_path, 'test_log.DEBUG')
time_shift = find_time_shift(file_name)
- logging.info('%s time_shift: %.4f ms, corr: %.6f', return_string,
- time_shift['time_shift'], time_shift['corr'])
- if time_shift['corr'] < _CORR_DIST_THRESH_MAX:
- time_shifts.append(time_shift)
+ if time_shift is not None:
+ logging.info('%s time_shift: %.4f ms, corr: %.6f', return_string,
+ time_shift['time_shift'], time_shift['corr'])
+ if time_shift['corr'] < _CORR_DIST_THRESH_MAX:
+ time_shifts.append(time_shift)
+ else:
+ logging.info('Correlation distance too large. Not used for stats.')
else:
- logging.info('Correlation distance too large. Not used for stats.')
+ logging.info('time_shift not found')
# Summarize results with stats
times = [t['time_shift'] for t in time_shifts]
diff --git a/apps/CameraITS/utils/capture_request_utils.py b/apps/CameraITS/utils/capture_request_utils.py
index 2887925..521ec84 100644
--- a/apps/CameraITS/utils/capture_request_utils.py
+++ b/apps/CameraITS/utils/capture_request_utils.py
@@ -173,7 +173,7 @@
out_sizes = [(cfg['width'], cfg['height']) for cfg in out_configs]
if max_size:
out_sizes = [
- s for s in out_sizes if s[0] <= max_size[0] and s[1] <= max_size[1]
+ s for s in out_sizes if s[0] <= int(max_size[0]) and s[1] <= int(max_size[1])
]
if match_ar_size:
ar = match_ar_size[0] / float(match_ar_size[1])
diff --git a/apps/CameraITS/utils/its_session_utils.py b/apps/CameraITS/utils/its_session_utils.py
index b1fb77a..3caad99 100644
--- a/apps/CameraITS/utils/its_session_utils.py
+++ b/apps/CameraITS/utils/its_session_utils.py
@@ -38,6 +38,15 @@
ANDROID13_API_LEVEL = 33
LOAD_SCENE_DELAY_SEC = 3
SUB_CAMERA_SEPARATOR = '.'
+DEFAULT_TABLET_BRIGHTNESS = 192 # 8-bit tablet 75% brightness
+ELEVEN_BIT_TABLET_BRIGHTNESS = 1536
+ELEVEN_BIT_TABLET_NAMES = ('nabu',)
+LEGACY_TABLET_BRIGHTNESS = 96
+LEGACY_TABLET_NAME = 'dragon'
+TABLET_REQUIREMENTS_URL = 'https://source.android.com/docs/compatibility/cts/camera-its-box#tablet-requirements'
+BRIGHTNESS_ERROR_MSG = ('Tablet brightness not set as per '
+ f'{TABLET_REQUIREMENTS_URL} in the config file')
+
_VALIDATE_LIGHTING_PATCH_H = 0.05
_VALIDATE_LIGHTING_PATCH_W = 0.05
_VALIDATE_LIGHTING_REGIONS = {
@@ -50,6 +59,27 @@
_VALIDATE_LIGHTING_THRESH = 0.05 # Determined empirically from scene[1:6] tests
+def validate_tablet_brightness(tablet_name, brightness):
+ """Ensures tablet brightness is set according to documentation.
+
+ https://source.android.com/docs/compatibility/cts/camera-its-box#tablet-requirements
+ Args:
+ tablet_name: tablet product name specified by `ro.build.product`.
+ brightness: brightness specified by config file.
+ """
+ name_to_brightness = {
+ LEGACY_TABLET_NAME: LEGACY_TABLET_BRIGHTNESS,
+ }
+ for name in ELEVEN_BIT_TABLET_NAMES:
+ name_to_brightness[name] = ELEVEN_BIT_TABLET_BRIGHTNESS
+ if tablet_name in name_to_brightness:
+ if brightness != name_to_brightness[tablet_name]:
+ raise AssertionError(BRIGHTNESS_ERROR_MSG)
+ else:
+ if brightness != DEFAULT_TABLET_BRIGHTNESS:
+ raise AssertionError(BRIGHTNESS_ERROR_MSG)
+
+
class ItsSession(object):
"""Controls a device over adb to run ITS scripts.
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 80b4d13..960d649 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -271,6 +271,8 @@
android:value="multi_display_mode" />
<meta-data android:name="ApiTest"
android:value="android.companion.CompanionDeviceManager#associate" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<activity android:name=".companion.CompanionDeviceServiceTestActivity"
@@ -288,6 +290,8 @@
android:value="multi_display_mode" />
<meta-data android:name="ApiTest"
android:value="android.companion.CompanionDeviceManager#startObservingDevicePresence|android.companion.CompanionDeviceManager#stopObservingDevicePresence" />
+ <meta-data android:name="test_excluded_features"
+ android:value="android.hardware.type.watch" />
</activity>
<service
diff --git a/apps/CtsVerifier/res/values-watch/strings.xml b/apps/CtsVerifier/res/values-watch/strings.xml
index e594b9e..4f412bf 100644
--- a/apps/CtsVerifier/res/values-watch/strings.xml
+++ b/apps/CtsVerifier/res/values-watch/strings.xml
@@ -61,4 +61,7 @@
7) Repeat steps (1) through (6) for each screen lock type other than \"None\".
</string>
<string name="usb_tapjacking_usb_debugging_component">com.google.android.apps.wearable.settings/com.google.android.clockwork.settings.SecureAdbActivityAlias</string>
+
+ <!-- Adjusted for watches to leave out second part, since not applicable to watches. -->
+ <string name="add_screen_lock">Add a secure screen lock of any type.</string>
</resources>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 27eb6ee..8596554 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -5772,6 +5772,7 @@
<string name="audio_tap2tone_too_few">Not enough edges. Use fingernail.</string>
<string name="audio_tap2tone_too_many">Too many edges. Use fingernail. Ensure there is
no background noise.</string>
+ <string name="audio_tap2tone_bad_streams">Can\'t open streams.</string>
<!-- Strings for 6DoF test -->
<string name="six_dof_test">6DoF Test</string>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
index 8ecd14a..3b207b3d 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AnalogHeadsetAudioActivity.java
@@ -154,7 +154,9 @@
mHeadsetVolUpText = (TextView)findViewById(R.id.headset_keycode_volume_up);
mHeadsetVolDownText = (TextView)findViewById(R.id.headset_keycode_volume_down);
- if (isTelevision()) {
+ mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+
+ if (isTelevisionOrFixedVolume()) {
mButtonsPromptTxt.setVisibility(View.GONE);
mHeadsetHookText.setVisibility(View.GONE);
mHeadsetVolUpText.setVisibility(View.GONE);
@@ -164,8 +166,6 @@
mResultsTxt = (TextView)findViewById(R.id.headset_results);
- mAudioManager = (AudioManager)getSystemService(AUDIO_SERVICE);
-
setupPlayer();
mAudioManager.registerAudioDeviceCallback(new ConnectListener(), new Handler());
@@ -177,7 +177,7 @@
showKeyMessagesState();
- setInfoResources(R.string.analog_headset_test, isTelevision()
+ setInfoResources(R.string.analog_headset_test, isTelevisionOrFixedVolume()
? R.string.analog_headset_test_info_tv : R.string.analog_headset_test_info, -1);
setPassFailButtonClickListeners();
@@ -195,7 +195,7 @@
boolean pass = mPlugIntentReceived &&
mHeadsetDeviceInfo != null &&
mPlaybackSuccess &&
- (isTelevision()
+ (isTelevisionOrFixedVolume()
|| ((mHasHeadsetHook || mHasPlayPause) && mHasVolUp && mHasVolDown));
if (pass) {
mResultsTxt.setText(getResources().getString(R.string.analog_headset_pass));
@@ -499,7 +499,8 @@
return super.onKeyDown(keyCode, event);
}
- private boolean isTelevision() {
- return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
+ private boolean isTelevisionOrFixedVolume() {
+ return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || mAudioManager.isVolumeFixed();
}
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
index 3f1266e..5c3ee1c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioAEC.java
@@ -259,11 +259,15 @@
setLevelForStream(playbackStreamType, desiredLevel);
int currentLevel = getLevelForStream(playbackStreamType);
- if (currentLevel != desiredLevel) {
+ if (am.isVolumeFixed()) {
+ sendMessage(AudioTestRunner.TEST_MESSAGE,
+ "configured for Fixed volume, bypassing volume level check");
+
+ } else if (currentLevel != desiredLevel) {
am.setMode(originalMode);
sendMessage(AudioTestRunner.TEST_ENDED_ERROR,
- "Couldn't set level for STREAM_VOICE_CALL. Expected " +
- desiredLevel +" got: " + currentLevel);
+ "Couldn't set level for STREAM_VOICE_CALL. Expected " +
+ desiredLevel +" got: " + currentLevel);
return;
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
index cf09a74..c61689c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/AudioTap2ToneActivity.java
@@ -44,6 +44,7 @@
import com.android.cts.verifier.audio.sources.BlipAudioSourceProvider;
import org.hyphonate.megaaudio.common.BuilderBase;
+import org.hyphonate.megaaudio.common.StreamBase;
import org.hyphonate.megaaudio.duplex.DuplexAudioManager;
import org.hyphonate.megaaudio.player.AudioSource;
import org.hyphonate.megaaudio.player.AudioSourceProvider;
@@ -270,12 +271,18 @@
mDuplexAudioManager.setNumRecorderChannels(NUM_RECORD_CHANNELS);
}
- mDuplexAudioManager.setupStreams(mPlayerType, BuilderBase.TYPE_JAVA);
- mDuplexAudioManager.start();
+ if (mDuplexAudioManager.setupStreams(BuilderBase.TYPE_OBOE, BuilderBase.TYPE_JAVA)
+ == StreamBase.OK) {
+ mDuplexAudioManager.start();
- mBlipSource = (AudioSource) mDuplexAudioManager.getAudioSource();
+ mBlipSource = (AudioSource) mDuplexAudioManager.getAudioSource();
- mIsRecording = true;
+ mIsRecording = true;
+ mResultsView.setText("Successfully opened streams");
+ } else {
+ mIsRecording = false;
+ mResultsView.setText(getString(R.string.audio_tap2tone_bad_streams));
+ }
enableAudioButtons();
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
old mode 100755
new mode 100644
index 793cbf7..c8cd8fd
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -653,7 +653,7 @@
rotation = (360 - rotation) % 360; // de-compensate the mirror
}
- if (rotation != 0) {
+ if (rotation != 0 && rotation != 180) {
Matrix transform = new Matrix();
mFormatView.setScaleType(ImageView.ScaleType.MATRIX);
Rect viewRect = mFormatView.getDrawable().getBounds();
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
index eddd930..a7b58fa 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/features/FeatureUtil.java
@@ -96,7 +96,7 @@
/**
* Checks whether the device is watch .
*/
- private static boolean isWatch(Context context) {
+ public static boolean isWatch(Context context) {
PackageManager pm = context.getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_WATCH);
}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java
index 760bd71..6c63037 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/notifications/NotificationPrivacyVerifierActivity.java
@@ -29,7 +29,6 @@
import android.app.Notification;
import android.app.NotificationChannel;
import android.content.Intent;
-import android.content.pm.PackageManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
@@ -39,6 +38,7 @@
import androidx.annotation.StringRes;
import com.android.cts.verifier.R;
+import com.android.cts.verifier.features.FeatureUtil;
import java.util.ArrayList;
import java.util.List;
@@ -105,12 +105,14 @@
@Override
protected List<InteractiveTestCase> createTestItems() {
- boolean isAutomotive = getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
List<InteractiveTestCase> tests = new ArrayList<>();
- if (!isAutomotive) {
- // FIRST: set redaction settings
- tests.add(new SetScreenLockEnabledStep());
+
+ // FIRST: enable lock screen
+ tests.add(new SetScreenLockEnabledStep());
+
+ // for watches, no notifications should appear on the secure lock screen
+ if (!FeatureUtil.isWatch(this)) {
+ // THEN: set redaction settings
tests.add(new SetGlobalVisibilityPublicStep());
tests.add(new SetChannelLockscreenVisibilityPrivateStep());
// NOW TESTING: redacted by channel
@@ -132,13 +134,16 @@
tests.add(new NotificationWhenOccludedShowsRedactedTest());
tests.add(new SetGlobalVisibilitySecretStep());
- // NOW TESTING: notifications do not appear
- tests.add(new NotificationWhenLockedIsHiddenTest());
- tests.add(new NotificationWhenOccludedIsHiddenTest());
-
- // FINALLY: restore device state
- tests.add(new SetScreenLockDisabledStep());
}
+
+ // NOW TESTING: notifications do not appear
+ tests.add(new NotificationWhenLockedIsHiddenTest());
+ if (!FeatureUtil.isWatch(this)) {
+ tests.add(new NotificationWhenOccludedIsHiddenTest());
+ }
+
+ // FINALLY: restore device state
+ tests.add(new SetScreenLockDisabledStep());
return tests;
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
index e4508a9..f63f257 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
@@ -98,6 +98,7 @@
@Test
public void resumeOnReboot_ManagedProfile_Success() throws Exception {
assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+ assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
if (!getDevice().hasFeature("android.software.managed_users")) {
CLog.v(TAG, "Device doesn't support managed users; skipping test");
@@ -139,6 +140,7 @@
@Test
public void resumeOnReboot_TwoUsers_SingleUserUnlock_Success() throws Exception {
assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+ assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
if (!mSupportsMultiUser) {
CLog.v(TAG, "Device doesn't support multi-user; skipping test");
@@ -191,6 +193,7 @@
@Test
public void resumeOnReboot_TwoUsers_BothUserUnlock_Success() throws Exception {
assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+ assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
if (!mSupportsMultiUser) {
CLog.v(TAG, "Device doesn't support multi-user; skipping test");
@@ -245,6 +248,7 @@
@Test
public void resumeOnReboot_SingleUser_ServerBased_Success() throws Exception {
assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+ assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
int[] users = Utils.prepareSingleUser(getDevice());
int initialUser = users[0];
@@ -278,6 +282,7 @@
@Test
public void resumeOnReboot_SingleUser_MultiClient_ClientASuccess() throws Exception {
assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+ assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
int[] users = Utils.prepareSingleUser(getDevice());
int initialUser = users[0];
@@ -318,6 +323,7 @@
@Test
public void resumeOnReboot_SingleUser_MultiClient_ClientBSuccess() throws Exception {
assumeTrue("Device isn't at least S or has no lock screen", isSupportedSDevice());
+ assumeTrue("Device does not support file-based encryption", supportFileBasedEncryption());
int[] users = Utils.prepareSingleUser(getDevice());
int initialUser = users[0];
@@ -570,6 +576,10 @@
return isAtleastS && getDevice().hasFeature(FEATURE_SECURE_LOCK_SCREEN);
}
+ private boolean supportFileBasedEncryption() throws Exception {
+ return "file".equals(getDevice().getProperty("ro.crypto.type"));
+ }
+
private class InstallMultiple extends BaseInstallMultiple<InstallMultiple> {
public InstallMultiple() {
super(getDevice(), getBuild(), getAbi());
diff --git a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
index 09a4d81..c368e2e 100644
--- a/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
+++ b/hostsidetests/appsecurity/test-apps/DocumentClient/src/com/android/cts/documentclient/DocumentsClientTestCase.java
@@ -61,6 +61,7 @@
@Override
public void setUp() throws Exception {
+ if (!supportedHardware()) return;
super.setUp();
final PackageManager pm = getInstrumentation().getContext().getPackageManager();
@@ -91,6 +92,7 @@
@Override
public void tearDown() throws Exception {
+ if (!supportedHardware()) return;
super.tearDown();
mActivity.finish();
diff --git a/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java b/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java
index 12fbb3c..aab1d9e 100644
--- a/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java
+++ b/hostsidetests/appsecurity/test-apps/ListeningPortsApp/src/android/appsecurity/cts/listeningports/ListeningPortsTest.java
@@ -16,6 +16,7 @@
package android.appsecurity.cts.listeningports;
+import android.app.UiAutomation;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Process;
@@ -138,8 +139,15 @@
}
private String uidToPackage(int uid) {
+ UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
PackageManager pm = this.getContext().getPackageManager();
- String[] packages = pm.getPackagesForUid(uid);
+ String[] packages;
+ try {
+ uiAutomation.adoptShellPermissionIdentity();
+ packages = pm.getPackagesForUid(uid);
+ } finally {
+ uiAutomation.dropShellPermissionIdentity();
+ }
if (packages == null) {
return "[unknown]";
}
diff --git a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
index b3d1d1c..56d2e07 100644
--- a/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
+++ b/hostsidetests/appsecurity/test-apps/MediaStorageApp/src/com/android/cts/mediastorageapp/MediaStorageTest.java
@@ -996,12 +996,7 @@
// to keep rolling forward if we can't find our grant button
final UiSelector grant = new UiSelector().textMatches("(?i)Allow");
if (isWatch()) {
- UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
- try {
- uiScrollable.scrollIntoView(grant);
- } catch (UiObjectNotFoundException e) {
- // Scrolling can fail if the UI is not scrollable
- }
+ scrollIntoView(grant);
}
final boolean grantExists = new UiObject(grant).waitForExists(timeout);
@@ -1016,8 +1011,11 @@
// Verify that we now have access
assertEquals(Activity.RESULT_OK, res.resultCode);
} else {
- // fine the Deny button
+ // find the Deny button
final UiSelector deny = new UiSelector().textMatches("(?i)Deny");
+ if (isWatch()) {
+ scrollIntoView(deny);
+ }
final boolean denyExists = new UiObject(deny).waitForExists(timeout);
assertThat(denyExists).isTrue();
@@ -1030,6 +1028,15 @@
}
}
+ private static void scrollIntoView(UiSelector selector) {
+ UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
+ try {
+ uiScrollable.scrollIntoView(selector);
+ } catch (UiObjectNotFoundException e) {
+ // Scrolling can fail if the UI is not scrollable
+ }
+ }
+
private static Uri createDownload() throws IOException {
final String content = "<html><body>Content</body></html>";
final String displayName = "cts" + System.nanoTime();
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java
index 94b83de..55e7dff 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/PermissionsTest.java
@@ -36,9 +36,11 @@
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.DeviceConfig;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.BySelector;
import android.support.test.uiautomator.UiDevice;
@@ -46,7 +48,7 @@
import android.util.Log;
import com.android.compatibility.common.util.PollingCheck;
-
+import com.android.compatibility.common.util.SystemUtil;
import com.android.cts.devicepolicy.PermissionBroadcastReceiver;
import com.android.cts.devicepolicy.PermissionUtils;
@@ -105,6 +107,11 @@
mContext.registerReceiver(mReceiver, new IntentFilter(ACTION_PERMISSION_RESULT));
mDevice = UiDevice.getInstance(getInstrumentation());
mUiAutomation = getInstrumentation().getUiAutomation();
+ SystemUtil.runWithShellPermissionIdentity(() -> {
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
+ "safety_center_qs_tile_component_setting_flags",
+ Integer.toString(PackageManager.DONT_KILL_APP), false);
+ });
}
@Override
diff --git a/hostsidetests/hdmicec/app/AndroidManifest.xml b/hostsidetests/hdmicec/app/AndroidManifest.xml
index 4eb046e3..4db04bd 100644
--- a/hostsidetests/hdmicec/app/AndroidManifest.xml
+++ b/hostsidetests/hdmicec/app/AndroidManifest.xml
@@ -22,7 +22,8 @@
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<activity android:name=".HdmiCecKeyEventCapture"
- android:exported="true">
+ android:exported="true"
+ android:launchMode="singleInstance">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LEANBACK_LAUNCHER"/>
diff --git a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
index 63736bf..d2070db 100644
--- a/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
+++ b/hostsidetests/hdmicec/app/src/android/hdmicec/app/HdmiCecKeyEventCapture.java
@@ -19,8 +19,8 @@
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
-import android.view.KeyEvent;
import android.view.Gravity;
+import android.view.KeyEvent;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TableRow;
@@ -81,4 +81,20 @@
return true;
}
-}
\ No newline at end of file
+ /*
+ Override onUserLeaveHint() to simulate KEYCODE_HOME pressing for now.
+ If the activity will be used to test other complicated scenarios
+ which will let the activity go into the background,
+ the onUserLeaveHint() might be called without KEYCODE_HOME pressing.
+ */
+ @Override
+ protected void onUserLeaveHint() {
+ text.setText((longPressed ? "Long press " : "Short press ")
+ + "KEYCODE_HOME");
+ Log.d(TAG, "onUserLeaveHint: KEYCODE_HOME Press");
+ Log.i(TAG, (longPressed ? "Long press " : "Short press ") + "KEYCODE_HOME");
+
+ longPressed = false;
+ super.onUserLeaveHint();
+ }
+}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
index c23e16b..33465a1 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
@@ -258,6 +258,11 @@
device,
CLASS,
"Short press KEYCODE_" + mUserControlPressKeys_20.get(userControlPressKey));
+ // KEYCODE_HOME pressing will let the activity HdmiCecKeyEventCapture be paused.
+ // Resume the activity after tesing for KEYCODE_HOME pressing.
+ if (userControlPressKey == HdmiCecConstants.CEC_KEYCODE_ROOT_MENU) {
+ device.executeShellCommand(START_COMMAND);
+ }
}
}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
index baaccc8..dad1800 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/playback/HdmiCecRemoteControlPassThroughTest.java
@@ -132,7 +132,7 @@
sendUcpMenuCommand(HdmiCecConstants.CEC_KEYCODE_SETUP_MENU, "SETTINGS");
}
if ((remoteControlProfileSource & 0x10) == 0x10) {
- sendUcpMenuCommand(HdmiCecConstants.CEC_KEYCODE_ROOT_MENU, "MENU");
+ sendUcpMenuCommand(HdmiCecConstants.CEC_KEYCODE_ROOT_MENU, "HOME");
}
}
diff --git a/hostsidetests/incident/AndroidTest.xml b/hostsidetests/incident/AndroidTest.xml
index 727277d..73be7b4 100644
--- a/hostsidetests/incident/AndroidTest.xml
+++ b/hostsidetests/incident/AndroidTest.xml
@@ -20,9 +20,6 @@
<option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
<option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />
<option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
- <target_preparer class="com.android.tradefed.targetprep.SwitchUserTargetPreparer">
- <option name="user-type" value="system" />
- </target_preparer>
<test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" >
<option name="jar" value="CtsIncidentHostTestCases.jar" />
</test>
diff --git a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
index 3b81acb..86df388 100644
--- a/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
+++ b/hostsidetests/usb/src/com/android/cts/usb/TestUsbTest.java
@@ -116,7 +116,7 @@
/**
* Check if adb serial number, USB serial number, ro.serialno, and android.os.Build.SERIAL
- * all matches and meets the format requirement [a-zA-Z0-9]{6,20}
+ * all matches and meets the format requirement [a-zA-Z0-9\\._\\-,]+
*/
@AppModeInstant(reason = "only instant apps fail when reading serial")
public void testInstantAppsCannotReadSerial() throws Exception {
@@ -127,7 +127,7 @@
/**
* Check if adb serial number, USB serial number, ro.serialno, and android.os.Build.SERIAL
- * all matches and meets the format requirement [a-zA-Z0-9]{6,20}
+ * all matches and meets the format requirement [a-zA-Z0-9\\._\\-,]+
*/
@AppModeFull(reason = "serial can not be read by instant apps")
public void testUsbSerialReadOnDeviceMatches() throws Exception {
@@ -148,7 +148,7 @@
CommandResult result = RunUtil.getDefault().runTimedCmd(15000, "lsusb", "-v");
assertEquals("lsusb -v failed", result.getStatus(), CommandStatus.SUCCESS);
String lsusbOutput = result.getStdout();
- Pattern pattern = Pattern.compile("^\\s+iSerial\\s+\\d+\\s+([a-zA-Z0-9]{6,20})",
+ Pattern pattern = Pattern.compile("^\\s+iSerial\\s+\\d+\\s+([a-zA-Z0-9\\._\\-,]+)",
Pattern.MULTILINE);
Matcher matcher = pattern.matcher(lsusbOutput);
String usbSerial = "";
@@ -166,7 +166,7 @@
runTestOnDevice("logSerial");
String logs = mDevice.executeAdbCommand(
"logcat", "-v", "brief", "-d", "CtsUsbSerialTest:W", "*:S");
- pattern = Pattern.compile("^.*CtsUsbSerialTest\\(.*\\):\\s+([a-zA-Z0-9]{6,20})",
+ pattern = Pattern.compile("^.*CtsUsbSerialTest\\(.*\\):\\s+([a-zA-Z0-9\\._\\-,]+)",
Pattern.MULTILINE);
matcher = pattern.matcher(logs);
String buildSerial = "";
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
index e3a3a41..7644c40 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/CloudPhotoPickerTest.java
@@ -52,6 +52,7 @@
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;
@@ -279,6 +280,7 @@
}
@Test
+ @Ignore("Ignored in Android T becauase this changed between T and U")
public void testUriAccessWithInvalidProjection() throws Exception {
initPrimaryCloudProviderWithImage(Pair.create(null, CLOUD_ID1));
@@ -290,8 +292,8 @@
final ContentResolver resolver = mContext.getContentResolver();
assertThrows(IllegalArgumentException.class, () -> resolver.query(
- clipData.getItemAt(0).getUri(),
- new String[] {MediaStore.MediaColumns.RELATIVE_PATH}, null, null));
+ clipData.getItemAt(0).getUri(),
+ new String[] {MediaStore.MediaColumns.RELATIVE_PATH}, null, null));
}
@Test
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
index e36d1ee..64cc0f1 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityFingerprintGestureTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
@@ -90,9 +91,10 @@
@Test
public void testGestureDetectionListener_whenAuthenticationStartsAndStops_calledBack() {
- if (!mFingerprintGestureController.isGestureDetectionAvailable()) {
- return;
- }
+ assumeTrue("Fingerprint gesture detection is not available",
+ mFingerprintGestureController.isGestureDetectionAvailable());
+ assumeTrue("No enrolled fingerprints; cannot open fingerprint prompt",
+ mFingerprintManager.hasEnrolledFingerprints());
// Launch an activity to make sure we're in the foreground
mActivityRule.launchActivity(null);
mFingerprintGestureController.registerFingerprintGestureCallback(
diff --git a/tests/app/src/android/app/cts/NotificationTemplateTest.kt b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
index cd1de26..f654724 100644
--- a/tests/app/src/android/app/cts/NotificationTemplateTest.kt
+++ b/tests/app/src/android/app/cts/NotificationTemplateTest.kt
@@ -300,9 +300,6 @@
checkViews(builder.createBigContentView()) {
val pictureView = requireViewByIdName<ImageView>("big_picture")
assertThat(pictureView.visibility).isEqualTo(View.VISIBLE)
- assertThat(pictureView.width.toFloat())
- .isWithin(1f)
- .of((pictureView.height * 4 / 3).toFloat())
assertThat(pictureView.scaleType).isEqualTo(ImageView.ScaleType.CENTER_CROP)
}
}
diff --git a/tests/autofillservice/res/layout/scrollable_login_activity.xml b/tests/autofillservice/res/layout/scrollable_login_activity.xml
new file mode 100644
index 0000000..dfa5227
--- /dev/null
+++ b/tests/autofillservice/res/layout/scrollable_login_activity.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:orientation="vertical" >
+
+ <ScrollView android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <include layout="@layout/login_activity" />
+
+ </LinearLayout>
+
+ </ScrollView>
+
+</LinearLayout>
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index 6dd4d1a..381eefb 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -543,10 +543,9 @@
// It works fine for portrait but for the platforms that the default orientation
// is landscape, e.g. automotive. Depending on the height of the IME, the ID_LOGIN
// button may not be visible.
- // In order to avoid that,
- // generate back key event to hide IME before pressing ID_LOGIN button.
- mUiBot.pressBack();
+ // In order to avoid that, scroll until the ID_LOGIN button appears.
+ mUiBot.scrollToTextObject(ID_LOGIN);
mUiBot.selectByRelativeId(ID_LOGIN);
mUiBot.assertSaveShowing(SAVE_DATA_TYPE_USERNAME);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
index 4cab12c..ca91090 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/activities/OutOfProcessLoginActivity.java
@@ -41,7 +41,7 @@
Log.i(TAG, "onCreate(" + savedInstanceState + ")");
super.onCreate(savedInstanceState);
- setContentView(R.layout.login_activity);
+ setContentView(R.layout.scrollable_login_activity);
findViewById(R.id.login).setOnClickListener((v) -> finish());
diff --git a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
index d45b6c1..d015959 100644
--- a/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -776,8 +776,7 @@
waiverKeys.add(CaptureResult.HOT_PIXEL_MODE);
}
- if (!staticInfo.isNoiseReductionModeControlSupported()
- && staticInfo.getAvailableNoiseReductionModesChecked().length == 0) {
+ if (!staticInfo.isNoiseReductionModeControlSupported()) {
waiverKeys.add(CaptureResult.NOISE_REDUCTION_MODE);
}
diff --git a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
index 4ee066f..70f0c06 100644
--- a/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
+++ b/tests/camera/src/android/hardware/camera2/cts/RobustnessTest.java
@@ -40,8 +40,8 @@
import static android.hardware.camera2.cts.RobustnessTest.MaxStreamSizes.VGA;
import static android.hardware.camera2.cts.RobustnessTest.MaxStreamSizes.YUV;
-import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
@@ -78,7 +78,6 @@
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageWriter;
-import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.util.Size;
@@ -95,12 +94,11 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
-import java.util.Iterator;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.LinkedBlockingQueue;
/**
* Tests exercising edge cases in camera setup, configuration, and usage.
@@ -217,28 +215,6 @@
* Test for making sure the mandatory stream combinations work as expected.
*/
private void testMandatoryOutputCombinations(boolean maxResolution) throws Exception {
- final int AVAILABILITY_TIMEOUT_MS = 10;
- final LinkedBlockingQueue<Pair<String, String>> unavailablePhysicalCamEventQueue =
- new LinkedBlockingQueue<>();
- CameraManager.AvailabilityCallback ac = new CameraManager.AvailabilityCallback() {
- @Override
- public void onPhysicalCameraUnavailable(String cameraId, String physicalCameraId) {
- unavailablePhysicalCamEventQueue.offer(new Pair<>(cameraId, physicalCameraId));
- }
- };
-
- mCameraManager.registerAvailabilityCallback(ac, mHandler);
- Set<Pair<String, String>> unavailablePhysicalCameras = new HashSet<Pair<String, String>>();
- Pair<String, String> candidatePhysicalIds =
- unavailablePhysicalCamEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
- java.util.concurrent.TimeUnit.MILLISECONDS);
- while (candidatePhysicalIds != null) {
- unavailablePhysicalCameras.add(candidatePhysicalIds);
- candidatePhysicalIds =
- unavailablePhysicalCamEventQueue.poll(AVAILABILITY_TIMEOUT_MS,
- java.util.concurrent.TimeUnit.MILLISECONDS);
- }
- mCameraManager.unregisterAvailabilityCallback(ac);
CameraCharacteristics.Key<MandatoryStreamCombination []> ck =
CameraCharacteristics.SCALER_MANDATORY_STREAM_COMBINATIONS;
@@ -276,22 +252,10 @@
if (mStaticInfo.isLogicalMultiCamera()) {
Set<String> physicalCameraIds =
mStaticInfo.getCharacteristics().getPhysicalCameraIds();
- boolean skipTest = false;
for (String physicalId : physicalCameraIds) {
if (Arrays.asList(mCameraIdsUnderTest).contains(physicalId)) {
// If physicalId is advertised in camera ID list, do not need to test
// its stream combination through logical camera.
- skipTest = true;
- }
- for (Pair<String, String> unavailPhysicalCam : unavailablePhysicalCameras) {
- if (unavailPhysicalCam.first.equals(id) ||
- unavailPhysicalCam.second.equals(physicalId)) {
- // This particular physical camera isn't available. Skip.
- skipTest = true;
- break;
- }
- }
- if (skipTest) {
continue;
}
StaticMetadata physicalStaticInfo = mAllStaticInfo.get(physicalId);
diff --git a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index f0bd2c9..3ae7558 100644
--- a/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/camera/utils/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -2413,16 +2413,7 @@
* @return {@code true} if noise reduction mode control is supported
*/
public boolean isNoiseReductionModeControlSupported() {
- if (!areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE)) {
- return false;
- }
- int[] availableModes = getAvailableNoiseReductionModesChecked();
- // Let's consider noise reduction is not supported if only "OFF" is reported.
- if (availableModes.length == 1
- && availableModes[0] == CaptureRequest.NOISE_REDUCTION_MODE_OFF) {
- return false;
- }
- return true;
+ return areKeysAvailable(CaptureRequest.NOISE_REDUCTION_MODE);
}
/**
diff --git a/tests/framework/base/windowmanager/app/AndroidManifest.xml b/tests/framework/base/windowmanager/app/AndroidManifest.xml
index 2e0a212..de97acc 100755
--- a/tests/framework/base/windowmanager/app/AndroidManifest.xml
+++ b/tests/framework/base/windowmanager/app/AndroidManifest.xml
@@ -301,7 +301,7 @@
android:exported="true"/>
<activity android:name=".ShowWhenLockedDialogActivity"
android:exported="true"
- android:theme="@android:style/Theme.Material.Dialog"/>
+ android:theme="@style/ShowWhenLockedDialogTheme"/>
<activity android:name=".ShowWhenLockedTranslucentActivity"
android:exported="true"
android:theme="@android:style/Theme.Translucent"/>
@@ -332,10 +332,11 @@
android:exported="true"
android:configChanges="uiMode"/>
<activity android:name=".FontScaleActivity"
+ android:configChanges="screenSize|screenLayout"
android:exported="true"/>
<activity android:name=".FontScaleNoRelaunchActivity"
android:exported="true"
- android:configChanges="fontScale"/>
+ android:configChanges="fontScale|screenSize|screenLayout"/>
<activity android:name=".DisplayAccessCheckEmbeddingActivity"
android:allowEmbedded="true"
android:exported="true"/>
diff --git a/tests/framework/base/windowmanager/app/res/values-watch/styles.xml b/tests/framework/base/windowmanager/app/res/values-watch/styles.xml
new file mode 100644
index 0000000..14da321
--- /dev/null
+++ b/tests/framework/base/windowmanager/app/res/values-watch/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 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>
+ <style name="ShowWhenLockedDialogTheme" parent="@android:style/Theme.Material.Dialog">
+ <!-- Wear dialog theme has been converted to non-floating, but this breaks occluding -->
+ <item name="@android:windowIsFloating">true</item>
+ <!-- Likewise, for the purpose of CTS, make this non-swipeable, as there are visibility
+ implications there as well -->
+ <item name="@android:windowSwipeToDismiss">false</item>
+ </style>
+</resources>
diff --git a/tests/framework/base/windowmanager/app/res/values/styles.xml b/tests/framework/base/windowmanager/app/res/values/styles.xml
index 43f60eb..d0e35c0 100644
--- a/tests/framework/base/windowmanager/app/res/values/styles.xml
+++ b/tests/framework/base/windowmanager/app/res/values/styles.xml
@@ -101,4 +101,7 @@
<item name="android:windowLayoutInDisplayCutoutMode">always</item>
<item name="android:windowSoftInputMode">stateHidden</item>
</style>
+ <style name="ShowWhenLockedDialogTheme" parent="@android:style/Theme.Material.Dialog">
+ <!-- no-op except on Wear, where dialog theme has been converted to non-floating -->
+ </style>
</resources>
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
index c2752e6..4326f7d 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
@@ -39,6 +39,7 @@
import static org.junit.Assume.assumeNotNull;
import android.graphics.Rect;
+import android.server.wm.IgnoreOrientationRequestSession;
import android.server.wm.jetpack.utils.TestActivity;
import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
import android.server.wm.jetpack.utils.TestValueCountJavaConsumer;
@@ -167,56 +168,66 @@
@Test
public void testGetWindowLayoutInfo_configChanged_windowLayoutUpdates()
- throws ExecutionException, InterruptedException, TimeoutException {
+ throws InterruptedException {
mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
assumeHasDisplayFeatures(mWindowLayoutInfo);
- TestConfigChangeHandlingActivity configHandlingActivity
+ final TestConfigChangeHandlingActivity configHandlingActivity
= (TestConfigChangeHandlingActivity) startActivityNewTask(
TestConfigChangeHandlingActivity.class);
- setActivityOrientationActivityHandlesOrientationChanges(configHandlingActivity,
- ORIENTATION_PORTRAIT);
- final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(
- configHandlingActivity);
- final Rect portraitBounds = getActivityBounds(configHandlingActivity);
- final Rect portraitMaximumBounds = getMaximumActivityBounds(configHandlingActivity);
+ try (IgnoreOrientationRequestSession session =
+ new IgnoreOrientationRequestSession(false /* enable */)) {
+ setActivityOrientationActivityHandlesOrientationChanges(configHandlingActivity,
+ ORIENTATION_PORTRAIT);
+ final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(
+ configHandlingActivity);
+ final Rect portraitBounds = getActivityBounds(configHandlingActivity);
+ final Rect portraitMaximumBounds = getMaximumActivityBounds(configHandlingActivity);
- setActivityOrientationActivityHandlesOrientationChanges(configHandlingActivity,
- ORIENTATION_LANDSCAPE);
- final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(
- configHandlingActivity);
- final Rect landscapeBounds = getActivityBounds(configHandlingActivity);
- final Rect landscapeMaximumBounds = getMaximumActivityBounds(configHandlingActivity);
+ setActivityOrientationActivityHandlesOrientationChanges(configHandlingActivity,
+ ORIENTATION_LANDSCAPE);
+ final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(
+ configHandlingActivity);
+ final Rect landscapeBounds = getActivityBounds(configHandlingActivity);
+ final Rect landscapeMaximumBounds = getMaximumActivityBounds(configHandlingActivity);
- final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
- portraitMaximumBounds, landscapeMaximumBounds);
- assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
- portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+ final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
+ portraitMaximumBounds, landscapeMaximumBounds);
+ assertTrue(doesDisplayRotateForOrientation);
+ assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
+ portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+ }
}
@Test
public void testGetWindowLayoutInfo_windowRecreated_windowLayoutUpdates()
- throws ExecutionException, InterruptedException, TimeoutException {
- mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
- assumeHasDisplayFeatures(mWindowLayoutInfo);
+ throws InterruptedException {
+ try (IgnoreOrientationRequestSession session =
+ new IgnoreOrientationRequestSession(false /* enable */)) {
+ mWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
+ assumeHasDisplayFeatures(mWindowLayoutInfo);
- setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
- ORIENTATION_PORTRAIT);
- final WindowLayoutInfo portraitWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
- final Rect portraitBounds = getActivityBounds(mActivity);
- final Rect portraitMaximumBounds = getMaximumActivityBounds(mActivity);
+ setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+ ORIENTATION_PORTRAIT);
+ final WindowLayoutInfo portraitWindowLayoutInfo =
+ getExtensionWindowLayoutInfo(mActivity);
+ final Rect portraitBounds = getActivityBounds(mActivity);
+ final Rect portraitMaximumBounds = getMaximumActivityBounds(mActivity);
- setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
- ORIENTATION_LANDSCAPE);
- final WindowLayoutInfo landscapeWindowLayoutInfo = getExtensionWindowLayoutInfo(mActivity);
- final Rect landscapeBounds = getActivityBounds(mActivity);
- final Rect landscapeMaximumBounds = getMaximumActivityBounds(mActivity);
+ setActivityOrientationActivityDoesNotHandleOrientationChanges(mActivity,
+ ORIENTATION_LANDSCAPE);
+ final WindowLayoutInfo landscapeWindowLayoutInfo =
+ getExtensionWindowLayoutInfo(mActivity);
+ final Rect landscapeBounds = getActivityBounds(mActivity);
+ final Rect landscapeMaximumBounds = getMaximumActivityBounds(mActivity);
- final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
- portraitMaximumBounds, landscapeMaximumBounds);
- assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
- portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+ final boolean doesDisplayRotateForOrientation = doesDisplayRotateForOrientation(
+ portraitMaximumBounds, landscapeMaximumBounds);
+ assertTrue(doesDisplayRotateForOrientation);
+ assertEqualWindowLayoutInfo(portraitWindowLayoutInfo, landscapeWindowLayoutInfo,
+ portraitBounds, landscapeBounds, doesDisplayRotateForOrientation);
+ }
}
/**
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
index f7b352f..143f7c0 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
@@ -16,9 +16,6 @@
package android.server.wm.jetpack.utils;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getActivityBounds;
-import static android.server.wm.jetpack.utils.WindowManagerJetpackTestBase.getMaximumActivityBounds;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -38,8 +35,6 @@
import androidx.window.extensions.layout.WindowLayoutComponent;
import androidx.window.extensions.layout.WindowLayoutInfo;
-import java.util.ArrayList;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
@@ -109,7 +104,7 @@
@Nullable
public static WindowLayoutInfo getExtensionWindowLayoutInfo(Activity activity)
- throws ExecutionException, InterruptedException, TimeoutException {
+ throws InterruptedException {
WindowLayoutComponent windowLayoutComponent = getExtensionWindowLayoutComponent();
if (windowLayoutComponent == null) {
return null;
@@ -117,7 +112,14 @@
TestValueCountJavaConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
new TestValueCountJavaConsumer<>();
windowLayoutComponent.addWindowLayoutInfoListener(activity, windowLayoutInfoConsumer);
- return windowLayoutInfoConsumer.waitAndGet();
+ WindowLayoutInfo info = windowLayoutInfoConsumer.waitAndGet();
+
+ // The default implementation only allows a single listener per activity. Since we are using
+ // a local windowLayoutInfoConsumer within this function, we must remember to clean up.
+ // Otherwise, subsequent calls to addWindowLayoutInfoListener with the same activity will
+ // fail to have its callback registered.
+ windowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
+ return info;
}
@NonNull
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
index 2d4260c..d47cc6d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ActivityTransitionTests.java
@@ -16,6 +16,7 @@
package android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.server.wm.ActivityTransitionTests.EdgeExtensionActivity.BOTTOM;
import static android.server.wm.ActivityTransitionTests.EdgeExtensionActivity.DIRECTION_KEY;
@@ -114,7 +115,9 @@
final Intent intent = new Intent(mContext, LauncherActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- return (LauncherActivity) instrumentation.startActivitySync(intent);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ return (LauncherActivity) instrumentation.startActivitySync(intent, options.toBundle());
}
@Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
index 79bbe9c..a975e5a 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/AssistantStackTests.java
@@ -65,7 +65,6 @@
public class AssistantStackTests extends ActivityManagerTestBase {
private int mAssistantDisplayId = DEFAULT_DISPLAY;
- private int mDefaultWindowingMode;
public void setUp() throws Exception {
super.setUp();
@@ -76,7 +75,6 @@
WindowManagerState.Task assistantStack =
mWmState.getRootTaskByActivityType(ACTIVITY_TYPE_ASSISTANT);
mAssistantDisplayId = assistantStack.mDisplayId;
- mDefaultWindowingMode = getDefaultDisplayWindowingMode();
}
}
@@ -92,7 +90,7 @@
// Ensure that the activity launched in the fullscreen assistant stack
assertAssistantStackExists();
// In a multi-window environment the assistant might not be fullscreen
- assumeTrue(mDefaultWindowingMode == WINDOWING_MODE_FULLSCREEN);
+ assumeTrue(getDefaultDisplayWindowingMode() == WINDOWING_MODE_FULLSCREEN);
assertTrue("Expected assistant stack to be fullscreen",
mWmState.getRootTaskByActivityType(
ACTIVITY_TYPE_ASSISTANT).isFullscreen());
@@ -134,7 +132,7 @@
@Test
public void testAssistantStackLaunchNewTask() throws Exception {
- assertAssistantStackCanLaunchAndReturnFromNewTask(mDefaultWindowingMode);
+ assertAssistantStackCanLaunchAndReturnFromNewTask();
}
@Test
@@ -151,7 +149,7 @@
//assertAssistantStackCanLaunchAndReturnFromNewTask(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
}
- private void assertAssistantStackCanLaunchAndReturnFromNewTask(int expectedWindowingMode)
+ private void assertAssistantStackCanLaunchAndReturnFromNewTask()
throws Exception {
// Enable the assistant and launch an assistant activity which will launch a new task
try (final AssistantSession assistantSession = new AssistantSession()) {
@@ -161,8 +159,7 @@
extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)),
extraString(EXTRA_ASSISTANT_DISPLAY_ID, Integer.toString(mAssistantDisplayId)));
// Ensure that the fullscreen stack is on top and the test activity is now visible
- waitForValidStateWithActivityTypeAndWindowingMode(
- TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, expectedWindowingMode);
+ waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
}
if (isAssistantOnTopOfDream()) {
@@ -175,11 +172,13 @@
mWmState.assertFocusedRootTask("Assistant stack should be focused.",
WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_ASSISTANT);
} else {
+ final int testActivityWindowingMode =
+ mWmState.getTaskDisplayArea(TEST_ACTIVITY).getWindowingMode();
mWmState.assertFocusedActivity("TestActivity should be resumed", TEST_ACTIVITY);
mWmState.assertFrontStack("TestActivity stack should be on top.",
- expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+ testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
- expectedWindowingMode, ACTIVITY_TYPE_STANDARD);
+ testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
}
// Now, tell it to finish itself and ensure that the assistant stack is brought back forward
@@ -211,15 +210,17 @@
mWmState.waitFor((amState) -> !amState.containsActivity(ASSISTANT_ACTIVITY),
getActivityName(ASSISTANT_ACTIVITY) + " finished");
}
- waitForValidStateWithActivityTypeAndWindowingMode(
- TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
+ waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
waitAndAssertTopResumedActivity(TEST_ACTIVITY, mAssistantDisplayId,
"TestActivity should be resumed");
mWmState.assertFocusedActivity("TestActivity should be focused", TEST_ACTIVITY);
- mWmState.assertFrontStack("Fullscreen stack should be on top.",
- mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
- mWmState.assertFocusedRootTask("Fullscreen stack should be focused.",
- mDefaultWindowingMode, ACTIVITY_TYPE_STANDARD);
+
+ final int testActivityWindowingMode =
+ mWmState.getTaskDisplayArea(TEST_ACTIVITY).getWindowingMode();
+ mWmState.assertFrontStack("TestActivity stack should be on top.",
+ testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
+ mWmState.assertFocusedRootTask("TestActivity stack should be focused.",
+ testActivityWindowingMode, ACTIVITY_TYPE_STANDARD);
}
@Test
@@ -273,8 +274,7 @@
launchActivityNoWait(LAUNCH_ASSISTANT_ACTIVITY_INTO_STACK,
extraString(EXTRA_ASSISTANT_IS_TRANSLUCENT, "true"),
extraString(EXTRA_ASSISTANT_LAUNCH_NEW_TASK, getActivityName(TEST_ACTIVITY)));
- waitForValidStateWithActivityTypeAndWindowingMode(
- TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD, mDefaultWindowingMode);
+ waitForValidStateWithActivityType(TEST_ACTIVITY, ACTIVITY_TYPE_STANDARD);
final ComponentName homeActivity = mWmState.getHomeActivityName();
int windowingMode = mWmState.getFocusedRootTaskWindowingMode();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
index c1396d6..6109dec 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ConfigChangeTests.java
@@ -253,17 +253,23 @@
separateTestJournal();
fontScaleSession.set(fontScale);
mWmState.computeState(activityName);
- assertRelaunchOrConfigChanged(activityName, relaunch ? 1 : 0, relaunch ? 0 : 1);
+ // The number of config changes could be greater than expected as there may have
+ // other configuration change events triggered after font scale changed, such as
+ // NavigationBar recreated.
+ new ActivityLifecycleCounts(activityName).assertCountWithRetry(
+ "relaunch or config changed",
+ countSpec(ActivityCallback.ON_DESTROY, CountSpec.EQUALS, relaunch ? 1 : 0),
+ countSpec(ActivityCallback.ON_CREATE, CountSpec.EQUALS, relaunch ? 1 : 0),
+ countSpec(ActivityCallback.ON_CONFIGURATION_CHANGED,
+ CountSpec.GREATER_THAN_OR_EQUALS, relaunch ? 0 : 1));
// Verify that the display metrics are updated, and therefore the text size is also
// updated accordingly.
final Bundle changedExtras = TestJournalContainer.get(activityName).extras;
+ final float scale = fontScale;
waitForOrFail("reported fontPixelSize from " + activityName,
- () -> changedExtras.containsKey(EXTRA_FONT_PIXEL_SIZE));
- final int expectedFontPixelSize =
- scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, fontScale, densityDpi);
- assertEquals("Expected font pixel size should match", expectedFontPixelSize,
- changedExtras.getInt(EXTRA_FONT_PIXEL_SIZE));
+ () -> scaledPixelsToPixels(EXPECTED_FONT_SIZE_SP, scale, densityDpi)
+ == changedExtras.getInt(EXTRA_FONT_PIXEL_SIZE));
}
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
index ac06678..713958d 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/ForceRelayoutTestBase.java
@@ -28,6 +28,8 @@
import static org.junit.Assume.assumeFalse;
import android.app.Activity;
+import android.content.res.Resources;
+import android.content.pm.PackageManager;
import android.graphics.Insets;
import android.os.Bundle;
import android.view.View;
@@ -55,6 +57,7 @@
assertNotNull("test setup failed", activity.mLastContentInsets);
assumeFalse(Insets.NONE.equals(activity.mLastContentInsets.getInsetsIgnoringVisibility(
statusBars() | navigationBars())));
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
activity.mLayoutHappened = false;
@@ -113,4 +116,15 @@
setContentView(view);
}
}
+
+ private static boolean remoteInsetsControllerControlsSystemBars() {
+ return InstrumentationRegistry.getInstrumentation().getTargetContext().getResources()
+ .getBoolean(android.R.bool.config_remoteInsetsControllerControlsSystemBars);
+ }
+
+ private boolean isCar() {
+ PackageManager pm = InstrumentationRegistry.getInstrumentation().getContext()
+ .getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ }
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
index c39aaa2..cbc4026 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/PrivacyIndicatorBoundsTests.java
@@ -89,6 +89,7 @@
// TODO(b/187757919): Allow Automotive to skip this test until privacy chip is implemented
// in immersive mode
assumeFalse(isCar());
+ assumeFalse(isWatch());
final PrivacyIndicatorBoundsTests.TestActivity activity = mTestActivity.launchActivity(
new Intent().putExtra(EXTRA_ORIENTATION, orientation));
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
index cfbf89e..87c683e 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java
@@ -16,6 +16,7 @@
package android.server.wm;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.server.wm.MockImeHelper.createManagedMockImeSession;
import static android.view.SurfaceControlViewHost.SurfacePackage;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -32,6 +33,7 @@
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ComponentName;
@@ -66,6 +68,7 @@
import android.widget.PopupWindow;
import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ActivityScenario;
import androidx.test.filters.FlakyTest;
import androidx.test.rule.ActivityTestRule;
@@ -96,6 +99,8 @@
private final ActivityTestRule<ConfigChangeHandlingActivity> mActivityRule =
new ActivityTestRule<>(ConfigChangeHandlingActivity.class);
+ private ActivityScenario<ConfigChangeHandlingActivity> mScenario;
+
private Instrumentation mInstrumentation;
private Activity mActivity;
private SurfaceView mSurfaceView;
@@ -919,6 +924,19 @@
@Test
public void testEmbeddedViewReceivesInputOnBottom() throws Throwable {
+ // Close the activity that was launched by setup
+ mActivityRule.finishActivity();
+
+ // Launch activity in fullscreen windowing mode
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(mInstrumentation.getTargetContext(), ConfigChangeHandlingActivity.class);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mScenario = ActivityScenario.launch(intent, options.toBundle());
+ mScenario.onActivity(activity -> {
+ mActivity = activity;
+ });
+
mEmbeddedView = new Button(mActivity);
mEmbeddedView.setOnClickListener((View v) -> {
mClicked = true;
@@ -929,7 +947,7 @@
waitUntilEmbeddedViewDrawn();
// We should receive no input until we punch a hole
- CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
+ CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mSurfaceView);
mInstrumentation.waitForIdleSync();
assertFalse(mClicked);
@@ -949,7 +967,7 @@
// operations
waitForTouchableRegionChanged(originalRegion);
- CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
+ CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mSurfaceView);
mInstrumentation.waitForIdleSync();
assertTrue(mClicked);
}
@@ -977,6 +995,19 @@
@Test
public void testHostInputTokenAllowsObscuredTouches() throws Throwable {
+ // Close the activity that was launched by setup
+ mActivityRule.finishActivity();
+
+ // Launch activity in fullscreen windowing mode
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(mInstrumentation.getTargetContext(), ConfigChangeHandlingActivity.class);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mScenario = ActivityScenario.launch(intent, options.toBundle());
+ mScenario.onActivity(activity -> {
+ mActivity = activity;
+ });
+
SurfaceControlViewHost.SurfacePackage p = null;
mTestService = getService();
@@ -987,7 +1018,7 @@
mSurfaceView.getRootSurfaceControl().setTouchableRegion(new Region());
});
mInstrumentation.waitForIdleSync();
- CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mSurfaceView);
+ CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mSurfaceView);
mInstrumentation.waitForIdleSync();
assertTrue(mTestService.getViewIsTouchedAndObscured());
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java b/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
index 6b8be2d..7a4c543 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/UnsupportedErrorDialogTests.java
@@ -60,7 +60,7 @@
resetAppErrors();
}
- /** Make sure the developer options apply correctly leading to the dialog being shown. */
+ /** Make sure the developer option applies correctly leading to the dialog being shown. */
@Test
public void testDevSettingOverride() {
try (SettingsSession<Integer> devDialogShow =
@@ -71,16 +71,6 @@
secureIntSession(Settings.Secure.SHOW_FIRST_CRASH_DIALOG_DEV_OPTION)) {
// set developer setting to show dialogs anyway
devDialogShow.set(1);
-
- // enable only the regular option for showing the crash dialog after the first crash
- showOnFirstCrash.set(1);
- showOnFirstCrashDev.set(0);
- launchActivityNoWait(Components.CRASHING_ACTIVITY);
- findCrashDialogAndCloseApp();
- ensureActivityNotFocused(Components.CRASHING_ACTIVITY);
-
- resetAppErrors();
-
// enable only the dev option for showing the crash dialog after the first crash
showOnFirstCrash.set(0);
showOnFirstCrashDev.set(1);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
index e73ae81..7bfc7cd 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInputTests.java
@@ -307,6 +307,7 @@
TAPPING_TARGET_WINDOW_SIZE);
// Any opacity higher than this would make InputDispatcher block the touch
params.alpha = mInputManager.getMaximumObscuringOpacityForTouch();
+ params.setFitInsetsTypes(0);
intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
mActivity.startForegroundService(intent);
});
@@ -361,6 +362,7 @@
placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
viewOnScreenLocation[0], viewOnScreenLocation[1],
TAPPING_TARGET_WINDOW_SIZE);
+ params.setFitInsetsTypes(0);
intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
mActivity.startForegroundService(intent);
});
@@ -462,6 +464,7 @@
placeWindowAtLayoutCenter(params, TAPPING_TARGET_WINDOW_SIZE,
viewOnScreenLocation[0], viewOnScreenLocation[1],
TAPPING_TARGET_WINDOW_SIZE);
+ params.setFitInsetsTypes(0);
intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
mActivity.startForegroundService(intent);
});
@@ -517,6 +520,7 @@
viewOnScreenLocation[0], viewOnScreenLocation[1], TAPPING_TARGET_WINDOW_SIZE);
// Move it off the touch path (center) but still overlap with window above
params.y += PARTIAL_OBSCURING_WINDOW_SIZE;
+ params.setFitInsetsTypes(0);
intent.putExtra(EXTRA_LAYOUT_PARAMS, params);
mActivity.startForegroundService(intent);
});
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
index 1d9164d..0281f55 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationControllerTests.java
@@ -246,6 +246,8 @@
@Presubmit
@Test
public void testControl_andCancel() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
runOnUiThread(() -> {
setupAnimationListener();
@@ -266,6 +268,8 @@
@Test
public void testControl_andImmediatelyCancel() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
runOnUiThread(() -> {
setupAnimationListener();
@@ -283,6 +287,8 @@
@Presubmit
@Test
public void testControl_immediately_show() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
setVisibilityAndWait(mType, false);
@@ -306,6 +312,8 @@
@Presubmit
@Test
public void testControl_immediately_hide() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
setVisibilityAndWait(mType, true);
@@ -329,6 +337,8 @@
@Presubmit
@Test
public void testControl_transition_show() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
setVisibilityAndWait(mType, false);
@@ -350,6 +360,8 @@
@Presubmit
@Test
public void testControl_transition_hide() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
setVisibilityAndWait(mType, true);
@@ -371,6 +383,8 @@
@Presubmit
@Test
public void testControl_transition_show_interpolator() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
mInterpolator = new DecelerateInterpolator();
setVisibilityAndWait(mType, false);
@@ -393,6 +407,8 @@
@Presubmit
@Test
public void testControl_transition_hide_interpolator() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
mInterpolator = new AccelerateInterpolator();
setVisibilityAndWait(mType, true);
@@ -414,6 +430,8 @@
@Test
public void testControl_andLoseControl() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars() && mType != ime());
+
retryIfCancelled(() -> {
mInterpolator = new AccelerateInterpolator();
setVisibilityAndWait(mType, true);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
index 86ec2fa..87c0fc8 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTests.java
@@ -29,6 +29,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
@@ -70,6 +71,7 @@
WINDOWING_MODE_FULLSCREEN);
mRootView = mActivity.getWindow().getDecorView();
assumeTrue(hasWindowInsets(mRootView, systemBars()));
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
}
@Test
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
index 91916b1..4a76d92 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsControllerTests.java
@@ -116,6 +116,8 @@
@Test
public void testHide() {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -134,6 +136,8 @@
@Test
public void testShow() {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -181,6 +185,8 @@
@Test
public void testTopAppHidesStatusBarByMethod() {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -190,6 +196,8 @@
@Test
public void testTopAppHidesStatusBarByWindowFlag() {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivity(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -199,6 +207,8 @@
@Test
public void testTopAppHidesStatusBarBySystemUiFlag() {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivity(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -291,6 +301,8 @@
@Test
public void testSetSystemBarsBehavior_default() throws InterruptedException {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -317,6 +329,8 @@
@Test
public void testSetSystemBarsBehavior_showTransientBarsBySwipe() throws InterruptedException {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivity(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -398,6 +412,8 @@
@Test
public void testSystemUiVisibilityCallbackCausedByInsets() {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivity(TestActivity.class);
final View controlTarget = activity.getWindow().getDecorView();
final int[] targetSysUiVis = new int[1];
@@ -425,6 +441,7 @@
private void testSysUiVisCallbackCausedByInsets(int insetsType, int sysUiFlag, View target,
int[] targetSysUiVis, int[] nonTargetSysUiVis) {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
if (target.getRootWindowInsets().isVisible(insetsType)) {
// Controlled by methods
@@ -453,6 +470,11 @@
public void testSystemUiVisibilityCallbackCausedByAppearance() {
final TestActivity activity = startActivity(TestActivity.class);
final View controlTarget = activity.getWindow().getDecorView();
+
+ // Assume we have at least one visible system bar.
+ assumeTrue(controlTarget.getRootWindowInsets().isVisible(statusBars()) ||
+ controlTarget.getRootWindowInsets().isVisible(navigationBars()));
+
final int[] targetSysUiVis = new int[1];
getInstrumentation().runOnMainSync(() -> {
controlTarget.setOnSystemUiVisibilityChangeListener(
@@ -468,6 +490,8 @@
@Test
public void testSetSystemUiVisibilityAfterCleared_showBarsBySwipe() throws Exception {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -527,6 +551,8 @@
@Test
public void testSetSystemUiVisibilityAfterCleared_showBarsByApp() throws Exception {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestActivity activity = startActivityInWindowingModeFullScreen(TestActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -567,6 +593,8 @@
@Test
public void testHideOnCreate() throws Exception {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestHideOnCreateActivity activity =
startActivityInWindowingModeFullScreen(TestHideOnCreateActivity.class);
final View rootView = activity.getWindow().getDecorView();
@@ -654,6 +682,8 @@
@Test
public void testInsetsDispatch() throws Exception {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
// Start an activity which hides system bars in fullscreen mode,
// otherwise, it might not be able to hide system bars in other windowing modes.
final TestHideOnCreateActivity activity = startActivityInWindowingModeFullScreen(
@@ -688,6 +718,8 @@
@Test
public void testWindowInsetsController_availableAfterAddView() throws Exception {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
final TestHideOnCreateActivity activity =
startActivityInWindowingModeFullScreen(TestHideOnCreateActivity.class);
final View rootView = activity.getWindow().getDecorView();
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
index 806cee5..b0c2a12 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsPolicyTest.java
@@ -199,6 +199,8 @@
@Test
public void testImmersiveFullscreenHidesSystemBars() throws Throwable {
+ assumeFalse(isCar() && remoteInsetsControllerControlsSystemBars());
+
// Run the test twice, because the issue that shows system bars even in the immersive mode,
// happens at the 2nd try.
for (int i = 1; i <= 2; ++i) {
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
index f895e4f..f9211904 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/lifecycle/ActivityLifecyclePipTests.java
@@ -240,6 +240,9 @@
assertEmptySequence(PipActivity.class, getTransitionLog(),
"launchBelow");
+ // Set secondary split as launch root
+ mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
+
// Launch second activity to side
getTransitionLog().clear();
new Launcher(SecondActivity.class)
@@ -264,6 +267,9 @@
// Enter split screen
moveTaskToPrimarySplitScreenAndVerify(firstActivity, sideActivity);
+ // Set secondary split as launch root
+ mTaskOrganizer.setLaunchRoot(mTaskOrganizer.getSecondarySplitTaskId());
+
// Launch second activity to side
final Activity secondActivity = new Launcher(SecondActivity.class)
.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_MULTIPLE_TASK)
diff --git a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
index 4608161..bfb3e88 100644
--- a/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
+++ b/tests/framework/base/windowmanager/util/src/android/server/wm/ActivityManagerTestBase.java
@@ -1999,6 +1999,7 @@
static final int EQUALS = 1;
static final int GREATER_THAN = 2;
static final int LESS_THAN = 3;
+ static final int GREATER_THAN_OR_EQUALS = 4;
final T mEvent;
final int mRule;
@@ -2022,6 +2023,9 @@
case LESS_THAN:
mMessage = event + " must be less than " + count;
break;
+ case GREATER_THAN_OR_EQUALS:
+ mMessage = event + " must be greater than (or equals to) " + count;
+ break;
default:
mMessage = "Don't care";
}
@@ -2039,6 +2043,8 @@
return value > mCount;
case LESS_THAN:
return value < mCount;
+ case GREATER_THAN_OR_EQUALS:
+ return value >= mCount;
default:
}
throw new RuntimeException("Unknown CountSpec rule");
diff --git a/tests/input/src/android/input/cts/IncompleteMotionTest.kt b/tests/input/src/android/input/cts/IncompleteMotionTest.kt
index d39958e..b9c6cbb 100644
--- a/tests/input/src/android/input/cts/IncompleteMotionTest.kt
+++ b/tests/input/src/android/input/cts/IncompleteMotionTest.kt
@@ -37,6 +37,7 @@
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
+import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.concurrent.thread
@@ -100,34 +101,42 @@
// Start a valid touch stream
sendEvent(downTime, ACTION_DOWN, x, y, true /*sync*/)
+ val resultFuture = CompletableFuture<Void>()
// Lock up the UI thread. This ensures that the motion event that we will write will
// not get processed by the app right away.
activity.runOnUiThread {
val sendMoveAndFocus = thread(start = true) {
- sendEvent(downTime, ACTION_MOVE, x, y + 10, false /*sync*/)
- // The MOVE event is sent async because the UI thread is blocked.
- // Give dispatcher some time to send it to the app
- SystemClock.sleep(700)
+ try {
+ sendEvent(downTime, ACTION_MOVE, x, y + 10, false /*sync*/)
+ // The MOVE event is sent async because the UI thread is blocked.
+ // Give dispatcher some time to send it to the app
+ SystemClock.sleep(700)
- val handlerThread = HandlerThread("Receive broadcast from overlay activity")
- handlerThread.start()
- val looper: Looper = handlerThread.looper
- val handler = Handler(looper)
- val receiver = OverlayFocusedBroadcastReceiver()
- val intentFilter = IntentFilter(OVERLAY_ACTIVITY_FOCUSED)
- activity.registerReceiver(receiver, intentFilter, null, handler)
+ val handlerThread = HandlerThread("Receive broadcast from overlay activity")
+ handlerThread.start()
+ val looper: Looper = handlerThread.looper
+ val handler = Handler(looper)
+ val receiver = OverlayFocusedBroadcastReceiver()
+ val intentFilter = IntentFilter(OVERLAY_ACTIVITY_FOCUSED)
+ activity.registerReceiver(receiver, intentFilter, null, handler)
- // Now send hasFocus=false event to the app by launching a new focusable window
- startOverlayActivity()
- PollingCheck.waitFor { receiver.overlayActivityIsFocused() }
- activity.unregisterReceiver(receiver)
- handlerThread.quit()
- // We need to ensure that the focus event has been written to the app's socket
- // before unblocking the UI thread. Having the overlay activity receive
- // hasFocus=true event is a good proxy for that. However, it does not guarantee
- // that dispatcher has written the hasFocus=false event to the current activity.
- // For safety, add another small sleep here
- SystemClock.sleep(300)
+ // Now send hasFocus=false event to the app by launching a new focusable window
+ startOverlayActivity()
+ PollingCheck.waitFor { receiver.overlayActivityIsFocused() }
+ activity.unregisterReceiver(receiver)
+ handlerThread.quit()
+ // We need to ensure that the focus event has been written to the app's socket
+ // before unblocking the UI thread. Having the overlay activity receive
+ // hasFocus=true event is a good proxy for that. However, it does not guarantee
+ // that dispatcher has written the hasFocus=false event to the current activity.
+ // For safety, add another small sleep here
+ SystemClock.sleep(300)
+ resultFuture.complete(null)
+ } catch (e: Throwable) {
+ // Catch potential throwable as to not crash UI thread, rethrow and validate
+ // outside.
+ resultFuture.completeExceptionally(e)
+ }
}
sendMoveAndFocus.join()
}
@@ -139,6 +148,9 @@
// If we wait too long here, we will cause ANR (if the platform has a bug).
// If the MOVE event is received, however, we can stop the test.
PollingCheck.waitFor { activity.receivedMove() }
+ // Before finishing the test, check that no exceptions occurred while running the
+ // instructions in the 'sendMoveAndFocus' thread.
+ resultFuture.get()
}
private fun sendEvent(downTime: Long, action: Int, x: Float, y: Float, sync: Boolean) {
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index e42835e..9ced552 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -28,6 +28,7 @@
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiTest;
+import com.android.compatibility.common.util.MediaUtils;
import org.junit.Assert;
import org.junit.Assume;
@@ -168,18 +169,37 @@
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatSurface));
}
+ }
- // For devices launching with Android T, if a codec supports an HDR profile and device
- // supports HDR display, it must advertise P010 support
+ /** For devices launching with Android T or higher, if a codec supports an HDR profile and
+ * device supports HDR display, it must support COLOR_FormatYUVP010 as a video decoder output
+ * format. For TVs, this requirement is optional.
+ */
+ @Test
+ public void testP010SupportForHDRDisplay() {
+ Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
+ MediaCodecInfo.CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mMediaType);
int[] HdrProfileArray = mProfileHdrMap.get(mMediaType);
if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T
&& HdrProfileArray != null && DISPLAY_HDR_TYPES.length > 0) {
for (CodecProfileLevel pl : caps.profileLevels) {
if (IntStream.of(HdrProfileArray).anyMatch(x -> x == pl.profile)) {
- assertFalse(mCodecInfo.getName() + " supports HDR profile " + pl.profile + "," +
- " but does not support COLOR_FormatYUVP010",
- IntStream.of(caps.colorFormats)
- .noneMatch(x -> x == COLOR_FormatYUVP010));
+ if (MediaUtils.isTv()) {
+ // Some TV devices support HDR10 display with VO instead of GPU. In this
+ // case, skip checking P010 on TV devices.
+ Assume.assumeFalse(mCodecInfo.getName() + " supports HDR profile "
+ + pl.profile + ","
+ + " but does not support COLOR_FormatYUVP010."
+ + " Skip checking on TV device",
+ IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUVP010));
+ } else {
+ assertFalse(mCodecInfo.getName() + " supports HDR profile "
+ + pl.profile + "," +
+ " but does not support COLOR_FormatYUVP010",
+ IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUVP010));
+ }
}
}
}
diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
index 10ad25c..2a4ece0 100644
--- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
+++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java
@@ -68,19 +68,33 @@
static {
// with a default-media-performance-class that can be configured through a command line
// argument.
- android.os.Bundle args = InstrumentationRegistry.getArguments();
- String mediaPerfClassArg = args.getString(MEDIA_PERF_CLASS_KEY);
- if (mediaPerfClassArg != null) {
- Log.d(TAG, "Running the tests with performance class set to " + mediaPerfClassArg);
- sPc = Integer.parseInt(mediaPerfClassArg);
- } else {
- sPc = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)
- ? Build.VERSION.MEDIA_PERFORMANCE_CLASS
- : SystemProperties.getInt("ro.odm.build.media_performance_class", 0);
+ android.os.Bundle args;
+ try {
+ args = InstrumentationRegistry.getArguments();
+ } catch (Exception e) {
+ args = null;
}
- Log.d(TAG, "performance class is " + sPc);
+ if (args != null) {
+ String mediaPerfClassArg = args.getString(MEDIA_PERF_CLASS_KEY);
+ if (mediaPerfClassArg != null) {
+ Log.d(TAG, "Running the tests with performance class set to " + mediaPerfClassArg);
+ sPc = Integer.parseInt(mediaPerfClassArg);
+ } else {
+ sPc = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S)
+ ? Build.VERSION.MEDIA_PERFORMANCE_CLASS
+ : SystemProperties.getInt("ro.odm.build.media_performance_class", 0);
+ }
+ Log.d(TAG, "performance class is " + sPc);
+ } else {
+ sPc = 0;
+ }
- Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ Context context;
+ try {
+ context = InstrumentationRegistry.getInstrumentation().getContext();
+ } catch (Exception e) {
+ context = null;
+ }
// When used from ItsService, context will be null
if (context != null) {
WindowManager windowManager = context.getSystemService(WindowManager.class);
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt
index ca63dd2..a37ced0 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSelfManagedTest.kt
@@ -8,6 +8,7 @@
import android.companion.cts.common.RecordingCallback.OnAssociationCreated
import android.content.Intent
import android.platform.test.annotations.AppModeFull
+import com.android.compatibility.common.util.FeatureUtil
import org.junit.Assume.assumeFalse
import org.junit.Test
import org.junit.runner.RunWith
@@ -34,6 +35,7 @@
override fun setUp() {
super.setUp()
+ assumeFalse(FeatureUtil.isWatch())
// TODO(b/211602270): Add support for WATCH and "null" profiles in the
// confirmation UI (the "self-managed" flow variant).
assumeFalse(profile == null)
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt
index 92e1b49..d1cee82 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndSingleDeviceTest.kt
@@ -5,6 +5,7 @@
import android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER
import android.platform.test.annotations.AppModeFull
+import com.android.compatibility.common.util.FeatureUtil
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -28,6 +29,7 @@
override fun setUp() {
super.setUp()
+ assumeFalse(FeatureUtil.isWatch())
// TODO(b/211722613): Add support for DEVICE_PROFILE_APP_STREAMING
// DEVICE_PROFILE_COMPUTER and DEVICE_PROFILE_AUTOMOTIVE_PROJECTION
// profiles in the confirmation UI (the "single_device" flow variant).
diff --git a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt
index ffc52eb..8da92e6 100644
--- a/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt
+++ b/tests/tests/companion/uiautomation/src/android/companion/cts/uiautomation/AssociationEndToEndTest.kt
@@ -20,6 +20,7 @@
import android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION
import android.companion.AssociationRequest.DEVICE_PROFILE_COMPUTER
import android.platform.test.annotations.AppModeFull
+import com.android.compatibility.common.util.FeatureUtil
import org.junit.Assume.assumeFalse
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,6 +42,7 @@
override fun setUp() {
super.setUp()
+ assumeFalse(FeatureUtil.isWatch())
// TODO(b/211590680): Add support for APP_STREAMING, AUTOMOTIVE_PROJECTION and COMPUTER
// in the confirmation UI (the "multiple devices" flow variant).
assumeFalse(profile == DEVICE_PROFILE_COMPUTER)
diff --git a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
index 68edc76..58a4011 100644
--- a/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
+++ b/tests/tests/content/src/android/content/pm/cts/FeatureTest.java
@@ -72,7 +72,7 @@
}
// Managed profiles only required for handheld devices
- if (!isHandheldDevice()) {
+ if (!isHandheldOrTabletDevice()) {
return;
}
@@ -91,12 +91,20 @@
}
/**
- * The CDD defines a handheld device as one that has a battery and a screen size between
- * 2.5 and 8 inches.
+ * The CDD defines:
+ * - A handheld device as one that has a battery and a screen size between 2.5 and 8 inches.
+ * - A tablet device as one that has a battery and a screen size between 7 and 18 inches.
*/
- private boolean isHandheldDevice() throws Exception {
+ private boolean isHandheldOrTabletDevice() throws Exception {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ || mPackageManager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
+ return false;
+ }
+
double screenInches = getScreenSizeInInches();
- return deviceHasBattery() && screenInches >= 2.5 && screenInches <= 8.0;
+ return deviceHasBattery() && screenInches >= 2.5 && screenInches <= 18.0;
}
private boolean deviceHasBattery() {
diff --git a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
index ef44528..852223c 100644
--- a/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/BitmapFactoryTest.java
@@ -1010,7 +1010,7 @@
@Test
@RequiresDevice
- public void testDecode10BitHEIFTo10BitBitmap() {
+ public void testDecode10BitHEIF() {
assumeTrue(
"Test needs Android T.", ApiLevelUtil.isFirstApiAtLeast(Build.VERSION_CODES.TIRAMISU));
assumeTrue(
@@ -1018,13 +1018,23 @@
SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+ Config preferredConfig = Config.RGBA_1010102;
+
+ // For TVs, even if the device advertises that 10 bits profile is supported, the output
+ // format might not be CPU readable, but can still be displayed. When the TV device is
+ // not capable to decode to YUVP010 format, it should be able to fall back to decode to
+ // RGB_565 format.
+ if (MediaUtils.isTv() && !hasHEVCDecoderSupportsYUVP010()) {
+ preferredConfig = Config.RGB_565;
+ }
+
BitmapFactory.Options opt = new BitmapFactory.Options();
- opt.inPreferredConfig = Config.RGBA_1010102;
+ opt.inPreferredConfig = preferredConfig;
Bitmap bm = BitmapFactory.decodeStream(obtainInputStream(R.raw.heifimage_10bit), null, opt);
assertNotNull(bm);
assertEquals(4096, bm.getWidth());
assertEquals(3072, bm.getHeight());
- assertEquals(Config.RGBA_1010102, bm.getConfig());
+ assertEquals(preferredConfig, bm.getConfig());
}
@Test
@@ -1037,6 +1047,16 @@
SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+ // For TVs, even if the device advertises that 10 bits profile is supported, the output
+ // format might not be CPU readable, but can still be displayed, and only when the TV
+ // is capable to decode to YUVP010 format, the image can be converted into RGBA_1010102,
+ // and this test can continue.
+ if (MediaUtils.isTv()) {
+ assumeTrue(
+ "The TV is unable to decode to RGBA_1010102 format, skip the test",
+ hasHEVCDecoderSupportsYUVP010());
+ }
+
BitmapFactory.Options opt = new BitmapFactory.Options();
opt.inPreferredConfig = Config.ARGB_8888;
Bitmap bm1 =
@@ -1113,4 +1133,26 @@
}
return true;
}
+
+ private static boolean hasHEVCDecoderSupportsYUVP010() {
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) {
+ if (mediaCodecInfo.isEncoder()) {
+ continue;
+ }
+ for (String mediaType : mediaCodecInfo.getSupportedTypes()) {
+ if (mediaType.equalsIgnoreCase("video/hevc")) {
+ MediaCodecInfo.CodecCapabilities codecCapabilities =
+ mediaCodecInfo.getCapabilitiesForType(mediaType);
+ for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) {
+ if (codecCapabilities.colorFormats[i]
+ == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
index b6689d8..8bb2a3c 100644
--- a/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/ImageDecoderTest.java
@@ -252,6 +252,16 @@
SystemProperties.getInt("ro.vndk.version", 0) >= Build.VERSION_CODES.TIRAMISU);
assumeTrue("No 10-bit HEVC decoder, skip the test.", has10BitHEVCDecoder());
+ // For TVs, even if the device advertises that 10 bits profile is supported, the output
+ // format might not be CPU readable, but can still be displayed, and only when the TV
+ // is capable to decode to YUVP010 format, the image can be converted into RGBA_1010102,
+ // and this test can continue.
+ if (MediaUtils.isTv()) {
+ assumeTrue(
+ "The TV is unable to decode to YUVP010 format, skip the test",
+ hasHEVCDecoderSupportsYUVP010());
+ }
+
try {
ImageDecoder.Source src = ImageDecoder
.createSource(getResources(), R.raw.heifimage_10bit);
@@ -2789,4 +2799,26 @@
}
return true;
}
+
+ private static boolean hasHEVCDecoderSupportsYUVP010() {
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.ALL_CODECS);
+ for (MediaCodecInfo mediaCodecInfo : codecList.getCodecInfos()) {
+ if (mediaCodecInfo.isEncoder()) {
+ continue;
+ }
+ for (String mediaType : mediaCodecInfo.getSupportedTypes()) {
+ if (mediaType.equalsIgnoreCase("video/hevc")) {
+ MediaCodecInfo.CodecCapabilities codecCapabilities =
+ mediaCodecInfo.getCapabilitiesForType(mediaType);
+ for (int i = 0; i < codecCapabilities.colorFormats.length; ++i) {
+ if (codecCapabilities.colorFormats[i]
+ == MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index 56dd1b0..bf2e941 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -16,11 +16,13 @@
package android.keystore.cts;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -37,6 +39,13 @@
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.bedstead.nene.annotations.Nullable;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
@@ -63,6 +72,7 @@
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
+import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
@@ -78,11 +88,6 @@
import javax.crypto.SecretKey;
import javax.security.auth.x500.X500Principal;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
@RunWith(AndroidJUnit4.class)
public class AndroidKeyStoreTest {
private static final String TAG = AndroidKeyStoreTest.class.getSimpleName();
@@ -823,6 +828,12 @@
expectedAliases.length, count);
}
+ private void deleteEntryIfNotNull(@Nullable String alias) throws Exception {
+ if (alias != null) {
+ mKeyStore.deleteEntry(alias);
+ }
+ }
+
@Test
public void testKeyStore_Aliases_Unencrypted_Success() throws Exception {
mKeyStore.load(null, null);
@@ -2161,8 +2172,9 @@
PrivateKey privateKey3 = generatePrivateKey("RSA", FAKE_RSA_KEY_1);
final int MAX_NUMBER_OF_KEYS = 2500;
- final String ALIAS_PREFIX = "test_large_number_of_rsa_keys_";
+ final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_rsa_keys_");
int keyCount = 0;
+ String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2175,11 +2187,12 @@
new KeyStore.PrivateKeyEntry(privateKey1, new Certificate[] {cert1}),
protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
- new PrivateKeyEntry(privateKey3, new Certificate[] {cert3}), protectionParams);
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
+ new PrivateKeyEntry(privateKey3, new Certificate[] {cert3}),
+ protectionParams);
keyCount++;
- String entryName2 = "test" + keyCount;
+ entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2,
new KeyStore.PrivateKeyEntry(privateKey2, new Certificate[] {cert2}),
protectionParams);
@@ -2206,7 +2219,9 @@
sig.update(message);
assertTrue(sig.verify(signature));
} finally {
- deleteManyTestKeys(keyCount, ALIAS_PREFIX);
+ mKeyStore.deleteEntry(entryName1);
+ deleteEntryIfNotNull(entryName2);
+ deleteManyTestKeys(keyCount, aliasPrefix);
}
}
@@ -2235,8 +2250,9 @@
PrivateKey privateKey3 = generatePrivateKey("EC", FAKE_EC_KEY_1);
final int MAX_NUMBER_OF_KEYS = 2500;
- final String ALIAS_PREFIX = "test_large_number_of_ec_keys_";
+ final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_ec_keys_");
int keyCount = 0;
+ String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2248,12 +2264,12 @@
new KeyStore.PrivateKeyEntry(privateKey1, new Certificate[] {cert1}),
protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
new KeyStore.PrivateKeyEntry(privateKey3, new Certificate[] {cert3}),
protectionParams);
keyCount++;
- String entryName2 = "test" + keyCount;
+ entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2,
new KeyStore.PrivateKeyEntry(privateKey2, new Certificate[] {cert2}),
protectionParams);
@@ -2280,7 +2296,9 @@
sig.update(message);
assertTrue(sig.verify(signature));
} finally {
- deleteManyTestKeys(keyCount, ALIAS_PREFIX);
+ mKeyStore.deleteEntry(entryName1);
+ deleteEntryIfNotNull(entryName2);
+ deleteManyTestKeys(keyCount, aliasPrefix);
}
}
@@ -2307,8 +2325,9 @@
HexEncoding.decode("33333333333333333333777777777777"), "AES");
final int MAX_NUMBER_OF_KEYS = 10000;
- final String ALIAS_PREFIX = "test_large_number_of_aes_keys_";
+ final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_aes_keys_");
int keyCount = 0;
+ String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2319,11 +2338,11 @@
.build();
mKeyStore.setEntry(entryName1, new KeyStore.SecretKeyEntry(key1), protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
new KeyStore.SecretKeyEntry(key3), protectionParams);
++keyCount;
- String entryName2 = "test" + keyCount;
+ entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2, new KeyStore.SecretKeyEntry(key2), protectionParams);
SecretKey keystoreKey2 = (SecretKey) mKeyStore.getKey(entryName2, null);
SecretKey keystoreKey1 = (SecretKey) mKeyStore.getKey(entryName1, null);
@@ -2345,7 +2364,9 @@
cipher.init(Cipher.DECRYPT_MODE, key2, cipherParams);
assertArrayEquals(plaintext, cipher.doFinal(ciphertext));
} finally {
- deleteManyTestKeys(keyCount, ALIAS_PREFIX);
+ mKeyStore.deleteEntry(entryName1);
+ deleteEntryIfNotNull(entryName2);
+ deleteManyTestKeys(keyCount, aliasPrefix);
}
}
@@ -2374,8 +2395,9 @@
HexEncoding.decode("33333333333333333333777777777777"), "HmacSHA256");
final int MAX_NUMBER_OF_KEYS = 10000;
- final String ALIAS_PREFIX = "test_large_number_of_hmac_keys_";
+ final StringBuilder aliasPrefix = new StringBuilder("test_large_number_of_hmac_keys_");
int keyCount = 0;
+ String entryName2 = null;
mKeyStore.load(null);
try {
@@ -2384,11 +2406,11 @@
.build();
mKeyStore.setEntry(entryName1, new KeyStore.SecretKeyEntry(key1), protectionParams);
- keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, ALIAS_PREFIX,
+ keyCount = importKeyManyTimes(MAX_NUMBER_OF_KEYS, aliasPrefix,
new KeyStore.SecretKeyEntry(key3), protectionParams);
keyCount++;
- String entryName2 = "test" + keyCount;
+ entryName2 = "test" + keyCount;
mKeyStore.setEntry(entryName2, new KeyStore.SecretKeyEntry(key2), protectionParams);
SecretKey keystoreKey2 = (SecretKey) mKeyStore.getKey(entryName2, null);
SecretKey keystoreKey1 = (SecretKey) mKeyStore.getKey(entryName1, null);
@@ -2408,7 +2430,9 @@
"59b57e77e4e2cb36b5c7b84af198ac004327bc549de6931a1b5505372dd8c957"),
mac.doFinal(message));
} finally {
- deleteManyTestKeys(keyCount, ALIAS_PREFIX);
+ mKeyStore.deleteEntry(entryName1);
+ deleteEntryIfNotNull(entryName2);
+ deleteManyTestKeys(keyCount, aliasPrefix);
}
}
@@ -2606,8 +2630,8 @@
*
* This method is time-bounded
*/
- private int importKeyManyTimes(int numberOfKeys, String aliasPrefix, Entry keyEntry,
- KeyProtection protectionParams)
+ private int importKeyManyTimes(int numberOfKeys, StringBuilder aliasPrefix, Entry keyEntry,
+ KeyProtection protectionParams, boolean isTimeBound)
throws InterruptedException {
TimeBox timeBox = new TimeBox(mMaxImportDuration);
AtomicInteger keyCounter = new AtomicInteger(0);
@@ -2616,7 +2640,7 @@
threads.add(new Thread(() -> {
// Import key lots of times, under different aliases. Do this until we either run
// out of time or we import the key numberOfKeys times.
- while (!timeBox.isOutOfTime()) {
+ while (!isTimeBound || !timeBox.isOutOfTime()) {
int count = keyCounter.incrementAndGet();
if (count > numberOfKeys) {
// The loop is inherently racy, as multiple threads are simultaneously
@@ -2629,7 +2653,7 @@
if ((count % 1000) == 0) {
Log.i(TAG, "Imported " + count + " keys");
}
- String entryAlias = aliasPrefix + count;
+ String entryAlias = aliasPrefix.toString() + count;
try {
mKeyStore.setEntry(entryAlias, keyEntry, protectionParams);
} catch (Throwable e) {
@@ -2646,7 +2670,7 @@
threads.get(i).join();
}
Log.i(TAG, "Imported " + keyCounter.get() + " keys in " + timeBox.elapsed());
- if (keyCounter.get() < MIN_SUPPORTED_KEY_COUNT) {
+ if (keyCounter.get() != numberOfKeys && keyCounter.get() < MIN_SUPPORTED_KEY_COUNT) {
fail("Failed to import " + MIN_SUPPORTED_KEY_COUNT + " keys in "
+ timeBox.elapsed() + ". Imported: " + keyCounter.get() + " keys");
}
@@ -2654,11 +2678,22 @@
return keyCounter.get();
}
+ private int importKeyManyTimes(int numberOfKeys, StringBuilder aliasPrefix, Entry keyEntry,
+ KeyProtection protectionParams) throws InterruptedException {
+ return importKeyManyTimes(numberOfKeys, aliasPrefix, keyEntry, protectionParams, true);
+ }
+
+ private int importKeyManyTimesWithoutTimeLimit(int numberOfKeys, StringBuilder aliasPrefix,
+ Entry keyEntry,
+ KeyProtection protectionParams) throws InterruptedException {
+ return importKeyManyTimes(numberOfKeys, aliasPrefix, keyEntry, protectionParams, false);
+ }
+
/**
* Delete <code>numberOfKeys</code> keys that follow the pattern "[aliasPrefix][keyCounter]".
* This is done across multiple threads to both increase throughput as well as stress keystore.
*/
- private void deleteManyTestKeys(int numberOfKeys, String aliasPrefix)
+ private void deleteManyTestKeys(int numberOfKeys, StringBuilder aliasPrefix)
throws InterruptedException {
// Clean up Keystore without using KeyStore.aliases() which can't handle this many
// entries.
@@ -2673,8 +2708,9 @@
if ((key > 0) && ((key % 1000) == 0)) {
Log.i(TAG, "Deleted " + key + " keys");
}
+ String entryAlias = aliasPrefix.toString() + key;
try {
- mKeyStore.deleteEntry("test" + key);
+ mKeyStore.deleteEntry(entryAlias);
} catch (Exception e) {
fail("Unexpected exception in key cleanup: " + e);
}
@@ -2690,4 +2726,114 @@
}
Log.i(TAG, "Deleted " + numberOfKeys + " keys");
}
+
+ private Set<String> createLargeNumberOfKeyStoreEntryAliases(int numberOfKeys,
+ StringBuilder aliasPrefix)
+ throws Exception {
+ Certificate cert = generateCertificate(FAKE_RSA_USER_1);
+ PrivateKey privateKey = generatePrivateKey("RSA", FAKE_RSA_KEY_1);
+
+ mKeyStore.load(null);
+ KeyProtection protectionParams = new KeyProtection.Builder(
+ KeyProperties.PURPOSE_SIGN)
+ .setDigests(KeyProperties.DIGEST_SHA256)
+ .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1)
+ .build();
+
+ int keyCount = importKeyManyTimesWithoutTimeLimit(numberOfKeys, aliasPrefix,
+ new PrivateKeyEntry(privateKey, new Certificate[]{cert}), protectionParams);
+
+ // Construct expected aliases list.
+ final Set<String> expectedAliases = new HashSet<>(keyCount);
+ for (int count = 1; count <= keyCount; count++) {
+ String entryAlias = aliasPrefix.toString() + count;
+ expectedAliases.add(entryAlias);
+ }
+
+ return expectedAliases;
+ }
+
+ private void importLargeNumberOfKeysValidateAliases(int numberOfKeys, StringBuilder aliasPrefix)
+ throws Exception {
+ Set<String> importedKeyAliases = createLargeNumberOfKeyStoreEntryAliases(numberOfKeys,
+ aliasPrefix);
+ assertThat(importedKeyAliases.size()).isEqualTo(numberOfKeys);
+
+ try {
+ // b/222287335 Currently, limiting Keystore `listEntries` API to return subset of the
+ // Keystore entries to avoid running out of binder buffer space.
+ // To verify that all the imported key aliases are present in Keystore, get the list of
+ // aliases from Keystore, delete the matched aliases from Keystore and imported list of
+ // key aliases, continue this till all the imported key aliases are matched.
+ while (!importedKeyAliases.isEmpty()) {
+ // List the keystore entries aliases until all the imported key aliases are matched.
+ Set<String> aliases = new HashSet<String>(Collections.list(mKeyStore.aliases()));
+
+ // Try to match the aliases with imported key aliases.
+ // Cleanup matching aliases from Keystore and imported key aliases list.
+ for (String alias: aliases) {
+ if (importedKeyAliases.contains(alias)) {
+ mKeyStore.deleteEntry(alias);
+ importedKeyAliases.remove(alias);
+ }
+ }
+ }
+ assertTrue("Failed to match imported keystore entries.",
+ importedKeyAliases.isEmpty());
+ } finally {
+ if (!importedKeyAliases.isEmpty()) {
+ Log.i(TAG, "Final cleanup of imported keys");
+ for (String alias: importedKeyAliases) {
+ mKeyStore.deleteEntry(alias);
+ }
+ }
+ }
+ assertTrue(importedKeyAliases.isEmpty());
+ }
+
+ /**
+ * Create long alias prefix of length 6000 characters.
+ */
+ private StringBuilder createLongAliasPrefix() {
+ char[] prefixChar = new char[6000];
+ Arrays.fill(prefixChar, 'T');
+ StringBuilder prefixAlias = new StringBuilder();
+ prefixAlias.append(prefixChar);
+
+ return prefixAlias;
+ }
+
+ /**
+ * Create large number of Keystore entries with long aliases and try to list aliases of all the
+ * entries in the keystore.
+ */
+ @Test
+ public void testKeyStore_LargeNumberOfLongAliases() throws Exception {
+ final int maxNumberOfKeys = 100;
+
+ importLargeNumberOfKeysValidateAliases(maxNumberOfKeys, createLongAliasPrefix());
+ }
+
+ /**
+ * Create limited number of Keystore entries with long aliases and try to list aliases of all
+ * the entries in the keystore. Test should successfully list all the Keystore entries aliases.
+ */
+ @Test
+ public void testKeyStore_LimitedNumberOfLongAliasesSuccess() throws Exception {
+ final int maxNumberOfKeys = 10;
+ importLargeNumberOfKeysValidateAliases(maxNumberOfKeys, createLongAliasPrefix());
+ }
+
+ /**
+ * Create large number of Keystore entries with short length aliases and try to list aliases of
+ * all the entries in the keystore. Test should successfully list all the Keystore entries
+ * aliases.
+ */
+ @Test
+ public void testKeyStore_LargeNumberShortAliasesSuccess() throws Exception {
+ final int maxNumberOfKeys = 2500;
+ final StringBuilder aliasPrefix = new StringBuilder("test_short_key_alias_");
+
+ importLargeNumberOfKeysValidateAliases(maxNumberOfKeys, aliasPrefix);
+ }
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
index e6de053..26b3658 100644
--- a/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/CipherTest.java
@@ -616,16 +616,11 @@
return (pm != null && pm.hasSystemFeature("android.software.leanback_only"));
}
- private boolean hasSecureLockScreen() {
- PackageManager pm = getContext().getPackageManager();
- return (pm != null && pm.hasSystemFeature("android.software.secure_lock_screen"));
- }
-
@Presubmit
@Test
public void testKeyguardLockAndUnlock()
throws Exception {
- if (!hasSecureLockScreen()) {
+ if (!TestUtils.hasSecureLockScreen(getContext())) {
return;
}
@@ -647,7 +642,7 @@
final boolean isUnlockedDeviceRequired = true;
final boolean isUserAuthRequired = false;
- if (!hasSecureLockScreen()) {
+ if (!TestUtils.hasSecureLockScreen(getContext())) {
return;
}
@@ -1165,7 +1160,7 @@
final boolean isUnlockedDeviceRequired = false;
final boolean isUserAuthRequired = true;
- if (!hasSecureLockScreen()) {
+ if (!TestUtils.hasSecureLockScreen(getContext())) {
return;
}
diff --git a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
index 043b5de..99e3d75 100644
--- a/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/KeyAttestationTest.java
@@ -60,6 +60,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -494,6 +495,9 @@
@Test
public void testEcAttestation_UniqueIdWorksWithCorrectPermission() throws Exception {
+ assumeTrue("Device doesn't have secure lock screen",
+ TestUtils.hasSecureLockScreen(getContext()));
+
String keystoreAlias = "test_key";
KeyGenParameterSpec spec = new KeyGenParameterSpec.Builder(keystoreAlias, PURPOSE_SIGN)
.setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
diff --git a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
index 84e8969..b965204 100644
--- a/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
+++ b/tests/tests/keystore/src/android/keystore/cts/util/TestUtils.java
@@ -24,8 +24,8 @@
import static org.junit.Assume.assumeTrue;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.content.pm.FeatureInfo;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.SystemProperties;
import android.security.keystore.KeyGenParameterSpec;
@@ -55,6 +55,7 @@
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
+import java.security.SecureRandom;
import java.security.UnrecoverableEntryException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
@@ -76,7 +77,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.security.SecureRandom;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
@@ -1140,4 +1140,9 @@
public static boolean isAttestationSupported() {
return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.O;
}
+
+ public static boolean hasSecureLockScreen(Context context) {
+ PackageManager pm = context.getPackageManager();
+ return (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN));
+ }
}
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 5ba8f7e..c9588f4 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
@@ -107,7 +107,7 @@
private final static String TAG = "AudioManagerTest";
private final static long ASYNC_TIMING_TOLERANCE_MS = 50;
- private final static long POLL_TIME_VOLUME_ADJUST = 200;
+ private final static long POLL_TIME_VOLUME_ADJUST = 400;
private final static long POLL_TIME_UPDATE_INTERRUPTION_FILTER = 5000;
private final static int MP3_TO_PLAY = R.raw.testmp3; // ~ 5 second mp3
private final static long POLL_TIME_PLAY_MUSIC = 2000;
diff --git a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
index ac09cef..3de299c 100644
--- a/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
+++ b/tests/tests/media/player/src/android/media/player/cts/MediaPlayerTest.java
@@ -115,6 +115,8 @@
private static final int RECORDED_VIDEO_HEIGHT = 144;
private static final long RECORDED_DURATION_MS = 3000;
private static final float FLOAT_TOLERANCE = .0001f;
+ private static final int PLAYBACK_DURATION_MS = 10000;
+ private static final int ANR_DETECTION_TIME_MS = 20000;
private final Vector<Integer> mTimedTextTrackIndex = new Vector<>();
private final Monitor mOnTimedTextCalled = new Monitor();
@@ -713,9 +715,9 @@
player.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
player.prepare();
// Test needs the mediaplayer to playback at least about 5 seconds of content.
- // Clip used here has a duration of 61 seconds, so seek to 50 seconds in the media file.
+ // Clip used here has a duration of 61 seconds, given PLAYBACK_DURATION_MS for play.
// This leaves enough remaining time, with gapless enabled or disabled,
- player.seekTo(50000);
+ player.seekTo(player.getDuration() - PLAYBACK_DURATION_MS);
}
}
@@ -757,6 +759,8 @@
@Test
public void testSetNextMediaPlayer() throws Exception {
+ final int TOTAL_TIMEOUT_MS = PLAYBACK_DURATION_MS * 4 + ANR_DETECTION_TIME_MS
+ + 5000 /* listener latency(ms) */;
initMediaPlayer(mMediaPlayer);
final Monitor mTestCompleted = new Monitor();
@@ -770,9 +774,9 @@
return;
}
long now = SystemClock.elapsedRealtime();
- if ((now - startTime) > 45000) {
- // We've been running for 45 seconds and still aren't done, so we're stuck
- // somewhere. Signal ourselves to dump the thread stacks.
+ if ((now - startTime) > TOTAL_TIMEOUT_MS) {
+ // We've been running beyond TOTAL_TIMEOUT and still aren't done,
+ // so we're stuck somewhere. Signal ourselves to dump the thread stacks.
android.os.Process.sendSignal(android.os.Process.myPid(), 3);
SystemClock.sleep(2000);
fail("Test is stuck, see ANR stack trace for more info. You may need to" +
diff --git a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java
index f5b0140..d83cd94 100644
--- a/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java
+++ b/tests/tests/networksecurityconfig/src/android/security/net/config/cts/BaseTestCase.java
@@ -17,6 +17,7 @@
package android.security.net.config.cts;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.net.wifi.WifiManager;
import android.test.AndroidTestCase;
@@ -26,12 +27,24 @@
* Base test case for all tests under {@link android.security.net.config.cts}.
*/
public class BaseTestCase extends AndroidTestCase {
+
+ private boolean isWifiSupported(Context context) {
+ final PackageManager packageManager = context.getPackageManager();
+ return packageManager.hasSystemFeature(PackageManager.FEATURE_WIFI);
+ }
+
@Override
public void setUp() throws Exception {
// Instant Apps cannot access WifiManager, skip wifi check.
if (getContext().getPackageManager().isInstantApp()) {
return;
}
+
+ // Skip accessing wifi manager if Wifi feature is not supported.
+ if (!isWifiSupported(getContext())) {
+ return;
+ }
+
WifiManager wifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
if (!wifiManager.isWifiEnabled()) {
SystemUtil.runShellCommand("svc wifi enable"); // toggle wifi on.
diff --git a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
index ece130d..3e2aeee 100644
--- a/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
+++ b/tests/tests/os/src/android/os/cts/AppHibernationUtils.kt
@@ -40,6 +40,7 @@
import android.util.Log
import androidx.test.InstrumentationRegistry
import com.android.compatibility.common.util.ExceptionUtils.wrappingExceptions
+import com.android.compatibility.common.util.FeatureUtil
import com.android.compatibility.common.util.LogcatInspector
import com.android.compatibility.common.util.SystemUtil.eventually
import com.android.compatibility.common.util.SystemUtil.runShellCommandOrThrow
@@ -68,6 +69,7 @@
const val SYSUI_PKG_NAME = "com.android.systemui"
const val NOTIF_LIST_ID = "com.android.systemui:id/notification_stack_scroller"
+const val NOTIF_LIST_ID_AUTOMOTIVE = "com.android.systemui:id/notifications"
const val CLEAR_ALL_BUTTON_ID = "dismiss_text"
// Time to find a notification. Unlikely, but in cases with a lot of notifications, it may take
// time to find the notification we're looking for
@@ -278,7 +280,12 @@
while (view == null && start + timeoutMs > System.currentTimeMillis()) {
view = uiDevice.wait(Until.findObject(selector), VIEW_WAIT_TIMEOUT)
if (view == null) {
- val notificationList = UiScrollable(UiSelector().resourceId(NOTIF_LIST_ID))
+ val notificationListId = if (FeatureUtil.isAutomotive()) {
+ NOTIF_LIST_ID_AUTOMOTIVE
+ } else {
+ NOTIF_LIST_ID
+ }
+ val notificationList = UiScrollable(UiSelector().resourceId(notificationListId))
wrappingExceptions({ cause: Throwable? -> UiDumpUtils.wrapWithUiDump(cause) }) {
Assert.assertTrue("Notification list view not found",
notificationList.waitForExists(VIEW_WAIT_TIMEOUT))
diff --git a/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
index fd7e977..030f341 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWakeLockPermissionTest.java
@@ -17,6 +17,8 @@
package android.permission.cts;
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
import android.content.Context;
import android.media.MediaPlayer;
import android.net.wifi.WifiManager;
@@ -49,6 +51,10 @@
@AppModeFull(reason = "Instant apps cannot access the WifiManager")
@SmallTest
public void testWifiLockAcquire() {
+ if (!mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI)) {
+ return;
+ }
+
final WifiManager wifiManager = (WifiManager) mContext.getSystemService(
Context.WIFI_SERVICE);
final WifiLock wifiLock = wifiManager.createWifiLock("WakeLockPermissionTest");
diff --git a/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
index d8acd50..6be8d7d 100644
--- a/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoWifiStatePermissionTest.java
@@ -16,6 +16,8 @@
package android.permission.cts;
+import static android.content.pm.PackageManager.FEATURE_WIFI;
+
import android.content.Context;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
@@ -32,10 +34,17 @@
private static final int TEST_NET_ID = 1;
private static final WifiConfiguration TEST_WIFI_CONFIGURATION = new WifiConfiguration();
private WifiManager mWifiManager;
+ private boolean mHasWifi;
@Override
protected void setUp() throws Exception {
super.setUp();
+
+ mHasWifi = mContext.getPackageManager().hasSystemFeature(FEATURE_WIFI);
+ if (!mHasWifi) {
+ return;
+ }
+
mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
assertNotNull(mWifiManager);
}
@@ -46,6 +55,10 @@
* {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
*/
public void testGetWifiState() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.getWifiState();
fail("WifiManager.getWifiState didn't throw SecurityException as expected");
@@ -60,6 +73,10 @@
* {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
*/
public void testGetConfiguredNetworks() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.getConfiguredNetworks();
fail("WifiManager.getConfiguredNetworks didn't throw SecurityException as expected");
@@ -74,6 +91,10 @@
* {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
*/
public void testGetConnectionInfo() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.getConnectionInfo();
fail("WifiManager.getConnectionInfo didn't throw SecurityException as expected");
@@ -88,6 +109,10 @@
* {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
*/
public void testGetScanResults() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.getScanResults();
fail("WifiManager.getScanResults didn't throw SecurityException as expected");
@@ -102,6 +127,10 @@
* {@link android.Manifest.permission#ACCESS_WIFI_STATE}.
*/
public void testGetDhcpInfo() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.getDhcpInfo();
fail("WifiManager.getDhcpInfo didn't throw SecurityException as expected");
@@ -116,6 +145,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testDisconnect() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.disconnect();
fail("WifiManager.disconnect didn't throw SecurityException as expected");
@@ -130,6 +163,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testReconnect() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.reconnect();
fail("WifiManager.reconnect didn't throw SecurityException as expected");
@@ -144,6 +181,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testReassociate() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.reassociate();
fail("WifiManager.reassociate didn't throw SecurityException as expected");
@@ -158,6 +199,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testAddNetwork() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.addNetwork(TEST_WIFI_CONFIGURATION);
fail("WifiManager.addNetwork didn't throw SecurityException as expected");
@@ -172,6 +217,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testUpdateNetwork() {
+ if (!mHasWifi) {
+ return;
+ }
+
TEST_WIFI_CONFIGURATION.networkId = 2;
try {
@@ -188,6 +237,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testRemoveNetwork() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.removeNetwork(TEST_NET_ID);
fail("WifiManager.removeNetwork didn't throw SecurityException as expected");
@@ -202,6 +255,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testEnableNetwork() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.enableNetwork(TEST_NET_ID, false);
fail("WifiManager.enableNetwork didn't throw SecurityException as expected");
@@ -216,6 +273,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testDisableNetwork() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.disableNetwork(TEST_NET_ID);
fail("WifiManager.disableNetwork didn't throw SecurityException as expected");
@@ -230,6 +291,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testPingSupplicant() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.pingSupplicant();
fail("WifiManager.pingSupplicant didn't throw SecurityException as expected");
@@ -244,6 +309,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testStartScan() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.startScan();
fail("WifiManager.startScan didn't throw SecurityException as expected");
@@ -258,6 +327,10 @@
* {@link android.Manifest.permission#CHANGE_WIFI_STATE}.
*/
public void testSetWifiEnabled() {
+ if (!mHasWifi) {
+ return;
+ }
+
try {
mWifiManager.setWifiEnabled(true);
fail("WifiManager.setWifiEnabled didn't throw SecurityException as expected");
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 104655f..3c8a35c 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
@@ -22,6 +22,7 @@
import android.app.NotificationManager
import android.content.Intent
import android.content.pm.PackageManager
+import android.os.Bundle
import android.os.Handler
import android.os.Looper
@@ -43,9 +44,13 @@
lateinit var notificationManager: NotificationManager
var launchActivityOnSecondResume = false
var isFirstResume = true
+ var windowHasFocus = false
+ var pendingCreateChannel = false
val handler = Handler(Looper.getMainLooper())
- override fun onStart() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
val launchSecondActivity = intent.getBooleanExtra(EXTRA_START_SECOND_ACTIVITY, false)
notificationManager = baseContext.getSystemService(NotificationManager::class.java)!!
if (intent.getBooleanExtra(EXTRA_START_SECOND_APP, false)) {
@@ -73,7 +78,6 @@
}
}
-
if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS, false)) {
requestPermissions(arrayOf(Manifest.permission.RECORD_AUDIO), 0)
} else if (intent.getBooleanExtra(EXTRA_REQUEST_OTHER_PERMISSIONS_DELAYED, false)) {
@@ -85,8 +89,6 @@
if (intent.getBooleanExtra(EXTRA_REQUEST_NOTIF_PERMISSION, false)) {
requestPermissions(arrayOf(Manifest.permission.POST_NOTIFICATIONS), 0)
}
-
- super.onStart()
}
private fun launchSecondActivity() {
@@ -99,7 +101,21 @@
}, LONG_DELAY_MS)
}
+ override fun onWindowFocusChanged(hasFocus: Boolean) {
+ windowHasFocus = hasFocus
+ if (windowHasFocus && pendingCreateChannel) {
+ pendingCreateChannel = false
+ createChannel()
+ }
+ }
+
private fun createChannel() {
+ // Wait until window has focus so the permission prompt can be displayed
+ if (!windowHasFocus) {
+ pendingCreateChannel = true
+ return
+ }
+
if (notificationManager.getNotificationChannel(CHANNEL_ID_31) == null) {
notificationManager.createNotificationChannel(NotificationChannel(CHANNEL_ID_31,
"Foreground Services", NotificationManager.IMPORTANCE_HIGH))
diff --git a/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp b/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp
index 876b68f..293897c 100644
--- a/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp
+++ b/tests/tests/permission3/CreateNotificationChannelsApp33/Android.bp
@@ -23,7 +23,7 @@
defaults: ["mts-target-sdk-version-current"],
// TODO ntmyren: change to "33" when it is a valid target
sdk_version: "test_current",
- min_sdk_version: "test_current",
+ min_sdk_version: "current",
static_libs: [
"kotlin-stdlib",
diff --git a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
index d55e3a4..dee76c2 100644
--- a/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/NotificationPermissionTest.kt
@@ -194,6 +194,7 @@
fun notificationPromptShownForSubsequentStartsIfTaskStartWasLauncher() {
installPackage(APP_APK_PATH_CREATE_NOTIFICATION_CHANNELS_31, expectSuccess = true)
launchApp(startSecondActivity = true)
+ waitFindObject(By.res(ALLOW_BUTTON))
pressBack()
clickPermissionRequestAllowButton()
}
diff --git a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
index 5ad3cf5..48f55be 100644
--- a/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
+++ b/tests/tests/provider/src/android/provider/cts/ProviderTestUtils.java
@@ -279,7 +279,8 @@
// file creation fails, we ignore and let `dd` command create it instead.
}
- executeShellCommand(String.format("dd bs=1 if=%s skip=%d count=%d of=%s",
+ executeShellCommand(String.format(
+ "dd bs=4K if=%s iflag=skip_bytes,count_bytes skip=%d count=%d of=%s",
source.getAbsolutePath(), skip, count, file.getAbsolutePath()));
// Force sync to try updating other views
diff --git a/tests/tests/systemui/AndroidManifest.xml b/tests/tests/systemui/AndroidManifest.xml
index 15933b6..3bcb78e 100644
--- a/tests/tests/systemui/AndroidManifest.xml
+++ b/tests/tests/systemui/AndroidManifest.xml
@@ -29,13 +29,11 @@
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application android:requestLegacyExternalStorage="true">
- <!-- Have LightBarActivity always take up the full screen, regardless of orientation,
- so it's never letterboxed. If the activity is letterboxed, then the status icons will
- be outside of the activity and the tests will fail. See b/246515090. -->
+ <!-- Have LightBarActivity always be in portrait orientation, since the test's screenshots
+ rely on portrait orientation. See b/260069585. -->
<activity android:name=".LightBarActivity"
android:theme="@android:style/Theme.Material.NoActionBar"
- android:screenOrientation="unspecified"
- android:resizeableActivity="true"/>
+ android:screenOrientation="portrait"/>
<activity android:name=".LightBarThemeActivity"
android:theme="@style/LightBarTheme"
android:screenOrientation="portrait"/>
diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
index 5079217..c09cb53 100644
--- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
+++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java
@@ -41,6 +41,7 @@
import android.permission.PermissionManager;
import android.permission.cts.PermissionUtils;
import android.platform.test.annotations.AppModeFull;
+import android.server.wm.IgnoreOrientationRequestSession;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.MotionEvent;
@@ -54,6 +55,8 @@
import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.ThrowingRunnable;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
@@ -86,6 +89,7 @@
private final String NOTIFICATION_CHANNEL_ID = "test_channel";
private final String NOTIFICATION_GROUP_KEY = "test_group";
private NotificationManager mNm;
+ private IgnoreOrientationRequestSession mOrientationRequestSession;
@Rule
public ActivityTestRule<LightBarActivity> mActivityRule = new ActivityTestRule<>(
@@ -93,6 +97,28 @@
@Rule
public TestName mTestName = new TestName();
+
+
+ @Before
+ public void setUp() {
+ // We need to prevent letterboxing because when an activity is letterboxed, then the status
+ // bar icons are outside the activity space so our verification will fail. See b/246515090.
+ //
+ // When ignore_orientation_request is set to true and the device is in landscape but the
+ // activity is in portrait, then the device remains in landscape but letterboxes the
+ // activity (so the activity is *not* full screen). Setting ignore_orientation_request to
+ // false will cause the device to instead rotate to portrait to match the activity, thus
+ // preventing letterboxing.
+ mOrientationRequestSession = new IgnoreOrientationRequestSession(false /* enable */);
+ }
+
+ @After
+ public void tearDown() {
+ if (mOrientationRequestSession != null) {
+ mOrientationRequestSession.close();
+ }
+ }
+
@Test
@AppModeFull // Instant apps cannot create notifications
public void testLightStatusBarIcons() throws Throwable {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
index cf46203..291ce7c 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyManagerTest.java
@@ -1210,10 +1210,8 @@
Build::getSerial);
assertNotNull("Non-telephony devices must have a Build.getSerial() number.",
serial);
- assertTrue("Hardware id must be no longer than 20 characters.",
- serial.length() <= 20);
assertTrue("Hardware id must be alphanumeric.",
- Pattern.matches("[0-9A-Za-z]+", serial));
+ Pattern.matches("[0-9A-Za-z.,_-]+", serial));
}
private void assertMacAddress(String macAddress) {
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
index 7a91ab9..08666e2 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.kt
@@ -81,7 +81,9 @@
}
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
- View.SYSTEM_UI_FLAG_FULLSCREEN
+ View.SYSTEM_UI_FLAG_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
+ View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
window.decorView.keepScreenOn = true
mHandler = RenderSpecHandler()
diff --git a/tests/tests/view/src/android/view/cts/OWNERS b/tests/tests/view/src/android/view/cts/OWNERS
index b7cb836..3ecbdbc 100644
--- a/tests/tests/view/src/android/view/cts/OWNERS
+++ b/tests/tests/view/src/android/view/cts/OWNERS
@@ -2,6 +2,7 @@
per-file ASurfaceControlTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
per-file AttachedSurfaceControlSyncTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
per-file AttachedSurfaceControlTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
+per-file SetTouchableRegionTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
per-file SurfaceViewSyncTest.java = file:platform/frameworks/base:/services/core/java/com/android/server/wm/OWNERS
per-file *ScrollCapture*.java = file:platform/frameworks/base:/packages/SystemUI/src/com/android/systemui/screenshot/OWNERS
diff --git a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
index c89cdb8..9cff62b 100644
--- a/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
+++ b/tests/tests/view/src/android/view/cts/PixelCopyViewProducerActivity.java
@@ -72,6 +72,9 @@
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
mContent.getViewTreeObserver().addOnDrawListener(this);
mContent.setOnApplyWindowInsetsListener(this);
+
+ //setDecorFitsSystemWindows to false will ignore the cutout
+ getWindow().setDecorFitsSystemWindows(false);
}
@Override
diff --git a/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java b/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java
index ad73c21..2cf7b5c 100644
--- a/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java
+++ b/tests/tests/view/src/android/view/cts/SetTouchableRegionTest.java
@@ -16,14 +16,17 @@
package android.view.cts;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.app.Instrumentation;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Region;
-import android.view.AttachedSurfaceControl;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
@@ -33,22 +36,18 @@
import com.android.compatibility.common.util.CtsTouchUtils;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.LargeTest;
-import androidx.test.rule.ActivityTestRule;
+import androidx.test.core.app.ActivityScenario;
import androidx.test.runner.AndroidJUnit4;
@RunWith(AndroidJUnit4.class)
public class SetTouchableRegionTest {
private Instrumentation mInstrumentation;
private Activity mActivity;
- @Rule
- public ActivityTestRule<CtsActivity> mActivityRule =
- new ActivityTestRule<>(CtsActivity.class);
+ private ActivityScenario<CtsActivity> mScenario;
class MotionRecordingView extends View {
public MotionRecordingView(Context context) {
@@ -80,20 +79,28 @@
@Before
public void setup() {
mInstrumentation = InstrumentationRegistry.getInstrumentation();
- mActivity = mActivityRule.getActivity();
+ // Launch activity in fullscreen windowing mode
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(mInstrumentation.getTargetContext(), CtsActivity.class);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ mScenario = ActivityScenario.launch(intent, options.toBundle());
+ mScenario.onActivity(activity -> {
+ mActivity = activity;
+ });
}
void tapSync() {
mInstrumentation.waitForIdleSync();
assertFalse(mMotionRecordingView.gotEvent());
- CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, mActivityRule, mMotionRecordingView);
+ CtsTouchUtils.emulateTapOnViewCenter(mInstrumentation, null, mMotionRecordingView);
mInstrumentation.waitForIdleSync();
}
@Test
public void testClickthroughRegion() throws Throwable {
- mActivityRule.runOnUiThread(() -> {
+ mScenario.onActivity(activity -> {
mMotionRecordingView = new MotionRecordingView(mActivity);
mActivity.setContentView(mMotionRecordingView);
});
@@ -101,7 +108,7 @@
// We have a view filling our entire hierarchy and so a tap should reach it
assertTrue(mMotionRecordingView.gotEvent());
- mActivityRule.runOnUiThread(() -> {
+ mScenario.onActivity(activity -> {
mPopupView = new View(mActivity);
PopupWindow popup = new PopupWindow(mPopupView,
ViewGroup.LayoutParams.FILL_PARENT,
@@ -114,7 +121,7 @@
// and so the tap should not reach us
assertFalse(mMotionRecordingView.gotEvent());
- mActivityRule.runOnUiThread(() -> {
+ mScenario.onActivity(activity -> {
mPopupView.getRootSurfaceControl().setTouchableRegion(new Region());
});
tapSync();
diff --git a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
index c4f36b7..08c2231 100644
--- a/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
+++ b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
@@ -97,6 +97,7 @@
decorView.setPointerIcon(
PointerIcon.getSystemIcon(this, PointerIcon.TYPE_NULL));
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ getWindow().setDecorFitsSystemWindows(false);
mLayoutParams = new FrameLayout.LayoutParams(DEFAULT_LAYOUT_WIDTH, DEFAULT_LAYOUT_HEIGHT,
Gravity.LEFT | Gravity.TOP);
@@ -156,6 +157,12 @@
}
public void verifyScreenshot(PixelChecker pixelChecker, TestName name) {
+ int retries = 0;
+ int maxRetries = 2;
+ int numMatchingPixels = 0;
+ Rect bounds = null;
+ boolean success = false;
+
// Wait for the stable insets update. The position of the surface view is in correct before
// the update. Sometimes this callback isn't called, so we don't want to fail the test
// because it times out.
@@ -163,33 +170,44 @@
Log.w(TAG, "Insets animation wait timed out.");
}
- final CountDownLatch countDownLatch = new CountDownLatch(1);
- UiAutomation uiAutomation = mInstrumentation.getUiAutomation();
+ while (retries < maxRetries) {
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ UiAutomation uiAutomation = mInstrumentation.getUiAutomation();
+ mHandler.post(() -> {
+ mScreenshot = uiAutomation.takeScreenshot(getWindow());
+ countDownLatch.countDown();
+ });
+
+ try {
+ countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS);
+ } catch (Exception e) {
+ }
+
+ assertNotNull(mScreenshot);
+
+ Bitmap swBitmap = mScreenshot.copy(Bitmap.Config.ARGB_8888, false);
+ mScreenshot.recycle();
+
+ numMatchingPixels = pixelChecker.getNumMatchingPixels(swBitmap);
+ bounds = pixelChecker.getBoundsToCheck(swBitmap);
+ success = pixelChecker.checkPixels(numMatchingPixels, swBitmap.getWidth(),
+ swBitmap.getHeight());
+ if (!success) {
+ saveFailureCapture(swBitmap, name);
+ swBitmap.recycle();
+ retries++;
+ try {
+ Thread.sleep(300);
+ } catch (InterruptedException e) {
+ }
+ } else {
+ swBitmap.recycle();
+ break;
+ }
+ }
mHandler.post(() -> {
- mScreenshot = uiAutomation.takeScreenshot(getWindow());
mParent.removeAllViews();
- countDownLatch.countDown();
});
-
- try {
- countDownLatch.await(WAIT_TIMEOUT_S, TimeUnit.SECONDS);
- } catch (Exception e) {
- }
-
- assertNotNull(mScreenshot);
-
- Bitmap swBitmap = mScreenshot.copy(Bitmap.Config.ARGB_8888, false);
- mScreenshot.recycle();
-
- int numMatchingPixels = pixelChecker.getNumMatchingPixels(swBitmap);
- Rect bounds = pixelChecker.getBoundsToCheck(swBitmap);
- boolean success = pixelChecker.checkPixels(numMatchingPixels, swBitmap.getWidth(),
- swBitmap.getHeight());
- if (!success) {
- saveFailureCapture(swBitmap, name);
- }
- swBitmap.recycle();
-
assertTrue("Actual matched pixels:" + numMatchingPixels
+ " Bitmap size:" + bounds.width() + "x" + bounds.height(), success);
}
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index dd10626..928dcf8 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -24,6 +24,7 @@
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.view.ViewGroup;
+import android.view.ViewParent;
import android.webkit.HttpAuthHandler;
import android.webkit.RenderProcessGoneDetail;
import android.webkit.SafeBrowsingResponse;
@@ -157,56 +158,70 @@
final WebView childWebView = mOnUiThread.createWebView();
- WebViewOnUiThread childWebViewOnUiThread = new WebViewOnUiThread(childWebView);
- mOnUiThread.setWebChromeClient(new WebChromeClient() {
- @Override
- public boolean onCreateWindow(
- WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
- WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
- childWebView.setWebViewClient(childWebViewClient);
- childWebView.getSettings().setJavaScriptEnabled(true);
- transport.setWebView(childWebView);
- getActivity().addContentView(childWebView, new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.FILL_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT));
- resultMsg.sendToTarget();
- return true;
- }
- });
- {
- final int childCallCount = childWebViewClient.getShouldOverrideUrlLoadingCallCount();
- mOnUiThread.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_TAG_URL));
+ try {
+ WebViewOnUiThread childWebViewOnUiThread = new WebViewOnUiThread(childWebView);
+ mOnUiThread.setWebChromeClient(new WebChromeClient() {
+ @Override
+ public boolean onCreateWindow(
+ WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
+ WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
+ childWebView.setWebViewClient(childWebViewClient);
+ childWebView.getSettings().setJavaScriptEnabled(true);
+ transport.setWebView(childWebView);
+ getActivity().addContentView(childWebView, new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.FILL_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ resultMsg.sendToTarget();
+ return true;
+ }
+ });
+ {
+ final int childCallCount =
+ childWebViewClient.getShouldOverrideUrlLoadingCallCount();
+ mOnUiThread.loadUrl(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_TAG_URL));
- new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
- @Override
- protected boolean check() {
- return childWebViewClient.hasOnPageFinishedCalled();
- }
- }.run();
- new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
- @Override
- protected boolean check() {
- return childWebViewClient.getShouldOverrideUrlLoadingCallCount() > childCallCount;
- }
- }.run();
- assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.PAGE_WITH_LINK_URL),
- childWebViewClient.getLastShouldOverrideUrl());
+ new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+ @Override
+ protected boolean check() {
+ return childWebViewClient.hasOnPageFinishedCalled();
+ }
+ }.run();
+ new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+ @Override
+ protected boolean check() {
+ return childWebViewClient
+ .getShouldOverrideUrlLoadingCallCount() > childCallCount;
+ }
+ }.run();
+ assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.PAGE_WITH_LINK_URL),
+ childWebViewClient.getLastShouldOverrideUrl());
+ }
+
+ final int childCallCount =
+ childWebViewClient.getShouldOverrideUrlLoadingCallCount();
+ final int mainCallCount = mainWebViewClient.getShouldOverrideUrlLoadingCallCount();
+ clickOnLinkUsingJs("link", childWebViewOnUiThread);
+ new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
+ @Override
+ protected boolean check() {
+ return childWebViewClient
+ .getShouldOverrideUrlLoadingCallCount() > childCallCount;
+ }
+ }.run();
+ assertEquals(mainCallCount, mainWebViewClient.getShouldOverrideUrlLoadingCallCount());
+ // PAGE_WITH_LINK_URL has a link to BLANK_PAGE_URL (an arbitrary page
+ // also controlled by the test server)
+ assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_PAGE_URL),
+ childWebViewClient.getLastShouldOverrideUrl());
+ } finally {
+ WebkitUtils.onMainThreadSync(() -> {
+ ViewParent parent = childWebView.getParent();
+ if (parent instanceof ViewGroup) {
+ ((ViewGroup) parent).removeView(childWebView);
+ }
+ childWebView.destroy();
+ });
}
-
- final int childCallCount = childWebViewClient.getShouldOverrideUrlLoadingCallCount();
- final int mainCallCount = mainWebViewClient.getShouldOverrideUrlLoadingCallCount();
- clickOnLinkUsingJs("link", childWebViewOnUiThread);
- new PollingCheck(WebkitUtils.TEST_TIMEOUT_MS) {
- @Override
- protected boolean check() {
- return childWebViewClient.getShouldOverrideUrlLoadingCallCount() > childCallCount;
- }
- }.run();
- assertEquals(mainCallCount, mainWebViewClient.getShouldOverrideUrlLoadingCallCount());
- // PAGE_WITH_LINK_URL has a link to BLANK_PAGE_URL (an arbitrary page also controlled by the
- // test server)
- assertEquals(mWebServer.getAssetUrl(TestHtmlConstants.BLANK_PAGE_URL),
- childWebViewClient.getLastShouldOverrideUrl());
}
private void clickOnLinkUsingJs(final String linkId, WebViewOnUiThread webViewOnUiThread) {
diff --git a/tests/tests/widget/res/values/styles.xml b/tests/tests/widget/res/values/styles.xml
index f75cabf..3d1a7a7 100644
--- a/tests/tests/widget/res/values/styles.xml
+++ b/tests/tests/widget/res/values/styles.xml
@@ -400,6 +400,8 @@
</style>
<style name="Theme.PopupWindowCtsActivity" parent="@android:style/Theme.Holo">
+ <item name="android:windowSwipeToDismiss">false</item>
+ <item name="android:windowLayoutInDisplayCutoutMode">never</item>
</style>
<style name="TextView_FontResource">
diff --git a/tests/tests/widget/res/values/themes.xml b/tests/tests/widget/res/values/themes.xml
index 938452e..374834a 100644
--- a/tests/tests/widget/res/values/themes.xml
+++ b/tests/tests/widget/res/values/themes.xml
@@ -25,7 +25,7 @@
<item name="themeString">@string/remoteviews_theme_string</item>
</style>
- <style name="HorizontalScrollViewCtsActivityTheme" parent="@android:style/Theme.DeviceDefault">
+ <style name="HorizontalScrollViewCtsActivityTheme" parent="@android:style/Theme.Material.Light.DarkActionBar">
<item name="android:windowSwipeToDismiss">false</item>
</style>
</resources>
diff --git a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
index c74f21b..d94667c 100644
--- a/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ListPopupWindowTest.java
@@ -16,6 +16,8 @@
package android.widget.cts;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -34,8 +36,10 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.app.Instrumentation;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -56,6 +60,7 @@
import android.widget.TextView;
import androidx.test.InstrumentationRegistry;
+import androidx.test.core.app.ActivityScenario;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -89,6 +94,8 @@
private AdapterView.OnItemClickListener mItemClickListener;
+ private ActivityScenario<ListPopupWindowCtsActivity> mScenario;
+
/**
* Item click listener that dismisses our <code>ListPopupWindow</code> when any item
* is clicked. Note that this needs to be a separate class that is also protected (not
@@ -500,7 +507,7 @@
final ListView popupListView = mPopupWindow.getListView();
final Rect rect = new Rect();
mPopupWindow.getBackground().getPadding(rect);
- CtsTouchUtils.emulateTapOnView(instrumentation, mActivityRule, popupListView,
+ CtsTouchUtils.emulateTapOnView(instrumentation, null, popupListView,
-rect.left - 20, popupListView.getHeight() / 2);
// At this point our popup should not be showing and should have notified its
@@ -515,6 +522,21 @@
@Test
public void testDismissalOutsideNonModal() {
+ // Close the activity that was launched by setup
+ mActivityRule.finishActivity();
+
+ // Launch activity in fullscreen windowing mode
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClass(mInstrumentation.getTargetContext(), ListPopupWindowCtsActivity.class);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+ mScenario = ActivityScenario.launch(intent, options.toBundle());
+ mScenario.onActivity(activity -> {
+ mActivity = activity;
+ mActivity.getApplicationInfo().setEnableOnBackInvokedCallback(false);
+ });
+
verifyDismissalViaTouch(false);
}
diff --git a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
index bca2bc7..50ee3b1 100755
--- a/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
+++ b/tests/tests/widget/src/android/widget/cts/SpinnerTest.java
@@ -403,34 +403,6 @@
TestUtils.assertAllPixelsOfColor("Drop down should be blue", dropDownBackground,
dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
false, Color.BLUE, 1, true);
- waitForHasFocusMS(SPINNER_HAS_FOCUS_DELAY_MS);
- // Dismiss the popup with the emulated back key
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- // Verify that we're not showing the popup
- PollingCheck.waitFor(() -> !mSpinnerDropdownMode.isPopupShowing());
-
- // Set yellow background on the popup
- mActivityRule.runOnUiThread(() ->
- mSpinnerDropdownMode.setPopupBackgroundDrawable(
- mActivity.getDrawable(R.drawable.yellow_fill)));
-
- // Use instrumentation to emulate a tap on the spinner to bring down its popup
- WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mSpinnerDropdownMode, () -> {
- mSpinnerDropdownMode.performClick();
- });
- // Verify that we're showing the popup
- PollingCheck.waitFor(() -> mSpinnerDropdownMode.isPopupShowing());
- // And test its fill
- dropDownBackground = mSpinnerDropdownMode.getPopupBackground();
- TestUtils.assertAllPixelsOfColor("Drop down should be yellow", dropDownBackground,
- dropDownBackground.getBounds().width(), dropDownBackground.getBounds().height(),
- false, Color.YELLOW, 1, true);
-
- waitForHasFocusMS(SPINNER_HAS_FOCUS_DELAY_MS);
- // Dismiss the popup with the emulated escape key
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ESCAPE);
- // Verify that we're not showing the popup
- PollingCheck.waitFor(() -> !mSpinnerDropdownMode.isPopupShowing());
}
@Test
@@ -450,38 +422,5 @@
PollingCheck.waitFor(() -> mSpinnerDialogMode.isPopupShowing());
// And test that getPopupBackground returns null
assertNull(mSpinnerDialogMode.getPopupBackground());
-
- // Dismiss the popup with the emulated back key
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
- // Verify that we're not showing the popup
- PollingCheck.waitFor(() -> !mSpinnerDialogMode.isPopupShowing());
-
- // Set yellow background on the popup
- mActivityRule.runOnUiThread(() ->
- mSpinnerDialogMode.setPopupBackgroundDrawable(
- mActivity.getDrawable(R.drawable.yellow_fill)));
-
- // Use instrumentation to emulate a tap on the spinner to bring down its popup
- WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mSpinnerDialogMode, () -> {
- mSpinnerDialogMode.performClick();
- });
- // Verify that we're showing the popup
- PollingCheck.waitFor(() -> mSpinnerDialogMode.isPopupShowing());
- // And test that getPopupBackground returns null
- assertNull(mSpinnerDialogMode.getPopupBackground());
-
- // Use emulated escape key to close popup
- mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ESCAPE);
- // Verify that we're not showing the popup
- PollingCheck.waitFor(() -> !mSpinnerDropdownMode.isPopupShowing());
- }
-
- private void waitForHasFocusMS(int milliseconds) {
- try {
- Thread.sleep(milliseconds);
- } catch (InterruptedException e) {
- fail("unexpected InterruptedException : "+ e);
- }
-
}
}
diff --git a/tests/tests/widget/src/android/widget/cts/ToastTest.java b/tests/tests/widget/src/android/widget/cts/ToastTest.java
index 38dedf6..ca8dfb0 100644
--- a/tests/tests/widget/src/android/widget/cts/ToastTest.java
+++ b/tests/tests/widget/src/android/widget/cts/ToastTest.java
@@ -64,6 +64,7 @@
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.PollingCheck;
import com.android.compatibility.common.util.SystemUtil;
import com.android.compatibility.common.util.TestUtils;
@@ -989,7 +990,9 @@
* us to wait a given amount of time to test that the limit has been enforced/lifted.
*/
@Test
+ @ApiTest(apis = {"android.widget.Toast#show"})
public void testRateLimitingToastsWhenInBackground() throws Throwable {
+ assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
// enable rate limiting to test it
SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
.setToastRateLimitingEnabled(true));
@@ -1051,7 +1054,9 @@
}
@Test
+ @ApiTest(apis = {"android.widget.Toast#show"})
public void testAppWithUnlimitedToastsPermissionCanPostUnlimitedToasts() throws Throwable {
+ assumeFalse("Skipping test: Watch does not support new Toast behavior yet", isWatch());
// enable rate limiting to test it
SystemUtil.runWithShellPermissionIdentity(() -> mNotificationManager
.setToastRateLimitingEnabled(true));
diff --git a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
index 1063fc4..47dce91 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/MultiStaConcurrencyWifiNetworkSpecifierTest.java
@@ -200,13 +200,19 @@
@After
public void tearDown() throws Exception {
+ if (!WifiFeature.isWifiSupported(mContext)) {
+ return;
+ }
+
// Re-enable networks.
ShellIdentityUtils.invokeWithShellPermissions(
() -> {
- for (WifiConfiguration savedNetwork : mWifiManager.getConfiguredNetworks()) {
+ for (WifiConfiguration savedNetwork :
+ mWifiManager.getConfiguredNetworks()) {
mWifiManager.enableNetwork(savedNetwork.networkId, false);
}
});
+
// Release the requests after the test.
if (mNetworkCallback != null) {
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
@@ -214,6 +220,7 @@
if (mNrNetworkCallback != null) {
mConnectivityManager.unregisterNetworkCallback(mNrNetworkCallback);
}
+
// Clear any existing app state after each test.
ShellIdentityUtils.invokeWithShellPermissions(
() -> mWifiManager.removeAppState(myUid(), mContext.getPackageName()));
@@ -312,4 +319,4 @@
// Ensure that there is only 1 wifi connection available for apps.
assertThat(mTestHelper.getNumWifiConnections()).isEqualTo(1);
}
-}
\ No newline at end of file
+}
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 45f5325..732e07c 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -1885,6 +1885,7 @@
TestSoftApCallback lohsSoftApCallback = new TestSoftApCallback(mLock);
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
setWifiEnabled(false);
+ Thread.sleep(TEST_WAIT_DURATION_MS);
boolean wifiEnabled = mWifiManager.isWifiEnabled();
try {
uiAutomation.adoptShellPermissionIdentity();
@@ -2726,6 +2727,11 @@
*/
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTetheredBridgedAp() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
// check that softap bridged mode is supported by the device
if (!mWifiManager.isBridgedApConcurrencySupported()) {
return;
@@ -2790,6 +2796,11 @@
*/
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.S)
public void testTetheredBridgedApWifiForcedChannel() throws Exception {
+ if (!WifiFeature.isWifiSupported(getContext())) {
+ // skip the test if WiFi is not supported
+ return;
+ }
+
// check that softap bridged mode is supported by the device
if (!mWifiManager.isBridgedApConcurrencySupported()) {
return;
diff --git a/tools/cts-tradefed/etc/cts-tradefed b/tools/cts-tradefed/etc/cts-tradefed
index 21b36ca..0c40259 100755
--- a/tools/cts-tradefed/etc/cts-tradefed
+++ b/tools/cts-tradefed/etc/cts-tradefed
@@ -99,6 +99,9 @@
for JAR in ${JAR_DIR}/*.jar; do
JAR_PATH=${JAR_PATH}:${JAR}
done
+# Move 'tradefed.jar' to the front of the jar path
+TRADEFED_JAR=":${JAR_DIR}/tradefed.jar"
+JAR_PATH="${TRADEFED_JAR}${JAR_PATH/$TRADEFED_JAR}"
JAR_PATH=${JAR_PATH:1} # Strip off leading ':'
# load any shared libraries for host-side executables
diff --git a/tools/cts-tradefed/res/config/cts-known-failures.xml b/tools/cts-tradefed/res/config/cts-known-failures.xml
index 4f6360f..39e5c1f 100644
--- a/tools/cts-tradefed/res/config/cts-known-failures.xml
+++ b/tools/cts-tradefed/res/config/cts-known-failures.xml
@@ -314,4 +314,9 @@
<!-- b/266101051-->
<option name="compatibility:exclude-filter" value="CtsGameServiceTestCases" />
+
+ <!--- b/260389884 -->
+ <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode" />
+ <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStatePerformanceMode_withParams" />
+ <option name="compatibility:exclude-filter" value="CtsGameManagerTestCases android.gamemanager.cts.GameManagerTest#testSetGameStateStandardMode" />
</configuration>
diff --git a/tools/cts-tradefed/res/config/cts-system.xml b/tools/cts-tradefed/res/config/cts-system.xml
new file mode 100644
index 0000000..530fe79
--- /dev/null
+++ b/tools/cts-tradefed/res/config/cts-system.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 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="Runs a subset of CTS tests when vendor image is not changed">
+ <option name="plan" value="cts-system" />
+ <option name="result-attribute" key="system" value="1" />
+
+ <include name="cts" />
+
+ <!-- dEQP tests to be included in this plan-->
+ <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-EGL.*" />
+ <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-VK.wsi.*" />
+ <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES2.functional.prerequisite#*" />
+ <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-GLES3.functional.prerequisite#*" />
+ <option name="compatibility:module-arg" value="CtsDeqpTestCases:include-filter:dEQP-VK.api.smoke#*" />
+
+</configuration>
\ No newline at end of file