diff options
41 files changed, 495 insertions, 261 deletions
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java index d1c44ec4051..3eeadac3873 100644 --- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java +++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/its/ItsService.java @@ -260,7 +260,7 @@ public class ItsService extends Service implements SensorEventListener { private volatile BlockingQueue<Object[]> mSerializerQueue = new LinkedBlockingDeque<Object[]>(); - private AtomicInteger mCountCallbacksRemaining = new AtomicInteger(); + private final AtomicInteger mCountCallbacksRemaining = new AtomicInteger(); private AtomicInteger mCountRawOrDng = new AtomicInteger(); private AtomicInteger mCountRaw10 = new AtomicInteger(); private AtomicInteger mCountRaw12 = new AtomicInteger(); @@ -2714,7 +2714,7 @@ public class ItsService extends Service implements SensorEventListener { return previewSize; } - private void configureAndCreateExtensionSession( + private Surface configureAndCreateExtensionSession( Surface captureSurface, int extension, CameraExtensionSession.StateCallback stateCallback) throws ItsException { @@ -2739,6 +2739,7 @@ public class ItsService extends Service implements SensorEventListener { } catch (CameraAccessException e) { throw new ItsException("Error creating extension session: " + e); } + return previewSurface; } private void configureAndCreateCaptureSession(int requestTemplate, Surface recordSurface, @@ -2991,11 +2992,6 @@ public class ItsService extends Service implements SensorEventListener { List<CaptureRequest.Builder> requests = ItsSerializer.deserializeRequestList( mCamera, params, "captureRequests"); - // optional background preview requests - List<CaptureRequest.Builder> backgroundRequests = ItsSerializer.deserializeRequestList( - mCamera, params, "repeatRequests"); - boolean backgroundRequest = backgroundRequests.size() > 0; - int numSurfaces = 0; int numCaptureSurfaces = 0; BlockingExtensionSessionCallback sessionListener = @@ -3013,28 +3009,42 @@ public class ItsService extends Service implements SensorEventListener { JSONArray jsonOutputSpecs = ItsUtils.getOutputSpecs(params); prepareImageReadersWithOutputSpecs(jsonOutputSpecs, /*inputSize*/null, - /*inputFormat*/0, /*maxInputBuffers*/0, backgroundRequest); + /*inputFormat*/0, /*maxInputBuffers*/0, /*backgroundRequest*/ false); numSurfaces = mOutputImageReaders.length; - numCaptureSurfaces = numSurfaces - (backgroundRequest ? 1 : 0); + numCaptureSurfaces = numSurfaces; - configureAndCreateExtensionSession(mOutputImageReaders[0].getSurface(), extension, + Surface previewSurface = configureAndCreateExtensionSession( + mOutputImageReaders[0].getSurface(), + extension, sessionListener); mExtensionSession = sessionListener.waitAndGetSession(TIMEOUT_IDLE_MS); - for (int i = 0; i < numSurfaces; i++) { - ImageReader.OnImageAvailableListener readerListener; - if (backgroundRequest && i == numSurfaces - 1) { - readerListener = createAvailableListenerDropper(); - } else { - // When image is available, decrements mCountCallbacksRemaining - readerListener = createExtensionAvailableListener(mCaptureCallback); - } - mOutputImageReaders[i].setOnImageAvailableListener(readerListener, - mSaveHandlers[i]); + CaptureRequest.Builder captureBuilder = requests.get(0); + + if (params.optBoolean("waitAE", true)) { + // Set repeating request and wait for AE convergence. + Logt.i(TAG, "Waiting for AE to converge before taking extensions capture."); + captureBuilder.addTarget(previewSurface); + ImageReader.OnImageAvailableListener dropperListener = + createAvailableListenerDropper(); + mOutputImageReaders[0].setOnImageAvailableListener(dropperListener, + mSaveHandlers[0]); + mExtensionSession.setRepeatingRequest(captureBuilder.build(), + new HandlerExecutor(mResultHandler), + mExtAEResultListener); + mCountCallbacksRemaining.set(1); + long timeout = TIMEOUT_CALLBACK * 1000; + waitForCallbacks(timeout); + mExtensionSession.stopRepeating(); + captureBuilder.removeTarget(previewSurface); + mResultThread.sleep(PIPELINE_WARMUP_TIME_MS); } - CaptureRequest.Builder captureBuilder = requests.get(0); + ImageReader.OnImageAvailableListener readerListener = + createExtensionAvailableListener(mCaptureCallback); + mOutputImageReaders[0].setOnImageAvailableListener(readerListener, + mSaveHandlers[0]); captureBuilder.addTarget(mOutputImageReaders[0].getSurface()); mExtensionSession.capture(captureBuilder.build(), new HandlerExecutor(mResultHandler), mExtCaptureResultListener); @@ -3049,6 +3059,8 @@ public class ItsService extends Service implements SensorEventListener { BlockingExtensionSessionCallback.SESSION_CLOSED, TIMEOUT_SESSION_CLOSE); } catch (android.hardware.camera2.CameraAccessException e) { throw new ItsException("Access error: ", e); + } catch (InterruptedException e) { + throw new ItsException("Unexpected InterruptedException: ", e); } } @@ -3862,6 +3874,41 @@ public class ItsService extends Service implements SensorEventListener { } }; + private final ExtensionCaptureResultListener mExtAEResultListener = + new ExtensionCaptureResultListener() { + @Override + public void onCaptureProcessStarted(CameraExtensionSession session, + CaptureRequest request) { + } + + @Override + public void onCaptureResultAvailable(CameraExtensionSession session, + CaptureRequest request, + TotalCaptureResult result) { + try { + if (request == null || result == null) { + throw new ItsException("Request/result is invalid"); + } + if (result.get(CaptureResult.CONTROL_AE_STATE) == + CaptureResult.CONTROL_AE_STATE_CONVERGED) { + synchronized(mCountCallbacksRemaining) { + mCountCallbacksRemaining.decrementAndGet(); + mCountCallbacksRemaining.notify(); + } + } + } catch (ItsException e) { + Logt.e(TAG, "Script error: ", e); + } catch (Exception e) { + Logt.e(TAG, "Script error: ", e); + } + } + + @Override + public void onCaptureFailed(CameraExtensionSession session, CaptureRequest request) { + Logt.e(TAG, "Script error: capture failed"); + } + }; + private class CaptureCallbackWaiter extends CameraCaptureSession.CaptureCallback { private final LinkedBlockingQueue<TotalCaptureResult> mResultQueue = new LinkedBlockingQueue<>(); diff --git a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java index 1d49c7eba81..0e09981bf7c 100644 --- a/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java +++ b/common/device-side/bedstead/harrier/common/src/main/java/com/android/bedstead/harrier/policies/DefaultSmsApplication.java @@ -17,7 +17,6 @@ package com.android.bedstead.harrier.policies; import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_DEVICE_OWNER; -import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIED_BY_ORGANIZATION_OWNED_PROFILE_OWNER_PROFILE; import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.APPLIES_TO_OWN_USER; import static com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy.CANNOT_BE_APPLIED_BY_ROLE_HOLDER; @@ -29,7 +28,6 @@ import com.android.bedstead.harrier.annotations.enterprise.EnterprisePolicy; * <p>This is used by {@code DevicePolicyManager#setDefaultSmsApplication(ComponentName, String)}. */ @EnterprisePolicy(dpc = APPLIED_BY_DEVICE_OWNER - | APPLIED_BY_ORGANIZATION_OWNED_PROFILE_OWNER_PROFILE | APPLIES_TO_OWN_USER | CANNOT_BE_APPLIED_BY_ROLE_HOLDER) public final class DefaultSmsApplication { diff --git a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java index 79492ec86bb..1217a4fc237 100644 --- a/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java +++ b/common/device-side/bedstead/nene/src/main/java/com/android/bedstead/nene/packages/Package.java @@ -716,18 +716,20 @@ public final class Package { PackageManager userPackageManager = TestApis.context().androidContextAsUser(user).getPackageManager(); - + boolean shouldCheckPreviousProcess = runningProcess() != null; // In most cases this should work first time, however if a user restriction has been // recently removed we may need to retry - int previousPid = runningProcess().pid(); + + int previousPid = shouldCheckPreviousProcess ? runningProcess().pid() : -1; + Poll.forValue("Application flag", () -> { userActivityManager.forceStopPackage(mPackageName); - return userPackageManager.getPackageInfo(mPackageName, PackageManager.GET_META_DATA) - .applicationInfo.flags; - }) - .toMeet(flag ->(flag & FLAG_STOPPED) == FLAG_STOPPED - || previousPid != runningProcess().pid()) + return userPackageManager.getPackageInfo(mPackageName, + PackageManager.GET_META_DATA) + .applicationInfo.flags; + }).toMeet(flag -> !shouldCheckPreviousProcess || (flag & FLAG_STOPPED) == FLAG_STOPPED + || previousPid != runningProcess().pid()) .errorOnFail("Expected application flags to contain FLAG_STOPPED (" + FLAG_STOPPED + ")") .await(); diff --git a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java index 7998334ebb1..3d14dce9966 100644 --- a/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java +++ b/common/device-side/bedstead/nene/src/test/java/com/android/bedstead/nene/packages/PackageTest.java @@ -21,6 +21,7 @@ import static android.os.Build.VERSION_CODES.R; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assume.assumeNotNull; import static org.testng.Assert.assertThrows; import android.content.Context; @@ -364,6 +365,17 @@ public class PackageTest { } @Test + public void forceStop_whenNoRunningProcess_doesNotThrowException() { + final Package notRunningPackage = TestApis.packages().installedForUser().stream() + .filter(aPackage -> aPackage.runningProcess() == null) + .findFirst() + .get(); + assumeNotNull(notRunningPackage); + + notRunningPackage.forceStop(); + } + + @Test @EnsureHasSecondaryUser @RequireRunNotOnSecondaryUser public void installedOnUsers_doesNotIncludeUserWithoutPackageInstalled() throws Exception { diff --git a/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java b/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java index 05c9834fbd2..02badd90758 100644 --- a/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java +++ b/hostsidetests/appsecurity/test-apps/SettingsProviderInvalidKeyTestApp/src/com/android/cts/settingsproviderinvalidkeytestapp/SettingsProviderInvalidKeyTest.java @@ -27,11 +27,10 @@ import com.google.common.base.Strings; public final class SettingsProviderInvalidKeyTest extends AndroidTestCase { public void testLongKeysAreRejected() { final ContentResolver resolver = getContext().getContentResolver(); - IllegalStateException thrown = expectThrows(IllegalStateException.class, + expectThrows(Throwable.class, () -> Settings.System.putString(resolver, Strings.repeat("A", 65000), "")); - assertTrue(thrown.getMessage().contains("adding too many system settings")); // Repeated calls should throw as well - expectThrows(IllegalStateException.class, + expectThrows(Throwable.class, () -> Settings.System.putString(resolver, Strings.repeat("A", 65000), "")); } } diff --git a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java index cb120a0744f..184a41d5874 100644 --- a/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java +++ b/hostsidetests/car/src/android/car/cts/PowerPolicyHostTest.java @@ -51,12 +51,18 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { "am start -n " + ANDROID_CLIENT_ACTIVITY + " --es powerpolicy "; private static final int DEFAULT_TIMEOUT_SEC = 20; + private static final int BOOT_TIMEOUT_SEC = 60; private final PowerPolicyTestAnalyzer mTestAnalyzer = new PowerPolicyTestAnalyzer(this); @Before public void checkPrecondition() throws Exception { - checkDefaultPowerPolicySet("pre-condition"); + waitForPowerState(PowerPolicyConstants.CarPowerState.ON); + PowerPolicyTestHelper testHelper = new PowerPolicyTestHelper( + /* testcase= */ "pre-condition", /* step= */ "testStep1", + /* frameCpms= */ getCpmsFrameworkLayerStateInfo(), + /* sysCpms= */ getCpmsSystemLayerStateInfo(), /* silentMode= */ null); + checkDefaultPowerPolicySet(testHelper); } @After @@ -77,6 +83,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { teststep = "switch to forced silent"; enterForcedSilentMode(); testHelper = getTestHelper(testcase, 1, teststep); + // Test starts in ON state, state shouldn't change between test start and this check testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON); testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.NO_USER_INTERACTION); testHelper.checkSilentModeStatus(true); @@ -86,6 +93,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { teststep = "restore to normal mode"; leaveForcedSilentMode(); testHelper = getTestHelper(testcase, 2, teststep); + // Test starts in ON state, state shouldn't change between test start and this check testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON); testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON); testHelper.checkSilentModeStatus(false); @@ -116,6 +124,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { for (int i = 0; i < stepNames.length; i++) { triggerVhalPowerStateReq(vhalReqs[i], PowerPolicyConstants.ShutdownParam.NOT_USED); PowerPolicyTestHelper testHelper = getTestHelper(testcase, i + 1, stepNames[i]); + // power state shouldn't change testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON); testHelper.checkCurrentPolicy(PowerPolicyDef.IdSet.DEFAULT_ALL_ON); } @@ -130,6 +139,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { teststep = "check the inital power policies"; testHelper = getTestHelper(testcase, stepNo++, teststep); + // Test starts in ON state, state shouldn't change between test start and this check testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON); // save number of device power policies int registeredPoliciesNumber = testHelper.getNumberOfRegisteredPolicies(); @@ -205,8 +215,9 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { // need to find a way to move reboot device into AfterAll rebootDevice(); teststep = "reboot to clear added test power policies"; + // device was restarted, need to wait for ON state + waitForPowerState(PowerPolicyConstants.CarPowerState.ON); testHelper = getTestHelper(testcase, stepNo++, teststep); - testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON); testHelper.checkTotalRegisteredPolicies(registeredPoliciesNumber); } @@ -214,6 +225,18 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { return executeCommand("dumpsys activity %s", ANDROID_CLIENT_ACTIVITY); } + private void waitForPowerState(int powerState) throws Exception { + //need to wait for ON state + CommonTestUtils.waitUntil("timed out (" + BOOT_TIMEOUT_SEC + + "s) waiting for ON state", BOOT_TIMEOUT_SEC, + () -> { + CpmsFrameworkLayerStateInfo frameworkLayerStateInfo = + getCpmsFrameworkLayerStateInfo(); + return frameworkLayerStateInfo != null + && frameworkLayerStateInfo.getCurrentState() == powerState; + }); + } + private PowerPolicyTestHelper getTestHelper(String testcase, int stepNo, String stepName) throws Exception { CpmsSystemLayerStateInfo cpmsSystemInfo = getCpmsSystemLayerStateInfo(); @@ -359,11 +382,7 @@ public final class PowerPolicyHostTest extends CarHostJUnit4TestCase { } } - private void checkDefaultPowerPolicySet(String testcase) throws Exception { - String teststep = "check if the car power is on the ON state"; - PowerPolicyTestHelper testHelper = new PowerPolicyTestHelper(testcase, teststep, - getCpmsFrameworkLayerStateInfo(), getCpmsSystemLayerStateInfo(), null); - testHelper.checkCurrentState(PowerPolicyConstants.CarPowerState.ON); + private void checkDefaultPowerPolicySet(PowerPolicyTestHelper testHelper) throws Exception { testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.INITIAL_ALL_ON); testHelper.checkRegisteredPolicy(PowerPolicyDef.PolicySet.DEFAULT_ALL_ON); } diff --git a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java index 84d37ad407f..82790090dae 100644 --- a/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java +++ b/hostsidetests/car/src/android/car/cts/powerpolicy/PowerPolicyTestHelper.java @@ -93,31 +93,6 @@ public final class PowerPolicyTestHelper { assertWithMessage(REGISTERED_POLICY_ASSERT_MSG).that(status).isTrue(); } - public void checkRegisteredPolicy(String policyId) { - boolean status = false; - for (PowerPolicyDef def : mSystemCpms.getRegisteredPolicies()) { - if (def.getPolicyId().equals(policyId)) { - status = true; - break; - } - } - assertWithMessage(REGISTERED_POLICY_ASSERT_MSG).that(status).isTrue(); - } - - public void checkPendingPolicyId(String id) { - boolean status = false; - if (id == null) { - if (mSystemCpms.getPendingPolicyId() != null) { - CLog.w("PowerPolicyTestHelper expected non null pending policy"); - } else { - status = true; - } - } else { - status = id.equals(mSystemCpms.getPendingPolicyId()); - } - assertWithMessage(PENDING_POLICY_ASSERT_MSG).that(status).isTrue(); - } - public void checkTotalRegisteredPolicies(int totalNum) { assertWithMessage(TOTAL_REGISTERED_POLICIES_ASSERT_MSG) .that(mSystemCpms.getRegisteredPolicies().size()).isEqualTo(totalNum); @@ -138,11 +113,6 @@ public final class PowerPolicyTestHelper { .that(expected.equals(mFrameCpms.getCurrentPolicyGroupId())).isTrue(); } - public void checkPowerPolicyGroups(PowerPolicyGroups expected) { - assertWithMessage("checkPowerPolicyGroups") - .that(expected.equals(mFrameCpms.getPowerPolicyGroups())).isTrue(); - } - public int getNumberOfRegisteredPolicies() { return mSystemCpms.getTotalRegisteredPolicies(); } @@ -158,7 +128,7 @@ public final class PowerPolicyTestHelper { } } - public String getCurrentPolicyId() { - return mFrameCpms.getCurrentPolicyId(); + public int getCurrentPowerState() { + return mFrameCpms.getCurrentState(); } } diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java index b191de53ed1..a764358194d 100644 --- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java +++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnTest.java @@ -126,7 +126,7 @@ public class AlwaysOnVpnTest extends BaseDeviceAdminTest { VpnTestHelper.setAlwaysOnVpn( mContext, VPN_PACKAGE, /* lockdown */ false, /* allowlist */ false); - assertConnectivity(true, "VPN service not started, no lockdown"); + waitForConnectivity("VPN service not started, no lockdown"); assertNotNull(receiver.awaitForBroadcast(VPN_ON_START_TIMEOUT_MS)); VpnTestHelper.setAlwaysOnVpn( @@ -138,7 +138,7 @@ public class AlwaysOnVpnTest extends BaseDeviceAdminTest { VpnTestHelper.setAlwaysOnVpn( mContext, VPN_PACKAGE, /* lockdown */ true, /* allowlist */ true); - assertConnectivity(true, "VPN in lockdown, service not started, app allowlisted"); + waitForConnectivity("VPN in lockdown, service not started, app allowlisted"); assertNotNull(receiver.awaitForBroadcast(VPN_ON_START_TIMEOUT_MS)); VpnTestHelper.setAlwaysOnVpn( @@ -167,7 +167,7 @@ public class AlwaysOnVpnTest extends BaseDeviceAdminTest { VpnTestHelper.setAlwaysOnVpn( mContext, VPN_PACKAGE, /* lockdown */ true, /* allowlist */ true); - assertConnectivity(true, "VPN in lockdown, service not started, app allowlisted"); + waitForConnectivity("VPN in lockdown, service not started, app allowlisted"); assertNotNull(receiver.awaitForBroadcast(VPN_ON_START_TIMEOUT_MS)); // Make VPN workable again and restart. diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java index 6d699a83769..1fbcc9e290a 100644 --- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java +++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/SecurityLoggingTest.java @@ -28,6 +28,8 @@ import static android.app.admin.SecurityLog.LEVEL_WARNING; import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD; import static android.app.admin.SecurityLog.TAG_ADB_SHELL_INTERACTIVE; import static android.app.admin.SecurityLog.TAG_APP_PROCESS_START; +import static android.app.admin.SecurityLog.TAG_BLUETOOTH_CONNECTION; +import static android.app.admin.SecurityLog.TAG_BLUETOOTH_DISCONNECTION; import static android.app.admin.SecurityLog.TAG_CAMERA_POLICY_SET; import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_INSTALLED; import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_REMOVED; @@ -162,6 +164,8 @@ public class SecurityLoggingTest extends BaseDeviceAdminTest { .put(TAG_CAMERA_POLICY_SET, of(S, I, I, I)) .put(TAG_PASSWORD_COMPLEXITY_REQUIRED, of(S, I, I, I)) .put(TAG_PASSWORD_CHANGED, of(I, I)) + .put(TAG_BLUETOOTH_CONNECTION, of(S, I, S)) + .put(TAG_BLUETOOTH_DISCONNECTION, of(S, S)) .build(); private static final String GENERATED_KEY_ALIAS = "generated_key_alias"; diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java index 8dd4f7a8211..026e9753282 100644 --- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java +++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/StableUrisTest.java @@ -18,6 +18,7 @@ package android.scopedstorage.cts.device; import static android.app.AppOpsManager.permissionToOp; import static android.os.SystemProperties.getBoolean; +import static android.scopedstorage.cts.device.FileCreationUtils.createContentFromResource; import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid; import static android.scopedstorage.cts.lib.TestUtils.getPicturesDir; import static android.scopedstorage.cts.lib.TestUtils.readMaximumRowIdFromDatabaseAs; @@ -32,13 +33,15 @@ import static org.junit.Assume.assumeTrue; import android.Manifest; import android.app.Instrumentation; import android.content.ContentResolver; +import android.content.ContentValues; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; +import android.database.Cursor; import android.net.Uri; import android.os.Bundle; +import android.platform.test.annotations.FlakyTest; import android.provider.MediaStore; -import android.scopedstorage.cts.lib.TestUtils; import android.util.Log; import androidx.test.core.app.ApplicationProvider; @@ -47,6 +50,8 @@ import androidx.test.uiautomator.UiDevice; import com.android.cts.install.lib.TestApp; +import com.google.common.io.Files; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -60,6 +65,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; @RunWith(Parameterized.class) public final class StableUrisTest extends ScopedStorageBaseDeviceTest { @@ -71,9 +77,6 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { "android.scopedstorage.cts.testapp.filemanager", 1, false, "CtsScopedStorageTestAppFileManager.apk"); - private static final TestApp APP_NO_PERMS = new TestApp("TestAppB", - "android.scopedstorage.cts.testapp.B.noperms", 1, false, - "CtsScopedStorageTestAppB.apk"); private static final String OPSTR_MANAGE_EXTERNAL_STORAGE = permissionToOp(Manifest.permission.MANAGE_EXTERNAL_STORAGE); @@ -99,8 +102,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { mContentResolver = mContext.getContentResolver(); final Instrumentation inst = InstrumentationRegistry.getInstrumentation(); mDevice = UiDevice.getInstance(inst); - final int mMediaFilesCount = TestUtils.queryWithArgsAs(APP_FM, - MediaStore.Files.getContentUri(mVolumeName), null); + final int mMediaFilesCount = getMediaFilesCount(); Log.d(TAG, "Number of media files on device: " + mMediaFilesCount); assumeTrue("The number of media files is too large; Skipping the test as it " @@ -115,6 +117,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { } @Test + @FlakyTest public void testAttributesRestoration() throws Exception { Map<File, Uri> fileToUriMap = new HashMap<>(); @@ -122,7 +125,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { setFlag("persist.sys.fuse.backup.internal_db_backup", true); setFlag("persist.sys.fuse.backup.external_volume_backup", true); - fileToUriMap = createFilesAsTestApp(APP_NO_PERMS, 5); + fileToUriMap = createFiles(5); final Map<File, Bundle> fileToAttributesMapBeforeRestore = setAttributes(fileToUriMap); final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); @@ -135,7 +138,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { mDevice.executeShellCommand("pm clear " + getMediaProviderPackageName()); // Sleeping to make sure the db recovering is completed - Thread.sleep(20000); + Thread.sleep(40000); verifyAttributes(fileToUriMap, fileToAttributesMapBeforeRestore); } finally { @@ -160,7 +163,7 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { 0); allowAppOpsToUid(fmUid, OPSTR_MANAGE_EXTERNAL_STORAGE); - files.addAll(createFilesAsTestApp(APP_FM, 5).keySet()); + files.addAll(createFiles(5).keySet()); long maxRowIdOfInternalDbBeforeReset = readMaximumRowIdFromDatabaseAs(APP_FM, MediaStore.Files.getContentUri(MediaStore.VOLUME_INTERNAL)); @@ -208,18 +211,20 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { } } - private Map<File, Uri> createFilesAsTestApp(TestApp app, int count) throws Exception { + private Map<File, Uri> createFiles(int count) throws Exception { final Map<File, Uri> files = new HashMap<>(); + File buffer = new File(getPicturesDir(), + "Cts_buffer_" + System.currentTimeMillis() + ".jpg"); + createContentFromResource(R.raw.img_with_metadata, buffer); for (int i = 1; i <= count; i++) { final File file = new File(getPicturesDir(), "Cts_" + System.currentTimeMillis() + ".jpg"); - final boolean isFileCreated = !file.exists() - && TestUtils.createFileAs(app, file.getAbsolutePath()); - if (!isFileCreated) { + if (!file.createNewFile()) { throw new RuntimeException( "File was not created on path: " + file.getAbsolutePath()); } + Files.copy(buffer, file); final Uri uri = MediaStore.scanFile(mContentResolver, file); if (uri == null) { @@ -233,12 +238,12 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { } private void verifyAttributes(Map<File, Uri> fileToUriMap, - Map<File, Bundle> fileToAttributesMapBeforeRestore) throws Exception { + Map<File, Bundle> fileToAttributesMapBeforeRestore) { Log.d(TAG, "Started attributes verification after db restore"); for (Map.Entry<File, Uri> entry : fileToUriMap.entrySet()) { final Bundle originalAttributes = fileToAttributesMapBeforeRestore.get(entry.getKey()); - final Bundle attributesAfterRestore = TestUtils.queryMediaByUriAs(APP_NO_PERMS, - entry.getValue(), originalAttributes.keySet()); + final Bundle attributesAfterRestore = queryMedia(entry.getValue(), + originalAttributes.keySet()); assertWithMessage("Uri doesn't point to a media file after db restore") .that(attributesAfterRestore.isEmpty()).isFalse(); @@ -257,22 +262,23 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { Log.d(TAG, "Finished attributes verification after db restore"); } - private Map<File, Bundle> setAttributes(Map<File, Uri> fileToUriMap) throws Exception { + private Map<File, Bundle> setAttributes(Map<File, Uri> fileToUriMap) { final Map<File, Bundle> fileToAttributes = new HashMap<>(); int seed = 0; for (Map.Entry<File, Uri> entry : fileToUriMap.entrySet()) { final Bundle attributes = generateAttributes(seed++); + updateMedia(entry.getValue(), attributes); - TestUtils.updateMediaByUriAs(APP_NO_PERMS, entry.getValue(), attributes); - - final Bundle autoGeneratedAttributes = TestUtils.queryMediaByUriAs(APP_NO_PERMS, - entry.getValue(), new HashSet<>(Arrays.asList( + final Bundle autoGeneratedAttributes = queryMedia(entry.getValue(), + new HashSet<>(Arrays.asList( MediaStore.MediaColumns._ID, MediaStore.MediaColumns.DATE_EXPIRES, MediaStore.MediaColumns.OWNER_PACKAGE_NAME))); attributes.putAll(autoGeneratedAttributes); fileToAttributes.put(entry.getKey(), attributes); + Log.d(TAG, String.format("Attributes to verify - uri: %s, attributes: %s", + entry.getKey(), attributes)); } return fileToAttributes; } @@ -288,10 +294,41 @@ public final class StableUrisTest extends ScopedStorageBaseDeviceTest { return attributes; } - private void setFlag(String flagName, boolean value) throws Exception { - mDevice.executeShellCommand( + private Bundle queryMedia(Uri uri, Set<String> projection) { + try (Cursor c = mContentResolver.query(uri, + projection.toArray(new String[0]), null, null)) { + final Bundle result = new Bundle(); + c.moveToFirst(); + for (String column : projection) { + result.putString(column, c.getString(c.getColumnIndex(column))); + } + + return result; + } + } + + private int getMediaFilesCount() { + try (Cursor c = mContentResolver.query(MediaStore.Files.getContentUri(mVolumeName), + new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, + null, null)) { + return c.getCount(); + } + } + + private boolean updateMedia(Uri uri, Bundle attributes) { + final ContentValues values = new ContentValues(); + for (String key : attributes.keySet()) { + values.put(key, attributes.getString(key)); + } + return mContentResolver.update(uri, values, null, null) == 1; + } + + private static void setFlag(String flagName, boolean value) throws Exception { + final Instrumentation inst = InstrumentationRegistry.getInstrumentation(); + final UiDevice uiDevice = UiDevice.getInstance(inst); + uiDevice.executeShellCommand( "setprop " + flagName + " " + value); - final String newValue = mDevice.executeShellCommand("getprop " + flagName).trim(); + final String newValue = uiDevice.executeShellCommand("getprop " + flagName).trim(); assumeTrue("Not able to set flag: " + flagName, String.valueOf(value).equals(newValue)); diff --git a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java index fc7373c886d..051d23dd490 100644 --- a/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java +++ b/tests/autofillservice/src/android/autofillservice/cts/servicebehavior/PccFieldClassificationTest.java @@ -270,7 +270,7 @@ public class PccFieldClassificationTest extends sClassificationReplier.getNextFieldClassificationRequest(); // Set expected value - activity.expectPasswordAutoFill("sweet"); + activity.expectAutoFill("dude", "sweet"); // Click on password field to trigger autofill mUiBot.selectByRelativeId(ID_PASSWORD); @@ -295,19 +295,6 @@ public class PccFieldClassificationTest extends // Set expected value activity.expectAutoFill("dude"); - // Click on username field to see presentation from previous autofill request. - mUiBot.selectByRelativeId(ID_USERNAME); - mUiBot.waitForIdleSync(); - - - // Auto-fill it. - picker = mUiBot.assertDatasetsWithBorders( - null /* expectedHeader */, null /* expectedFooter */, DROPDOWN_PRESENTATION); - mUiBot.selectDataset(picker, DROPDOWN_PRESENTATION); - - // Check the results. - activity.assertAutoFilled(); - sClassificationReplier.assertNoUnhandledFieldClassificationRequests(); sReplier.assertNoUnhandledFillRequests(); } diff --git a/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java b/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java index be35647561f..92258354445 100644 --- a/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java +++ b/tests/backup/src/android/backup/cts/BackupRestoreEventLoggerTest.java @@ -18,8 +18,6 @@ package android.backup.cts; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assume.assumeTrue; - import android.Manifest; import android.app.UiAutomation; import android.app.backup.BackupManager; @@ -32,20 +30,16 @@ import android.content.Context; import android.os.Bundle; import android.platform.test.annotations.AppModeFull; -import androidx.test.runner.AndroidJUnit4; - import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import org.junit.runner.RunWith; - @AppModeFull -@RunWith(AndroidJUnit4.class) public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest { private static final String BACKUP_APP_PACKAGE = "android.cts.backup.backuprestoreeventloggerapp"; private static final int OPERATION_TIMEOUT_SECONDS = 30; + private static final int BACKUP_APP_RESTART_SLEEP_MS = 3_000; // Copied from LoggingFullBackupAgent.java @@ -69,8 +63,6 @@ public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest { public void setUp() throws Exception { super.setUp(); - assumeTrue(isBackupSupported()); - Context context = getInstrumentation().getTargetContext(); mUiAutomation = getInstrumentation().getUiAutomation(); @@ -93,6 +85,10 @@ public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest { } public void testBackupRestoreRoundTrip_logsSentToMonitor() throws Exception { + if (!isBackupSupported()) { + return; + } + // Ensure the app is not in stopped state. createTestFileOfSize(BACKUP_APP_PACKAGE, /* size */ 1); @@ -103,6 +99,9 @@ public class BackupRestoreEventLoggerTest extends BaseBackupCtsTest { boolean backupFinished = mOperationLatch.await(OPERATION_TIMEOUT_SECONDS, TimeUnit.SECONDS); + // Sleep to allow the app to be killed, so that this doesn't disrupt the restore operation + Thread.sleep(BACKUP_APP_RESTART_SLEEP_MS); + // Run a restore. mOperationLatch = new CountDownLatch(/* count */ 1); mRestoreSession = mBackupManager.beginRestoreSession(); diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java index 4dfee59f22a..3841b98eca4 100644 --- a/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java +++ b/tests/devicepolicy/src/android/devicepolicy/cts/DefaultSmsApplicationTest.java @@ -55,6 +55,7 @@ import com.android.bedstead.testapp.TestAppInstance; import org.junit.Before; import org.junit.ClassRule; +import org.junit.Ignore; import org.junit.Rule; import org.junit.runner.RunWith; @@ -221,6 +222,7 @@ public final class DefaultSmsApplicationTest { } } + @Ignore("b/300397938") @Postsubmit(reason = "new test") // We don't include non device admin states as passing a null admin is a NullPointerException @CannotSetPolicyTest(policy = { diff --git a/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java b/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java index b1de6181e86..4fe81680666 100644 --- a/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java +++ b/tests/devicepolicy/src/android/devicepolicy/cts/PermissionGrantTest.java @@ -1053,6 +1053,7 @@ public final class PermissionGrantTest { Settings.Global.ALLOW_WORK_PROFILE_TELEPHONY_FOR_NON_DPM_ROLE_HOLDERS, value = "1") @RequireRunOnWorkProfile(isOrganizationOwned = true) @Test + @Ignore("b/300397938") public void grantSmsPermission_orgOwnedDeviceWithManagedSubscriptionsPolicySet_granted() { RemoteDevicePolicyManager devicePolicyManager = sDeviceState.profileOwner( WORK_PROFILE).devicePolicyManager(); diff --git a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java index da85c3214a2..71b82ae1272 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/BlurTests.java @@ -54,7 +54,6 @@ import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.mockito.Mockito; -import java.util.Optional; import java.util.function.Consumer; @Presubmit @@ -95,12 +94,8 @@ public class BlurTests extends WindowManagerTestBase { WindowManagerState.WindowState windowState = mWmState.getWindowState(cn); WindowManagerState.Activity act = mWmState.getActivity(cn); mBackgroundActivityBounds = act.getBounds(); - Optional<WindowManagerState.InsetsSource> captionInsetsOptional = - windowState.getMergedLocalInsetsSources().stream().filter( - insets -> insets.isCaptionBar()).findFirst(); - captionInsetsOptional.ifPresent(captionInsets -> { - captionInsets.insetGivenFrame(mBackgroundActivityBounds); - }); + insetGivenFrame(windowState, WindowManagerState.InsetsSource::isCaptionBar, + mBackgroundActivityBounds); // Wait for the first frame *after* the splash screen is removed to take screenshots. // We don't currently have a definite event / callback for this. diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java index 6a556288f2e..b03c52b58c4 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepScreenOnTests.java @@ -47,10 +47,12 @@ public class KeepScreenOnTests extends MultiDisplayTestBase { private int mInitialStayOnWhilePluggedInSetting; private PowerManager mPowerManager; private ContentResolver mContentResolver; + private boolean mIsTv; @Before public void setUp() throws Exception { super.setUp(); + mIsTv = mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK); mContentResolver = mContext.getContentResolver(); mInitialDisplayTimeout = Settings.System.getString(mContentResolver, SCREEN_OFF_TIMEOUT); @@ -86,6 +88,8 @@ public class KeepScreenOnTests extends MultiDisplayTestBase { @ApiTest(apis = "android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON") @Test public void testKeepScreenOn_activityNotForeground_screenTurnsOff() { + assumeFalse("TVs may start screen saver instead of turning screen off - skipping test", + mIsTv); setScreenOffTimeoutMs("500"); launchActivity(TURN_SCREEN_ON_ACTIVITY); diff --git a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java index e3fbf67c952..bb01bbbe86f 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/PinnedStackTests.java @@ -296,12 +296,14 @@ public class PinnedStackTests extends ActivityManagerTestBase { @Test public void testEnterPipToOtherOrientation() { + assumeTrue("Skipping test: no orientation request support", supportsOrientationRequest()); // Launch a portrait only app on the fullscreen stack launchActivity(TEST_ACTIVITY, extraString(EXTRA_FIXED_ORIENTATION, String.valueOf(SCREEN_ORIENTATION_PORTRAIT))); // Launch the PiP activity fixed as landscape launchActivity(PIP_ACTIVITY, extraString(EXTRA_PIP_ORIENTATION, String.valueOf(SCREEN_ORIENTATION_LANDSCAPE))); + mWmState.waitForActivityOrientation(PIP_ACTIVITY, Configuration.ORIENTATION_LANDSCAPE); // Enter PiP, and assert that the PiP is within bounds now that the device is back in // portrait mBroadcastActionTrigger.doAction(ACTION_ENTER_PIP); diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java index d943e39c876..929a42f0482 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/SplashscreenTests.java @@ -217,6 +217,10 @@ public class SplashscreenTests extends ActivityManagerTestBase { } else { appBounds = new Rect(startingWindow.getFrame()); } + + insetGivenFrame(startingWindow, WindowManagerState.InsetsSource::isCaptionBar, + appBounds); + assertFalse("Couldn't find splash screen bounds. Impossible to assert the colors", appBounds.isEmpty()); 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 8ed33a692f8..e17c7ec826d 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/SurfaceControlViewHostTests.java @@ -64,6 +64,7 @@ import android.server.wm.shared.ICrossProcessSurfaceControlViewHostTestService; import android.util.ArrayMap; import android.view.Gravity; import android.view.MotionEvent; +import android.view.SurfaceControl; import android.view.SurfaceControlViewHost; import android.view.SurfaceHolder; import android.view.SurfaceView; @@ -787,13 +788,23 @@ public class SurfaceControlViewHostTests extends ActivityManagerTestBase impleme mVr.setView(mEmbeddedView, mEmbeddedViewWidth, mEmbeddedViewHeight); }); - surfaceCreated.await(); + assertTrue("Failed to wait for SurfaceView created", + surfaceCreated.await(5, TimeUnit.SECONDS)); // Make a copy of the SurfacePackage and release the original package. SurfacePackage surfacePackage = mVr.getSurfacePackage(); SurfacePackage copy = new SurfacePackage(surfacePackage); surfacePackage.release(); - mSurfaceView.setChildSurfacePackage(copy); + + CountDownLatch surfacePackageReparented = new CountDownLatch(1); + mActivityRule.runOnUiThread(() -> { + mSurfaceView.setChildSurfacePackage(copy); + SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + t.addTransactionCommittedListener(Runnable::run, surfacePackageReparented::countDown); + mSurfaceView.getRootSurfaceControl().applyTransactionOnDraw(t); + }); + assertTrue("Failed to wait for surface package to get reparented", + surfacePackageReparented.await(5, TimeUnit.SECONDS)); mInstrumentation.waitForIdleSync(); waitUntilEmbeddedViewDrawn(); diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java index 29e9dc3ba9f..202d2b09b1f 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationImeTests.java @@ -108,7 +108,7 @@ public class WindowInsetsAnimationImeTests extends WindowInsetsAnimationTestBase getInstrumentation().runOnMainSync( () -> mRootView.getWindowInsetsController().show(ime())); - waitForOrFail("Waiting until IME animation starts", () -> callback.imeAnim != null); + waitForOrFail("Waiting until IME animation starts", () -> callback.imeAnimStarted); waitForOrFail("Waiting until animation done", () -> callback.runningAnims.isEmpty()); WindowInsets after = mActivity.mLastWindowInsets; diff --git a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java index a403eb7dc60..47ef2cef998 100644 --- a/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java +++ b/tests/framework/base/windowmanager/src/android/server/wm/WindowInsetsAnimationTestBase.java @@ -53,7 +53,6 @@ import com.android.compatibility.common.util.OverrideAnimationScaleRule; import org.junit.Assert; import org.junit.Rule; -import org.junit.rules.TestRule; import org.mockito.InOrder; import java.util.ArrayList; @@ -233,6 +232,7 @@ public class WindowInsetsAnimationTestBase extends WindowManagerTestBase { WindowInsetsAnimation statusBarAnim; WindowInsetsAnimation navBarAnim; WindowInsetsAnimation imeAnim; + volatile boolean imeAnimStarted; volatile boolean animationDone; final ArrayList<AnimationStep> statusAnimSteps = new ArrayList<>(); final ArrayList<AnimationStep> navAnimSteps = new ArrayList<>(); @@ -264,6 +264,9 @@ public class WindowInsetsAnimationTestBase extends WindowManagerTestBase { startRunnable.run(); } runningAnims.add(animation); + if (animation.equals(imeAnim)) { + imeAnimStarted = true; + } return bounds; } 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 5f6215d9bc4..7d8098210a1 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 @@ -207,12 +207,14 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BooleanSupplier; import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -3459,4 +3461,19 @@ public abstract class ActivityManagerTestBase { mWmState.computeState(new WaitForValidActivityState(activityName)); return mWmState.getActivity(activityName); } + + /** + * Inset given frame if the insets source exist. + * + * @param windowState The window which have the insets source. + * @param predicate Inset source predicate. + * @param inOutBounds In/out the given frame from the inset source. + */ + public static void insetGivenFrame(WindowManagerState.WindowState windowState, + Predicate<WindowManagerState.InsetsSource> predicate, Rect inOutBounds) { + Optional<WindowManagerState.InsetsSource> insetsOptional = + windowState.getMergedLocalInsetsSources().stream().filter( + predicate).findFirst(); + insetsOptional.ifPresent(insets -> insets.insetGivenFrame(inOutBounds)); + } } diff --git a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java index 21d945faaf0..4ef76ae632c 100644 --- a/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java +++ b/tests/inputmethod/src/android/view/inputmethod/cts/KeyboardVisibilityControlTest.java @@ -98,7 +98,6 @@ import android.widget.TextView; import android.window.OnBackInvokedDispatcher; import androidx.annotation.ColorInt; -import androidx.annotation.IntRange; import androidx.annotation.NonNull; import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; @@ -1309,11 +1308,18 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase { */ @Test public void testRotateScreenWithKeyboardShownImplicitly() throws Exception { + // Test only when both portrait and landscape mode are supported. + final PackageManager pm = mInstrumentation.getTargetContext().getPackageManager(); + assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT)); + assumeTrue(pm.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE)); + final InputMethodManager imm = mInstrumentation .getTargetContext().getSystemService(InputMethodManager.class); // Disable auto-rotate screen and set the screen orientation to portrait mode. setAutoRotateScreen(false); - rotateScreen(0); + final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation); + uiDevice.setOrientationPortrait(); + mInstrumentation.waitForIdleSync(); // Set FullscreenModePolicy as OS_DEFAULT to call the original // InputMethodService#onEvaluateFullscreenMode() @@ -1345,14 +1351,9 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase { View.VISIBLE, TIMEOUT); expectImeVisible(TIMEOUT); - // Rotate screen right - rotateScreen(3); - expectImeVisible(TIMEOUT); - assertTrue("IME should be in fullscreen mode", - getOnMainSync(() -> imm.isFullscreenMode())); - - // Rotate screen left - rotateScreen(1); + // Rotate screen to landscape. + uiDevice.setOrientationLandscape(); + mInstrumentation.waitForIdleSync(); expectImeVisible(TIMEOUT); assertTrue("IME should be in fullscreen mode", getOnMainSync(() -> imm.isFullscreenMode())); @@ -1666,17 +1667,6 @@ public class KeyboardVisibilityControlTest extends EndToEndImeTestBase { } } - private void rotateScreen(@IntRange(from = 0, to = 3) int rotation) { - try { - final Instrumentation instrumentation = mInstrumentation; - SystemUtil.runShellCommand(instrumentation, "settings put system user_rotation " - + rotation); - instrumentation.waitForIdleSync(); - } catch (IOException io) { - fail("Couldn't rotate screen"); - } - } - private static ImeSettings.Builder getFloatingImeSettings(@ColorInt int navigationBarColor) { final ImeSettings.Builder builder = new ImeSettings.Builder(); builder.setWindowFlags(0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); diff --git a/tests/media/AndroidTest.xml b/tests/media/AndroidTest.xml index afb4861c438..9056d6dcf12 100644 --- a/tests/media/AndroidTest.xml +++ b/tests/media/AndroidTest.xml @@ -35,7 +35,7 @@ </target_preparer> <target_preparer class="com.android.compatibility.common.tradefed.targetprep.MediaPreparer"> <option name="push-all" value="true" /> - <option name="media-folder-name" value="CtsMediaV2TestCases-3.5" /> + <option name="media-folder-name" value="CtsMediaV2TestCases-3.6" /> <option name="dynamic-config-module" value="CtsMediaV2TestCases" /> </target_preparer> <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> diff --git a/tests/media/DynamicConfig.xml b/tests/media/DynamicConfig.xml index e3643d73789..3ab84f67812 100644 --- a/tests/media/DynamicConfig.xml +++ b/tests/media/DynamicConfig.xml @@ -1,5 +1,5 @@ <dynamicConfig> <entry key="media_files_url"> - <value>https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.5.zip</value> + <value>https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.6.zip</value> </entry> </dynamicConfig> diff --git a/tests/media/README.md b/tests/media/README.md index 5601ad3d379..fc25fe57b2a 100644 --- a/tests/media/README.md +++ b/tests/media/README.md @@ -3,7 +3,7 @@ Current folder comprises of files necessary for testing media extractor, media m The aim of these tests is not solely to verify the CDD requirements but also to test components, their plugins and their interactions with media framework. -The test vectors used by the test suite is available at [link](https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.5.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory. +The test vectors used by the test suite is available at [link](https://dl.google.com/android/xts/cts/tests/media/CtsMediaV2TestCases-3.6.zip) and is downloaded automatically while running tests. Manual installation of these can be done using copy_media.sh script in this directory. All Big Buck Bunny(bbb) test vectors are of 8-bit format. They are downloaded from [link](https://peach.blender.org/download/) and resampled according to the test requirements. All Cosmos Laundromat(cosmat) test vectors are of 10-bit format. They are downloaded from [link](https://media.xiph.org/) and resampled according to the test requirements. diff --git a/tests/media/copy_media.sh b/tests/media/copy_media.sh index b0850ad64d1..c402f156e7d 100755 --- a/tests/media/copy_media.sh +++ b/tests/media/copy_media.sh @@ -17,7 +17,7 @@ ## script to install mediav2 test files manually adbOptions=" " -resLabel=CtsMediaV2TestCases-3.5 +resLabel=CtsMediaV2TestCases-3.6 srcDir="/tmp/$resLabel" tgtDir="/sdcard/test" usage="Usage: $0 [-h] [-s serial]" diff --git a/tests/media/src/android/mediav2/cts/WorkDir.java b/tests/media/src/android/mediav2/cts/WorkDir.java index de9f200d7a8..9584c741198 100644 --- a/tests/media/src/android/mediav2/cts/WorkDir.java +++ b/tests/media/src/android/mediav2/cts/WorkDir.java @@ -24,6 +24,6 @@ import android.mediav2.common.cts.WorkDirBase; */ class WorkDir extends WorkDirBase { static final String getMediaDirString() { - return getMediaDirString("CtsMediaV2TestCases-3.5"); + return getMediaDirString("CtsMediaV2TestCases-3.6"); } } diff --git a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java index a283ec38c46..cd5f0f33af7 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/PerformanceClassEvaluator.java @@ -369,16 +369,18 @@ public class PerformanceClassEvaluator { * ms or less for a 1080p or smaller video encoding session for all hardware video * encoders when under load. Load here is defined as a concurrent 1080p to 720p * video-only transcoding session using hardware video codecs together with the 1080p - * audio-video recording initialization. + * audio-video recording initialization. For Dolby vision codec, the codec initialization + * latency MUST be 50 ms or less. */ - public static CodecInitLatencyRequirement createR5_1__H_1_7() { + public static CodecInitLatencyRequirement createR5_1__H_1_7(String mediaType) { + long latency = mediaType.equals(MediaFormat.MIMETYPE_VIDEO_DOLBY_VISION) ? 50L : 40L; RequiredMeasurement<Long> codec_init_latency = RequiredMeasurement.<Long>builder().setId(RequirementConstants.CODEC_INIT_LATENCY) .setPredicate(RequirementConstants.LONG_LTE) .addRequiredValue(Build.VERSION_CODES.R, 65L) .addRequiredValue(Build.VERSION_CODES.S, 50L) - .addRequiredValue(Build.VERSION_CODES.TIRAMISU, 40L) - .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, 40L) + .addRequiredValue(Build.VERSION_CODES.TIRAMISU, latency) + .addRequiredValue(Build.VERSION_CODES.UPSIDE_DOWN_CAKE, latency) .build(); return new CodecInitLatencyRequirement(RequirementConstants.R5_1__H_1_7, @@ -2206,8 +2208,8 @@ public class PerformanceClassEvaluator { return this.addRequirement(ConcurrentCodecRequirement.createR5_1__H_1_6_4k()); } - public CodecInitLatencyRequirement addR5_1__H_1_7() { - return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7()); + public CodecInitLatencyRequirement addR5_1__H_1_7(String mediaType) { + return this.addRequirement(CodecInitLatencyRequirement.createR5_1__H_1_7(mediaType)); } public CodecInitLatencyRequirement addR5_1__H_1_8() { 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 258b30f7cc9..55955913b96 100644 --- a/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java +++ b/tests/mediapc/common/src/android/mediapc/cts/common/Utils.java @@ -123,7 +123,9 @@ public class Utils { final double diagonalInch = Math.sqrt(widthInch * widthInch + heightInch * heightInch); final double maxDiagonalPixels = Math.sqrt(maxWidthPixels * maxWidthPixels + maxHeightPixels * maxHeightPixels); - DISPLAY_DPI = (int) (maxDiagonalPixels / diagonalInch); + // Use max of computed dpi and advertised dpi as these values differ in some devices. + DISPLAY_DPI = Math.max((int) (maxDiagonalPixels / diagonalInch), + context.getResources().getConfiguration().densityDpi); ActivityManager activityManager = context.getSystemService(ActivityManager.class); ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo(); diff --git a/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java b/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java index 6ae69665ebc..e668ddb310f 100644 --- a/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java +++ b/tests/mediapc/src/android/mediapc/cts/AudioPlaybackLoad.java @@ -126,13 +126,7 @@ class AudioPlaybackLoad extends CodecDecoderTestBase { } @Override - void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { - if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - mSawOutputEOS = true; - } - if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { - mOutputCount++; - } + void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) { final ByteBuffer buffer = mCodec.getOutputBuffer(bufferIndex); final byte[] audio = new byte[info.size]; buffer.clear(); // prepare buffer for reading diff --git a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java index 4ff5f6b71fc..020ddeb0905 100644 --- a/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java +++ b/tests/mediapc/src/android/mediapc/cts/CodecInitializationLatencyTest.java @@ -350,8 +350,8 @@ public class CodecInitializationLatencyTest { PerformanceClassEvaluator pce = new PerformanceClassEvaluator(this.mTestName); PerformanceClassEvaluator.CodecInitLatencyRequirement r5_1__H_1_Latency = - isEncoder ? isAudio ? pce.addR5_1__H_1_8() : pce.addR5_1__H_1_7() - : isAudio ? pce.addR5_1__H_1_13() : pce.addR5_1__H_1_12(); + isEncoder ? isAudio ? pce.addR5_1__H_1_8() : pce.addR5_1__H_1_7(mMime) + : isAudio ? pce.addR5_1__H_1_13() : pce.addR5_1__H_1_12(); r5_1__H_1_Latency.setCodecInitLatencyMs(initializationLatency); @@ -533,6 +533,13 @@ public class CodecInitializationLatencyTest { public long calculateInitLatency() throws Exception { MediaCodec.BufferInfo outInfo = new MediaCodec.BufferInfo(); MediaFormat format = setUpSource(mTestFile); + ArrayList<MediaFormat> formats = new ArrayList<>(); + formats.add(format); + // If the decoder doesn't support the formats, then return Integer.MAX_VALUE to + // indicate that all decode was not successful + if (!areFormatsSupported(mDecoderName, formats)) { + return Integer.MAX_VALUE; + } long enqueueTimeStamp = 0; long dequeueTimeStamp = 0; long baseTimeStamp = SystemClock.elapsedRealtimeNanos(); diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java index 29ed734acb9..53dbce6ebd6 100644 --- a/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java +++ b/tests/mediapc/src/android/mediapc/cts/CodecTestBase.java @@ -57,6 +57,7 @@ import java.util.concurrent.Callable; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.Consumer; class CodecAsyncHandler extends MediaCodec.Callback { private static final String LOG_TAG = CodecAsyncHandler.class.getSimpleName(); @@ -214,7 +215,49 @@ abstract class CodecTestBase { abstract void enqueueInput(int bufferIndex) throws IOException; - abstract void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info); + // Callback for each time the output count changes. + // This can be used to measure codec performance. + Consumer<Integer> mOutputCountListener; + + // must not be called during doWork + void setOutputCountListener(Consumer<Integer> listener) { + mOutputCountListener = listener; + } + + /** + * Called to handle a dequeued output buffer. + * + * We account for EOS and the number of full output frames. + */ + protected void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { + if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { + mSawOutputEOS = true; + } + int outputCount = mOutputCount; + // handle output count prior to releasing the buffer as that can take time + if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { + mOutputCount++; + if (mOutputCountListener != null) { + mOutputCountListener.accept(mOutputCount); + } + } + releaseOutput(outputCount, bufferIndex, info); + } + + /** + * Called to handle releasing an output buffer. + */ + abstract void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info); + + /** + * Called to handle releasing an output buffer. + * + * @param outputCount total count of full output frames prior to + * this point (not including this buffer). + */ + protected void releaseOutput(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) { + releaseOutput(bufferIndex, info); + } void configureCodec(MediaFormat format, boolean isAsync, boolean signalEOSWithLastFrame, boolean isEncoder) throws Exception { @@ -627,13 +670,7 @@ class CodecDecoderTestBase extends CodecTestBase { } } - void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { - if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - mSawOutputEOS = true; - } - if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { - mOutputCount++; - } + void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) { mCodec.releaseOutputBuffer(bufferIndex, false); } } @@ -819,13 +856,7 @@ class CodecEncoderTestBase extends CodecTestBase { } } - void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { - if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - mSawOutputEOS = true; - } - if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { - mOutputCount++; - } + void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) { mCodec.releaseOutputBuffer(bufferIndex, false); } } @@ -844,6 +875,9 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> { String.format("%s?video_id=%s&provider=%s", WIDEVINE_LICENSE_SERVER_URL, "GTS_HW_SECURE_ALL", PROVIDER); final boolean mIsAsync; + private int mInitialFramesToIgnoreCount = 1; + private long mStartTimeMillis = 0; + private long mEndTimeMillis = 0; Decode(String mime, String testFile, String decoderName, boolean isAsync) { this(mime, testFile,decoderName, isAsync, false); @@ -857,8 +891,29 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> { mSecureMode = secureMode; } + public void setInitialFramesToIgnoreCount(int count) { + mInitialFramesToIgnoreCount = count; + } + + // measure throughput at the output port + private void onOutputCountListener(int count) { + // keep the timestamp of the last output frame + mEndTimeMillis = System.currentTimeMillis(); + + // don't count the time for the initial frames that are ignored + if (count == mInitialFramesToIgnoreCount) { + mStartTimeMillis = mEndTimeMillis; + } + } + public Double doDecode() throws Exception { MediaFormat format = setUpSource(mTestFile); + ArrayList<MediaFormat> formats = new ArrayList<>(); + formats.add(format); + // If the decoder doesn't support the formats, then return 0 to indicate that decode failed + if (!areFormatsSupported(mDecoderName, formats)) { + return (Double) 0.0; + } mCodec = MediaCodec.createByCodecName(mDecoderName); mExtractor.seekTo(0, MediaExtractor.SEEK_TO_CLOSEST_SYNC); configureCodec(format, mIsAsync, false, false, mServerURL); @@ -870,11 +925,14 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> { mCodec.release(); return (Double) 0.0; } - long start = System.currentTimeMillis(); + + // capture timestamps at receipt of output buffers + setOutputCountListener(i -> onOutputCountListener(i)); + doWork(Integer.MAX_VALUE); queueEOS(); waitForAllOutputs(); - long end = System.currentTimeMillis(); + mCodec.stop(); mCodec.release(); mExtractor.release(); @@ -884,7 +942,8 @@ class Decode extends CodecDecoderTestBase implements Callable<Double> { if (mDrm != null) { mDrm.close(); } - double fps = mOutputCount / ((end - start) / 1000.0); + double fps = (mOutputCount - mInitialFramesToIgnoreCount) / + ((mEndTimeMillis - mStartTimeMillis) / 1000.0); Log.d(LOG_TAG, "Decode Mime: " + mMime + " Decoder: " + mDecoderName + " Achieved fps: " + fps); return fps; @@ -908,13 +967,7 @@ class DecodeToSurface extends Decode { mSurface = surface; } - void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { - if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - mSawOutputEOS = true; - } - if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { - mOutputCount++; - } + void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) { mCodec.releaseOutputBuffer(bufferIndex, true); } } @@ -930,6 +983,10 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> { private final boolean mIsAsync; private final int mBitrate; + private int mInitialFramesToIgnoreCount = 1; + private long mStartTimeMillis = 0; + private long mEndTimeMillis = 0; + Encode(String mime, String encoderName, boolean isAsync, int height, int width, int frameRate, int bitrate) { super(mime); @@ -941,6 +998,21 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> { mWidth = width; } + public void setInitialFramesToIgnoreCount(int count) { + mInitialFramesToIgnoreCount = count; + } + + // measure throughput at the output port + private void onOutputCountListener(int count) { + // keep the timestamp of the last output frame + mEndTimeMillis = System.currentTimeMillis(); + + // don't count the time for the initial frames that are ignored + if (count == mInitialFramesToIgnoreCount) { + mStartTimeMillis = mEndTimeMillis; + } + } + private MediaFormat setUpFormat() { MediaFormat format = new MediaFormat(); format.setString(MediaFormat.KEY_MIME, mMime); @@ -964,14 +1036,18 @@ class Encode extends CodecEncoderTestBase implements Callable<Double> { mCodec = MediaCodec.createByCodecName(mEncoderName); configureCodec(format, mIsAsync, false, true); mCodec.start(); - long start = System.currentTimeMillis(); + + // capture timestamps at receipt of output buffers + setOutputCountListener(i -> onOutputCountListener(i)); + doWork(Integer.MAX_VALUE); queueEOS(); waitForAllOutputs(); - long end = System.currentTimeMillis(); + mCodec.stop(); mCodec.release(); - double fps = mOutputCount / ((end - start) / 1000.0); + double fps = (mOutputCount - mInitialFramesToIgnoreCount) / + ((mEndTimeMillis - mStartTimeMillis) / 1000.0); Log.d(LOG_TAG, "Encode Mime: " + mMime + " Encoder: " + mEncoderName + " Achieved fps: " + fps); return fps; diff --git a/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java b/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java index 37267b275d3..cfd1b5d9749 100644 --- a/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java +++ b/tests/mediapc/src/android/mediapc/cts/CodecTranscoderTestBase.java @@ -17,6 +17,7 @@ package android.mediapc.cts; import static android.mediav2.common.cts.CodecTestBase.PROFILE_HLG_MAP; +import static android.mediapc.cts.CodecTestBase.areFormatsSupported; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -31,6 +32,7 @@ import android.view.Surface; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Objects; import java.util.concurrent.Callable; @@ -383,6 +385,13 @@ class Transcode extends CodecTranscoderTestBase implements Callable<Double> { public Double doTranscode() throws Exception { MediaFormat decoderFormat = setUpSource(mTestFile); + ArrayList<MediaFormat> formats = new ArrayList<>(); + formats.add(decoderFormat); + // If the decoder doesn't support the formats, then return 0 to indicate that decode failed + if (!areFormatsSupported(mDecoderName, formats)) { + return (Double) 0.0; + } + mDecoder = MediaCodec.createByCodecName(mDecoderName); MediaFormat encoderFormat = setUpEncoderFormat(decoderFormat); mEncoder = MediaCodec.createByCodecName(mEncoderName); diff --git a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java index aad1c621f97..9fffb349568 100644 --- a/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java +++ b/tests/mediapc/src/android/mediapc/cts/FrameDropTestBase.java @@ -95,7 +95,8 @@ public class FrameDropTestBase { m2160p60FpsTestFiles.put(HEVC, "bbb_3840x2160_18mbps_60fps_hevc.mkv"); m2160p60FpsTestFiles.put(VP8, "bbb_3840x2160_24mbps_60fps_vp8.webm"); m2160p60FpsTestFiles.put(VP9, "bbb_3840x2160_18mbps_60fps_vp9.webm"); - m2160p60FpsTestFiles.put(AV1, "bbb_3840x2160_18mbps_60fps_av1.mp4"); + // Limit AV1 4k tests to 1080p as per PC14 requirements + m2160p60FpsTestFiles.put(AV1, "bbb_1920x1080_6mbps_60fps_av1.mp4"); m540p30FpsTestFiles.put(AVC, "bbb_960x540_2mbps_30fps_avc.mp4"); m540p30FpsTestFiles.put(HEVC, "bbb_960x540_2mbps_30fps_hevc.mp4"); diff --git a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java index 393d9044b76..c7d100e736b 100644 --- a/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java +++ b/tests/mediapc/src/android/mediapc/cts/PlaybackFrameDrop.java @@ -27,7 +27,6 @@ import android.view.Surface; import java.io.File; import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.LinkedList; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -40,7 +39,7 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase { private static final int AV1_INITIAL_DELAY = 8; private final String mDecoderName; private final String[] mTestFiles; - private final int mEachFrameTimeIntervalUs; + private final long mEachFrameTimeIntervalUs; private final boolean mIsAsync; private int mFrameDropCount; @@ -60,33 +59,48 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase { private Thread mThread; class OutputHandler implements Runnable { - private final LinkedList<Pair<Integer, MediaCodec.BufferInfo>> mQueue = new LinkedList<>(); + class BufferData { + public final int frameCount; // total count of full frames up to this point + public final int bufferIndex; + public final MediaCodec.BufferInfo info; + + public BufferData(int frameCount, int bufferIndex, MediaCodec.BufferInfo info) { + this.frameCount = frameCount; + this.bufferIndex = bufferIndex; + this.info = info; + } + }; + + private final ArrayList<BufferData> mQueue = new ArrayList<>(); private boolean mStop = false; private final Lock mLock = new ReentrantLock(); private final Condition mCondition = mLock.newCondition(); - private Pair<Integer, MediaCodec.BufferInfo> getOutput() throws InterruptedException { - Pair<Integer, MediaCodec.BufferInfo> element = null; + private BufferData getOutput() throws InterruptedException { + BufferData output = null; mLock.lock(); - while (!mStop) { - if (mQueue.isEmpty()) { - mCondition.await(); - } else { - element = mQueue.remove(0); - break; + try { + while (!mStop) { + if (mQueue.isEmpty()) { + mCondition.await(); + } else { + output = mQueue.remove(0); + break; + } } + } finally { + mLock.unlock(); } - mLock.unlock(); - return element; + return output; } @Override public void run() { try { while (true) { - Pair<Integer, MediaCodec.BufferInfo> element = getOutput(); - if (element != null) { - releaseOutput(element.first, element.second); + BufferData output = getOutput(); + if (output != null) { + delayedReleaseOutput(output.frameCount, output.bufferIndex, output.info); } else { break; } @@ -96,18 +110,24 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase { } } - public void add(int bufferIndex, MediaCodec.BufferInfo info) { + public void add(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) { mLock.lock(); - mQueue.add(new Pair<>(bufferIndex, info)); - mCondition.signal(); - mLock.unlock(); + try { + mQueue.add(new BufferData(outputCount, bufferIndex, info)); + mCondition.signal(); + } finally { + mLock.unlock(); + } } public void stop() throws Exception { mLock.lock(); - mStop = true; - mCondition.signal(); - mLock.unlock(); + try { + mStop = true; + mCondition.signal(); + } finally { + mLock.unlock(); + } } } @@ -260,27 +280,25 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase { } @Override - void dequeueOutput(int bufferIndex, MediaCodec.BufferInfo info) { - mOutputHandler.add(bufferIndex, info); - if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) { - mSawOutputEOS = true; - } + protected void releaseOutput(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) { + mOutputHandler.add(outputCount, bufferIndex, info); } - void releaseOutput(int bufferIndex, MediaCodec.BufferInfo info) { + + void delayedReleaseOutput(int outputCount, int bufferIndex, MediaCodec.BufferInfo info) { // We will limit the playback to 60 fps using the system timestamps. long nowUs = System.nanoTime() / 1000; - if (mOutputCount == 0) { + if (outputCount == 0) { // delay rendering the first frame by the specific delay mRenderStartTimeUs = nowUs + mInitialDelay * mEachFrameTimeIntervalUs; } - if (nowUs > getRenderTimeUs(mOutputCount + 1)) { + if (nowUs > getRenderTimeUs(outputCount + 1)) { // If the current sample timeStamp is greater than the actual presentation timeStamp // of the next sample, we will consider it as a frame drop and don't render. mFrameDropCount++; mCodec.releaseOutputBuffer(bufferIndex, false); - } else if (nowUs > getRenderTimeUs(mOutputCount)) { + } else if (nowUs > getRenderTimeUs(outputCount)) { // If the current sample timeStamp is greater than the actual presentation timeStamp // of the current sample, we can render it. mCodec.releaseOutputBuffer(bufferIndex, true); @@ -289,9 +307,9 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase { // We are okay with directly rendering the sample if we are less by not more than // half of one sample duration. Otherwise we sleep for how much more we are less // than the half of one sample duration. - if ((getRenderTimeUs(mOutputCount) - nowUs) > (mEachFrameTimeIntervalUs / 2)) { + if ((getRenderTimeUs(outputCount) - nowUs) > (mEachFrameTimeIntervalUs / 2)) { try { - Thread.sleep(((getRenderTimeUs(mOutputCount) - nowUs) - + Thread.sleep(((getRenderTimeUs(outputCount) - nowUs) - (mEachFrameTimeIntervalUs / 2)) / 1000); } catch (InterruptedException e) { // Do nothing. @@ -299,8 +317,5 @@ public class PlaybackFrameDrop extends CodecDecoderTestBase { } mCodec.releaseOutputBuffer(bufferIndex, true); } - if (info.size > 0 && (info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) == 0) { - mOutputCount++; - } } } diff --git a/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java b/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java index 4117a5c4d36..2a0403ee4d4 100644 --- a/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java +++ b/tests/tests/nfc/src/android/nfc/cts/NfcAntennaLocationApiTest.java @@ -64,18 +64,7 @@ public class NfcAntennaLocationApiTest { public void testGetNfcAntennaInfo() { NfcAntennaInfo nfcAntennaInfo = mAdapter.getNfcAntennaInfo(); - if (nfcAntennaInfo == null) { - return; - } - - assertEquals("Device widths do not match", 0, - nfcAntennaInfo.getDeviceWidth()); - assertEquals("Device heights do not match", 0, - nfcAntennaInfo.getDeviceHeight()); - assertEquals("Device foldable do not match", false, - nfcAntennaInfo.isDeviceFoldable()); - assertEquals("Wrong number of available antennas", 0, - nfcAntennaInfo.getAvailableNfcAntennas().size()); + assertNotNull(nfcAntennaInfo); AvailableNfcAntenna availableNfcAntenna = new AvailableNfcAntenna(ANTENNA_X, ANTENNA_Y); diff --git a/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java b/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java index 5c5327037c7..57287081fa4 100644 --- a/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java +++ b/tests/tests/os/src/android/os/storage/cts/StorageManagerHelper.java @@ -32,11 +32,15 @@ import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Supplier; final class StorageManagerHelper { + private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(20); + private static final long POLLING_SLEEP_MILLIS = 100; + /** * Creates a virtual disk that simulates SDCard on a device. It is * mounted as a public visible disk. @@ -96,11 +100,11 @@ final class StorageManagerHelper { private static void pollForCondition(Supplier<Boolean> condition, String errorMessage) throws Exception { Thread.sleep(2000); - for (int i = 0; i < 20; i++) { + for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) { if (condition.get()) { return; } - Thread.sleep(100); + Thread.sleep(POLLING_SLEEP_MILLIS); } throw new TimeoutException(errorMessage); } diff --git a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java index c09cb536d3c..c8a42febc2d 100644 --- a/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java +++ b/tests/tests/systemui/src/android/systemui/cts/LightBarTests.java @@ -57,6 +57,7 @@ import com.android.compatibility.common.util.ThrowingRunnable; import org.junit.After; import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; @@ -246,11 +247,12 @@ public class LightBarTests extends LightBarTestBase { Thread.sleep(WAIT_TIME); Bitmap bitmap = takeStatusBarScreenshot(activity); - Stats s = evaluateDarkBarBitmap(bitmap, Color.BLACK, 0); + Stats s = evaluateDarkBarBitmap(bitmap, Color.TRANSPARENT, 0); assertStats(bitmap, s, false /* light */); }); } + @Ignore @Test @AppModeFull // Instant apps cannot create notifications public void testLightBarIsNotAllowed_fitDisplayCutout() throws Throwable { 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 aaa61439b67..8535ae68631 100644 --- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java +++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java @@ -116,6 +116,7 @@ import com.android.compatibility.common.util.FeatureUtil; import com.android.compatibility.common.util.PollingCheck; import com.android.compatibility.common.util.PropertyUtil; import com.android.compatibility.common.util.ShellIdentityUtils; +import com.android.compatibility.common.util.SystemUtil; import com.android.compatibility.common.util.ThrowingRunnable; import com.android.modules.utils.build.SdkLevel; import com.android.net.module.util.MacAddressUtils; @@ -1149,6 +1150,14 @@ public class WifiManagerTest extends WifiJUnit4TestBase { return; } boolean wifiEnabled = sWifiManager.isWifiEnabled(); + if (wifiEnabled) { + // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no + // STA+AP concurrency. + ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false)); + PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled()); + SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled"); + PollingCheck.check("Wifi turn on failed!", 2_000, () -> sWifiManager.isWifiEnabled()); + } TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); // add sleep to avoid calling stopLocalOnlyHotspot before TetherController initialization. @@ -1922,6 +1931,14 @@ public class WifiManagerTest extends WifiJUnit4TestBase { boolean caughtException = false; boolean wifiEnabled = sWifiManager.isWifiEnabled(); + if (wifiEnabled) { + // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no + // STA+AP concurrency. + ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false)); + PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled()); + SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled"); + PollingCheck.check("Wifi turn on failed!", 2_000, () -> sWifiManager.isWifiEnabled()); + } TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); @@ -3636,13 +3653,20 @@ public class WifiManagerTest extends WifiJUnit4TestBase { } /** - * Tests {@link WifiManager#isStaApConcurrencySupported(). + * Tests {@link WifiManager#isStaApConcurrencySupported()}. */ @Test public void testIsStaApConcurrencySupported() throws Exception { // check that softap mode is supported by the device assumeTrue(sWifiManager.isPortableHotspotSupported()); + // Re-enabled Wi-Fi as shell for HalDeviceManager legacy LOHS behavior when there's no + // STA+AP concurrency. + ShellIdentityUtils.invokeWithShellPermissions(() -> sWifiManager.setWifiEnabled(false)); + PollingCheck.check("Wifi turn off failed!", 2_000, () -> !sWifiManager.isWifiEnabled()); + SystemUtil.runShellCommand("cmd wifi set-wifi-enabled enabled"); + PollingCheck.check("Wifi turn on failed!", 2_000, () -> sWifiManager.isWifiEnabled()); + boolean isStaApConcurrencySupported = sWifiManager.isStaApConcurrencySupported(); // start local only hotspot. TestLocalOnlyHotspotCallback callback = startLocalOnlyHotspot(); diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml index 56944d2bef9..6fbc15c21a4 100644 --- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml +++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml @@ -159,9 +159,15 @@ <option name="compatibility:exclude-filter" value="CtsSecurityTestCases android.security.cts.CertificateTest#testNoRemovedCertificates" /> <!-- b/296896687 --> - <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_30ms" /> - <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_100ms" /> - <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setFrameTimeline_preferredIndex" /> - <option name="compatibility:exclude-filter" value="CtsViewTestCases android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setFrameTimeline_notPreferredIndex" /> + <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_30ms" /> + <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setDesiredPresentTime_100ms" /> + <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setFrameTimeline_preferredIndex" /> + <option name="compatibility:exclude-filter" value="CtsSurfaceControlTests android.view.surfacecontrol.cts.ASurfaceControlTest#testSurfaceTransaction_setFrameTimeline_notPreferredIndex" /> + + <!-- b/298915013 Remove CtsKeystoreTestCases android.keystore.cts.KeyAttestationTest from cts-on-gsi --> + <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.AttestKeyTest#testEcAttestKey_StrongBox" /> + <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.AttestKeyTest#testRsaAttestKey_StrongBox" /> + <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.AttestKeyTest#testAttestationKmVersionMatchesFeatureVersionStrongBox" /> + <option name="compatibility:exclude-filter" value="CtsKeystoreTestCases android.keystore.cts.AttestKeyTest#testAllVariationsOfDeviceIdAttestationUsingStrongBox" /> </configuration> |