Merge "Update cect_hf4_6_22_interruptedPowerOn and cect_hf4_6_23_interruptedStandby"
diff --git a/OWNERS b/OWNERS
index 8771ccd..adb9461 100644
--- a/OWNERS
+++ b/OWNERS
@@ -12,6 +12,6 @@
# Android EngProd Approvers
wenshan@google.com
-guangzhu@google.com
-jdesprez@google.com
+guangzhu@google.com #{LAST_RESORT_SUGGESTION}
+jdesprez@google.com #{LAST_RESORT_SUGGESTION}
normancheung@google.com #{LAST_RESORT_SUGGESTION}
\ No newline at end of file
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index e357e8f..2001b7b 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -5445,6 +5445,7 @@
<category android:name="android.cts.intent.category.MANUAL_TEST" />
</intent-filter>
<meta-data android:name="test_category" android:value="@string/test_category_audio" />
+ <meta-data android:name="test_required_features" android:value="android.hardware.hdmi.cec" />
<meta-data android:name="display_mode" android:value="multi_display_mode" />
<meta-data android:name="ApiTest"
android:value="android.media.AudioDescriptor#getStandard|
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS
index cf88726..00ad35c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/OWNERS
@@ -1,2 +1,5 @@
# Bug template url: https://b.corp.google.com/issues/new?component=100560&template=63204
-file:platform/frameworks/base:/core/java/android/app/admin/EnterprisePlatform_OWNERS
\ No newline at end of file
+file:platform/frameworks/base:/core/java/android/app/admin/EnterprisePlatform_OWNERS
+
+# Bug component: 801321 = per-file Screenshot*.java
+per-file Screenshot*.java = mrenouf@google.com, mrcasey@google.com
\ No newline at end of file
diff --git a/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java b/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java
index c5cd4dd..20fbc4f 100644
--- a/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java
+++ b/common/device-side/bedstead/testapp/src/processor/main/java/com/android/bedstead/testapp/processor/Processor.java
@@ -155,6 +155,7 @@
} catch (MirroredTypesException e) {
return e.getTypeMirrors().stream()
.map(t -> (TypeElement) types.asElement(t))
+ .sorted()
.collect(Collectors.toList());
}
throw new AssertionError("Could not extract classes from annotation");
@@ -830,10 +831,12 @@
}
}
- private Set<ExecutableElement> getMethods(TypeElement interfaceClass, Elements elements) {
+ private List<ExecutableElement> getMethods(TypeElement interfaceClass, Elements elements) {
Map<String, ExecutableElement> methods = new HashMap<>();
getMethods(methods, interfaceClass, elements);
- return new HashSet<>(methods.values());
+ ArrayList<ExecutableElement> methodList = new ArrayList<>(methods.values());
+ methodList.sort((e1, e2) -> Integer.compare(e1.getSimpleName().hashCode(), e2.getSimpleName().hashCode()));
+ return methodList;
}
private void getMethods(Map<String, ExecutableElement> methods, TypeElement interfaceClass,
diff --git a/common/device-side/device-info/Android.bp b/common/device-side/device-info/Android.bp
index a3e618b..6729ed2 100644
--- a/common/device-side/device-info/Android.bp
+++ b/common/device-side/device-info/Android.bp
@@ -29,11 +29,14 @@
"compatibility-device-util-axt",
"cts_window_jetpack_utils",
"junit",
+ "android-key-attestation",
+ "Nene",
],
-
libs: [
"android.test.base",
],
sdk_version: "test_current",
+ min_sdk_version: "21",
+ dxflags: ["--multi-dex"],
}
diff --git a/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/KeystoreAttestationDeviceInfo.java b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/KeystoreAttestationDeviceInfo.java
new file mode 100644
index 0000000..f0f5c62
--- /dev/null
+++ b/common/device-side/device-info/src/com/android/compatibility/common/deviceinfo/KeystoreAttestationDeviceInfo.java
@@ -0,0 +1,201 @@
+/*
+ * 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.
+ */
+package com.android.compatibility.common.deviceinfo;
+
+import static android.security.keystore.KeyProperties.DIGEST_SHA256;
+import static android.security.keystore.KeyProperties.KEY_ALGORITHM_EC;
+import static android.security.keystore.KeyProperties.PURPOSE_SIGN;
+import static android.security.keystore.KeyProperties.PURPOSE_VERIFY;
+
+import static com.android.bedstead.nene.packages.CommonPackages.FEATURE_DEVICE_ID_ATTESTATION;
+
+import static com.google.android.attestation.ParsedAttestationRecord.createParsedAttestationRecord;
+
+import static org.junit.Assert.assertTrue;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.content.pm.PackageManager;
+import android.security.keystore.DeviceIdAttestationException;
+import android.security.keystore.KeyGenParameterSpec;
+import android.util.Log;
+
+import com.android.compatibility.common.util.DeviceInfoStore;
+
+import com.google.android.attestation.AuthorizationList;
+import com.google.android.attestation.ParsedAttestationRecord;
+import com.google.android.attestation.RootOfTrust;
+
+import java.io.IOException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.spec.ECGenParameterSpec;
+import java.util.Base64;
+import java.util.Objects;
+import java.util.Optional;
+
+/**
+ * Feature Keystore Attestation device info collector. Collector collects information from the
+ * device's KeyMint implementation as reflected by the data in the key attestation record. These
+ * will be collected across devices and do not collect and PII outside of the device information.
+ */
+public final class KeystoreAttestationDeviceInfo extends DeviceInfo {
+ private static final String LOG_TAG = "KeystoreAttestationDeviceInfo";
+ private static final String TEST_ALIAS_KEYSTORE = "testKeystore";
+ private static final String TEST_ALIAS_STRONG_BOX = "testStrongBox";
+ private static final byte[] CHALLENGE = "challenge".getBytes();
+
+ @Override
+ protected void collectDeviceInfo(DeviceInfoStore store) throws Exception {
+ collectKeystoreAttestation(store);
+ if (getContext()
+ .getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_STRONGBOX_KEYSTORE)) {
+ collectStrongBoxAttestation(store);
+ }
+ }
+
+ private void generateKeyPair(String algorithm, KeyGenParameterSpec spec)
+ throws NoSuchAlgorithmException,
+ NoSuchProviderException,
+ InvalidAlgorithmParameterException {
+ KeyPairGenerator keyPairGenerator =
+ KeyPairGenerator.getInstance(algorithm, "AndroidKeyStore");
+ keyPairGenerator.initialize(spec);
+ KeyPair kp = keyPairGenerator.generateKeyPair();
+
+ if (kp == null) {
+ Log.e(LOG_TAG, "Key generation failed");
+ return;
+ }
+ }
+
+ private void collectKeystoreAttestation(DeviceInfoStore localStore) throws Exception {
+ KeyStore mKeyStore = KeyStore.getInstance("AndroidKeyStore");
+ mKeyStore.load(null);
+ mKeyStore.deleteEntry(TEST_ALIAS_KEYSTORE);
+
+ localStore.startGroup("keymint_key_attestation");
+ loadCertAndCollectAttestation(mKeyStore, localStore, TEST_ALIAS_KEYSTORE, false);
+ localStore.endGroup();
+ }
+
+ private void collectStrongBoxAttestation(DeviceInfoStore localStore) throws Exception {
+ KeyStore mKeyStore = KeyStore.getInstance("AndroidKeyStore");
+ mKeyStore.load(null);
+ mKeyStore.deleteEntry(TEST_ALIAS_STRONG_BOX);
+
+ localStore.startGroup("strong_box_key_attestation");
+ loadCertAndCollectAttestation(mKeyStore, localStore, TEST_ALIAS_STRONG_BOX, true);
+ localStore.endGroup();
+ }
+
+ private void loadCertAndCollectAttestation(
+ KeyStore keystore,
+ DeviceInfoStore localStore,
+ String testAlias,
+ boolean isStrongBoxBacked)
+ throws Exception {
+ Objects.requireNonNull(keystore);
+ KeyGenParameterSpec spec =
+ new KeyGenParameterSpec.Builder(testAlias, PURPOSE_SIGN | PURPOSE_VERIFY)
+ .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1"))
+ .setDigests(DIGEST_SHA256)
+ .setDevicePropertiesAttestationIncluded(
+ getContext()
+ .getPackageManager()
+ .hasSystemFeature(FEATURE_DEVICE_ID_ATTESTATION))
+ .setAttestationChallenge(CHALLENGE)
+ .setIsStrongBoxBacked(isStrongBoxBacked)
+ .build();
+
+ generateKeyPair(KEY_ALGORITHM_EC, spec);
+
+ Certificate[] certificates = keystore.getCertificateChain(testAlias);
+ assertTrue(certificates.length >= 1);
+
+ final X509Certificate attestationCert = (X509Certificate) certificates[0];
+ final AuthorizationList keyDetailsList;
+
+ ParsedAttestationRecord parsedAttestationRecord =
+ createParsedAttestationRecord(attestationCert);
+
+ keyDetailsList = parsedAttestationRecord.teeEnforced;
+
+ collectStoredInformation(localStore, keyDetailsList);
+ }
+
+ private static void collectStoredInformation(
+ DeviceInfoStore localStore, AuthorizationList keyDetailsList)
+ throws DeviceIdAttestationException, IOException {
+ if (keyDetailsList.rootOfTrust.isPresent()) {
+ collectRootOfTrust(keyDetailsList.rootOfTrust, localStore);
+ }
+ if (keyDetailsList.osVersion.isPresent()) {
+ localStore.addResult("os_version", keyDetailsList.osVersion.get());
+ }
+ if (keyDetailsList.osPatchLevel.isPresent()) {
+ localStore.addResult("patch_level", keyDetailsList.osPatchLevel.get());
+ }
+ if (keyDetailsList.attestationIdBrand.isPresent()) {
+ localStore.addResult(
+ "id_brand", new String(keyDetailsList.attestationIdBrand.get(), UTF_8));
+ }
+ if (keyDetailsList.attestationIdDevice.isPresent()) {
+ localStore.addResult(
+ "id_device", new String(keyDetailsList.attestationIdDevice.get(), UTF_8));
+ }
+ if (keyDetailsList.attestationIdProduct.isPresent()) {
+ localStore.addResult(
+ "id_product", new String(keyDetailsList.attestationIdProduct.get(), UTF_8));
+ }
+ if (keyDetailsList.attestationIdManufacturer.isPresent()) {
+ localStore.addResult(
+ "build_manufacturer",
+ new String(keyDetailsList.attestationIdManufacturer.get(), UTF_8));
+ }
+ if (keyDetailsList.attestationIdModel.isPresent()) {
+ localStore.addResult(
+ "build_model", new String(keyDetailsList.attestationIdModel.get(), UTF_8));
+ }
+ if (keyDetailsList.vendorPatchLevel.isPresent()) {
+ localStore.addResult("vendor_patch_level", keyDetailsList.vendorPatchLevel.get());
+ }
+ if (keyDetailsList.bootPatchLevel.isPresent()) {
+ localStore.addResult("boot_patch_level", keyDetailsList.bootPatchLevel.get());
+ }
+ }
+
+ private static void collectRootOfTrust(
+ Optional<RootOfTrust> rootOfTrust, DeviceInfoStore localStore) throws IOException {
+ if (rootOfTrust.isPresent()) {
+ localStore.addResult(
+ "verified_boot_key",
+ Base64.getEncoder().encodeToString(rootOfTrust.get().verifiedBootKey));
+ localStore.addResult("device_locked", rootOfTrust.get().deviceLocked);
+ localStore.addResult("verified_boot_state", rootOfTrust.get().verifiedBootState.name());
+ localStore.addResult(
+ "verified_boot_hash",
+ Base64.getEncoder().encodeToString(rootOfTrust.get().verifiedBootHash));
+ }
+ }
+}
diff --git a/common/device-side/util-axt/Android.bp b/common/device-side/util-axt/Android.bp
index d07fe3d..68f7637 100644
--- a/common/device-side/util-axt/Android.bp
+++ b/common/device-side/util-axt/Android.bp
@@ -19,6 +19,8 @@
java_defaults {
name: "compatibility-device-util-axt-default",
sdk_version: "test_current",
+ min_sdk_version: "21",
+ dxflags: ["--multi-dex"],
srcs: [
"src/**/*.java",
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
index 2e17a8c..209ce99 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/OWNERS
@@ -1,6 +1,9 @@
per-file AmMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
per-file AnrMonitor.java = file:platform/frameworks/base:/services/core/java/com/android/server/am/OWNERS
per-file BaseDefaultPermissionGrantPolicyTest.java = file:platform/frameworks/base:/core/java/android/permission/DEFAULT_PERMISSION_GRANT_POLICY_OWNERS
+per-file CtsKeyEventUtil.java = file:platform/cts:/tests/tests/widget/OWNERS
+per-file CtsMouseUtil.java = file:platform/cts:/tests/tests/widget/OWNERS
+per-file CtsTouchUtils.java = file:platform/cts:/tests/tests/widget/OWNERS
per-file ReadElf.java = enh@google.com
per-file *Settings*.java = felipeal@google.com
per-file User*Helper*.java = felipeal@google.com
diff --git a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
index d02dc42..c76b5aa 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -342,105 +342,10 @@
// TODO: b/223837004
private static final ImmutableSet<String> BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST =
ImmutableSet.of(
- // Already duplicate in BCP.
- "Landroid/hidl/base/V1_0/DebugInfo;",
- "Landroid/hidl/base/V1_0/IBase;",
// /apex/com.android.btservices/javalib/framework-bluetooth.jar
- "Lcom/android/bluetooth/x/android/sysprop/AdbProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/ApkVerityProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/BluetoothProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/CarProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/ContactsProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/CryptoProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/DeviceProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/DisplayProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/HdmiProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/HypervisorProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/InputProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/MediaProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/NetworkProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/OtaProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/PowerProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/SetupWizardProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/SocProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/TelephonyProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/TraceProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/VndkProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/VoldProperties;",
- "Lcom/android/bluetooth/x/android/sysprop/WifiProperties;",
"Lcom/android/bluetooth/x/com/android/modules/utils/ISynchronousResultReceiver;",
"Lcom/android/bluetooth/x/com/android/modules/utils/SynchronousResultReceiver-IA;",
"Lcom/android/bluetooth/x/com/android/modules/utils/SynchronousResultReceiver;",
- // /system/framework/services.jar
- "Landroid/net/DataStallReportParcelable;",
- "Landroid/net/DhcpResultsParcelable;",
- "Landroid/net/IIpMemoryStore;",
- "Landroid/net/IIpMemoryStoreCallbacks;",
- "Landroid/net/INetworkMonitor;",
- "Landroid/net/INetworkMonitorCallbacks;",
- "Landroid/net/INetworkStackConnector;",
- "Landroid/net/INetworkStackStatusCallback;",
- "Landroid/net/InformationElementParcelable;",
- "Landroid/net/InitialConfigurationParcelable;",
- "Landroid/net/IpMemoryStoreClient;",
- "Landroid/net/Layer2InformationParcelable;",
- "Landroid/net/Layer2PacketParcelable;",
- "Landroid/net/NattKeepalivePacketDataParcelable;",
- "Landroid/net/NetworkFactory;",
- "Landroid/net/NetworkFactoryShim;",
- "Landroid/net/NetworkMonitorManager;",
- "Landroid/net/NetworkTestResultParcelable;",
- "Landroid/net/PrivateDnsConfigParcel;",
- "Landroid/net/ProvisioningConfigurationParcelable;",
- "Landroid/net/ScanResultInfoParcelable;",
- "Landroid/net/TcpKeepalivePacketDataParcelable;",
- "Landroid/net/dhcp/DhcpLeaseParcelable;",
- "Landroid/net/dhcp/DhcpServingParamsParcel;",
- "Landroid/net/dhcp/IDhcpEventCallbacks;",
- "Landroid/net/dhcp/IDhcpServer;",
- "Landroid/net/dhcp/IDhcpServerCallbacks;",
- "Landroid/net/ip/IIpClient;",
- "Landroid/net/ip/IIpClientCallbacks;",
- "Landroid/net/ip/IpClientCallbacks;",
- "Landroid/net/ip/IpClientManager;",
- "Landroid/net/ip/IpClientUtil;",
- "Landroid/net/ipmemorystore/Blob;",
- "Landroid/net/ipmemorystore/IOnBlobRetrievedListener;",
- "Landroid/net/ipmemorystore/IOnL2KeyResponseListener;",
- "Landroid/net/ipmemorystore/IOnNetworkAttributesRetrievedListener;",
- "Landroid/net/ipmemorystore/IOnSameL3NetworkResponseListener;",
- "Landroid/net/ipmemorystore/IOnStatusAndCountListener;",
- "Landroid/net/ipmemorystore/IOnStatusListener;",
- "Landroid/net/ipmemorystore/NetworkAttributes;",
- "Landroid/net/ipmemorystore/NetworkAttributesParcelable;",
- "Landroid/net/ipmemorystore/OnBlobRetrievedListener;",
- "Landroid/net/ipmemorystore/OnDeleteStatusListener;",
- "Landroid/net/ipmemorystore/OnL2KeyResponseListener;",
- "Landroid/net/ipmemorystore/OnNetworkAttributesRetrievedListener;",
- "Landroid/net/ipmemorystore/OnSameL3NetworkResponseListener;",
- "Landroid/net/ipmemorystore/OnStatusListener;",
- "Landroid/net/ipmemorystore/SameL3NetworkResponse;",
- "Landroid/net/ipmemorystore/SameL3NetworkResponseParcelable;",
- "Landroid/net/ipmemorystore/Status;",
- "Landroid/net/ipmemorystore/StatusParcelable;",
- "Landroid/net/networkstack/NetworkStackClientBase;",
- "Landroid/net/networkstack/aidl/NetworkMonitorParameters;",
- "Landroid/net/networkstack/aidl/dhcp/DhcpOption;",
- "Landroid/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable;",
- "Landroid/net/networkstack/aidl/ip/ReachabilityLossReason;",
- "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirk;",
- "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable;",
- "Landroid/net/shared/InitialConfiguration;",
- "Landroid/net/shared/IpConfigurationParcelableUtil;",
- "Landroid/net/shared/Layer2Information;",
- "Landroid/net/shared/ParcelableUtil;",
- "Landroid/net/shared/PrivateDnsConfig;",
- "Landroid/net/shared/ProvisioningConfiguration;",
- "Landroid/net/util/KeepalivePacketDataUtil;",
- "Landroid/net/IpMemoryStore;",
- "Landroid/net/NetworkFactoryLegacyImpl;",
- "Landroid/net/networkstack/ModuleNetworkStackClient;",
- "Landroid/net/NetworkFactoryImpl;",
// /system/framework/framework.jar
"Landroid/bluetooth/BluetoothProtoEnums;",
"Landroid/bluetooth/a2dp/BluetoothA2dpProtoEnums;",
diff --git a/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java b/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java
index 173a6da..4226251 100644
--- a/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java
+++ b/hostsidetests/dumpsys/src/android/dumpsys/cts/GfxInfoDumpsysTest.java
@@ -52,6 +52,9 @@
installResult);
getDevice().executeShellCommand("am start -W " + TEST_PKG);
+ // Currently "wait for launch" doesn't actually wait for the frame to be finished
+ // So do a little sleep to let things stabilize
+ Thread.sleep(500);
String frameinfo = mDevice.executeShellCommand("dumpsys gfxinfo " +
TEST_PKG + " framestats");
diff --git a/hostsidetests/gwp_asan/Android.bp b/hostsidetests/gwp_asan/Android.bp
index 2b938eb..14b7205 100644
--- a/hostsidetests/gwp_asan/Android.bp
+++ b/hostsidetests/gwp_asan/Android.bp
@@ -30,6 +30,7 @@
],
data: [
":CtsGwpAsanEnabled",
+ ":CtsGwpAsanRecoverable",
],
}
@@ -49,5 +50,5 @@
"general-tests",
],
jni_libs: ["libgwp_asan_cts_library_jni"],
- sdk_version: "current",
+ sdk_version: "test_current",
}
diff --git a/hostsidetests/gwp_asan/common/Android.bp b/hostsidetests/gwp_asan/common/Android.bp
index 30a086b..caf2f07 100644
--- a/hostsidetests/gwp_asan/common/Android.bp
+++ b/hostsidetests/gwp_asan/common/Android.bp
@@ -19,12 +19,12 @@
java_library {
name: "gwp_asan_cts_common",
srcs: ["android/**/*.java"],
- sdk_version: "current",
static_libs: [
- "ctstestrunner-axt",
"androidx.test.rules",
"androidx.test.core",
"androidx.test.ext.junit",
+ "compatibility-device-util-axt",
+ "ctstestrunner-axt",
],
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
index 802f829..1b63808 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
@@ -23,6 +23,9 @@
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.compatibility.common.util.DropBoxReceiver;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -48,8 +51,49 @@
@Test
public void testEnablement() throws Exception {
TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
- activity.callActivity(GwpAsanEnabledActivity.class);
- activity.callActivity(GwpAsanDefaultActivity.class);
- activity.callActivity(GwpAsanDisabledActivity.class);
+ activity.callActivityAndCheckSuccess(
+ GwpAsanEnabledActivity.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+ activity.callActivityAndCheckSuccess(
+ GwpAsanDefaultActivity.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+ activity.callActivityAndCheckSuccess(
+ GwpAsanDisabledActivity.class, Utils.TEST_IS_GWP_ASAN_DISABLED);
+ }
+
+ @Test
+ public void testCrashToDropboxRecoverableEnabled() throws Exception {
+ TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+ activity.callActivity(GwpAsanEnabledActivity.class, Utils.TEST_USE_AFTER_FREE);
+ Assert.assertTrue(receiver.await());
+ }
+
+ @Test
+ public void testCrashToDropboxRecoverableDefault() throws Exception {
+ TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+ DropBoxReceiver receiver =
+ Utils.getDropboxReceiver(
+ mContext, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG);
+ // Ensure the recoverable mode recovers, and returns success.
+ activity.callActivityAndCheckSuccess(
+ GwpAsanDefaultActivity.class, Utils.TEST_USE_AFTER_FREE);
+ Assert.assertTrue(receiver.await());
+ }
+
+ @Test
+ public void testCrashToDropboxEnabled() throws Exception {
+ TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+ activity.callActivity(GwpAsanEnabledActivity.class, Utils.TEST_USE_AFTER_FREE);
+ Assert.assertTrue(receiver.await());
+ }
+
+ @Test
+ public void testCrashToDropboxDefault() throws Exception {
+ TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_default");
+ // Inherits from the app-wide property, which was `gwpAsanMode=always`. So, this should
+ // crash.
+ activity.callActivity(GwpAsanDefaultActivity.class, Utils.TEST_USE_AFTER_FREE);
+ Assert.assertTrue(receiver.await());
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
index 227377c..c67f569 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultActivity.java
@@ -23,15 +23,7 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- try {
- if (Utils.isGwpAsanEnabled()) {
- setResult(Utils.TEST_SUCCESS);
- } else {
- setResult(Utils.TEST_FAILURE);
- }
- } catch (Exception e) {
- setResult(Utils.TEST_FAILURE);
- }
+ setResult(Utils.runTest(getIntent().getExtras().getInt("testId")));
finish();
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
index 84a44b0..dcff09a 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDefaultService.java
@@ -32,16 +32,9 @@
public class LocalBinder extends Binder {
@Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
- if (code == Utils.SERVICE_IS_GWP_ASAN_ENABLED) {
- try {
- reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
- } catch (Exception e) {
- reply.writeInt(-1);
- }
- return true;
- }
- return false;
+ public boolean onTransact(int testId, Parcel data, Parcel reply, int flags) {
+ reply.writeInt(Utils.runTest(testId));
+ return true;
}
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
index d87b541..4d3443b 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledActivity.java
@@ -23,15 +23,7 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- try {
- if (Utils.isGwpAsanDisabled()) {
- setResult(Utils.TEST_SUCCESS);
- } else {
- setResult(Utils.TEST_FAILURE);
- }
- } catch (Exception e) {
- setResult(Utils.TEST_FAILURE);
- }
+ setResult(Utils.runTest(getIntent().getExtras().getInt("testId")));
finish();
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
index 2e7f18c..19eeedd 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanDisabledService.java
@@ -32,16 +32,9 @@
public class LocalBinder extends Binder {
@Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
- if (code == Utils.SERVICE_IS_GWP_ASAN_DISABLED) {
- try {
- reply.writeInt(Utils.isGwpAsanDisabled() ? 1 : 0);
- } catch (Exception e) {
- reply.writeInt(-1);
- }
- return true;
- }
- return false;
+ public boolean onTransact(int testId, Parcel data, Parcel reply, int flags) {
+ reply.writeInt(Utils.runTest(testId));
+ return true;
}
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
index 6bdeed8..4d2658b 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledActivity.java
@@ -23,15 +23,7 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- try {
- if (Utils.isGwpAsanEnabled()) {
- setResult(Utils.TEST_SUCCESS);
- } else {
- setResult(Utils.TEST_FAILURE);
- }
- } catch (Exception e) {
- setResult(Utils.TEST_FAILURE);
- }
+ setResult(Utils.runTest(getIntent().getExtras().getInt("testId")));
finish();
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
index f195480..1d1a1f7 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanEnabledService.java
@@ -32,16 +32,9 @@
public class LocalBinder extends Binder {
@Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags) {
- if (code == Utils.SERVICE_IS_GWP_ASAN_ENABLED) {
- try {
- reply.writeInt(Utils.isGwpAsanEnabled() ? 1 : 0);
- } catch (Exception e) {
- reply.writeInt(-1);
- }
- return true;
- }
- return false;
+ public boolean onTransact(int testId, Parcel data, Parcel reply, int flags) {
+ reply.writeInt(Utils.runTest(testId));
+ return true;
}
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
index f4ec2be..817acbc 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
@@ -18,8 +18,10 @@
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.Parcel;
@@ -27,6 +29,9 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ServiceTestRule;
+import com.android.compatibility.common.util.DropBoxReceiver;
+
+import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,26 +39,63 @@
@RunWith(AndroidJUnit4.class)
public class GwpAsanServiceTest {
@Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
+ private Context mContext;
- private boolean runService(Class<?> cls, int testNum) throws Exception {
+ @Before
+ public void setUp() throws Exception {
+ mContext = getApplicationContext();
+ }
+
+ private void runServiceAndCheckSuccess(Class<?> cls, int testNum) throws Exception {
Intent serviceIntent = new Intent(getApplicationContext(), cls);
IBinder binder = mServiceRule.bindService(serviceIntent);
- final Parcel request = Parcel.obtain();
final Parcel reply = Parcel.obtain();
- if (!binder.transact(testNum, request, reply, 0)) {
+ if (!binder.transact(testNum, Parcel.obtain(), reply, 0)) {
throw new Exception();
}
- int res = reply.readInt();
- if (res < 0) {
- throw new Exception();
- }
- return res != 0;
+ assertEquals(reply.readInt(), Utils.TEST_SUCCESS);
+ }
+
+ private void runService(Class<?> cls, int testNum) throws Exception {
+ Intent serviceIntent = new Intent(getApplicationContext(), cls);
+ IBinder binder = mServiceRule.bindService(serviceIntent);
+ binder.transact(testNum, Parcel.obtain(), Parcel.obtain(), IBinder.FLAG_ONEWAY);
}
@Test
public void testEnablement() throws Exception {
- assertTrue(runService(GwpAsanEnabledService.class, Utils.SERVICE_IS_GWP_ASAN_ENABLED));
- assertTrue(runService(GwpAsanDefaultService.class, Utils.SERVICE_IS_GWP_ASAN_ENABLED));
- assertTrue(runService(GwpAsanDisabledService.class, Utils.SERVICE_IS_GWP_ASAN_DISABLED));
+ runServiceAndCheckSuccess(GwpAsanEnabledService.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+ runServiceAndCheckSuccess(GwpAsanDefaultService.class, Utils.TEST_IS_GWP_ASAN_ENABLED);
+ runServiceAndCheckSuccess(GwpAsanDisabledService.class, Utils.TEST_IS_GWP_ASAN_DISABLED);
+ }
+
+ @Test
+ public void testCrashToDropboxEnabled() throws Exception {
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+ runService(GwpAsanEnabledService.class, Utils.TEST_USE_AFTER_FREE);
+ assertTrue(receiver.await());
+ }
+
+ @Test
+ public void testCrashToDropboxDefault() throws Exception {
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_default");
+ runService(GwpAsanDefaultService.class, Utils.TEST_USE_AFTER_FREE);
+ assertTrue(receiver.await());
+ }
+
+ @Test
+ public void testCrashToDropboxRecoverableEnabled() throws Exception {
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
+ runService(GwpAsanEnabledService.class, Utils.TEST_USE_AFTER_FREE);
+ assertTrue(receiver.await());
+ }
+
+ @Test
+ public void testCrashToDropboxRecoverableDefault() throws Exception {
+ DropBoxReceiver receiver =
+ Utils.getDropboxReceiver(
+ mContext, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG);
+ runServiceAndCheckSuccess(GwpAsanDefaultService.class, Utils.TEST_USE_AFTER_FREE);
+ assertTrue(receiver.await());
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
index 95c8ecc..bdcfd73 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/TestActivityLauncher.java
@@ -17,7 +17,6 @@
package android.cts.gwp_asan;
import android.app.Activity;
-import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
@@ -41,14 +40,27 @@
}
}
- public void callActivity(Class<?> cls) throws Exception {
+ public void callActivity(Class<?> cls, int testId) throws Exception {
+ Thread thread =
+ new Thread() {
+ @Override
+ public void run() {
+ Intent intent = new Intent(getApplicationContext(), cls);
+ intent.putExtra("testId", testId);
+ startActivity(intent);
+ }
+ };
+ thread.start();
+ }
+
+ public void callActivityAndCheckSuccess(Class<?> cls, int testId) throws Exception {
Thread thread =
new Thread() {
@Override
public void run() {
try {
- Context context = getApplicationContext();
- Intent intent = new Intent(context, cls);
+ Intent intent = new Intent(getApplicationContext(), cls);
+ intent.putExtra("testId", testId);
startActivityForResult(intent, 0);
synchronized (mFinishEvent) {
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
index cf08537..b2ed1e3 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
@@ -18,8 +18,11 @@
import android.app.Activity;
import android.app.Application;
+import android.content.Context;
import android.util.Log;
+import com.android.compatibility.common.util.DropBoxReceiver;
+
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
@@ -32,15 +35,17 @@
public static final int TEST_SUCCESS = Activity.RESULT_FIRST_USER + 100;
public static final int TEST_FAILURE = Activity.RESULT_FIRST_USER + 101;
- public static final int SERVICE_IS_GWP_ASAN_ENABLED = 42;
- public static final int SERVICE_IS_GWP_ASAN_DISABLED = 43;
+ public static final int TEST_IS_GWP_ASAN_ENABLED = 42;
+ public static final int TEST_IS_GWP_ASAN_DISABLED = 43;
+ public static final int TEST_USE_AFTER_FREE = 44;
- // Check that GWP-ASan is enabled by allocating a whole bunch of heap
- // pointers and making sure one of them is a GWP-ASan allocation (by
- // comparing with /proc/self/maps).
+ public static final String DROPBOX_TAG = "data_app_native_crash";
+ public static final String DROPBOX_RECOVERABLE_TAG = "data_app_native_recoverable_crash";
+
+ // Check that GWP-ASan is enabled by allocating a whole bunch of heap pointers and making sure
+ // one of them is a GWP-ASan allocation (by comparing with /proc/self/maps).
public static native boolean isGwpAsanEnabled();
- // Check that GWP-ASan is disabled by ensuring there's no GWP-ASan mappings
- // in /proc/self/maps.
+ // Check that GWP-ASan is disabled by ensuring there's no GWP-ASan mappings in /proc/self/maps.
public static boolean isGwpAsanDisabled() throws IOException {
try (FileReader fr = new FileReader("/proc/self/maps");
BufferedReader reader = new BufferedReader(fr)) {
@@ -55,4 +60,44 @@
}
return true;
}
+
+ // Trigger a GWP-ASan instrumented use-after-free. This should always trigger a GWP-ASan report
+ // if it's enabled. In non-recoverable mode (i.e. gwpAsanMode=always), then this will crash the
+ // app with SEGV. In recoverable mode (i.e. gwpAsanMode=default), then this won't crash, but
+ // should still trigger all the dropbox/debuggerd entries.
+ public static native void instrumentedUseAfterFree();
+
+ public static int runTest(int testId) {
+ try {
+ if (testId == TEST_IS_GWP_ASAN_ENABLED) {
+ return Utils.isGwpAsanEnabled() ? Utils.TEST_SUCCESS : Utils.TEST_FAILURE;
+ }
+ if (testId == TEST_IS_GWP_ASAN_DISABLED) {
+ return Utils.isGwpAsanDisabled() ? Utils.TEST_SUCCESS : Utils.TEST_FAILURE;
+ }
+ if (testId == TEST_USE_AFTER_FREE) {
+ Utils.instrumentedUseAfterFree();
+ return Utils.TEST_SUCCESS;
+ }
+ } catch (Exception e) {
+ return Utils.TEST_FAILURE;
+ }
+ return Utils.TEST_FAILURE;
+ }
+
+ public static DropBoxReceiver getDropboxReceiver(
+ Context context, String processNameSuffix, String crashTag) {
+ return new DropBoxReceiver(
+ context,
+ crashTag,
+ context.getPackageName() + ":" + processNameSuffix,
+ "SEGV_ACCERR",
+ "Cause: [GWP-ASan]: Use After Free",
+ "deallocated by",
+ "backtrace:");
+ }
+
+ public static DropBoxReceiver getDropboxReceiver(Context context, String processNameSuffix) {
+ return getDropboxReceiver(context, processNameSuffix, DROPBOX_TAG);
+ }
}
diff --git a/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp b/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
index f7d0176..5a5aa81 100644
--- a/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
+++ b/hostsidetests/gwp_asan/common/jni/gwp_asan_cts_library.cpp
@@ -91,3 +91,14 @@
std::unique_ptr<char[]> gwp_asan_ptr = get_gwp_asan_pointer();
return gwp_asan_ptr.get() == nullptr ? JNI_FALSE : JNI_TRUE;
}
+
+extern "C" JNIEXPORT void JNICALL
+Java_android_cts_gwp_1asan_Utils_instrumentedUseAfterFree(JNIEnv*) {
+ char* volatile p = nullptr;
+ {
+ std::unique_ptr<char[]> gwp_asan_ptr = get_gwp_asan_pointer();
+ p = gwp_asan_ptr.get();
+ }
+ if (!p) return;
+ __attribute__((unused)) volatile char c = *p;
+}
diff --git a/hostsidetests/gwp_asan/enabled/Android.bp b/hostsidetests/gwp_asan/enabled/Android.bp
index df592d2..b5a0b9f 100644
--- a/hostsidetests/gwp_asan/enabled/Android.bp
+++ b/hostsidetests/gwp_asan/enabled/Android.bp
@@ -19,8 +19,5 @@
android_test_helper_app {
name: "CtsGwpAsanEnabled",
defaults: ["cts_gwp_asan_app_defaults"],
- srcs: [
- "src/**/*.java",
- ],
use_embedded_native_libs: false,
}
diff --git a/hostsidetests/gwp_asan/enabled/AndroidManifest.xml b/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
index 414d0c5..96f510e 100644
--- a/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
+++ b/hostsidetests/gwp_asan/enabled/AndroidManifest.xml
@@ -18,6 +18,10 @@
package="android.cts.gwp_asan"
android:targetSandboxVersion="2">
+ <!-- Needed for DropBoxManager.getNextEntry(...) -->
+ <uses-permission android:name="android.permission.READ_LOGS"/>
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+
<uses-sdk android:targetSdkVersion="30" />
<application android:debuggable="true"
android:extractNativeLibs="true"
diff --git a/hostsidetests/gwp_asan/recoverable/Android.bp b/hostsidetests/gwp_asan/recoverable/Android.bp
new file mode 100644
index 0000000..466944f
--- /dev/null
+++ b/hostsidetests/gwp_asan/recoverable/Android.bp
@@ -0,0 +1,23 @@
+// 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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CtsGwpAsanRecoverable",
+ defaults: ["cts_gwp_asan_app_defaults"],
+ use_embedded_native_libs: false,
+}
diff --git a/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml b/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml
new file mode 100644
index 0000000..ab0c632
--- /dev/null
+++ b/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml
@@ -0,0 +1,60 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.cts.gwp_asan"
+ android:targetSandboxVersion="2">
+
+ <!-- Needed for DropBoxManager.getNextEntry(...) -->
+ <uses-permission android:name="android.permission.READ_LOGS"/>
+ <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"/>
+
+ <uses-sdk android:targetSdkVersion="30" />
+ <application android:debuggable="true"
+ android:extractNativeLibs="true">
+ <processes>
+ <process />
+ <process android:process=":gwp_asan_enabled"
+ android:gwpAsanMode="always" />
+ <process android:process=":gwp_asan_disabled"
+ android:gwpAsanMode="never" />
+ <process android:process=":gwp_asan_default" />
+ </processes>
+
+ <uses-library android:name="android.test.runner" />
+
+ <activity android:name=".TestActivityLauncher" />
+ <activity android:name=".GwpAsanActivityTest" />
+
+ <activity android:name=".GwpAsanEnabledActivity"
+ android:process=":gwp_asan_enabled" />
+ <activity android:name=".GwpAsanDisabledActivity"
+ android:process=":gwp_asan_disabled" />
+ <activity android:name=".GwpAsanDefaultActivity"
+ android:process=":gwp_asan_default" />
+
+ <service android:name=".GwpAsanEnabledService"
+ android:process=":gwp_asan_enabled" />
+ <service android:name=".GwpAsanDisabledService"
+ android:process=":gwp_asan_disabled" />
+ <service android:name=".GwpAsanDefaultService"
+ android:process=":gwp_asan_default" />
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.cts.gwp_asan"
+ android:label="CTS tests of GWP-ASan" />
+</manifest>
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
index 012a2ba..0ee8380 100644
--- a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
@@ -16,31 +16,16 @@
package android.cts.gwp_asan;
-import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-import org.junit.After;
import org.junit.Assert;
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class EnabledTest extends BaseHostJUnit4Test {
- private static final String TEST_APK = "CtsGwpAsanEnabled.apk";
- private static final String TEST_PKG = "android.cts.gwp_asan";
- private ITestDevice mDevice;
-
- @Before
- public void setUp() throws Exception {
- mDevice = getDevice();
- installPackage(TEST_APK, new String[0]);
- }
-
- @After
- public void tearDown() throws Exception {
- uninstallPackage(mDevice, TEST_PKG);
+public class EnabledTest extends GwpAsanBaseTest {
+ protected String getTestApk() {
+ return "CtsGwpAsanEnabled.apk";
}
@Test
@@ -50,4 +35,20 @@
Assert.assertTrue(
runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testEnablement"));
}
+
+ @Test
+ public void testCrashToDropbox() throws Exception {
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testCrashToDropboxEnabled"));
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testCrashToDropboxDefault"));
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testCrashToDropboxEnabled"));
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testCrashToDropboxDefault"));
+ }
}
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/GwpAsanBaseTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/GwpAsanBaseTest.java
new file mode 100644
index 0000000..2935af3
--- /dev/null
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/GwpAsanBaseTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package android.cts.gwp_asan;
+
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public abstract class GwpAsanBaseTest extends BaseHostJUnit4Test {
+ protected static final String TEST_PKG = "android.cts.gwp_asan";
+ protected ITestDevice mDevice;
+
+ protected abstract String getTestApk();
+
+ @Before
+ public void setUp() throws Exception {
+ mDevice = getDevice();
+ installPackage(getTestApk(), new String[0]);
+
+ // Reset the rate-limiting counters inside DropBoxManager, which only allows up to six
+ // dropbox entries with the same {process name + entry tag} within any 10 minute period. We
+ // can run the full suite right now without hitting the limit, but running the tests
+ // multiple times runs into the limit. See
+ // `services/core/java/com/android/server/am/DropboxRateLimiter.java` for more information.
+ mDevice.executeShellCommand("am reset-dropbox-rate-limiter");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ uninstallPackage(mDevice, TEST_PKG);
+ }
+}
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java
new file mode 100644
index 0000000..08f9186
--- /dev/null
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package android.cts.gwp_asan;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class RecoverableTest extends GwpAsanBaseTest {
+ private static final String PROCESS_SAMPLING_SYSPROP = "libc.debug.gwp_asan.process_sampling.";
+
+ protected String getTestApk() {
+ return "CtsGwpAsanRecoverable.apk";
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ // Recoverable mode uses process sampling, which only enables GWP-ASan a fraction of the
+ // time (to preserve system-wide memory overhead). Make sure that our test app doesn't use
+ // process sampling, and enables GWP-ASan, when requested, every time. Note: We don't set
+ // the property on the ":gwp_asan_disabled" subprocess, because libc will enable GWP-ASan
+ // because a GWP-ASan property was overwritten.
+ mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG, "1");
+ mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "1");
+ mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_default", "1");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG, "");
+ mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "");
+ mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_default", "");
+ }
+
+ @Test
+ public void testGwpAsanRecoverable() throws Exception {
+ Assert.assertTrue(
+ runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanActivityTest", "testEnablement"));
+ Assert.assertTrue(
+ runDeviceTests(TEST_PKG, TEST_PKG + ".GwpAsanServiceTest", "testEnablement"));
+ }
+
+ @Test
+ public void testCrashToDropboxRecoverable() throws Exception {
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG,
+ TEST_PKG + ".GwpAsanActivityTest",
+ "testCrashToDropboxRecoverableEnabled"));
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG,
+ TEST_PKG + ".GwpAsanActivityTest",
+ "testCrashToDropboxRecoverableDefault"));
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG,
+ TEST_PKG + ".GwpAsanServiceTest",
+ "testCrashToDropboxRecoverableEnabled"));
+ Assert.assertTrue(
+ runDeviceTests(
+ TEST_PKG,
+ TEST_PKG + ".GwpAsanServiceTest",
+ "testCrashToDropboxRecoverableDefault"));
+ }
+}
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/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
index 772e9a9..5323edf 100644
--- a/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
+++ b/hostsidetests/statsdatom/apps/statsdapp/src/com/android/server/cts/device/statsdatom/AtomTests.java
@@ -52,6 +52,7 @@
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
+import android.media.MediaDrm;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.Network;
@@ -95,6 +96,7 @@
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
@@ -1199,4 +1201,22 @@
assertNotNull(session);
}
+
+ @Test
+ public void testMediaDrmAtoms() throws Exception {
+ UUID clearKeyUuid = new UUID(0xe2719d58a985b3c9L, 0x781ab030af78d30eL);
+ byte[] sid = null;
+ try (MediaDrm drm = new MediaDrm(clearKeyUuid)) {
+ drm.setPropertyString("drmErrorTest", "lostState");
+ for (int i = 0; i < 2; i++) {
+ sid = drm.openSession();
+ Assert.assertNotNull("null session id", sid);
+ try {
+ drm.closeSession(sid);
+ } catch (MediaDrm.MediaDrmStateException e) {
+ Log.d(TAG, "expected for lost state");
+ }
+ }
+ }
+ }
}
diff --git a/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaDrmAtomTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaDrmAtomTests.java
new file mode 100644
index 0000000..d752fa3
--- /dev/null
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaDrmAtomTests.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package android.cts.statsdatom.media;
+
+import static android.media.drm.Enums.DrmScheme.CLEAR_KEY_DASH_IF;
+import static android.media.drm.Enums.IDrmFrontend.IDRM_JNI;
+import static android.media.drm.Enums.SecurityLevel.SECURITY_LEVEL_MAX;
+import static android.media.drm.Enums.SecurityLevel.SECURITY_LEVEL_SW_SECURE_CRYPTO;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.cts.statsdatom.lib.AtomTestUtils;
+import android.cts.statsdatom.lib.ConfigUtils;
+import android.cts.statsdatom.lib.DeviceUtils;
+import android.cts.statsdatom.lib.ReportUtils;
+
+import com.android.os.AtomsProto;
+import com.android.os.StatsLog;
+import com.android.os.media.MediaDrmAtoms;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+public class MediaDrmAtomTests extends DeviceTestCase implements IBuildReceiver {
+
+ private IBuildInfo mCtsBuild;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ assertThat(mCtsBuild).isNotNull();
+ // Put a delay to give statsd enough time to remove previous configs and
+ // reports, as well as install the test app.
+ ConfigUtils.removeConfig(getDevice());
+ ReportUtils.clearReports(getDevice());
+ DeviceUtils.installTestApp(getDevice(), DeviceUtils.STATSD_ATOM_TEST_APK,
+ DeviceUtils.STATSD_ATOM_TEST_PKG, mCtsBuild);
+ Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ ConfigUtils.removeConfig(getDevice());
+ ReportUtils.clearReports(getDevice());
+ DeviceUtils.uninstallTestApp(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG);
+ super.tearDown();
+ }
+
+ @Override
+ public void setBuild(IBuildInfo buildInfo) {
+ mCtsBuild = buildInfo;
+ }
+
+ public void testMediaDrmAtom() throws Throwable {
+ // Upload the config.
+ ConfigUtils.uploadConfigForPushedAtoms(getDevice(),
+ DeviceUtils.STATSD_ATOM_TEST_PKG,
+ new int[]{
+ AtomsProto.Atom.MEDIA_DRM_CREATED_FIELD_NUMBER,
+ AtomsProto.Atom.MEDIA_DRM_ERRORED_FIELD_NUMBER,
+ AtomsProto.Atom.MEDIA_DRM_SESSION_OPENED_FIELD_NUMBER
+ });
+ // Trigger AtomTests.
+ DeviceUtils.runDeviceTests(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, ".AtomTests",
+ "testMediaDrmAtoms");
+ List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
+ assertThat(data.size()).isAtLeast(1);
+
+ List<MediaDrmAtoms.MediaDrmCreated> createdList = new ArrayList<>();
+ List<MediaDrmAtoms.MediaDrmSessionOpened> openedList = new ArrayList<>();
+ List<MediaDrmAtoms.MediaDrmErrored> erroredList = new ArrayList<>();
+ int testAppUid = DeviceUtils.getStatsdTestAppUid(getDevice());
+
+ for (StatsLog.EventMetricData event : data) {
+ MediaDrmAtoms.MediaDrmCreated created = event.getAtom().getMediaDrmCreated();
+ MediaDrmAtoms.MediaDrmSessionOpened opened = event.getAtom().getMediaDrmSessionOpened();
+ MediaDrmAtoms.MediaDrmErrored errored = event.getAtom().getMediaDrmErrored();
+
+ if (created != null && created.getUid() == testAppUid) {
+ createdList.add(created);
+ }
+
+ if (opened != null && opened.getUid() == testAppUid) {
+ openedList.add(opened);
+ }
+
+ if (errored != null && errored.getUid() == testAppUid) {
+ erroredList.add(errored);
+ }
+ }
+ UUID clearKeyUuid = new UUID(0xe2719d58a985b3c9L, 0x781ab030af78d30eL);
+ // verify the events
+ assertThat(createdList.size()).isEqualTo(1);
+ assertThat(createdList.get(0).getScheme()).isEqualTo(CLEAR_KEY_DASH_IF);
+ assertThat(createdList.get(0).getUuidMsb())
+ .isEqualTo(clearKeyUuid.getMostSignificantBits());
+ assertThat(createdList.get(0).getUuidLsb())
+ .isEqualTo(clearKeyUuid.getLeastSignificantBits());
+ assertThat(createdList.get(0).getFrontend()).isEqualTo(IDRM_JNI);
+ assertThat(createdList.get(0).getVersion()).isNotEmpty();
+ assertThat(openedList.size()).isEqualTo(2);
+ assertThat(openedList.get(0).getObjectNonce()).isNotEmpty();
+ assertThat(openedList.get(0).getRequestedSecurityLevel()).isEqualTo(SECURITY_LEVEL_MAX);
+ assertThat(openedList.get(0).getOpenedSecurityLevel()).isEqualTo(
+ SECURITY_LEVEL_SW_SECURE_CRYPTO);
+ // TODO : to add check for erroredlist, cdm_error and error_code
+ }
+}
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 7f5e8d3..e8a58bd 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -542,10 +542,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/TEST_MAPPING b/tests/camera/TEST_MAPPING
new file mode 100644
index 0000000..683f34c
--- /dev/null
+++ b/tests/camera/TEST_MAPPING
@@ -0,0 +1,113 @@
+{
+ "kernel-presubmit": [
+ {
+ "name": "CtsCameraTestCases",
+ "options": [
+ {
+ // b/209623644 Unfit for Cuttlefish. Permanently excluded from presubmit.
+ "exclude-filter": "android.hardware.cts.CameraGLTest#testCameraToSurfaceTextureMetadata"
+ },
+ {
+ // b/204295528 Unsuitable for CF. Permanently excluded from presubmit.
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testBasicVideoStabilizationRecording"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testSupportedVideoSizes"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testVideoPreviewSurfaceSharing"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testBasicRecording"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testRecordingFramerateLowToHigh"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testRecordingFromPersistentSurface"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testVideoSnapshot"
+ },
+ {
+ // TODO(b/264226747)
+ "exclude-filter": "android.hardware.camera2.cts.CameraManagerTest#testCameraManagerListenerCallbacks"
+ },
+ {
+ // TODO(b/275072581)
+ "exclude-filter": "android.hardware.camera2.cts.CaptureRequestTest#testFocusDistanceControl"
+ },
+ {
+ // TODO(b/273837507)
+ "exclude-filter": "android.hardware.camera2.cts.DngCreatorTest#testRaw16JpegConsistency"
+ },
+ {
+ // TODO(b/275072024)
+ "exclude-filter": "android.hardware.camera2.cts.ExtendedCameraCharacteristicsTest#testLandscapeToPortraitOverride"
+ },
+ {
+ // TODO(b/274666525)
+ "exclude-filter": "android.hardware.camera2.cts.ImageReaderTest#testLongProcessingRepeatingFlexibleYuv"
+ },
+ {
+ // TODO(b/230479954)
+ "exclude-filter": "android.hardware.camera2.cts.RecordingTest#testIntermediateSurfaceRecording"
+ },
+ {
+ // TODO(b/266222245)
+ "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testAeAndAfCausality"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testBasicTriggerSequence"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testAeThenAfTrigger"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testAfThenAeTrigger"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.RobustnessTest#testSimultaneousTriggers"
+ },
+ {
+ // TODO(b/269815708)
+ "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testAeCompensation"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testBasicRawZslCapture"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testPreviewPersistence"
+ },
+ {
+ "exclude-filter": "android.hardware.camera2.cts.StillCaptureTest#testStillPreviewCombination"
+ },
+ {
+ // TODO(b/269968837)
+ "exclude-filter": "android.hardware.cts.CameraTest#testFocusDistances"
+ },
+ {
+ // TODO(b/262491831)
+ "exclude-filter": "android.hardware.cts.CameraTest#testMustPlayShutterSound"
+ },
+ {
+ "exclude-filter": "android.hardware.cts.CameraTest#testPreviewCallbackWithBuffer"
+ },
+ {
+ "exclude-filter": "android.hardware.cts.CameraTest#testPreviewPictureSizesCombination"
+ },
+ {
+ "exclude-filter": "android.hardware.cts.CameraTest#testTakePicture"
+ },
+ {
+ // TODO(b/269968837)
+ "exclude-filter": "android.hardware.cts.CameraTest#testVideoSnapshot"
+ },
+ {
+ // TODO(b/267597879)
+ "exclude-filter": "android.hardware.multiprocess.camera.cts.CameraEvictionTest#testCamera2AccessCallbackInSplitMode"
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
index 55eae8c..81173bb 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/KeepClearRectsTests.java
@@ -361,6 +361,7 @@
final Rect keepClearRect = new Rect(0, 0, 25, 25);
final View v = createTestViewInActivity(activity, keepClearRect);
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
mTestSession.runOnMainSyncAndWait(() -> v.setPreferKeepClear(true));
assertSameElementsEventually(Arrays.asList(keepClearRect),
() -> getKeepClearRectsForActivity(activity));
@@ -372,15 +373,16 @@
assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
() -> getKeepClearRectsForActivity(activity));
- final List<Rect> expectedRectsInScreenSpace =
- getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName());
- assertSameElementsEventually(expectedRectsInScreenSpace,
+ final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(
+ getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, activity.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
() -> getKeepClearRectsOnDefaultDisplay());
activity.finishAndRemoveTask();
- assertTrue(Collections.disjoint(
- expectedRectsInScreenSpace,
- getKeepClearRectsOnDefaultDisplay()));
+ assertSameElementsEventually(prevKeepClearRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
@@ -419,6 +421,7 @@
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity1, viewBounds);
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
mTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
assertSameElementsEventually(Arrays.asList(viewBounds),
() -> getKeepClearRectsForActivity(activity1));
@@ -438,8 +441,12 @@
mWmState.assertVisibility(activity2.getComponentName(), true);
// Since both activities are fullscreen, WM only takes the keep clear areas from the top one
- assertSameElementsEventually(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
- activity2.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
+ final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS,
+ activity2.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
@@ -449,15 +456,24 @@
translucentTestSession.launchTestActivityOnDisplaySync(
TranslucentTestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity1 = translucentTestSession.getActivity();
-
final Rect viewBounds = new Rect(0, 0, 25, 25);
final View v1 = createTestViewInActivity(activity1, viewBounds);
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
translucentTestSession.runOnMainSyncAndWait(() -> v1.setPreferKeepClear(true));
- assertSameElementsEventually(getRectsInScreenSpace(Arrays.asList(viewBounds),
- activity1.getComponentName()), () -> getKeepClearRectsOnDefaultDisplay());
+ // Add keep-clear rects in the activity
+ final List<Rect> expectedRectsOnDisplay = new ArrayList<Rect>();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(getRectsInScreenSpace(Arrays.asList(viewBounds),
+ activity1.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
+
+ // Start an opaque activity on top
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
final TestActivity activity2 = mTestSession.getActivity();
+
+ // Add keep-clear rects in the opaque activity
final View v2 = createTestViewInActivity(activity2);
mTestSession.runOnMainSyncAndWait(() -> v2.setPreferKeepClearRects(TEST_KEEP_CLEAR_RECTS));
assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
@@ -466,8 +482,13 @@
mWmState.waitAndAssertVisibilityGone(activity1.getComponentName());
mWmState.assertVisibility(activity2.getComponentName(), true);
- assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
- () -> getKeepClearRectsForActivity(activity2));
+ // Only the opaque activity's keep-clear areas should be reported on the display
+ expectedRectsOnDisplay.clear();
+ expectedRectsOnDisplay.addAll(prevKeepClearRectsOnDisplay);
+ expectedRectsOnDisplay.addAll(getRectsInScreenSpace(
+ TEST_KEEP_CLEAR_RECTS, activity2.getComponentName()));
+ assertSameElementsEventually(expectedRectsOnDisplay,
+ () -> getKeepClearRectsOnDefaultDisplay());
}
@Test
@@ -475,30 +496,15 @@
assumeTrue("Skipping test: no split multi-window support",
supportsSplitScreenMultiWindow());
- final LaunchActivityBuilder activityBuilder1 = getLaunchActivityBuilder()
- .setUseInstrumentation()
- .setIntentExtra(extra -> {
- extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
- new ArrayList(TEST_KEEP_CLEAR_RECTS));
- })
- .setTargetActivity(KEEP_CLEAR_RECTS_ACTIVITY);
+ startKeepClearActivitiesInSplitscreen(KEEP_CLEAR_RECTS_ACTIVITY,
+ KEEP_CLEAR_RECTS_ACTIVITY2, Collections.emptyList(), Collections.emptyList());
+ final List<Rect> prevKeepClearRectsOnDisplay = getKeepClearRectsOnDefaultDisplay();
- final LaunchActivityBuilder activityBuilder2 = getLaunchActivityBuilder()
- .setUseInstrumentation()
- .setIntentExtra(extra -> {
- extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
- new ArrayList(TEST_KEEP_CLEAR_RECTS_2));
- })
- .setTargetActivity(KEEP_CLEAR_RECTS_ACTIVITY2);
+ removeRootTask(mWmState.getTaskByActivity(KEEP_CLEAR_RECTS_ACTIVITY).mTaskId);
+ removeRootTask(mWmState.getTaskByActivity(KEEP_CLEAR_RECTS_ACTIVITY2).mTaskId);
- launchActivitiesInSplitScreen(activityBuilder1, activityBuilder2);
-
- waitAndAssertResumedActivity(KEEP_CLEAR_RECTS_ACTIVITY, KEEP_CLEAR_RECTS_ACTIVITY
- + " must be resumed");
- waitAndAssertResumedActivity(KEEP_CLEAR_RECTS_ACTIVITY2, KEEP_CLEAR_RECTS_ACTIVITY2
- + " must be resumed");
- mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY, true);
- mWmState.assertVisibility(KEEP_CLEAR_RECTS_ACTIVITY2, true);
+ startKeepClearActivitiesInSplitscreen(KEEP_CLEAR_RECTS_ACTIVITY,
+ KEEP_CLEAR_RECTS_ACTIVITY2, TEST_KEEP_CLEAR_RECTS, TEST_KEEP_CLEAR_RECTS_2);
assertSameElementsEventually(TEST_KEEP_CLEAR_RECTS,
() -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY));
@@ -506,11 +512,38 @@
() -> getKeepClearRectsForActivity(KEEP_CLEAR_RECTS_ACTIVITY2));
final List<Rect> expected = new ArrayList();
+ expected.addAll(prevKeepClearRectsOnDisplay);
expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS, KEEP_CLEAR_RECTS_ACTIVITY));
expected.addAll(getRectsInScreenSpace(TEST_KEEP_CLEAR_RECTS_2, KEEP_CLEAR_RECTS_ACTIVITY2));
assertSameElementsEventually(expected, () -> getKeepClearRectsOnDefaultDisplay());
}
+ private void startKeepClearActivitiesInSplitscreen(ComponentName activity1,
+ ComponentName activity2, List<Rect> keepClearRects1, List<Rect> keepClearRects2) {
+ final LaunchActivityBuilder activityBuilder1 = getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(activity1)
+ .setIntentExtra(extra -> {
+ extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
+ new ArrayList(keepClearRects1));
+ });
+
+ final LaunchActivityBuilder activityBuilder2 = getLaunchActivityBuilder()
+ .setUseInstrumentation()
+ .setTargetActivity(activity2)
+ .setIntentExtra(extra -> {
+ extra.putParcelableArrayList(EXTRA_KEEP_CLEAR_RECTS,
+ new ArrayList(keepClearRects2));
+ });
+
+ launchActivitiesInSplitScreen(activityBuilder1, activityBuilder2);
+
+ waitAndAssertResumedActivity(activity1, activity1 + " must be resumed");
+ waitAndAssertResumedActivity(activity2, activity2 + " must be resumed");
+ mWmState.assertVisibility(activity1, true);
+ mWmState.assertVisibility(activity2, true);
+ }
+
@Test
public void testUnrestrictedKeepClearRects() throws Exception {
mTestSession.launchTestActivityOnDisplaySync(TestActivity.class, DEFAULT_DISPLAY);
@@ -547,6 +580,7 @@
mTestSession.runOnMainSyncAndWait(() -> {
activity.addView(newView, params);
});
+ waitForIdle();
return newView;
}
@@ -607,7 +641,8 @@
private static <T> void assertSameElementsEventually(List<T> expected, Callable<List<T>> actual)
throws Exception {
- PollingCheck.check("Lists do not have the same elements.",
+ PollingCheck.check("Lists do not have the same elements."
+ + "Expected=" + expected + ", actual=" + actual.call(),
SAME_ELEMENT_ASSERTION_TIMEOUT,
() -> hasSameElements(expected, actual.call()));
}
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java b/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
index 59a1a2b..198e4b3 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/SnapshotTaskTests.java
@@ -17,6 +17,7 @@
package android.server.wm;
import static android.server.wm.WindowManagerTestBase.startActivity;
+import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
@@ -85,6 +86,9 @@
@Test
public void testSetDisablePreviewScreenshots() throws Exception {
+ final View decor = mActivity.getWindow().getDecorView();
+ final int captionBarHeight = decor.getRootWindowInsets().getInsets(captionBar()).top;
+
BitmapPixelChecker pixelChecker = new BitmapPixelChecker(PixelColor.RED);
int retries = 0;
@@ -93,7 +97,8 @@
Bitmap bitmap = mWindowManager.snapshotTaskForRecents(mActivity.getTaskId());
if (bitmap != null) {
int expectedMatching =
- bitmap.getWidth() * bitmap.getHeight() - MATCHING_PIXEL_MISMATCH_ALLOWED;
+ bitmap.getWidth() * bitmap.getHeight() - MATCHING_PIXEL_MISMATCH_ALLOWED
+ - (captionBarHeight * decor.getWidth());
Rect boundToCheck = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
int matchingPixels = pixelChecker.getNumMatchingPixels(bitmap, boundToCheck);
matchesPixels = matchingPixels >= expectedMatching;
diff --git a/tests/media/AndroidManifest.xml b/tests/media/AndroidManifest.xml
index 3a97bbe..0a1f5e0 100644
--- a/tests/media/AndroidManifest.xml
+++ b/tests/media/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.CAMERA" />
<application
android:requestLegacyExternalStorage="true"
diff --git a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
index b1ccc46..4aafdb2 100644
--- a/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
+++ b/tests/media/common/src/android/mediav2/common/cts/CodecTestBase.java
@@ -26,6 +26,11 @@
import static org.junit.Assert.fail;
import android.content.Context;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.params.DynamicRangeProfiles;
import android.hardware.display.DisplayManager;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
@@ -57,6 +62,7 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -65,6 +71,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
/**
* This class comprises of routines that are generic to media codec component trying and testing.
@@ -115,6 +122,7 @@
SystemProperties.getInt("ro.vndk.version", Build.VERSION_CODES.CUR_DEVELOPMENT)
>= Build.VERSION_CODES.TIRAMISU;
public static final boolean IS_HDR_EDITING_SUPPORTED;
+ public static final boolean IS_HDR_CAPTURE_SUPPORTED;
private static final String LOG_TAG = CodecTestBase.class.getSimpleName();
public static final ArrayList<String> HDR_INFO_IN_BITSTREAM_CODECS = new ArrayList<>();
@@ -191,6 +199,26 @@
AACObjectLD, AACObjectELD, AACObjectXHE};
public static final Context CONTEXT =
InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ public static final int MAX_DISPLAY_HEIGHT_CURRENT =
+ Arrays.stream(CONTEXT.getSystemService(DisplayManager.class).getDisplays())
+ .map(Display::getSupportedModes)
+ .flatMap(Stream::of)
+ .max(Comparator.comparing(Display.Mode::getPhysicalHeight))
+ .orElseThrow(() -> new RuntimeException("Failed to determine max height"))
+ .getPhysicalHeight();
+ public static final int MAX_DISPLAY_WIDTH_CURRENT =
+ Arrays.stream(CONTEXT.getSystemService(DisplayManager.class).getDisplays())
+ .map(Display::getSupportedModes)
+ .flatMap(Stream::of)
+ .max(Comparator.comparing(Display.Mode::getPhysicalHeight))
+ .orElseThrow(() -> new RuntimeException("Failed to determine max height"))
+ .getPhysicalWidth();
+ public static final int MAX_DISPLAY_WIDTH_LAND =
+ Math.max(MAX_DISPLAY_WIDTH_CURRENT, MAX_DISPLAY_HEIGHT_CURRENT);
+ public static final int MAX_DISPLAY_HEIGHT_LAND =
+ Math.min(MAX_DISPLAY_WIDTH_CURRENT, MAX_DISPLAY_HEIGHT_CURRENT);
+
public static String mediaTypeSelKeys;
public static String codecPrefix;
public static String mediaTypePrefix;
@@ -199,6 +227,10 @@
CODEC_ALL, // All codecs must support
CODEC_ANY, // At least one codec must support
CODEC_DEFAULT, // Default codec must support
+ CODEC_HW, // If the component is hardware, then it must support
+ CODEC_SHOULD, // Codec support is optional, but recommended
+ CODEC_HW_RECOMMENDED, // Codec support is optional, but strongly recommended if component
+ // is hardware accelerated
CODEC_OPTIONAL; // Codec support is optional
public static String toString(SupportClass supportRequirements) {
@@ -209,6 +241,12 @@
return "CODEC_ANY";
case CODEC_DEFAULT:
return "CODEC_DEFAULT";
+ case CODEC_HW:
+ return "CODEC_HW";
+ case CODEC_SHOULD:
+ return "CODEC_SHOULD";
+ case CODEC_HW_RECOMMENDED:
+ return "CODEC_HW_RECOMMENDED";
case CODEC_OPTIONAL:
return "CODEC_OPTIONAL";
default:
@@ -280,6 +318,7 @@
static {
MEDIA_CODEC_LIST_ALL = new MediaCodecList(MediaCodecList.ALL_CODECS);
MEDIA_CODEC_LIST_REGULAR = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ IS_HDR_CAPTURE_SUPPORTED = isHDRCaptureSupported();
IS_HDR_EDITING_SUPPORTED = isHDREditingSupported();
CODEC_SEL_KEY_MEDIA_TYPE_MAP.put("vp8", MediaFormat.MIMETYPE_VIDEO_VP8);
CODEC_SEL_KEY_MEDIA_TYPE_MAP.put("vp9", MediaFormat.MIMETYPE_VIDEO_VP9);
@@ -435,6 +474,23 @@
+ "for mediaType : " + mediaType + " formats: " + formats);
}
break;
+ case CODEC_HW:
+ if (isHardwareAcceleratedCodec(codecName)) {
+ fail("format(s) not supported by codec: " + codecName + " for mediaType : "
+ + mediaType + " formats: " + formats);
+ }
+ break;
+ case CODEC_SHOULD:
+ Assume.assumeTrue(String.format("format(s) not supported by codec: %s for"
+ + " mediaType : %s. It is recommended to support it",
+ codecName, mediaType), false);
+ break;
+ case CODEC_HW_RECOMMENDED:
+ Assume.assumeTrue(String.format(
+ "format(s) not supported by codec: %s for mediaType : %s. It is %s "
+ + "recommended to support it", codecName, mediaType,
+ isHardwareAcceleratedCodec(codecName) ? "strongly" : ""), false);
+ break;
case CODEC_OPTIONAL:
default:
// the later assumeTrue() ensures we skip the test for unsupported codecs
@@ -455,6 +511,31 @@
return isSupported;
}
+ public static boolean isHDRCaptureSupported() {
+ // If the device supports HDR, hlg support should always return true
+ if (!MediaUtils.hasCamera()) return false;
+ CameraManager cm = CONTEXT.getSystemService(CameraManager.class);
+ try {
+ String[] cameraIds = cm.getCameraIdList();
+ for (String id : cameraIds) {
+ CameraCharacteristics ch = cm.getCameraCharacteristics(id);
+ int[] caps = ch.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES);
+ if (IntStream.of(caps).anyMatch(x -> x
+ == CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT)) {
+ Set<Long> profiles =
+ ch.get(CameraCharacteristics.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES)
+ .getSupportedProfiles();
+ if (profiles.contains(DynamicRangeProfiles.HLG10)) return true;
+ }
+ }
+ } catch (CameraAccessException e) {
+ Log.e(LOG_TAG, "encountered " + e.getMessage()
+ + " marking hdr capture to be available to catch your attention");
+ return true;
+ }
+ return false;
+ }
+
public static boolean isHDREditingSupported() {
for (MediaCodecInfo codecInfo : MEDIA_CODEC_LIST_REGULAR.getCodecInfos()) {
if (!codecInfo.isEncoder()) {
@@ -508,7 +589,7 @@
public static boolean canDisplaySupportHDRContent() {
DisplayManager displayManager = CONTEXT.getSystemService(DisplayManager.class);
return displayManager.getDisplay(Display.DEFAULT_DISPLAY).getHdrCapabilities()
- .getSupportedHdrTypes().length != 0;
+ .getSupportedHdrTypes().length > 0;
}
public static boolean areFormatsSupported(String name, String mediaType,
diff --git a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
index 799aa72..8162e55 100644
--- a/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecDecoderValidationTest.java
@@ -19,6 +19,7 @@
import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ALL;
import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ANY;
import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_DEFAULT;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
@@ -34,6 +35,7 @@
import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.MediaUtils;
import org.junit.Assume;
import org.junit.Test;
@@ -86,6 +88,7 @@
private static final String MEDIA_TYPE_VORBIS = MediaFormat.MIMETYPE_AUDIO_VORBIS;
private static final String MEDIA_TYPE_OPUS = MediaFormat.MIMETYPE_AUDIO_OPUS;
private static final String MEDIA_TYPE_MPEG2 = MediaFormat.MIMETYPE_VIDEO_MPEG2;
+ private static final String MEDIA_TYPE_H263 = MediaFormat.MIMETYPE_VIDEO_H263;
private static final String MEDIA_TYPE_MPEG4 = MediaFormat.MIMETYPE_VIDEO_MPEG4;
private static final String MEDIA_TYPE_AVC = MediaFormat.MIMETYPE_VIDEO_AVC;
private static final String MEDIA_TYPE_VP8 = MediaFormat.MIMETYPE_VIDEO_VP8;
@@ -126,6 +129,7 @@
// mediaType, array list of test files (underlying elementary stream is same, except they
// are placed in different containers), ref file, rms error, checksum, sample rate,
// channel count, width, height, SupportClass
+ // TODO(b/275171549) Add tests as per TV multimedia requirements in 2.3.2
final List<Object[]> exhaustiveArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
// vp9 test vectors with no-show frames signalled in alternate ways
{MEDIA_TYPE_VP9, new String[]{"bbb_340x280_768kbps_30fps_vp9.webm",
@@ -151,19 +155,10 @@
{MEDIA_TYPE_MP3, new String[]{"bbb_2ch_44kHz_lame_crc.mp3"},
"bbb_2ch_44kHz_s16le.raw", 104.089027f, -1L, 44100, 2, -1, -1, CODEC_ALL},
- // vp9 test vectors with AQ mode enabled
- {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9.webm"},
- null, -1.0f, 1319105122L, -1, -1, 1280, 720, CODEC_ALL},
- {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9.webm"},
- null, -1.0f, 4128150660L, -1, -1, 1280, 720, CODEC_ALL},
- {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9.webm"},
- null, -1.0f, 156928091L, -1, -1, 1280, 720, CODEC_ALL},
- {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"},
- null, -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ALL},
-
// video test vectors of non standard sizes
{MEDIA_TYPE_MPEG2, new String[]{"bbb_642x642_2mbps_30fps_mpeg2.mp4"},
- null, -1.0f, -1L, -1, -1, 642, 642, CODEC_ANY},
+ null, -1.0f, -1L, -1, -1, 642, 642,
+ MediaUtils.isTv() ? CODEC_ANY : CODEC_OPTIONAL},
{MEDIA_TYPE_AVC, new String[]{"bbb_642x642_1mbps_30fps_avc.mp4"},
null, -1.0f, 3947092788L, -1, -1, 642, 642, CODEC_ANY},
{MEDIA_TYPE_VP8, new String[]{"bbb_642x642_1mbps_30fps_vp8.webm"},
@@ -177,6 +172,62 @@
{MEDIA_TYPE_MPEG4, new String[]{"bbb_130x130_192kbps_15fps_mpeg4.mp4"},
null, -1.0f, -1L, -1, -1, 130, 130, CODEC_ANY},
+ // video test vectors covering cdd requirements
+ // @CddTest(requirement="5.3.1/C-1-1")
+ {MEDIA_TYPE_MPEG2, new String[]{"bbb_1920x1080_mpeg2_main_high.mp4"}, null, -1.0f,
+ -1L, -1, -1, 1920, 1080, MediaUtils.isTv() ? CODEC_ANY : CODEC_OPTIONAL},
+
+ // @CddTest(requirement="5.3.2/C-1-1")
+ {MEDIA_TYPE_H263, new String[]{"bbb_352x288_384kbps_30fps_h263_baseline_l3.mp4"},
+ null, -1.0f, -1L, -1, -1, 352, 288, CODEC_ALL},
+ {MEDIA_TYPE_H263, new String[]{"bbb_176x144_125kbps_15fps_h263_baseline_l45.mkv"},
+ null, -1.0f, -1L, -1, -1, 176, 144, CODEC_ALL},
+
+ // @CddTest(requirement="5.3.3/C-1-1")
+ {MEDIA_TYPE_MPEG4, new String[]{"bbb_352x288_384kbps_30fps_mpeg4_simple_l3.mp4"},
+ null, -1.0f, -1L, -1, -1, 352, 288, CODEC_ALL},
+
+ // @CddTest(requirements={"5.3.4/C-1-1", "5.3.4/C-1-2", "5.3.4/C-2-1"})
+ {MEDIA_TYPE_AVC, new String[]{"bbb_320x240_30fps_avc_baseline_l13.mp4"}, null,
+ -1.0f, 2227756491L, -1, -1, 320, 240, CODEC_ALL},
+ {MEDIA_TYPE_AVC, new String[]{"bbb_320x240_30fps_avc_main_l31.mp4"}, null, -1.0f,
+ 3167475817L, -1, -1, 320, 240, CODEC_ALL},
+ {MEDIA_TYPE_AVC, new String[]{"bbb_720x480_30fps_avc_baseline_l30.mp4"}, null,
+ -1.0f, 256699624L, -1, -1, 720, 480, CODEC_ALL},
+ {MEDIA_TYPE_AVC, new String[]{"bbb_720x480_30fps_avc_main_l31.mp4"}, null, -1.0f,
+ 1729385096L, -1, -1, 720, 480, CODEC_ALL},
+ // 5.3.4/C-1-2 mandates 720p support for avc decoders, hence this is being tested
+ // without any resolution check unlike the higher resolution tests for other codecs
+ {MEDIA_TYPE_AVC, new String[]{"bbb_1280x720_30fps_avc_baseline_l31.mp4"}, null,
+ -1.0f, 4290313980L, -1, -1, 1280, 720, CODEC_ALL},
+ {MEDIA_TYPE_AVC, new String[]{"bbb_1280x720_30fps_avc_main_l31.mp4"}, null, -1.0f,
+ 3895426718L, -1, -1, 1280, 720, CODEC_ALL},
+
+ // @CddTest(requirement="5.3.5/C-1-1")
+ {MEDIA_TYPE_HEVC, new String[]{"bbb_352x288_30fps_hevc_main_l2.mp4"}, null, -1.0f,
+ 40958220L, -1, -1, 352, 288, CODEC_ALL},
+ {MEDIA_TYPE_HEVC, new String[]{"bbb_720x480_30fps_hevc_main_l3.mp4"}, null, -1.0f,
+ 3167173427L, -1, -1, 720, 480, CODEC_ALL},
+
+ // @CddTest(requirement="5.3.6/C-1-1")
+ {MEDIA_TYPE_VP8, new String[]{"bbb_320x180_30fps_vp8.mkv"}, null, -1.0f,
+ 434981332L, -1, -1, 320, 180, CODEC_ALL},
+ {MEDIA_TYPE_VP8, new String[]{"bbb_640x360_512kbps_30fps_vp8.webm"}, null, -1.0f,
+ 1625674868L, -1, -1, 640, 360, CODEC_ALL},
+
+ // @CddTest(requirement="5.3.7/C-1-1")
+ {MEDIA_TYPE_VP9, new String[]{"bbb_320x180_30fps_vp9.mkv"}, null, -1.0f,
+ 2746035687L, -1, -1, 320, 180, CODEC_ALL},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_640x360_512kbps_30fps_vp9.webm"}, null, -1.0f,
+ 2974952943L, -1, -1, 640, 360, CODEC_ALL},
+
+ // @CddTest(requirement="5.3.9/C-1-1")
+ {MEDIA_TYPE_AV1, new String[]{"cosmat_720x480_30fps_av1_10bit.mkv"}, null,
+ -1.0f, 2380523095L, -1, -1, 720, 480, CODEC_ALL},
+ {MEDIA_TYPE_AV1, new String[]{"bbb_720x480_30fps_av1.mkv"}, null, -1.0f,
+ 3229978305L, -1, -1, 720, 480, CODEC_ALL},
+
+
// audio test vectors covering cdd sec 5.1.3
// amrnb
{MEDIA_TYPE_AMRNB, new String[]{"audio/bbb_mono_8kHz_12.2kbps_amrnb.3gp"},
@@ -630,6 +681,76 @@
CODEC_ALL},
}));
}
+
+ // video test vectors covering cdd requirements
+ if (MAX_DISPLAY_HEIGHT_LAND >= 2160) {
+ exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
+ // @CddTest(requirements={"5.3.5/C-1-2", "5.3.5/C-2-1"})
+ {MEDIA_TYPE_HEVC, new String[]{"bbb_3840x2160_30fps_hevc_main_l50.mp4"}, null,
+ -1.0f, 2312004815L, -1, -1, 3840, 2160, CODEC_ANY},
+ {MEDIA_TYPE_VP8, new String[]{"bbb_3840x2160_30fps_vp8.mkv"}, null, -1.0f,
+ 632639587L, -1, -1, 3840, 2160, CODEC_ANY},
+ // @CddTest(requirements={"5.3.7/C-2-1", "5.3.7/C-3-1"})
+ {MEDIA_TYPE_VP9, new String[]{"bbb_3840x2160_30fps_vp9.mkv"}, null, -1.0f,
+ 279585450L, -1, -1, 3840, 2160, CODEC_ANY},
+ // @CddTest(requirements={"5.3.9/C-2-2"})
+ {MEDIA_TYPE_AV1, new String[]{"bbb_3840x2160_30fps_av1.mkv"}, null, -1.0f,
+ 100543644L, -1, -1, 3840, 2160, CODEC_ANY},
+ {MEDIA_TYPE_AV1, new String[]{"cosmat_3840x2160_30fps_av1_10bit.mkv"}, null,
+ -1.0f, 4214931794L, -1, -1, 3840, 2160, CODEC_ANY},
+ }));
+ }
+ if (MAX_DISPLAY_HEIGHT_LAND >= 1080) {
+ exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
+ // @CddTest(requirement="5.3.4/C-2-2")
+ {MEDIA_TYPE_AVC, new String[]{"bbb_1920x1080_avc_baseline_l40.mp4"}, null,
+ -1.0f, 1332773556L, -1, -1, 1920, 1080, CODEC_ANY},
+ {MEDIA_TYPE_AVC, new String[]{"bbb_1920x1080_avc_main_l40.mp4"}, null, -1.0f,
+ 2656846432L, -1, -1, 1920, 1080, CODEC_ANY},
+ // @CddTest(requirements={"5.3.5/C-1-2", "5.3.5/C-2-1"})
+ {MEDIA_TYPE_HEVC, new String[]{"bbb_1920x1080_hevc_main_l40.mp4"}, null,
+ -1.0f, 3214459078L, -1, -1, 1920, 1080, CODEC_ANY},
+ // @CddTest(requirement="5.3.6/C-2-2")
+ {MEDIA_TYPE_VP8, new String[]{"bbb_1920x1080_30fps_vp8.mkv"}, null, -1.0f,
+ 2302247702L, -1, -1, 1920, 1080, CODEC_ANY},
+ // @CddTest(requirements={"5.3.7/C-2-1", "5.3.7/C-3-1"})
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1920x1080_vp9_main_l40.mkv"}, null, -1.0f,
+ 2637993192L, -1, -1, 1920, 1080, CODEC_ANY},
+ // @CddTest(requirements={"5.3.9/C-2-2"})
+ {MEDIA_TYPE_AV1, new String[]{"bbb_1920x1080_30fps_av1.mkv"}, null, -1.0f,
+ 3428220318L, -1, -1, 1920, 1080, CODEC_ANY},
+ {MEDIA_TYPE_AV1, new String[]{"cosmat_1920x1080_30fps_av1_10bit.mkv"}, null,
+ -1.0f, 3477727836L, -1, -1, 1920, 1080, CODEC_ANY},
+ }));
+ }
+ if (MAX_DISPLAY_HEIGHT_LAND >= 720) {
+ exhaustiveArgsList.addAll(Arrays.asList(new Object[][]{
+ // @CddTest(requirement="5.3.5/C-1-2")
+ {MEDIA_TYPE_HEVC, new String[]{"bbb_1280x720_1mbps_30fps_hevc_nob.mp4"},
+ null, -1.0f, 3576783828L, -1, -1, 1280, 720, CODEC_ANY},
+ // @CddTest(requirement="5.3.6/C-2-1")
+ {MEDIA_TYPE_VP8, new String[]{"bbb_1280x720_30fps_vp8.mkv"}, null, -1.0f,
+ 2390565854L, -1, -1, 1280, 720, CODEC_ANY},
+ // @CddTest(requirements={"5.3.7/C-2-1", "5.3.7/C-3-1"})
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"}, null,
+ -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ANY},
+ // @CddTest(requirements={"5.3.9/C-2-1"})
+ {MEDIA_TYPE_AV1, new String[]{"bbb_1280x720_1mbps_30fps_av1.webm"}, null, -1.0f,
+ 4202081555L, -1, -1, 1280, 720, CODEC_ANY},
+ {MEDIA_TYPE_AV1, new String[]{"cosmat_1280x720_24fps_1200kbps_av1_10bit.mkv"},
+ null, -1.0f, 2039973562L, -1, -1, 1280, 720, CODEC_ANY},
+
+ // vp9 test vectors with AQ mode enabled
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_800kbps_30fps_vp9.webm"},
+ null, -1.0f, 1319105122L, -1, -1, 1280, 720, CODEC_ANY},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1200kbps_30fps_vp9.webm"},
+ null, -1.0f, 4128150660L, -1, -1, 1280, 720, CODEC_ANY},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_1600kbps_30fps_vp9.webm"},
+ null, -1.0f, 156928091L, -1, -1, 1280, 720, CODEC_ANY},
+ {MEDIA_TYPE_VP9, new String[]{"bbb_1280x720_2000kbps_30fps_vp9.webm"},
+ null, -1.0f, 3902485256L, -1, -1, 1280, 720, CODEC_ANY},
+ }));
+ }
return prepareParamList(exhaustiveArgsList, isEncoder, needAudio, needVideo, false);
}
@@ -642,7 +763,11 @@
// "5.1.3", "5.1.2/C-1-11" are covered partially
@CddTest(requirements = {"5.1.2/C-1-1", "5.1.2/C-1-2", "5.1.2/C-1-3", "5.1.2/C-1-4",
"5.1.2/C-1-11", "5.1.2/C-1-5", "5.1.2/C-1-6", "5.1.2/C-1-8", "5.1.2/C-1-9",
- "5.1.2/C-1-10", "5.1.2/C-2-1", "5.1.2/C-6-1", "5.1.3"})
+ "5.1.2/C-1-10", "5.1.2/C-2-1", "5.1.2/C-6-1", "5.1.3", "5.3.1/C-1-1", "5.3.2/C-1-1",
+ "5.3.3/C-1-1", "5.3.4/C-1-1", "5.3.4/C-1-2", "5.3.4/C-2-1", "5.3.4/C-2-2",
+ "5.3.5/C-1-1", "5.3.5/C-1-2", "5.3.5/C-2-1", "5.3.6/C-1-1", "5.3.6/C-2-1",
+ "5.3.6/C-2-2", "5.3.7/C-1-1", "5.3.7/C-2-1", "5.3.7/C-3-1", "5.3.9/C-1-1",
+ "5.3.9/C-2-1", "5.3.9/C-2-2"})
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testDecodeAndValidate() throws IOException, InterruptedException {
diff --git a/tests/media/src/android/mediav2/cts/CodecInfoTest.java b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
index 5896b23..d295a59 100644
--- a/tests/media/src/android/mediav2/cts/CodecInfoTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecInfoTest.java
@@ -19,28 +19,30 @@
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_Format32bitABGR2101010;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedPlanar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420PackedSemiPlanar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar;
+import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
import static android.media.MediaCodecInfo.CodecCapabilities.FEATURE_HdrEditing;
-import static android.mediav2.common.cts.CodecTestBase.CONTEXT;
import static android.mediav2.common.cts.CodecTestBase.FIRST_SDK_IS_AT_LEAST_T;
import static android.mediav2.common.cts.CodecTestBase.IS_AT_LEAST_T;
+import static android.mediav2.common.cts.CodecTestBase.IS_HDR_CAPTURE_SUPPORTED;
import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR10_MAP;
import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR10_PLUS_MAP;
-import static android.mediav2.common.cts.CodecTestBase.PROFILE_HDR_MAP;
import static android.mediav2.common.cts.CodecTestBase.VNDK_IS_AT_LEAST_T;
+import static android.mediav2.common.cts.CodecTestBase.canDisplaySupportHDRContent;
import static android.mediav2.common.cts.CodecTestBase.isVendorCodec;
import static android.mediav2.common.cts.CodecTestBase.selectCodecs;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import android.hardware.display.DisplayManager;
import android.media.MediaCodecInfo;
import android.media.MediaCodecInfo.CodecProfileLevel;
import android.media.MediaCodecList;
import android.mediav2.common.cts.CodecTestBase;
import android.os.Build;
-import android.view.Display;
import androidx.test.filters.SmallTest;
@@ -68,19 +70,11 @@
@RunWith(Parameterized.class)
public class CodecInfoTest {
private static final String LOG_TAG = CodecInfoTest.class.getSimpleName();
- private static final int[] DISPLAY_HDR_TYPES;
public String mMediaType;
public String mCodecName;
public MediaCodecInfo mCodecInfo;
- static {
- DisplayManager displayManager = CONTEXT.getSystemService(DisplayManager.class);
- DISPLAY_HDR_TYPES =
- displayManager.getDisplay(Display.DEFAULT_DISPLAY).getHdrCapabilities()
- .getSupportedHdrTypes();
- }
-
public CodecInfoTest(String mediaType, String codecName, MediaCodecInfo codecInfo) {
mMediaType = mediaType;
mCodecName = codecName;
@@ -145,7 +139,7 @@
// native level, separate the following to independent checks for HDR10 and HDR10+
if (isHdr10Profile || isHdr10PlusProfile) {
assertTrue(mCodecInfo.getName() + " Advertises support for HDR10/HDR10+ profile " +
- pl.profile + " without any HDR display", DISPLAY_HDR_TYPES.length > 0);
+ pl.profile + " without any HDR display", canDisplaySupportHDRContent());
}
}
}
@@ -155,7 +149,8 @@
* formats. The test only checks if the decoder/encoder is advertising the required color
* format. It doesn't verify if it actually supports by decoding/encoding.
*/
- @CddTest(requirements = {"5.1.7/C-1-2", "5.1.7/C-4-1", "5.12/C-6-5", "5.12/C-7-3"})
+ @CddTest(requirements = {"5.1.7/C-1-2", "5.1.7/C-1-3", "5.1.7/C-4-1", "5.12/C-6-5",
+ "5.12/C-7-1", "5.12/C-7-3"})
@Test
public void testColorFormatSupport() {
Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
@@ -164,20 +159,54 @@
IntStream.of(caps.colorFormats)
.noneMatch(x -> x == COLOR_FormatYUV420Flexible));
- // Encoders that support FEATURE_HdrEditing, must support P010 and ABGR2101010
- // color format and at least one HDR profile
- boolean hdrEditingSupported = caps.isFeatureSupported(FEATURE_HdrEditing);
- if (mCodecInfo.isEncoder() && hdrEditingSupported) {
- boolean abgr2101010Supported =
- IntStream.of(caps.colorFormats)
- .anyMatch(x -> x == COLOR_Format32bitABGR2101010);
- boolean p010Supported =
- IntStream.of(caps.colorFormats).anyMatch(x -> x == COLOR_FormatYUVP010);
- assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support " +
- "COLOR_FormatABGR2101010 and COLOR_FormatYUVP010 color formats.",
- abgr2101010Supported && p010Supported);
- assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support any HDR " +
- "profiles.", CodecTestBase.doesCodecSupportHDRProfile(mCodecName, mMediaType));
+ assertFalse(mCodecInfo.getName()
+ + " does not support at least one of planar or semi planar yuv 420 888",
+ IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUV420PackedPlanar)
+ && IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUV420Planar)
+ && IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUV420PackedSemiPlanar)
+ && IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUV420SemiPlanar));
+
+ boolean canHandleHdr = CodecTestBase.doesCodecSupportHDRProfile(mCodecName, mMediaType);
+ if (mCodecInfo.isEncoder()) {
+ if (IS_HDR_CAPTURE_SUPPORTED && canHandleHdr) {
+ assertFalse(mCodecInfo.getName()
+ + " supports HDR profile but does not support COLOR_FormatYUVP010",
+ IntStream.of(caps.colorFormats).noneMatch(x -> x == COLOR_FormatYUVP010));
+ }
+
+ // Encoders that support FEATURE_HdrEditing, must support ABGR2101010 color format
+ // and at least one HDR profile
+ boolean hdrEditingSupported = caps.isFeatureSupported(FEATURE_HdrEditing);
+ if (hdrEditingSupported) {
+ boolean abgr2101010Supported = IntStream.of(caps.colorFormats)
+ .anyMatch(x -> x == COLOR_Format32bitABGR2101010);
+ assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support"
+ + " COLOR_FormatABGR2101010 color formats.", abgr2101010Supported);
+ assertTrue(mCodecName + " supports FEATURE_HdrEditing, but does not support"
+ + " any HDR profiles.", canHandleHdr);
+ }
+ } else {
+ if (FIRST_SDK_IS_AT_LEAST_T && VNDK_IS_AT_LEAST_T && canDisplaySupportHDRContent()) {
+ 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 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 but does not support "
+ + "COLOR_FormatYUVP010",
+ IntStream.of(caps.colorFormats)
+ .noneMatch(x -> x == COLOR_FormatYUVP010));
+ }
+ }
}
// COLOR_FormatSurface support is an existing requirement, but we did not
@@ -190,41 +219,6 @@
}
}
- /** 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.
- */
- @CddTest(requirements = "5.12/C-6-5")
- @Test
- public void testP010SupportForHDRDisplay() {
- Assume.assumeTrue("Test is applicable for video codecs", mMediaType.startsWith("video/"));
- MediaCodecInfo.CodecCapabilities caps = mCodecInfo.getCapabilitiesForType(mMediaType);
- int[] HdrProfileArray = PROFILE_HDR_MAP.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)) {
- 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));
- }
- }
- }
- }
- }
-
/**
* For all the available encoders on the device, the test checks if their encoding
* capabilities are in sync with the device's decoding capabilities.
diff --git a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
index 9a6b350..1405ed3 100644
--- a/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
+++ b/tests/media/src/android/mediav2/cts/EncoderProfileLevelTest.java
@@ -309,6 +309,10 @@
new Pair<>(new int[]{HEVCProfileMain}, HEVCMainTierLevel3));
PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_VP9,
new Pair<>(new int[]{VP9Profile0}, VP9Level3));
+ if (IS_AT_LEAST_U) {
+ PROFILE_LEVEL_CDD.put(MediaFormat.MIMETYPE_VIDEO_AV1,
+ new Pair<>(new int[]{AV1ProfileMain8, AV1ProfileMain10}, -1));
+ }
}
void checkIfTrackFormatIsOk(MediaFormat trackFormat) {
@@ -362,7 +366,7 @@
* Check description of class {@link EncoderProfileLevelTest}
*/
@CddTest(requirements = {"2.2.2/5.1/H-0-3", "2.2.2/5.1/H-0-4", "2.2.2/5.1/H-0-5", "5/C-0-3",
- "5.2.1/C-1-1", "5.2.2/C-1-1", "5.2.4/C-1-2", "5.2.5/C-1-1"})
+ "5.2.1/C-1-1", "5.2.2/C-1-1", "5.2.4/C-1-2", "5.2.5/C-1-1", "5.2.6/C-1-1"})
@ApiTest(apis = {"android.media.MediaFormat#KEY_PROFILE",
"android.media.MediaFormat#KEY_AAC_PROFILE",
"android.media.MediaFormat#KEY_LEVEL"})
diff --git a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
index 1ec8981..335099c 100644
--- a/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/VideoEncoderTest.java
@@ -18,10 +18,13 @@
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible;
import static android.media.MediaCodecInfo.CodecCapabilities.COLOR_FormatYUVP010;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_ANY;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_HW;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_HW_RECOMMENDED;
import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_OPTIONAL;
+import static android.mediav2.common.cts.CodecTestBase.SupportClass.CODEC_SHOULD;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
import android.media.MediaFormat;
import android.mediav2.common.cts.CodecEncoderTestBase;
@@ -39,7 +42,6 @@
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -58,100 +60,184 @@
*/
@RunWith(Parameterized.class)
public class VideoEncoderTest extends CodecEncoderTestBase {
+ private final SupportClass mSupportRequirements;
+
public VideoEncoderTest(String encoder, String mediaType, EncoderConfigParams encCfgParams,
- @SuppressWarnings("unused") String testLabel, String allTestParams) {
+ SupportClass supportRequirements, @SuppressWarnings("unused") String testLabel,
+ String allTestParams) {
super(encoder, mediaType, new EncoderConfigParams[]{encCfgParams}, allTestParams);
+ mSupportRequirements = supportRequirements;
}
private static EncoderConfigParams getVideoEncoderCfgParams(String mediaType, int bitRate,
- int width, int height, int colorFormat, int maxBFrames) {
+ int width, int height, int frameRate, int colorFormat, int maxBFrames) {
return new EncoderConfigParams.Builder(mediaType)
.setBitRate(bitRate)
.setWidth(width)
.setHeight(height)
+ .setFrameRate(frameRate)
.setColorFormat(colorFormat)
.setMaxBFrames(maxBFrames)
.build();
}
- private static List<Object[]> flattenParams(List<Object[]> params) {
+ private static List<Object[]> prepareTestArgs(List<Object[]> args) {
List<Object[]> argsList = new ArrayList<>();
- for (Object[] param : params) {
- String mediaType = (String) param[0];
- int[] bitRates = (int[]) param[1];
- int[] widths = (int[]) param[2];
- int[] heights = (int[]) param[3];
+ for (Object[] arg : args) {
+ String mediaType = (String) arg[0];
+ int bitRate = (int) arg[1];
+ int width = (int) arg[2];
+ int height = (int) arg[3];
+ int frameRate = (int) arg[4];
+ int colorFormat = (int) arg[5];
int[] maxBFrames = {0, 2};
- int colorFormat = (int) param[4];
- for (int br : bitRates) {
- for (int wd : widths) {
- for (int ht : heights) {
- for (int maxBframe : maxBFrames) {
- Object[] testArgs = new Object[3];
- if (maxBframe != 0) {
- if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
- && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
- continue;
- }
- }
- testArgs[0] = param[0];
- testArgs[1] = getVideoEncoderCfgParams(mediaType, br, wd, ht,
- colorFormat, maxBframe);
- testArgs[2] = String.format("%dkbps_%dx%d_%s_%d-bframes", br / 1000, wd,
- ht, colorFormatToString(colorFormat, -1), maxBframe);
- argsList.add(testArgs);
- }
+ for (int maxBframe : maxBFrames) {
+ Object[] testArgs = new Object[4];
+ if (maxBframe != 0) {
+ if (!mediaType.equals(MediaFormat.MIMETYPE_VIDEO_AVC)
+ && !mediaType.equals(MediaFormat.MIMETYPE_VIDEO_HEVC)) {
+ continue;
}
}
+ testArgs[0] = arg[0];
+ testArgs[1] = getVideoEncoderCfgParams(mediaType, bitRate, width, height, frameRate,
+ colorFormat, maxBframe);
+ testArgs[2] = arg[6];
+ testArgs[3] = String.format("%dkbps_%dx%d_%s_%d-bframes", bitRate / 1000, width,
+ height, colorFormatToString(colorFormat, -1), maxBframe);
+ argsList.add(testArgs);
}
}
return argsList;
}
- @Parameterized.Parameters(name = "{index}_{0}_{1}_{3}")
+ private static SupportClass getSupportRequirementsDynamic(String mediaType, int width,
+ int height) {
+ ArrayList<MediaFormat> formats = new ArrayList<>();
+ formats.add(MediaFormat.createVideoFormat(mediaType, width, height));
+ return selectCodecs(mediaType, formats, null, true).size() != 0 ? CODEC_ANY : CODEC_SHOULD;
+ }
+
+ @Parameterized.Parameters(name = "{index}_{0}_{1}_{4}")
public static Collection<Object[]> input() {
final boolean isEncoder = true;
final boolean needAudio = false;
final boolean needVideo = true;
List<Object[]> defArgsList = new ArrayList<>(Arrays.asList(new Object[][]{
- // mediaType, arrays of bit-rates, width, height, color format
- {MediaFormat.MIMETYPE_VIDEO_H263, new int[]{32000, 64000}, new int[]{176},
- new int[]{144}, COLOR_FormatYUV420Flexible},
- {MediaFormat.MIMETYPE_VIDEO_MPEG4, new int[]{32000, 64000}, new int[]{176},
- new int[]{144}, COLOR_FormatYUV420Flexible},
- {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUV420Flexible},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUV420Flexible},
- {MediaFormat.MIMETYPE_VIDEO_VP8, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUV420Flexible},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUV420Flexible},
- {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUV420Flexible},
+ // mediaType, width, height, bit-rate, frame-rate, color format, support class
+ {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 128, 96, 15, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_H263, 64000, 176, 144, 15, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 128, 96, 15, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_H263, 128000, 176, 144, 15, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+
+ {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 128, 96, 15, COLOR_FormatYUV420Flexible,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_MPEG4, 64000, 176, 144, 15, COLOR_FormatYUV420Flexible,
+ CODEC_OPTIONAL},
+
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30,
+ COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+ MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720)},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1080, 30,
+ COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+ MediaFormat.MIMETYPE_VIDEO_AVC, 1920, 1080)},
+
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 800000, 320, 180, 30, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 2000000, 640, 360, 30, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 4000000, 1280, 720, 30,
+ COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+ MediaFormat.MIMETYPE_VIDEO_VP8, 1280, 720)},
+ {MediaFormat.MIMETYPE_VIDEO_VP8, 10000000, 1920, 1080, 30,
+ COLOR_FormatYUV420Flexible, getSupportRequirementsDynamic(
+ MediaFormat.MIMETYPE_VIDEO_VP8, 1920, 1080)},
+
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, COLOR_FormatYUV420Flexible,
+ CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, COLOR_FormatYUV420Flexible,
+ CODEC_HW_RECOMMENDED},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30,
+ COLOR_FormatYUV420Flexible, CODEC_ANY},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW_RECOMMENDED},
+
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 5000000, 720, 480, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 8000000, 1280, 720, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 16000000, 1920, 1080, 30,
+ COLOR_FormatYUV420Flexible, CODEC_HW},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 50000000, 3840, 2160, 30,
+ COLOR_FormatYUV420Flexible, CODEC_SHOULD},
}));
// P010 support was added in Android T, hence limit the following tests to Android T and
// above
if (IS_AT_LEAST_T) {
defArgsList.addAll(Arrays.asList(new Object[][]{
- {MediaFormat.MIMETYPE_VIDEO_AVC, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUVP010},
- {MediaFormat.MIMETYPE_VIDEO_HEVC, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUVP010},
- {MediaFormat.MIMETYPE_VIDEO_VP9, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUVP010},
- {MediaFormat.MIMETYPE_VIDEO_AV1, new int[]{256000}, new int[]{352, 480},
- new int[]{240, 360}, COLOR_FormatYUVP010},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 384000, 320, 240, 20, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 2000000, 720, 480, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 3000000, 1280, 720, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_AVC, 10000000, 1920, 1080, 30,
+ COLOR_FormatYUVP010, CODEC_OPTIONAL},
+
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 1600000, 720, 480, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 4000000, 1280, 720, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 5000000, 1920, 1080, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_VP9, 20000000, 3840, 2160, 30,
+ COLOR_FormatYUVP010, CODEC_OPTIONAL},
+
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 1600000, 720, 480, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 4000000, 1280, 720, 30, COLOR_FormatYUVP010,
+ CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 5000000, 1920, 1080, 30,
+ COLOR_FormatYUVP010, CODEC_OPTIONAL},
+ {MediaFormat.MIMETYPE_VIDEO_HEVC, 20000000, 3840, 2160, 30,
+ COLOR_FormatYUVP010, CODEC_OPTIONAL},
+
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 5000000, 720, 480, 30, COLOR_FormatYUVP010,
+ CODEC_HW},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 8000000, 1280, 720, 30, COLOR_FormatYUVP010,
+ CODEC_HW},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 16000000, 1920, 1080, 30,
+ COLOR_FormatYUVP010, CODEC_HW},
+ {MediaFormat.MIMETYPE_VIDEO_AV1, 50000000, 3840, 2160, 30,
+ COLOR_FormatYUVP010, CODEC_SHOULD},
}));
}
- List<Object[]> argsList = flattenParams(defArgsList);
+ List<Object[]> argsList = prepareTestArgs(defArgsList);
return prepareParamList(argsList, isEncoder, needAudio, needVideo, false);
}
/**
* Check description of class {@link VideoEncoderTest}
*/
- @CddTest(requirements = {"5.1.7/C-1-2", "5.12/C-6-5"})
+ @CddTest(requirements = {"5.2.1/C-1-1", "5.2.2/C-1-2", "5.2.2/C-2-1", "5.2.3/C-1-1",
+ "5.2.3/C-1-2", "5.2.3/C-2-1", "5.2.4/C-1-1", "5.2.6/C-2-1"})
@ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Flexible",
"MediaCodecInfo.CodecCapabilities#COLOR_FormatYUVP010"})
@LargeTest
@@ -164,11 +250,11 @@
Assume.assumeTrue(mCodecName + " doesn't support " + colorFormatToString(
mEncCfgParams[0].mColorFormat, mEncCfgParams[0].mInputBitDepth),
hasSupportForColorFormat(mCodecName, mMediaType,
- mEncCfgParams[0].mColorFormat));
+ mEncCfgParams[0].mColorFormat));
}
ArrayList<MediaFormat> formats = new ArrayList<>();
formats.add(mEncCfgParams[0].getFormat());
- checkFormatSupport(mCodecName, mMediaType, true, formats, null, CODEC_OPTIONAL);
+ checkFormatSupport(mCodecName, mMediaType, true, formats, null, mSupportRequirements);
// encode
RawResource res = EncoderInput.getRawResource(mEncCfgParams[0]);
@@ -181,16 +267,10 @@
}
encodeToMemory(mCodecName, mEncCfgParams[0], res, Integer.MAX_VALUE, false, muxOutput);
- // cleanup tmp files
+ // validate output
if (muxOutput) {
- // validate output
validateEncodedPSNR(res, mMediaType, mMuxedOutputFile, true, mIsLoopBack,
ACCEPTABLE_WIRELESS_TX_QUALITY);
-
- File tmp = new File(mMuxedOutputFile);
- if (tmp.exists()) {
- assertTrue("unable to delete tmp file" + mMuxedOutputFile, tmp.delete());
- }
}
}
}
diff --git a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
index 2a85818..04971d6 100644
--- a/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/AppOpsLoggingTest.kt
@@ -41,6 +41,8 @@
import android.app.WallpaperManager
import android.app.WallpaperManager.FLAG_SYSTEM
import android.bluetooth.BluetoothManager
+import android.bluetooth.cts.BTAdapterUtils.disableAdapter as disableBTAdapter
+import android.bluetooth.cts.BTAdapterUtils.enableAdapter as enableBTAdapter
import android.bluetooth.le.ScanCallback
import android.content.BroadcastReceiver
import android.content.ComponentName
@@ -54,6 +56,7 @@
import android.content.pm.PackageManager.FEATURE_BLUETOOTH
import android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE
import android.content.pm.PackageManager.FEATURE_TELEPHONY
+import android.content.pm.PackageManager.FEATURE_WIFI
import android.content.pm.PackageManager.GET_ATTRIBUTIONS
import android.hardware.camera2.CameraCaptureSession
import android.hardware.camera2.CameraCharacteristics
@@ -83,6 +86,10 @@
import android.util.Size
import androidx.test.platform.app.InstrumentationRegistry
import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.Executor
+import java.util.concurrent.TimeUnit.MILLISECONDS
+import java.util.concurrent.TimeoutException
import org.junit.After
import org.junit.Assert.fail
import org.junit.Assume.assumeNoException
@@ -90,12 +97,6 @@
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
-import java.util.concurrent.CompletableFuture
-import java.util.concurrent.Executor
-import java.util.concurrent.TimeUnit.MILLISECONDS
-import java.util.concurrent.TimeoutException
-import android.bluetooth.cts.BTAdapterUtils.disableAdapter as disableBTAdapter
-import android.bluetooth.cts.BTAdapterUtils.enableAdapter as enableBTAdapter
private const val TEST_SERVICE_PKG = "android.app.appops.cts.appthatusesappops"
private const val TIMEOUT_MILLIS = 10000L
@@ -442,6 +443,9 @@
*/
@Test
fun getWifiScanResults() {
+ assumeTrue("Device does not support WiFi feature",
+ context.packageManager.hasSystemFeature(FEATURE_WIFI))
+
val wifiManager = context.createAttributionContext(TEST_ATTRIBUTION_TAG)
.getSystemService(WifiManager::class.java)
diff --git a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
index 9021f8e..843f490 100644
--- a/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
+++ b/tests/tests/hibernation/src/android/hibernation/cts/AppHibernationUtils.kt
@@ -25,6 +25,7 @@
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.graphics.Point
import android.os.Handler
import android.os.Looper
import android.os.ParcelFileDescriptor
@@ -235,7 +236,12 @@
waitFindObject(uiAutomation, By.text("Open")).click()
} else {
runShellCommandOrThrow(CMD_EXPAND_NOTIFICATIONS)
- waitFindNotification(notifSelector, NOTIF_FIND_TIMEOUT).click()
+ val notification = waitFindNotification(notifSelector, NOTIF_FIND_TIMEOUT)
+ if (FeatureUtil.isAutomotive()) {
+ notification.click(Point(0, 0))
+ } else {
+ notification.click()
+ }
}
}
diff --git a/tests/tests/identity/src/android/security/identity/cts/TestUtil.java b/tests/tests/identity/src/android/security/identity/cts/TestUtil.java
index 882439a..b3bf16e 100644
--- a/tests/tests/identity/src/android/security/identity/cts/TestUtil.java
+++ b/tests/tests/identity/src/android/security/identity/cts/TestUtil.java
@@ -150,4 +150,11 @@
}
return false;
}
+
+ // Returns true if the device supports secure lock screen.
+ static boolean isLockScreenSupported() {
+ Context appContext = InstrumentationRegistry.getTargetContext();
+ PackageManager pm = appContext.getPackageManager();
+ return pm.hasSystemFeature(PackageManager.FEATURE_SECURE_LOCK_SCREEN);
+ }
}
diff --git a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
index e4bd81f..1656190 100644
--- a/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
+++ b/tests/tests/identity/src/android/security/identity/cts/UserAuthTest.java
@@ -184,8 +184,9 @@
@Test
public void testUserAuth() throws Exception {
- String alias = "authbound";
+ assumeTrue("Device doesn't support lock screen", TestUtil.isLockScreenSupported());
+ String alias = "authbound";
try (DeviceLockSession dl = new DeviceLockSession()) {
Context appContext = InstrumentationRegistry.getTargetContext();
KeyguardManager keyguardManager = (KeyguardManager)appContext
diff --git a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
index bf2e941..fa7a2d8 100644
--- a/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/AndroidKeyStoreTest.java
@@ -40,6 +40,7 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.bedstead.nene.annotations.Nullable;
+import com.android.compatibility.common.util.ApiTest;
import org.junit.After;
import org.junit.Before;
@@ -2807,6 +2808,7 @@
* Create large number of Keystore entries with long aliases and try to list aliases of all the
* entries in the keystore.
*/
+ @ApiTest(apis = {"java.security.KeyStore#aliases"})
@Test
public void testKeyStore_LargeNumberOfLongAliases() throws Exception {
final int maxNumberOfKeys = 100;
@@ -2818,6 +2820,7 @@
* 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.
*/
+ @ApiTest(apis = {"java.security.KeyStore#aliases"})
@Test
public void testKeyStore_LimitedNumberOfLongAliasesSuccess() throws Exception {
final int maxNumberOfKeys = 10;
@@ -2829,6 +2832,7 @@
* all the entries in the keystore. Test should successfully list all the Keystore entries
* aliases.
*/
+ @ApiTest(apis = {"java.security.KeyStore#aliases"})
@Test
public void testKeyStore_LargeNumberShortAliasesSuccess() throws Exception {
final int maxNumberOfKeys = 2500;
diff --git a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
index a703ce2..26254b5 100644
--- a/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
+++ b/tests/tests/keystore/src/android/keystore/cts/DeviceOwnerKeyManagementTest.java
@@ -458,11 +458,7 @@
}
String expectedSecondImei = null;
if ((devIdOpt & ID_TYPE_IMEI) != 0) {
- // TODO(b/262255219): Remove this condition when StrongBox supports 2nd
- // IMEI attestation.
- if (!useStrongBox) {
- expectedSecondImei = secondImei;
- }
+ expectedSecondImei = secondImei;
}
validateDeviceIdAttestationData(attestation, expectedSerial,
expectedImei, expectedMeid, expectedSecondImei);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
index a24638f..b584643 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/DecodeEditEncodeTest.java
@@ -42,6 +42,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Before;
@@ -270,6 +271,15 @@
mUseHighBitDepth = useHighBitDepth;
}
+ @ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
+ "android.opengl.GLES20#glReadPixels",
+ "android.opengl.GLES30#glReadPixels",
+ "android.media.format.MediaFormat#KEY_ALLOW_FRAME_DROP",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_Format32bitABGR2101010",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testVideoEdit() throws Throwable {
VideoEditWrapper.runTest(this);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
index 79b5eac..894d4b1 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeDecodeTest.java
@@ -44,6 +44,7 @@
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Before;
@@ -1268,6 +1269,11 @@
* a series of byte[] buffers and decoded into ByteBuffers. The output is checked for
* validity.
*/
+ @ApiTest(apis = {"android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Planar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedSemiPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_TI_FormatYUV420PackedSemiPlanar"})
@Test
public void testEncodeDecodeVideoFromBufferToBuffer() throws Exception {
encodeDecodeVideoFromBuffer(false);
@@ -1285,6 +1291,16 @@
* the test thread, so we have to hand control off to a new thread for the duration of
* the test.
*/
+ @ApiTest(apis = {"android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Planar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420SemiPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420PackedSemiPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_TI_FormatYUV420PackedSemiPlanar",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.opengl.GLES20#glReadPixels",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testEncodeDecodeVideoFromBufferToSurface() throws Throwable {
BufferToSurfaceWrapper.runTest(this);
@@ -1294,11 +1310,22 @@
* Tests streaming of AVC through the encoder and decoder. Data is provided through
* a Surface and decoded onto a Surface. The output is checked for validity.
*/
+ @ApiTest(apis = {"android.media.MediaCodec#createInputSurface",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.opengl.GLES20#glReadPixels",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testEncodeDecodeVideoFromSurfaceToSurface() throws Throwable {
SurfaceToSurfaceWrapper.runTest(this, false, false);
}
-
+ @ApiTest(apis = {"AMediaCodec_createInputSurface",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.opengl.GLES20#glReadPixels",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testEncodeDecodeVideoFromSurfaceToSurfaceNdk() throws Throwable {
SurfaceToSurfaceWrapper.runTest(this, false, USE_NDK);
@@ -1308,11 +1335,25 @@
* Tests streaming of video through the encoder and decoder. Data is provided through
* a PersistentSurface and decoded onto a Surface. The output is checked for validity.
*/
+ @ApiTest(apis = {"android.media.MediaCodec#createPersistentInputSurface",
+ "android.media.MediaCodec#setInputSurface",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.opengl.GLES20#glReadPixels",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testEncodeDecodeVideoFromSurfaceToPersistentSurface() throws Throwable {
SurfaceToSurfaceWrapper.runTest(this, true, false);
}
+ @ApiTest(apis = {"AMediaCodec_createPersistentInputSurface",
+ "AMediaCodec_setInputSurface",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.opengl.GLES20#glReadPixels",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testEncodeDecodeVideoFromSurfaceToPersistentSurfaceNdk() throws Throwable {
SurfaceToSurfaceWrapper.runTest(this, true, USE_NDK);
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
old mode 100755
new mode 100644
index ca08397..fa4e2ac
--- a/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/EncodeVirtualDisplayTest.java
@@ -48,6 +48,7 @@
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Before;
@@ -189,6 +190,13 @@
*
* @throws Exception
*/
+ @ApiTest(apis = {"AMediaCodec_createInputSurface",
+ "android.hardware.display.DisplayManager#createVirtualDisplay",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.opengl.GLES20#glReadPixels",
+ "android.media.MediaFormat#KEY_COLOR_RANGE",
+ "android.media.MediaFormat#KEY_COLOR_STANDARD",
+ "android.media.MediaFormat#KEY_COLOR_TRANSFER"})
@Test
public void testEncodeVirtualDisplay() throws Throwable {
if (!MediaUtils.check(sIsAtLeastR, "test needs Android 11")) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
index 67c3ce8..1225822 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/ExtractDecodeEditEncodeMuxTest.java
@@ -41,7 +41,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
-import com.android.compatibility.common.util.CddTest;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.Preconditions;
import org.junit.After;
@@ -69,6 +69,30 @@
* <p>It also tests the way the codec config buffers need to be passed from the MediaCodec to the
* MediaMuxer.
*/
+@ApiTest(apis = {"android.opengl.GLES20#GL_FRAGMENT_SHADER",
+ "android.media.MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface",
+ "android.media.MediaFormat#KEY_BIT_RATE",
+ "android.media.MediaFormat#KEY_COLOR_FORMAT",
+ "android.media.MediaFormat#KEY_FRAME_RATE",
+ "android.media.MediaFormat#KEY_I_FRAME_INTERVAL",
+ "android.media.MediaFormat#KEY_SAMPLE_RATE",
+ "android.media.MediaFormat#KEY_CHANNEL_COUNT",
+ "android.media.MediaFormat#KEY_PROFILE",
+ "android.media.MediaFormat#KEY_AAC_PROFILE",
+ "android.media.MediaExtractor#setDataSource",
+ "android.media.MediaExtractor#getTrackCount",
+ "android.media.MediaExtractor#getTrackFormat",
+ "android.media.MediaExtractor#selectTrack",
+ "android.media.MediaExtractor#readSampleData",
+ "android.media.MediaExtractor#getSampleTime",
+ "android.media.MediaExtractor#getSampleFlags",
+ "android.media.MediaExtractor#advance",
+ "android.media.MediaExtractor#release",
+ "android.media.MediaMuxer#start",
+ "android.media.MediaMuxer#stop",
+ "android.media.MediaMuxer#addTrack",
+ "android.media.MediaMuxer#writeSampleData",
+ "android.media.MediaMuxer#release"})
@TargetApi(18)
@AppModeFull(reason = "Instant apps cannot access the SD card")
@RunWith(AndroidJUnit4.class)
@@ -145,7 +169,6 @@
super.tearDown();
}
- @CddTest(requirements = {"5.2", "5.3"})
@Test
public void testExtractDecodeEditEncodeMuxQCIF() throws Throwable {
if(!setSize(176, 144)) return;
@@ -155,7 +178,6 @@
TestWrapper.runTest(this);
}
- @CddTest(requirements = {"5.2", "5.3"})
@Test
public void testExtractDecodeEditEncodeMuxQVGA() throws Throwable {
if(!setSize(320, 240)) return;
@@ -165,7 +187,6 @@
TestWrapper.runTest(this);
}
- @CddTest(requirements = {"5.2", "5.3"})
@Test
public void testExtractDecodeEditEncodeMux720p() throws Throwable {
if(!setSize(1280, 720)) return;
@@ -175,7 +196,6 @@
TestWrapper.runTest(this);
}
- @CddTest(requirements = {"5.2", "5.3"})
@Test
public void testExtractDecodeEditEncodeMux2160pHevc() throws Throwable {
if(!setSize(3840, 2160)) return;
@@ -185,7 +205,6 @@
TestWrapper.runTest(this);
}
- @CddTest(requirements = {"5.1.1", "5.1.2"})
@Test
public void testExtractDecodeEditEncodeMuxAudio() throws Throwable {
if(!setSize(1280, 720)) return;
@@ -195,7 +214,6 @@
TestWrapper.runTest(this);
}
- @CddTest(requirements = {"5.1.1", "5.1.2", "5.2", "5.3"})
@Test
public void testExtractDecodeEditEncodeMuxAudioVideo() throws Throwable {
if(!setSize(1280, 720)) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
index 29a14a0..5822063 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecBlockModelTest.java
@@ -41,6 +41,7 @@
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.NonMainlineTest;
import com.android.compatibility.common.util.Preconditions;
@@ -92,6 +93,7 @@
@Presubmit
@SmallTest
@RequiresDevice
+ @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
@Test
public void testDecodeShortVideo() throws InterruptedException {
if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -112,6 +114,7 @@
@Presubmit
@SmallTest
@RequiresDevice
+ @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
@Test
public void testDecodeShortAudio() throws InterruptedException {
if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -132,6 +135,7 @@
@Presubmit
@SmallTest
@RequiresDevice
+ @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
@Test
public void testEncodeShortAudio() throws InterruptedException {
if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
@@ -145,6 +149,7 @@
@Presubmit
@SmallTest
@RequiresDevice
+ @ApiTest(apis = "MediaCodec#CONFIGURE_FLAG_USE_BLOCK_MODEL")
@Test
public void testEncodeShortVideo() throws InterruptedException {
if (!MediaUtils.check(mIsAtLeastR, "test needs Android 11")) return;
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
index bb769ca..b94f2de8 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecResourceTest.java
@@ -45,6 +45,8 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiTest;
+
import org.junit.Test;
import java.util.ArrayList;
@@ -80,6 +82,7 @@
public final int uid;
}
+ @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
@Test
public void testCreateCodecForAnotherProcessWithoutPermissionsThrows() throws Exception {
CodecInfo codecInfo = getFirstVideoHardwareDecoder();
@@ -102,6 +105,7 @@
// A process with lower priority (e.g. background app) should not be able to reclaim
// MediaCodec resources from a process with higher priority (e.g. foreground app).
+ @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
@Test
public void testLowerPriorityProcessFailsToReclaimResources() throws Exception {
CodecInfo codecInfo = getFirstVideoHardwareDecoder();
@@ -188,6 +192,7 @@
// A process with higher priority (e.g. foreground app) should be able to reclaim
// MediaCodec resources from a process with lower priority (e.g. background app).
+ @ApiTest(apis = "MediaCodec#createByCodecNameForClient")
@Test
public void testHigherPriorityProcessReclaimsResources() throws Exception {
CodecInfo codecInfo = getFirstVideoHardwareDecoder();
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
index 3173465..52d01b2 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/MediaCodecTest.java
@@ -68,6 +68,7 @@
import androidx.test.filters.SmallTest;
import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.Preconditions;
@@ -142,6 +143,18 @@
* A selective test to ensure proper exceptions are thrown from MediaCodec
* methods when called in incorrect operational states.
*/
+ @ApiTest(apis = {"MediaCodec#createByCodecName", "MediaCodec#createDecoderByType",
+ "MediaCodec#createEncoderByType", "MediaCodec#start", "MediaCodec#flush",
+ "MediaCodec#configure", "MediaCodec#dequeueInputBuffer",
+ "MediaCodec#dequeueOutputBuffer", "MediaCodec#createInputSurface",
+ "MediaCodec#getInputBuffers", "MediaCodec#getQueueRequest",
+ "MediaCodec#getOutputFrame", "MediaCodec#stop", "MediaCodec#release",
+ "MediaCodec#getCodecInfo", "MediaCodec#getSupportedVendorParameters",
+ "MediaCodec#getParameterDescriptor",
+ "MediaCodec#subscribeToVendorParameters",
+ "MediaCodec#unsubscribeFromVendorParameters",
+ "MediaCodec#getInputBuffer", "MediaCodec#getOutputBuffer",
+ "MediaCodec#setCallback", "MediaCodec#getName"})
@Test
public void testException() throws Exception {
boolean tested = false;
@@ -245,15 +258,6 @@
fail("flush should not return MediaCodec.CodecException on wrong state");
} catch (IllegalStateException e) { // expected
}
- try {
- codec.setParameters(new Bundle());
- fail("setParameters should not work if not yet configured/initialized");
- } catch (MediaCodec.CodecException e) {
- logMediaCodecException(e);
- fail("setParameters should not return MediaCodec.CodecException if not yet "
- + "configured/initialized");
- } catch (IllegalStateException e) { // expected
- }
MediaCodecInfo codecInfo = codec.getCodecInfo(); // obtaining the codec info now is fine.
try {
@@ -553,6 +557,7 @@
* <br> calling createInputSurface() after start() throws exception
* <br> calling createInputSurface() with a non-Surface color format is not required to throw exception
*/
+ @ApiTest(apis = "MediaCodec#createInputSurface")
@Test
public void testCreateInputSurfaceErrors() {
if (!supportsCodec(MIME_TYPE, true)) {
@@ -604,6 +609,7 @@
* <br> signaling EOS twice throws exception
* <br> submitting a frame after EOS throws exception [TODO]
*/
+ @ApiTest(apis = "MediaCodec#signalEndOfInputStream")
@Test
public void testSignalSurfaceEOS() {
if (!supportsCodec(MIME_TYPE, true)) {
@@ -662,6 +668,7 @@
* Tests:
* <br> stopping with buffers in flight doesn't crash or hang
*/
+ @ApiTest(apis = "MediaCodec#stop")
@Test
public void testAbruptStop() {
if (!supportsCodec(MIME_TYPE, true)) {
@@ -718,6 +725,7 @@
}
}
+ @ApiTest(apis = {"MediaCodec#flush", "MediaCodec#release"})
@Test
public void testReleaseAfterFlush() throws IOException, InterruptedException {
String mimes[] = new String[] { MIME_TYPE, MIME_TYPE_AUDIO};
@@ -781,11 +789,13 @@
callbackThread.join();
}
+ @ApiTest(apis = {"MediaCodec#setCallback", "MediaCodec#flush", "MediaCodec#reset"})
@Test
public void testAsyncFlushAndReset() throws Exception, InterruptedException {
testAsyncReset(false /* testStop */);
}
+ @ApiTest(apis = {"MediaCodec#setCallback", "MediaCodec#stop", "MediaCodec#reset"})
@Test
public void testAsyncStopAndReset() throws Exception, InterruptedException {
testAsyncReset(true /* testStop */);
@@ -1116,6 +1126,7 @@
* Tests:
* <br> dequeueInputBuffer() fails when encoder configured with an input Surface
*/
+ @ApiTest(apis = {"MediaCodec#dequeueInputBuffer", "MediaCodec#getMetrics"})
@Test
public void testDequeueSurface() {
if (!supportsCodec(MIME_TYPE, true)) {
@@ -1175,6 +1186,8 @@
* <br> configure() encoder with Surface, re-configure() without Surface works
* <br> sending EOS with signalEndOfInputStream on non-Surface encoder fails
*/
+ @ApiTest(apis = {"MediaCodec#configure", "MediaCodec#signalEndOfInputStream",
+ "MediaCodec#getMetrics"})
@Test
public void testReconfigureWithoutSurface() {
if (!supportsCodec(MIME_TYPE, true)) {
@@ -1244,6 +1257,7 @@
}
}
+ @ApiTest(apis = "MediaCodec#flush")
@Test
public void testDecodeAfterFlush() throws InterruptedException {
testDecodeAfterFlush(true /* audio */);
@@ -1425,6 +1439,7 @@
* Tests whether decoding a short group-of-pictures succeeds. The test queues a few video frames
* then signals end-of-stream. The test fails if the decoder doesn't output the queued frames.
*/
+ @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
@Test
public void testDecodeShortInput() throws InterruptedException {
// Input buffers from this input video are queued up to and including the video frame with
@@ -1536,6 +1551,10 @@
/**
* Tests creating two decoders for {@link #MIME_TYPE_AUDIO} at the same time.
*/
+ @ApiTest(apis = {"MediaCodec#createDecoderByType",
+ "android.media.MediaFormat#KEY_MIME",
+ "android.media.MediaFormat#KEY_SAMPLE_RATE",
+ "android.media.MediaFormat#KEY_CHANNEL_COUNT"})
@Test
public void testCreateTwoAudioDecoders() {
final MediaFormat format = MediaFormat.createAudioFormat(
@@ -1583,6 +1602,10 @@
/**
* Tests creating an encoder and decoder for {@link #MIME_TYPE_AUDIO} at the same time.
*/
+ @ApiTest(apis = {"MediaCodec#createDecoderByType", "MediaCodec#createEncoderByType",
+ "android.media.MediaFormat#KEY_MIME",
+ "android.media.MediaFormat#KEY_SAMPLE_RATE",
+ "android.media.MediaFormat#KEY_CHANNEL_COUNT"})
@Test
public void testCreateAudioDecoderAndEncoder() {
if (!supportsCodec(MIME_TYPE_AUDIO, true)) {
@@ -1641,6 +1664,12 @@
}
}
+ @ApiTest(apis = {"MediaCodec#createEncoderByType",
+ "android.media.MediaFormat#KEY_MIME",
+ "android.media.MediaFormat#KEY_SAMPLE_RATE",
+ "android.media.MediaFormat#KEY_CHANNEL_COUNT",
+ "android.media.MediaFormat#KEY_WIDTH",
+ "android.media.MediaFormat#KEY_HEIGHT"})
@Test
public void testConcurrentAudioVideoEncodings() throws InterruptedException {
if (!supportsCodec(MIME_TYPE_AUDIO, true)) {
@@ -1689,6 +1718,7 @@
public int mBitRate;
}
+ @ApiTest(apis = {"MediaCodec#CryptoInfo", "MediaCodec#CryptoInfo#Pattern"})
@Test
public void testCryptoInfoPattern() {
CryptoInfo info = new CryptoInfo();
@@ -1989,6 +2019,7 @@
/**
* Tests MediaCodec.CryptoException
*/
+ @ApiTest(apis = "MediaCodec#CryptoException")
@Test
public void testCryptoException() {
int errorCode = CryptoException.ERROR_KEY_EXPIRED;
@@ -2007,6 +2038,8 @@
*
* As of Q, any codec of type "audio/raw" must support PCM encoding float.
*/
+ @ApiTest(apis = {"android.media.AudioFormat#ENCODING_PCM_16BIT",
+ "android.media.AudioFormat#ENCODING_PCM_FLOAT"})
@MediumTest
@Test
public void testPCMEncoding() throws Exception {
@@ -2132,6 +2165,7 @@
return actualEncoding;
}
+ @ApiTest(apis = "android.media.AudioFormat#KEY_FLAC_COMPRESSION_LEVEL")
@SmallTest
@Test
public void testFlacIdentity() throws Exception {
@@ -2185,6 +2219,7 @@
}
}
+ @ApiTest(apis = "MediaCodec#release")
@Test
public void testAsyncRelease() throws Exception {
OutputSurface outputSurface = new OutputSurface(1, 1);
@@ -2272,6 +2307,7 @@
}
}
+ @ApiTest(apis = "MediaCodec#setAudioPresentation")
@Test
public void testSetAudioPresentation() throws Exception {
MediaFormat format = MediaFormat.createAudioFormat(
@@ -2287,6 +2323,7 @@
(new AudioPresentation.Builder(42 /* presentationId */)).build());
}
+ @ApiTest(apis = "android.media.MediaFormat#KEY_PREPEND_HEADER_TO_SYNC_FRAMES")
@Test
public void testPrependHeadersToSyncFrames() throws IOException {
MediaCodecList mcl = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
@@ -2361,6 +2398,7 @@
* codec is flushed after the first buffer is queued, so this test walks
* through the scenario.
*/
+ @ApiTest(apis = "MediaCodec#flush")
@Test
public void testFlushAfterFirstBuffer() throws Exception {
if (MediaUtils.check(mIsAtLeastR, "test needs Android 11")) {
@@ -2458,6 +2496,10 @@
}
}
+ @ApiTest(apis = {"MediaCodec#getSupportedVendorParameters",
+ "MediaCodec#getParameterDescriptor",
+ "MediaCodec#subscribeToVendorParameters",
+ "MediaCodec#unsubscribeFromVendorParameters"})
@Test
public void testVendorParameters() {
if (!MediaUtils.check(mIsAtLeastS, "test needs Android 12")) {
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
index ac0dd0f..6c67812 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoCodecTest.java
@@ -26,6 +26,7 @@
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Assume;
@@ -625,41 +626,65 @@
}
}
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+ "android.media.MediaFormat#KEY_BIT_RATE",
+ "android.media.MediaFormat#KEY_COLOR_FORMAT",
+ "android.media.MediaFormat#KEY_FRAME_RATE",
+ "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
@Test
public void testBasic() throws Exception {
internalTestBasic(mCodecName, mCodecMimeType, mBitRateMode);
}
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+ "android.media.MediaFormat#KEY_BIT_RATE",
+ "android.media.MediaFormat#KEY_COLOR_FORMAT",
+ "android.media.MediaFormat#KEY_FRAME_RATE",
+ "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
@Test
public void testAsyncEncode() throws Exception {
internalTestAsyncEncoding(mCodecName, mCodecMimeType, mBitRateMode);
}
+ @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
@Test
public void testSyncFrame() throws Exception {
internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, false);
}
+ @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_REQUEST_SYNC_FRAME")
@Test
public void testSyncFrameNdk() throws Exception {
internalTestSyncFrame(mCodecName, mCodecMimeType, mBitRateMode, true);
}
+ @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
@Test
public void testDynamicBitrateChange() throws Exception {
internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, false);
}
+ @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_VIDEO_BITRATE")
@Test
public void testDynamicBitrateChangeNdk() throws Exception {
internalTestDynamicBitrateChange(mCodecName, mCodecMimeType, mBitRateMode, true);
}
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+ "android.media.MediaFormat#KEY_BIT_RATE",
+ "android.media.MediaFormat#KEY_COLOR_FORMAT",
+ "android.media.MediaFormat#KEY_FRAME_RATE",
+ "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
@Test
public void testEncoderQuality() throws Exception {
internalTestEncoderQuality(mCodecName, mCodecMimeType, mBitRateMode);
}
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_BITRATE_MODE",
+ "android.media.MediaFormat#KEY_BIT_RATE",
+ "android.media.MediaFormat#KEY_COLOR_FORMAT",
+ "android.media.MediaFormat#KEY_FRAME_RATE",
+ "android.media.MediaFormat#KEY_I_FRAME_INTERVAL"})
@Test
public void testParallelEncodingAndDecoding() throws Exception {
Assume.assumeTrue("Parallel Encode Decode test is run only for VBR mode",
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
index 78021f4..fb61f78 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoDecoderRotationTest.java
@@ -26,6 +26,7 @@
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.NonMainlineTest;
import org.junit.Test;
@@ -96,6 +97,7 @@
return testParams;
}
+ @ApiTest(apis = "android.media.MediaFormat#KEY_ROTATION")
@Test
public void testRendering800x480Rotated() throws Throwable {
if (mImpl.isConcurrentEncodingDecodingSupported(
diff --git a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
index 4979f76..4239679 100644
--- a/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
+++ b/tests/tests/media/codec/src/android/media/codec/cts/VideoEncodingStatisticsTest.java
@@ -26,6 +26,7 @@
import android.platform.test.annotations.AppModeFull;
import android.util.Log;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Assume;
@@ -195,6 +196,9 @@
}
}
+ @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#FEATURE_EncodingStatistics",
+ "android.media.MediaFormat#KEY_VIDEO_ENCODING_STATISTICS_LEVEL",
+ "android.media.MediaFormat#KEY_VIDEO_QP_AVERAGE"})
@Test
public void testEncodingStatisticsAvgQp() throws Exception {
testEncStatRateAvgQp(mCodecName, mCodecMimeType, mBitRateMode);
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
index 6f9421d..cbfb26d 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/EncoderTest.java
@@ -23,7 +23,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
@@ -36,6 +35,7 @@
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.Preconditions;
@@ -197,11 +197,13 @@
mFormat.setInteger(MediaFormat.KEY_BIT_RATE, mBitrate);
}
+ // "5.1.3" is covered partially. For instance aac is not tested for 5.0 and 5.1, Opus is not
+ // tested for different sample rates.
+ // TODO (b/272014629): Update test accordingly
+ @CddTest(requirements = "5.1.3")
@Test(timeout = PER_TEST_TIMEOUT_SMALL_TEST_MS)
public void testEncoders() throws FileNotFoundException {
setUpFormat();
- assumeTrue("no encoders found for " + mFormat.toString(),
- MediaUtils.supports(mEncoderName, mFormat));
assertEquals(mMime, mFormat.getString(MediaFormat.KEY_MIME));
testEncoder(mEncoderName, mFormat);
}
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java
index 95ceec6..dd0bf6e 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/SurfaceEncodeTimestampTest.java
@@ -43,6 +43,7 @@
import androidx.test.filters.SdkSuppress;
import androidx.test.filters.SmallTest;
+import com.android.compatibility.common.util.ApiTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.After;
@@ -114,13 +115,14 @@
}
/*
- * Test KEY_MAX_PTS_GAP_TO_ENCODER
+ * Test KEY_MAX_PTS_GAP_TO_ENCODER when positive
*
* This key is supposed to cap the gap between any two frames fed to the encoder,
* and restore the output pts back to the original. Since the pts is not supposed
* to be modified, we can't really verify that the "capping" actually took place.
* However, we can at least verify that the pts is preserved.
*/
+ @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_PTS_GAP_TO_ENCODER")
@Test
public void testMaxPtsGap() throws Throwable {
long[] inputPts = {1000000, 2000000, 3000000, 4000000};
@@ -131,8 +133,10 @@
}
/*
- * Test that by default backward-going frames get dropped.
+ * Test pts behavior if KEY_MAX_PTS_GAP_TO_ENCODER is unspecified.
+ * (Tests that by default backward-going frames get dropped)
*/
+ @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_PTS_GAP_TO_ENCODER")
@Test
public void testBackwardFrameDroppedWithoutFixedPtsGap() throws Throwable {
long[] inputPts = {33333, 66667, 66000, 100000};
@@ -141,11 +145,12 @@
}
/*
- * Test KEY_MAX_PTS_GAP_TO_ENCODER
+ * Test KEY_MAX_PTS_GAP_TO_ENCODER when negative
*
- * Test that when fixed pts gap is used, backward-going frames are accepted
+ * Test that when negative pts gap is used, backward-going frames are accepted
* and the pts is preserved.
*/
+ @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_PTS_GAP_TO_ENCODER")
@Test
public void testBackwardFramePreservedWithFixedPtsGap() throws Throwable {
long[] inputPts = {33333, 66667, 66000, 100000};
@@ -161,6 +166,7 @@
* Input frames are timestamped at 60fps, the key is supposed to drop
* one every other frame to maintain 30fps output.
*/
+ @ApiTest(apis = "android.media.MediaFormat#KEY_MAX_FPS_TO_ENCODER")
@Test
public void testMaxFps() throws Throwable {
long[] inputPts = {16667, 33333, 50000, 66667, 83333};
@@ -178,6 +184,7 @@
* compress) the output timestamp so that the output fps becomes that specified
* by KEY_FRAME_RATE.
*/
+ @ApiTest(apis = "android.media.MediaFormat#KEY_CAPTURE_RATE")
@Test
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
public void testCaptureFps() throws Throwable {
@@ -213,6 +220,7 @@
* Test that the frame is repeated at least once if no new frame arrives after
* the specified amount of time.
*/
+ @ApiTest(apis = "android.media.MediaFormat#KEY_REPEAT_PREVIOUS_FRAME_AFTER")
@Test
public void testRepeatPreviousFrameAfter() throws Throwable {
long[] inputPts = {16667, 33333, -100000, 133333};
@@ -228,6 +236,8 @@
* Start the encoder with KEY_CREATE_INPUT_SURFACE_SUSPENDED set, then resume
* by PARAMETER_KEY_SUSPEND. Verify only frames after resume are captured.
*/
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_CREATE_INPUT_SURFACE_SUSPENDED",
+ "android.media.MediaCodec#PARAMETER_KEY_SUSPEND"})
@Test
public void testCreateInputSurfaceSuspendedResume() throws Throwable {
// Using PARAMETER_KEY_SUSPEND (instead of PARAMETER_KEY_SUSPEND +
@@ -256,6 +266,9 @@
* at specific time using PARAMETER_KEY_SUSPEND + PARAMETER_KEY_SUSPEND_TIME.
* Verify only frames after the specified time are captured.
*/
+ @ApiTest(apis = {"android.media.MediaFormat#KEY_CREATE_INPUT_SURFACE_SUSPENDED",
+ "android.media.MediaCodec#PARAMETER_KEY_SUSPEND",
+ "android.media.MediaCodec#PARAMETER_KEY_SUSPEND_TIME"})
@Test
public void testCreateInputSurfaceSuspendedResumeWithTime() throws Throwable {
// Unlike using PARAMETER_KEY_SUSPEND alone to resume, using PARAMETER_KEY_SUSPEND
@@ -279,6 +292,7 @@
* Suspend/resume during capture, and verify that frames during the suspension
* period are dropped.
*/
+ @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_SUSPEND")
@Test
public void testSuspendedResume() throws Throwable {
// Using PARAMETER_KEY_SUSPEND (instead of PARAMETER_KEY_SUSPEND +
@@ -307,6 +321,8 @@
* Suspend/resume with specified time during capture, and verify that frames during
* the suspension period are dropped.
*/
+ @ApiTest(apis = {"android.media.MediaCodec#PARAMETER_KEY_SUSPEND",
+ "android.media.MediaCodec#PARAMETER_KEY_SUSPEND_TIME"})
@Test
public void testSuspendedResumeWithTime() throws Throwable {
// Unlike using PARAMETER_KEY_SUSPEND alone to suspend/resume, requests using
@@ -334,6 +350,7 @@
* Apply PARAMETER_KEY_OFFSET_TIME during capture, and verify that the pts
* of frames after the request are adjusted by the offset correctly.
*/
+ @ApiTest(apis = "android.media.MediaCodec#PARAMETER_KEY_OFFSET_TIME")
@Test
public void testOffsetTime() throws Throwable {
long[] inputPts = {33333, 66667, -100000, 100000, 133333};
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
index 93f858e..613f462 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderCapabilitiesTest.java
@@ -22,6 +22,7 @@
import android.media.MediaFormat;
import android.platform.test.annotations.AppModeFull;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import org.junit.Test;
@@ -90,6 +91,7 @@
}
// Tests encoder profiles required by CDD.
+ @CddTest(requirements = {"5.2.2/C-1-2", "5.2.3/C-1-1", "5.2.4/C-SR-1", "5.2.5/C-SR-1"})
@Test
public void testEncoderAvailability() {
MediaFormat format = MediaFormat.createVideoFormat(mMediaType, mWidth, mHeight);
diff --git a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
index de642ed..bf0c71c 100644
--- a/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
+++ b/tests/tests/media/encoder/src/android/media/encoder/cts/VideoEncoderTest.java
@@ -50,6 +50,8 @@
import android.util.Size;
import android.view.Surface;
+import com.android.compatibility.common.util.ApiTest;
+import com.android.compatibility.common.util.CddTest;
import com.android.compatibility.common.util.MediaUtils;
import com.android.compatibility.common.util.Preconditions;
@@ -1353,6 +1355,17 @@
mMode = mode;
}
+ @CddTest(requirements = {"5.1.7/C-3-1"})
+ @ApiTest(apis = {"MediaCodecInfo.CodecCapabilities#FEATURE_IntraRefresh",
+ "android.media.MediaFormat#KEY_WIDTH",
+ "android.media.MediaFormat#KEY_HEIGHT",
+ "android.media.MediaFormat#KEY_FRAME_RATE",
+ "android.media.MediaFormat#KEY_BIT_RATE",
+ "android.media.MediaFormat#KEY_I_FRAME_INTERVAL",
+ "android.media.MediaFormat#KEY_INTRA_REFRESH_PERIOD",
+ "android.media.MediaFormat#KEY_MAX_INPUT_SIZE",
+ "MediaCodecInfo.CodecCapabilities#COLOR_FormatYUV420Flexible",
+ "MediaCodecInfo.CodecCapabilities#COLOR_FormatSurface"})
@Test
public void testEncode() {
int frameRate = 30;
diff --git a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
index 2a30898..383e4b4 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
@@ -114,13 +114,6 @@
// Copy the resource to cache.
private Uri resourceToUri(Context context, int resId, String name) throws IOException {
- Uri resUri = new Uri.Builder()
- .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
- .authority(context.getResources().getResourcePackageName(resId))
- .appendPath(context.getResources().getResourceTypeName(resId))
- .appendPath(context.getResources().getResourceEntryName(resId))
- .build();
-
Uri cacheUri = Uri.parse(ContentResolver.SCHEME_FILE + "://"
+ mContext.getCacheDir().getAbsolutePath() + "/" + name);
diff --git a/tests/tests/permission2/res/raw/wear_android_manifest.xml b/tests/tests/permission2/res/raw/wear_android_manifest.xml
deleted file mode 100644
index 08488bc..0000000
--- a/tests/tests/permission2/res/raw/wear_android_manifest.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?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.
- -->
-<!-- This file contains permissions which were back ported.
- These permissions are already present on future platform releases.
- -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="android" coreApp="true" android:sharedUserId="android.uid.system"
- android:sharedUserLabel="@string/android_system_label">
-
- <!-- @hide Allows an application to access wrist temperature data from the watch sensors.
- <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
- <p>Protection level: dangerous -->
- <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
- android:permissionGroup="android.permission-group.UNDEFINED"
- android:label="@string/permlab_bodySensorsWristTemperature"
- android:description="@string/permdesc_bodySensorsWristTemperature"
- android:backgroundPermission="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- android:protectionLevel="dangerous" />
-
- <!-- @hide Allows an application to access wrist temperature data from the watch sensors.
- If you're requesting this permission, you must also request
- {@link #BODY_SENSORS_WRIST_TEMPERATURE}. Requesting this permission by itself doesn't
- give you wrist temperature body sensors access.
- <p class="note"><strong>Note: </strong> This permission is for Wear OS only.
- <p>Protection level: dangerous
-
- <p> This is a hard restricted permission which cannot be held by an app until
- the installer on record allowlists the permission. For more details see
- {@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
- -->
- <permission android:name="android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- android:permissionGroup="android.permission-group.UNDEFINED"
- android:label="@string/permlab_bodySensors_wristTemperature_background"
- android:description="@string/permdesc_bodySensors_wristTemperature_background"
- android:protectionLevel="dangerous"
- android:permissionFlags="hardRestricted" />
-
-</manifest>
\ No newline at end of file
diff --git a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
index ac9c97a..d8ea3f7 100644
--- a/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
+++ b/tests/tests/permission2/src/android/permission2/cts/PermissionPolicyTest.java
@@ -167,9 +167,6 @@
}
declaredPermissionsMap.putAll(carServiceBuiltInPermissionsMap);
}
- if (sContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- expectedPermissions.addAll(loadExpectedPermissions(R.raw.wear_android_manifest));
- }
for (ExpectedPermissionInfo expectedPermission : expectedPermissions) {
String expectedPermissionName = expectedPermission.name;
diff --git a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
index feaf20e..a1eca49 100644
--- a/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
+++ b/tests/tests/permission2/src/android/permission2/cts/RuntimePermissionProperties.kt
@@ -54,7 +54,6 @@
import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
import android.Manifest.permission_group.UNDEFINED
import android.app.AppOpsManager.permissionToOp
-import android.content.pm.PackageManager
import android.content.pm.PackageManager.GET_PERMISSIONS
import android.content.pm.PermissionInfo.PROTECTION_DANGEROUS
import android.content.pm.PermissionInfo.PROTECTION_FLAG_APPOP
@@ -162,23 +161,6 @@
expectedPerms.add(POST_NOTIFICATIONS)
expectedPerms.add(NEARBY_WIFI_DEVICES)
- // Add runtime permissions added in V (back ported from U) which were _not_ split from a
- // previously existing runtime permission
- if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
- expectedPerms.add(BODY_SENSORS_WRIST_TEMPERATURE)
- expectedPerms.add(BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND)
- }
-
assertThat(expectedPerms).containsExactlyElementsIn(platformRuntimePerms.map { it.name })
}
-
- companion object {
- // These permissions are back ported from Android U to tm-wear, hidden in the
- // "core/res/AndroidManifest.xml" file of /framework/base repo. Added these 2 constants here
- // because hidden permissions can't be imported like other imported permissions in this file
- private const val BODY_SENSORS_WRIST_TEMPERATURE =
- "android.permission.BODY_SENSORS_WRIST_TEMPERATURE"
- private const val BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND =
- "android.permission.BODY_SENSORS_WRIST_TEMPERATURE_BACKGROUND"
- }
}
diff --git a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
index 0b88e01..7499e0f 100644
--- a/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/SensorBlockedBannerTest.kt
@@ -65,6 +65,7 @@
@Before
fun setup() {
Assume.assumeFalse(isTv)
+ Assume.assumeFalse(isWatch)
// TODO(b/203784852) Auto will eventually support the blocked sensor banner, but there won't
// be support in T or below
Assume.assumeFalse(isAutomotive)
diff --git a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
index acf38c7..a386ff6 100644
--- a/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
+++ b/tests/tests/security/native/encryption/FileBasedEncryptionPolicyTest.cpp
@@ -55,7 +55,10 @@
asm volatile("aesenc %%xmm1, %%xmm0" : : : "xmm0");
}
#else
-#warning "unknown architecture, assuming AES instructions are available"
+// For unknown architectures, we cannot confirm that AES instructions are
+// unsupported. So, assume they are supported, i.e. don't raise SIGILL. This
+// disallows Adiantum until code is explicitly added for the architecture.
+#warning "unknown architecture, assuming Adiantum is not allowed"
static void executeAESInstruction(void) {}
#endif
@@ -65,8 +68,8 @@
longjmp(jump_buf, 1);
}
-// This function checks for the presence of AES instructions, e.g. ARMv8 crypto
-// extensions for ARM, or AES-NI for x86.
+// Checks whether Adiantum encryption is allowed. Adiantum encryption is
+// allowed only when the CPU does *not* support AES instructions.
//
// ARM processors don't have a standard way for user processes to determine CPU
// features. On Linux it's possible to read the AT_HWCAP and AT_HWCAP2 values
@@ -76,10 +79,10 @@
//
// To keep things consistent we use the same approach on x86 to detect AES-NI,
// though in principle the 'cpuid' instruction could be used there.
-static bool cpuHasAESInstructions(void) {
+static bool isAdiantumEncryptionAllowed(void) {
struct sigaction act;
struct sigaction oldact;
- bool result;
+ bool allowed;
memset(&act, 0, sizeof(act));
act.sa_handler = handleSIGILL;
@@ -87,17 +90,20 @@
EXPECT_EQ(0, sigaction(SIGILL, &act, &oldact));
if (setjmp(jump_buf) != 0) {
- // SIGILL was received when executing the AES instruction.
- result = false;
+ // Trying to execute an AES instruction raised SIGILL, which shows that
+ // AES instructions are unsupported. Thus, Adiantum is allowed.
+ allowed = true;
} else {
executeAESInstruction();
- // Successfully executed the AES instruction.
- result = true;
+ // Either an AES instruction was successfully executed, or the
+ // architecture is unknown. So, it has *not* been shown that AES
+ // instructions are unsupported. Thus, Adiantum is *not* allowed.
+ allowed = false;
}
EXPECT_EQ(0, sigaction(SIGILL, &oldact, NULL));
- return result;
+ return allowed;
}
// CDD 9.9.3/C-1-5: must use AES-256-XTS or Adiantum contents encryption.
@@ -151,8 +157,7 @@
}
if (contents_mode == FSCRYPT_MODE_ADIANTUM || filenames_mode == FSCRYPT_MODE_ADIANTUM) {
- // Adiantum encryption is only allowed if the CPU doesn't have AES instructions.
- EXPECT_FALSE(cpuHasAESInstructions());
+ EXPECT_TRUE(isAdiantumEncryptionAllowed());
}
}
diff --git a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
index 4bfe8fe..b6ee6ed 100644
--- a/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
+++ b/tests/tests/security/src/android/security/cts/PackageSignatureTest.java
@@ -102,7 +102,7 @@
wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_runtime_debug));
wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_runtime_release));
wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata3));
- // The following keys are not not used by modules on the latest Android release, but it
+ // The following keys are not used by modules on the latest Android release, but it
// won't negatively affect tests to include their signatures here too.
wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata));
wellKnownSignatures.add(getSignature(R.raw.sig_com_google_android_tzdata2));
diff --git a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
index d012eb6..b6bedf0 100644
--- a/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
+++ b/tests/tests/simphonebookprovider/src/android/provider/cts/simphonebook/RemovableSims.java
@@ -71,6 +71,9 @@
List<SubscriptionInfo> allSubscriptions = SystemUtil.runWithShellPermissionIdentity(() ->
subscriptionManager.getActiveSubscriptionInfoList(),
Manifest.permission.READ_PHONE_STATE);
+ if (allSubscriptions == null) {
+ allSubscriptions = Collections.emptyList();
+ }
Map<Integer, List<SubscriptionInfo>> subscriptionsByCardId = allSubscriptions.stream()
.collect(Collectors.groupingBy(SubscriptionInfo::getCardId));
for (UiccCardInfo cardInfo : uiccCards) {
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java
index f5a8477..adee163 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/NetworkRegistrationInfoTest.java
@@ -101,10 +101,11 @@
NetworkRegistrationInfo.SERVICE_TYPE_VOICE), nri.getAvailableServices());
}
- /**
+ /**
* Basic test to ensure {@link NetworkRegistrationInfo#isSearching()} does not throw any
* exception.
*/
+ @SuppressWarnings("deprecation")
@Test
public void testNetworkRegistrationInfoIsSearching() {
NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
@@ -114,6 +115,18 @@
assertTrue(nri.isSearching());
}
+ /**
+ * Basic test to ensure {@link NetworkRegistrationInfo#isNetworkSearching()} does not throw any
+ * exception.
+ */
+ @Test
+ public void testNetworkRegistrationInfoIsNetworkSearching() {
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING)
+ .build();
+ assertTrue(nri.isNetworkSearching());
+ }
@Test
public void testGetDomain() {
@@ -123,6 +136,7 @@
assertEquals(NetworkRegistrationInfo.DOMAIN_CS, nri.getDomain());
}
+ @SuppressWarnings("deprecation")
@Test
public void testGetRegistrationState() {
NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
@@ -132,6 +146,16 @@
}
@Test
+ public void testGetNetworkRegistrationState() {
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING)
+ .build();
+ nri.setRoamingType(NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ assertEquals(NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING,
+ nri.getNetworkRegistrationState());
+ }
+
+ @Test
public void testGetTransportType() {
NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
@@ -175,6 +199,10 @@
assertEquals(ci, nri.getCellIdentity());
}
+ /**
+ * Test {@link NetworkRegistrationInfo#isRegistered()} to support backward compatibility.
+ */
+ @SuppressWarnings("deprecation")
@Test
public void testIsRegistered() {
final int[] registeredStates = new int[] {NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
@@ -200,14 +228,67 @@
}
@Test
+ public void testIsNetworkRegistered() {
+ final int[] registeredStates = new int[] {NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING};
+ for (int state : registeredStates) {
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(state)
+ .build();
+ assertTrue(nri.isNetworkRegistered());
+ }
+
+ final int[] unregisteredStates = new int[] {
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING,
+ NetworkRegistrationInfo.REGISTRATION_STATE_DENIED,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN};
+ for (int state : unregisteredStates) {
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(state)
+ .build();
+ assertFalse(nri.isNetworkRegistered());
+ }
+ }
+
+ /**
+ * Test {@link NetworkRegistrationInfo#isSearching()} to support backward compatibility.
+ */
+ @SuppressWarnings("deprecation")
+ @Test
public void testIsSearching() {
final int[] isSearchingStates = new int[] {
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING};
+ for (int state : isSearchingStates) {
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(state)
+ .build();
+ assertTrue(nri.isSearching());
+ }
+
+ final int[] isNotSearchingStates = new int[] {
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.REGISTRATION_STATE_DENIED,
+ NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN};
+ for (int state : isNotSearchingStates) {
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setRegistrationState(state)
+ .build();
+ assertFalse(nri.isSearching());
+ }
+ }
+
+ @Test
+ public void testIsNetworkSearching() {
+ final int[] isSearchingStates = new int[] {
NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING};
for (int state : isSearchingStates) {
NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
.setRegistrationState(state)
.build();
- assertTrue(nri.isSearching());
+ assertTrue(nri.isNetworkSearching());
}
final int[] isNotSearchingStates = new int[] {
@@ -220,7 +301,7 @@
NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
.setRegistrationState(state)
.build();
- assertFalse(nri.isSearching());
+ assertFalse(nri.isNetworkSearching());
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java
index 43c8be7..148c540 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/TelephonyDisplayInfoTest.java
@@ -30,10 +30,12 @@
Parcel p = Parcel.obtain();
p.writeInt(1);
p.writeInt(2);
+ p.writeBoolean(false);
p.setDataPosition(0);
TelephonyDisplayInfo tdi = TelephonyDisplayInfo.CREATOR.createFromParcel(p);
assertEquals(1, tdi.getNetworkType());
assertEquals(2, tdi.getOverrideNetworkType());
+ assertEquals(false, tdi.isRoaming());
}
}
diff --git a/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java b/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
index a2fe9d2..955d9da 100644
--- a/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
+++ b/tests/tests/telephony/current/src/android/telephony/cts/util/DefaultSmsAppHelper.java
@@ -110,6 +110,10 @@
Assume.assumeTrue(hasTelephony());
}
+ public static void assumeMessaging() {
+ Assume.assumeTrue(hasSms());
+ }
+
public static boolean hasTelephony() {
Context context = ApplicationProvider.getApplicationContext();
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
index 2d2c140..4831f23 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/LockedMessageTest.java
@@ -17,6 +17,7 @@
package android.telephonyprovider.cts;
import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -62,6 +63,7 @@
@Before
public void setupTestEnvironment() {
assumeTelephony();
+ assumeMessaging();
cleanup();
mContentResolver = getInstrumentation().getContext().getContentResolver();
}
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
index ca1f01a..087bfc5 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsPartTest.java
@@ -17,6 +17,7 @@
package android.telephonyprovider.cts;
import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -67,6 +68,7 @@
@Before
public void setupTestEnvironment() {
assumeTelephony();
+ assumeMessaging();
cleanup();
mContentResolver = getInstrumentation().getContext().getContentResolver();
}
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
index 89b27ef..3515225 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/MmsTest.java
@@ -17,6 +17,7 @@
package android.telephonyprovider.cts;
import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -72,6 +73,7 @@
@Before
public void setupTestEnvironment() {
assumeTelephony();
+ assumeMessaging();
cleanup();
mContentResolver = getInstrumentation().getContext().getContentResolver();
}
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
index 05e52ea..a09f1d2 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsConversationTest.java
@@ -17,6 +17,7 @@
package android.telephonyprovider.cts;
import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -60,6 +61,7 @@
@Before
public void setupTestEnvironment() {
assumeTelephony();
+ assumeMessaging();
cleanup();
mContentResolver = getInstrumentation().getContext().getContentResolver();
}
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
index f40f4d7..a950d4d 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/SmsTest.java
@@ -17,6 +17,7 @@
package android.telephonyprovider.cts;
import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -68,6 +69,7 @@
@Before
public void setupTestEnvironment() {
assumeTelephony();
+ assumeMessaging();
cleanup();
mContentResolver = getInstrumentation().getContext().getContentResolver();
mSmsTestHelper = new SmsTestHelper();
diff --git a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
index cbab7ef..739325f 100644
--- a/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
+++ b/tests/tests/telephonyprovider/src/android/telephonyprovider/cts/ThreadsTest.java
@@ -17,6 +17,7 @@
package android.telephonyprovider.cts;
import static android.telephony.cts.util.DefaultSmsAppHelper.assumeTelephony;
+import static android.telephony.cts.util.DefaultSmsAppHelper.assumeMessaging;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@@ -62,6 +63,7 @@
@Before
public void setupTestEnvironment() {
assumeTelephony();
+ assumeMessaging();
cleanup();
mContext = getInstrumentation().getContext();
mContentResolver = mContext.getContentResolver();
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java b/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
index d70cc2b..e1a2fd0 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/TestNetworkWrapper.java
@@ -99,7 +99,7 @@
public TestNetworkWrapper(
@NonNull Context context,
int mtu,
- boolean isMetered,
+ @NonNull Set<Integer> capabilities,
@NonNull Set<Integer> subIds,
@NonNull InetAddress localAddress)
throws Exception {
@@ -125,7 +125,7 @@
mConnectivityManager.requestNetwork(nr, vcnNetworkCallback);
final NetworkCapabilities nc =
- createNetworkCapabilitiesForIface(iface, isMetered, subIds);
+ createNetworkCapabilitiesForIface(iface, capabilities, subIds);
final LinkProperties lp = createLinkPropertiesForIface(iface, mtu);
final VcnNetworkPolicyResult policy = mVcnManager.applyVcnNetworkPolicy(nc, lp);
@@ -150,21 +150,19 @@
}
private static NetworkCapabilities createNetworkCapabilitiesForIface(
- @NonNull String iface, boolean isMetered, Set<Integer> subIds) {
+ @NonNull String iface, Set<Integer> capabilities, Set<Integer> subIds) {
NetworkCapabilities.Builder builder =
NetworkCapabilities.Builder.withoutDefaultCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_TEST)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
.setNetworkSpecifier(new TestNetworkSpecifier(iface))
.setSubscriptionIds(subIds);
- if (!isMetered) {
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
+ for (int cap : capabilities) {
+ builder.addCapability(cap);
}
+
return builder.build();
}
diff --git a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
index 6051a5c..eba8a03 100644
--- a/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
+++ b/tests/tests/vcn/src/android/net/vcn/cts/VcnManagerTest.java
@@ -19,11 +19,14 @@
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.ipsec.ike.cts.IkeTunUtils.PortPair;
import static android.net.ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_DNS_EVENTS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
+import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_ANY;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_FORBIDDEN;
import static android.net.vcn.VcnUnderlyingNetworkTemplate.MATCH_REQUIRED;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -51,6 +54,7 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.vcn.VcnCellUnderlyingNetworkTemplate;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkTemplate;
@@ -77,7 +81,9 @@
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@@ -364,18 +370,29 @@
}
private TestNetworkWrapper createTestNetworkWrapper(
- boolean isMetered, int subId, InetAddress localAddress) throws Exception {
+ int subId, InetAddress localAddress, Set<Integer> capabilities) throws Exception {
TestNetworkWrapper testNetworkWrapper =
new TestNetworkWrapper(
mContext,
TEST_NETWORK_MTU,
- isMetered,
+ capabilities,
Collections.singleton(subId),
localAddress);
assertNotNull("No test network found", testNetworkWrapper.tunNetwork);
return testNetworkWrapper;
}
+ private TestNetworkWrapper createTestNetworkWrapper(
+ boolean isMetered, int subId, InetAddress localAddress) throws Exception {
+ final Set<Integer> capabilities = new HashSet<>();
+ capabilities.add(NET_CAPABILITY_CBS);
+ if (!isMetered) {
+ capabilities.add(NET_CAPABILITY_NOT_METERED);
+ }
+
+ return createTestNetworkWrapper(subId, localAddress, capabilities);
+ }
+
@Test
public void testVcnManagedNetworkLosesNotVcnManagedCapability() throws Exception {
final int subId = verifyAndGetValidDataSubId();
@@ -519,108 +536,256 @@
}
}
+ private TestNetworkWrapper createTestNetworkForNetworkSelection(
+ int subId, Set<Integer> capabilities) throws Exception {
+ return createTestNetworkWrapper(subId, LOCAL_ADDRESS, capabilities);
+ }
+
+ private void verifyVcnMigratesToPreferredUnderlyingNetwork(
+ VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)
+ throws Exception {
+ final int subId = verifyAndGetValidDataSubId();
+
+ // Start on a less preferred network.
+ try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+ createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) {
+ verifyUnderlyingCellAndRunTest(
+ subId,
+ (subGrp, cellNetwork, cellNetworkCb) -> {
+ final VcnSetupResult vcnSetupResult =
+ setupAndGetVcnNetwork(
+ subGrp,
+ cellNetwork,
+ cellNetworkCb,
+ vcnConfig,
+ testNetworkWrapperLessPreferred);
+
+ // Then bring up a more preferred network, and expect to switch to it.
+ try (TestNetworkWrapper testNetworkWrapperPreferred =
+ createTestNetworkForNetworkSelection(subId, capSetPreferred)) {
+ injectAndVerifyIkeMobikePackets(
+ testNetworkWrapperPreferred.ikeTunUtils);
+
+ clearVcnConfigsAndVerifyNetworkTeardown(
+ subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+ }
+ });
+ }
+ }
+
+ private void verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+ VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)
+ throws Exception {
+ final int subId = verifyAndGetValidDataSubId();
+
+ // Start on a more preferred network.
+ try (TestNetworkWrapper testNetworkWrapperPreferred =
+ createTestNetworkForNetworkSelection(subId, capSetPreferred)) {
+ verifyUnderlyingCellAndRunTest(
+ subId,
+ (subGrp, cellNetwork, cellNetworkCb) -> {
+ final VcnSetupResult vcnSetupResult =
+ setupAndGetVcnNetwork(
+ subGrp,
+ cellNetwork,
+ cellNetworkCb,
+ vcnConfig,
+ testNetworkWrapperPreferred);
+
+ // Then bring up a less preferred network, and expect the VCN underlying
+ // network does not change.
+ try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+ createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) {
+ injectAndVerifyIkeDpdPackets(
+ testNetworkWrapperPreferred.ikeTunUtils,
+ vcnSetupResult.ikeExchangePortPair);
+
+ clearVcnConfigsAndVerifyNetworkTeardown(
+ subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+ }
+ });
+ }
+ }
+
+ private void verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+ VcnConfig vcnConfig, Set<Integer> capSetLessPreferred, Set<Integer> capSetPreferred)
+ throws Exception {
+ final int subId = verifyAndGetValidDataSubId();
+
+ // Start on a more preferred network
+ try (TestNetworkWrapper testNetworkWrapperPreferred =
+ createTestNetworkForNetworkSelection(subId, capSetPreferred)) {
+ verifyUnderlyingCellAndRunTest(
+ subId,
+ (subGrp, cellNetwork, cellNetworkCb) -> {
+ final VcnSetupResult vcnSetupResult =
+ setupAndGetVcnNetwork(
+ subGrp,
+ cellNetwork,
+ cellNetworkCb,
+ vcnConfig,
+ testNetworkWrapperPreferred);
+
+ // Bring up a less preferred network
+ try (TestNetworkWrapper testNetworkWrapperLessPreferred =
+ createTestNetworkForNetworkSelection(subId, capSetLessPreferred)) {
+ // Teardown the preferred network
+ testNetworkWrapperPreferred.close();
+ testNetworkWrapperPreferred.vcnNetworkCallback.waitForLost();
+
+ // Verify the VCN switches to the remaining less preferred network
+ injectAndVerifyIkeMobikePackets(
+ testNetworkWrapperLessPreferred.ikeTunUtils);
+
+ clearVcnConfigsAndVerifyNetworkTeardown(
+ subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
+ }
+ });
+ }
+ }
+
+ private VcnCellUnderlyingNetworkTemplate.Builder createCellTemplateBaseBuilder()
+ throws Exception {
+ return new VcnCellUnderlyingNetworkTemplate.Builder().setInternet(MATCH_ANY);
+ }
+
private VcnConfig createVcnConfigPrefersMetered() throws Exception {
final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
nwTemplates.add(
- new VcnWifiUnderlyingNetworkTemplate.Builder().setMetered(MATCH_REQUIRED).build());
+ createCellTemplateBaseBuilder()
+ .setCbs(MATCH_REQUIRED)
+ .setMetered(MATCH_REQUIRED)
+ .build());
nwTemplates.add(
- new VcnWifiUnderlyingNetworkTemplate.Builder().setMetered(MATCH_FORBIDDEN).build());
+ createCellTemplateBaseBuilder()
+ .setCbs(MATCH_REQUIRED)
+ .setMetered(MATCH_FORBIDDEN)
+ .build());
return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
}
@Test
- public void testVcnMigratesToPreferredUnderlyingNetwork() throws Exception {
- final int subId = verifyAndGetValidDataSubId();
- final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
- // Start on NOT_METERED, less preferred network.
- try (TestNetworkWrapper testNetworkWrapperNotMetered =
- createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
- verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
- final VcnSetupResult vcnSetupResult =
- setupAndGetVcnNetwork(
- subGrp,
- cellNetwork,
- cellNetworkCb,
- vcnConfig,
- testNetworkWrapperNotMetered);
-
- // Then bring up a more preferred network, and expect to switch to it.
- try (TestNetworkWrapper testNetworkWrapperMetered =
- createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
- injectAndVerifyIkeMobikePackets(testNetworkWrapperMetered.ikeTunUtils);
-
- clearVcnConfigsAndVerifyNetworkTeardown(
- subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
- }
- });
- }
+ public void testVcnMigratesToPreferredUnderlyingNetwork_preferMetered() throws Exception {
+ verifyVcnMigratesToPreferredUnderlyingNetwork(
+ createVcnConfigPrefersMetered(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS),
+ Set.of(NET_CAPABILITY_CBS));
}
@Test
- public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork() throws Exception {
- final int subId = verifyAndGetValidDataSubId();
- final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
-
- // Start on METERED, more preferred network
- try (TestNetworkWrapper testNetworkWrapperMetered =
- createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
- verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
- final VcnSetupResult vcnSetupResult =
- setupAndGetVcnNetwork(
- subGrp,
- cellNetwork,
- cellNetworkCb,
- vcnConfig,
- testNetworkWrapperMetered);
-
- // Then bring up a less preferred network, and expect the VCN underlying
- // network does not change.
- try (TestNetworkWrapper testNetworkWrapperNotMetered =
- createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
- injectAndVerifyIkeDpdPackets(
- testNetworkWrapperMetered.ikeTunUtils,
- vcnSetupResult.ikeExchangePortPair);
-
- clearVcnConfigsAndVerifyNetworkTeardown(
- subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
- }
- });
- }
+ public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferMetered()
+ throws Exception {
+ verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+ createVcnConfigPrefersMetered(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS),
+ Set.of(NET_CAPABILITY_CBS));
}
@Test
- public void testVcnMigratesAfterPreferredUnderlyingNetworkDies() throws Exception {
- final int subId = verifyAndGetValidDataSubId();
- final VcnConfig vcnConfig = createVcnConfigPrefersMetered();
+ public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferMetered()
+ throws Exception {
+ verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+ createVcnConfigPrefersMetered(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS),
+ Set.of(NET_CAPABILITY_CBS));
+ }
- // Start on METERED, more preferred network
- try (TestNetworkWrapper testNetworkWrapperMetered =
- createTestNetworkWrapper(true /* isMetered */, subId, LOCAL_ADDRESS)) {
- verifyUnderlyingCellAndRunTest(subId, (subGrp, cellNetwork, cellNetworkCb) -> {
- final VcnSetupResult vcnSetupResult =
- setupAndGetVcnNetwork(
- subGrp,
- cellNetwork,
- cellNetworkCb,
- vcnConfig,
- testNetworkWrapperMetered);
+ private VcnConfig createVcnConfigPrefersCbs() throws Exception {
+ final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+ nwTemplates.add(createCellTemplateBaseBuilder().setCbs(MATCH_REQUIRED).build());
+ nwTemplates.add(createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).build());
- // Bring up a NOT_METERED, less preferred network
- try (TestNetworkWrapper testNetworkWrapperNotMetered =
- createTestNetworkWrapper(false /* isMetered */, subId, LOCAL_ADDRESS)) {
- // Teardown the preferred network
- testNetworkWrapperMetered.close();
- testNetworkWrapperMetered.vcnNetworkCallback.waitForLost();
+ return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+ }
- // Verify the VCN switches to the remaining NOT_METERED network
- injectAndVerifyIkeMobikePackets(testNetworkWrapperNotMetered.ikeTunUtils);
+ @Test
+ public void testVcnMigratesToPreferredUnderlyingNetwork_preferCbs() throws Exception {
+ verifyVcnMigratesToPreferredUnderlyingNetwork(
+ createVcnConfigPrefersCbs(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS));
+ }
- clearVcnConfigsAndVerifyNetworkTeardown(
- subGrp, cellNetworkCb, vcnSetupResult.vcnNetwork);
- }
- });
- }
+ @Test
+ public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferCbs() throws Exception {
+ verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+ createVcnConfigPrefersCbs(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS));
+ }
+
+ @Test
+ public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferCbs() throws Exception {
+ verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+ createVcnConfigPrefersCbs(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_CBS));
+ }
+
+ private VcnConfig createVcnConfigPrefersNonCbs() throws Exception {
+ final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+ nwTemplates.add(
+ createCellTemplateBaseBuilder()
+ .setRcs(MATCH_REQUIRED)
+ .setCbs(MATCH_FORBIDDEN)
+ .build());
+ nwTemplates.add(
+ createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build());
+
+ return buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+ }
+
+ @Test
+ public void testVcnMigratesToPreferredUnderlyingNetwork_preferNonCbs() throws Exception {
+ verifyVcnMigratesToPreferredUnderlyingNetwork(
+ createVcnConfigPrefersNonCbs(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
+ }
+
+ @Test
+ public void testVcnDoesNotSelectLessPreferredUnderlyingNetwork_preferNonCbs() throws Exception {
+ verifyVcnDoesNotSelectLessPreferredUnderlyingNetwork(
+ createVcnConfigPrefersNonCbs(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
+ }
+
+ @Test
+ public void testVcnMigratesAfterPreferredUnderlyingNetworkDies_preferNonCbs() throws Exception {
+ verifyVcnMigratesAfterPreferredUnderlyingNetworkDies(
+ createVcnConfigPrefersNonCbs(),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
+ }
+
+ @Test
+ public void testSetVcnWithCbsMatchAny_preferCbsNetworkOverUnmatchedNetwork() throws Exception {
+ final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+ nwTemplates.add(
+ createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build());
+
+ final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+
+ verifyVcnMigratesToPreferredUnderlyingNetwork(
+ vcnConfig,
+ Set.of(NET_CAPABILITY_NOT_METERED),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS, NET_CAPABILITY_CBS));
+ }
+
+ @Test
+ public void testSetVcnWithCbsMatchAny_preferNonCbsNetworkOverUnmatchedNetwork()
+ throws Exception {
+ final List<VcnUnderlyingNetworkTemplate> nwTemplates = new ArrayList<>();
+ nwTemplates.add(
+ createCellTemplateBaseBuilder().setRcs(MATCH_REQUIRED).setCbs(MATCH_ANY).build());
+
+ final VcnConfig vcnConfig = buildVcnConfigBase(nwTemplates).setIsTestModeProfile().build();
+
+ verifyVcnMigratesToPreferredUnderlyingNetwork(
+ vcnConfig,
+ Set.of(NET_CAPABILITY_NOT_METERED),
+ Set.of(NET_CAPABILITY_NOT_METERED, NET_CAPABILITY_RCS));
}
@Test
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/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java b/tests/tests/view/surfacevalidator/src/android/view/cts/surfacevalidator/ASurfaceControlTestActivity.java
index d1e388b..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);
diff --git a/tools/cts-device-info/Android.bp b/tools/cts-device-info/Android.bp
index 21ec062..d6440b5 100644
--- a/tools/cts-device-info/Android.bp
+++ b/tools/cts-device-info/Android.bp
@@ -76,6 +76,7 @@
" -a com.android.compatibility.common.deviceinfo.GraphicsDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.HapticsDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.InputDeviceInfo " +
+ " -a com.android.compatibility.common.deviceinfo.KeystoreAttestationDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.LocaleDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.MediaDeviceInfo " +
" -a com.android.compatibility.common.deviceinfo.MemoryDeviceInfo " +