diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-09 12:00:49 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-04-09 12:00:49 +0000 |
commit | 5c4033e34e18a0a4db3144bc522b479548e3c5be (patch) | |
tree | f04ea5641738bbb2327806e7d922b88f270451f2 | |
parent | 1f86c289d9743718f0508c6a18e36133b98f0483 (diff) | |
parent | 76de60893079ca18f4596591adfa53f72acabcf9 (diff) | |
download | cts-android-mainline-12.0.0_r120.tar.gz |
Snap for 8431613 from 76de60893079ca18f4596591adfa53f72acabcf9 to mainline-media-swcodec-releaseandroid-mainline-12.0.0_r120
Change-Id: I02fd5602a0067bcbd2f8b8a903a59460027d0fc8
21 files changed, 985 insertions, 572 deletions
diff --git a/hostsidetests/appcompat/strictjavapackages/Android.bp b/hostsidetests/appcompat/strictjavapackages/Android.bp index 9ab8a832ca3..af734e33267 100644 --- a/hostsidetests/appcompat/strictjavapackages/Android.bp +++ b/hostsidetests/appcompat/strictjavapackages/Android.bp @@ -24,6 +24,7 @@ java_test_host { "cts-tradefed", "tradefed", "compatibility-host-util", + "cts-tradefed", ], static_libs: [ "compat-classpaths-testing", diff --git a/tests/tests/netpermission/internetpermission/Android.bp b/hostsidetests/appcompat/strictjavapackages/app/Android.bp index 37ad7cb2ac5..47e7f004f69 100644 --- a/tests/tests/netpermission/internetpermission/Android.bp +++ b/hostsidetests/appcompat/strictjavapackages/app/Android.bp @@ -1,4 +1,4 @@ -// Copyright (C) 2019 The Android Open Source Project +// Copyright (C) 2022 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,22 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -package { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_test { - name: "CtsNetTestCasesInternetPermission", +android_test_helper_app { + name: "StrictJavaPackagesTestApp", defaults: ["cts_defaults"], - srcs: ["src/**/*.java"], - - static_libs: ["ctstestrunner-axt"], - - // Tag this module as a cts test artifact + static_libs: [ + "androidx.test.rules", + "androidx.test.core", + ], + sdk_version: "test_current", test_suites: [ + "ats", "cts", + "gts", "general-tests", + "mts", + "tvts", ], - } diff --git a/hostsidetests/appcompat/strictjavapackages/app/AndroidManifest.xml b/hostsidetests/appcompat/strictjavapackages/app/AndroidManifest.xml new file mode 100644 index 00000000000..6ac77dbbad9 --- /dev/null +++ b/hostsidetests/appcompat/strictjavapackages/app/AndroidManifest.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android.compat.sjp.app" + android:targetSandboxVersion="2"> + <application android:requestLegacyExternalStorage="true"> + <uses-library android:name="android.test.runner" /> + </application> + + <instrumentation + android:name="androidx.test.runner.AndroidJUnitRunner" + android:targetPackage="android.compat.sjp.app" /> +</manifest> diff --git a/hostsidetests/appcompat/strictjavapackages/app/src/android/compat/sjp/app/ApexDeviceTest.java b/hostsidetests/appcompat/strictjavapackages/app/src/android/compat/sjp/app/ApexDeviceTest.java new file mode 100644 index 00000000000..fa98fe6a2a9 --- /dev/null +++ b/hostsidetests/appcompat/strictjavapackages/app/src/android/compat/sjp/app/ApexDeviceTest.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.compat.sjp.app; + +import static org.junit.Assert.assertNotNull; + +import android.content.pm.PackageManager; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Device-side helper app for obtaining Apex info. + * + * <p>It is not technically a test as it simply collects information, but it simplifies the usage + * and communication with host-side tests. + */ +@RunWith(AndroidJUnit4.class) +public class ApexDeviceTest { + + @Before + public void before() { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .adoptShellPermissionIdentity(); + } + + @After + public void after() { + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .dropShellPermissionIdentity(); + } + + /** + * Collects all apk-in-apex apps on the device and writes them to disk. + */ + @Test + public void testCollectApkInApexPaths() throws Exception { + Path detailsFilepath = new File("/sdcard/apk-in-apex-paths.txt").toPath(); + final PackageManager pm = InstrumentationRegistry.getInstrumentation().getTargetContext() + .getPackageManager(); + assertNotNull("No package manager instance!", pm); + final Set<String> lines = pm.getInstalledPackages(0).stream() + .map(pkg -> pkg.applicationInfo.sourceDir) + .filter(sourceDir -> sourceDir != null && sourceDir.contains("/apex/")) + .collect(Collectors.toSet()); + Files.write(detailsFilepath, lines); + } +} 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 5ac8f32f498..49a5a058f4a 100644 --- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java +++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java @@ -20,20 +20,28 @@ import static android.compat.testing.Classpaths.ClasspathType.BOOTCLASSPATH; import static android.compat.testing.Classpaths.ClasspathType.SYSTEMSERVERCLASSPATH; import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; import static org.junit.Assume.assumeTrue; import android.compat.testing.Classpaths; import android.compat.testing.SharedLibraryInfo; +import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper; import com.android.modules.utils.build.testing.DeviceSdkLevel; import com.android.tradefed.device.DeviceNotAvailableException; +import com.android.tradefed.device.ITestDevice; +import com.android.tradefed.invoker.TestInformation; import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; +import com.android.tradefed.testtype.junit4.BeforeClassWithInfo; +import com.android.tradefed.testtype.junit4.DeviceTestRunOptions; import com.google.common.collect.HashMultimap; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Multimap; @@ -45,6 +53,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.IOException; +import java.util.Arrays; import java.util.Collection; import java.util.Set; import java.util.stream.Stream; @@ -61,13 +70,14 @@ import java.util.stream.Stream; public class StrictJavaPackagesTest extends BaseHostJUnit4Test { private static final String ANDROID_TEST_MOCK_JAR = "/system/framework/android.test.mock.jar"; + private static final String TEST_HELPER_PACKAGE = "android.compat.sjp.app"; + private static final String TEST_HELPER_APK = "StrictJavaPackagesTestApp.apk"; - private static final Object sLock = new Object(); private static ImmutableList<String> sBootclasspathJars; private static ImmutableList<String> sSystemserverclasspathJars; private static ImmutableList<String> sSharedLibJars; private static ImmutableList<SharedLibraryInfo> sSharedLibs; - private static ImmutableSetMultimap<String, String> sJarsToClasses; + private static ImmutableMultimap<String, String> sJarsToClasses; private DeviceSdkLevel mDeviceSdkLevel; @@ -311,60 +321,483 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test { "Lorg/chromium/net/UrlRequest;", "Lorg/chromium/net/UrlResponseInfo;" ); - + // 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.bluetooth/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;", + "Landroid/bluetooth/hci/BluetoothHciProtoEnums;", + "Landroid/bluetooth/hfp/BluetoothHfpProtoEnums;", + "Landroid/bluetooth/smp/BluetoothSmpProtoEnums;", + "Landroid/hardware/radio/V1_0/ActivityStatsInfo;", + "Landroid/hardware/radio/V1_0/ApnAuthType;", + "Landroid/hardware/radio/V1_0/ApnTypes;", + "Landroid/hardware/radio/V1_0/AppState;", + "Landroid/hardware/radio/V1_0/AppStatus;", + "Landroid/hardware/radio/V1_0/AppType;", + "Landroid/hardware/radio/V1_0/Call;", + "Landroid/hardware/radio/V1_0/CallForwardInfo;", + "Landroid/hardware/radio/V1_0/CallForwardInfoStatus;", + "Landroid/hardware/radio/V1_0/CallPresentation;", + "Landroid/hardware/radio/V1_0/CallState;", + "Landroid/hardware/radio/V1_0/CardState;", + "Landroid/hardware/radio/V1_0/CardStatus;", + "Landroid/hardware/radio/V1_0/Carrier;", + "Landroid/hardware/radio/V1_0/CarrierMatchType;", + "Landroid/hardware/radio/V1_0/CarrierRestrictions;", + "Landroid/hardware/radio/V1_0/CdmaBroadcastSmsConfigInfo;", + "Landroid/hardware/radio/V1_0/CdmaCallWaiting;", + "Landroid/hardware/radio/V1_0/CdmaCallWaitingNumberPlan;", + "Landroid/hardware/radio/V1_0/CdmaCallWaitingNumberPresentation;", + "Landroid/hardware/radio/V1_0/CdmaCallWaitingNumberType;", + "Landroid/hardware/radio/V1_0/CdmaDisplayInfoRecord;", + "Landroid/hardware/radio/V1_0/CdmaInfoRecName;", + "Landroid/hardware/radio/V1_0/CdmaInformationRecord;", + "Landroid/hardware/radio/V1_0/CdmaInformationRecords;", + "Landroid/hardware/radio/V1_0/CdmaLineControlInfoRecord;", + "Landroid/hardware/radio/V1_0/CdmaNumberInfoRecord;", + "Landroid/hardware/radio/V1_0/CdmaOtaProvisionStatus;", + "Landroid/hardware/radio/V1_0/CdmaRedirectingNumberInfoRecord;", + "Landroid/hardware/radio/V1_0/CdmaRedirectingReason;", + "Landroid/hardware/radio/V1_0/CdmaRoamingType;", + "Landroid/hardware/radio/V1_0/CdmaSignalInfoRecord;", + "Landroid/hardware/radio/V1_0/CdmaSignalStrength;", + "Landroid/hardware/radio/V1_0/CdmaSmsAck;", + "Landroid/hardware/radio/V1_0/CdmaSmsAddress;", + "Landroid/hardware/radio/V1_0/CdmaSmsDigitMode;", + "Landroid/hardware/radio/V1_0/CdmaSmsErrorClass;", + "Landroid/hardware/radio/V1_0/CdmaSmsMessage;", + "Landroid/hardware/radio/V1_0/CdmaSmsNumberMode;", + "Landroid/hardware/radio/V1_0/CdmaSmsNumberPlan;", + "Landroid/hardware/radio/V1_0/CdmaSmsNumberType;", + "Landroid/hardware/radio/V1_0/CdmaSmsSubaddress;", + "Landroid/hardware/radio/V1_0/CdmaSmsSubaddressType;", + "Landroid/hardware/radio/V1_0/CdmaSmsWriteArgs;", + "Landroid/hardware/radio/V1_0/CdmaSmsWriteArgsStatus;", + "Landroid/hardware/radio/V1_0/CdmaSubscriptionSource;", + "Landroid/hardware/radio/V1_0/CdmaT53AudioControlInfoRecord;", + "Landroid/hardware/radio/V1_0/CdmaT53ClirInfoRecord;", + "Landroid/hardware/radio/V1_0/CellIdentity;", + "Landroid/hardware/radio/V1_0/CellIdentityCdma;", + "Landroid/hardware/radio/V1_0/CellIdentityGsm;", + "Landroid/hardware/radio/V1_0/CellIdentityLte;", + "Landroid/hardware/radio/V1_0/CellIdentityTdscdma;", + "Landroid/hardware/radio/V1_0/CellIdentityWcdma;", + "Landroid/hardware/radio/V1_0/CellInfo;", + "Landroid/hardware/radio/V1_0/CellInfoCdma;", + "Landroid/hardware/radio/V1_0/CellInfoGsm;", + "Landroid/hardware/radio/V1_0/CellInfoLte;", + "Landroid/hardware/radio/V1_0/CellInfoTdscdma;", + "Landroid/hardware/radio/V1_0/CellInfoType;", + "Landroid/hardware/radio/V1_0/CellInfoWcdma;", + "Landroid/hardware/radio/V1_0/CfData;", + "Landroid/hardware/radio/V1_0/ClipStatus;", + "Landroid/hardware/radio/V1_0/Clir;", + "Landroid/hardware/radio/V1_0/DataCallFailCause;", + "Landroid/hardware/radio/V1_0/DataProfileId;", + "Landroid/hardware/radio/V1_0/DataProfileInfo;", + "Landroid/hardware/radio/V1_0/DataProfileInfoType;", + "Landroid/hardware/radio/V1_0/DataRegStateResult;", + "Landroid/hardware/radio/V1_0/DeviceStateType;", + "Landroid/hardware/radio/V1_0/Dial;", + "Landroid/hardware/radio/V1_0/EvdoSignalStrength;", + "Landroid/hardware/radio/V1_0/GsmBroadcastSmsConfigInfo;", + "Landroid/hardware/radio/V1_0/GsmSignalStrength;", + "Landroid/hardware/radio/V1_0/GsmSmsMessage;", + "Landroid/hardware/radio/V1_0/HardwareConfig;", + "Landroid/hardware/radio/V1_0/HardwareConfigModem;", + "Landroid/hardware/radio/V1_0/HardwareConfigSim;", + "Landroid/hardware/radio/V1_0/HardwareConfigState;", + "Landroid/hardware/radio/V1_0/HardwareConfigType;", + "Landroid/hardware/radio/V1_0/IccIo;", + "Landroid/hardware/radio/V1_0/IccIoResult;", + "Landroid/hardware/radio/V1_0/ImsSmsMessage;", + "Landroid/hardware/radio/V1_0/IndicationFilter;", + "Landroid/hardware/radio/V1_0/LastCallFailCause;", + "Landroid/hardware/radio/V1_0/LastCallFailCauseInfo;", + "Landroid/hardware/radio/V1_0/LceDataInfo;", + "Landroid/hardware/radio/V1_0/LceStatus;", + "Landroid/hardware/radio/V1_0/LceStatusInfo;", + "Landroid/hardware/radio/V1_0/LteSignalStrength;", + "Landroid/hardware/radio/V1_0/MvnoType;", + "Landroid/hardware/radio/V1_0/NeighboringCell;", + "Landroid/hardware/radio/V1_0/NvItem;", + "Landroid/hardware/radio/V1_0/NvWriteItem;", + "Landroid/hardware/radio/V1_0/OperatorInfo;", + "Landroid/hardware/radio/V1_0/OperatorStatus;", + "Landroid/hardware/radio/V1_0/P2Constant;", + "Landroid/hardware/radio/V1_0/PcoDataInfo;", + "Landroid/hardware/radio/V1_0/PersoSubstate;", + "Landroid/hardware/radio/V1_0/PhoneRestrictedState;", + "Landroid/hardware/radio/V1_0/PinState;", + "Landroid/hardware/radio/V1_0/PreferredNetworkType;", + "Landroid/hardware/radio/V1_0/RadioAccessFamily;", + "Landroid/hardware/radio/V1_0/RadioBandMode;", + "Landroid/hardware/radio/V1_0/RadioCapability;", + "Landroid/hardware/radio/V1_0/RadioCapabilityPhase;", + "Landroid/hardware/radio/V1_0/RadioCapabilityStatus;", + "Landroid/hardware/radio/V1_0/RadioCdmaSmsConst;", + "Landroid/hardware/radio/V1_0/RadioConst;", + "Landroid/hardware/radio/V1_0/RadioError;", + "Landroid/hardware/radio/V1_0/RadioIndicationType;", + "Landroid/hardware/radio/V1_0/RadioResponseInfo;", + "Landroid/hardware/radio/V1_0/RadioResponseType;", + "Landroid/hardware/radio/V1_0/RadioState;", + "Landroid/hardware/radio/V1_0/RadioTechnology;", + "Landroid/hardware/radio/V1_0/RadioTechnologyFamily;", + "Landroid/hardware/radio/V1_0/RegState;", + "Landroid/hardware/radio/V1_0/ResetNvType;", + "Landroid/hardware/radio/V1_0/RestrictedState;", + "Landroid/hardware/radio/V1_0/SapApduType;", + "Landroid/hardware/radio/V1_0/SapConnectRsp;", + "Landroid/hardware/radio/V1_0/SapDisconnectType;", + "Landroid/hardware/radio/V1_0/SapResultCode;", + "Landroid/hardware/radio/V1_0/SapStatus;", + "Landroid/hardware/radio/V1_0/SapTransferProtocol;", + "Landroid/hardware/radio/V1_0/SelectUiccSub;", + "Landroid/hardware/radio/V1_0/SendSmsResult;", + "Landroid/hardware/radio/V1_0/SetupDataCallResult;", + "Landroid/hardware/radio/V1_0/SignalStrength;", + "Landroid/hardware/radio/V1_0/SimApdu;", + "Landroid/hardware/radio/V1_0/SimRefreshResult;", + "Landroid/hardware/radio/V1_0/SimRefreshType;", + "Landroid/hardware/radio/V1_0/SmsAcknowledgeFailCause;", + "Landroid/hardware/radio/V1_0/SmsWriteArgs;", + "Landroid/hardware/radio/V1_0/SmsWriteArgsStatus;", + "Landroid/hardware/radio/V1_0/SrvccState;", + "Landroid/hardware/radio/V1_0/SsInfoData;", + "Landroid/hardware/radio/V1_0/SsRequestType;", + "Landroid/hardware/radio/V1_0/SsServiceType;", + "Landroid/hardware/radio/V1_0/SsTeleserviceType;", + "Landroid/hardware/radio/V1_0/StkCcUnsolSsResult;", + "Landroid/hardware/radio/V1_0/SubscriptionType;", + "Landroid/hardware/radio/V1_0/SuppServiceClass;", + "Landroid/hardware/radio/V1_0/SuppSvcNotification;", + "Landroid/hardware/radio/V1_0/TdScdmaSignalStrength;", + "Landroid/hardware/radio/V1_0/TimeStampType;", + "Landroid/hardware/radio/V1_0/TtyMode;", + "Landroid/hardware/radio/V1_0/UiccSubActStatus;", + "Landroid/hardware/radio/V1_0/UssdModeType;", + "Landroid/hardware/radio/V1_0/UusDcs;", + "Landroid/hardware/radio/V1_0/UusInfo;", + "Landroid/hardware/radio/V1_0/UusType;", + "Landroid/hardware/radio/V1_0/VoiceRegStateResult;", + "Landroid/hardware/radio/V1_0/WcdmaSignalStrength;", + "Landroid/hardware/radio/V1_0/IRadio;", + "Landroid/hardware/radio/V1_0/IRadioIndication;", + "Landroid/hardware/radio/V1_0/IRadioResponse;", + "Landroid/hardware/radio/V1_0/ISap;", + "Landroid/hardware/radio/V1_0/ISapCallback;", + "Lcom/android/internal/util/IState;", + "Lcom/android/internal/util/StateMachine;", + "Lcom/google/android/mms/ContentType;", + "Lcom/google/android/mms/MmsException;", + "Lcom/google/android/mms/pdu/Base64;", + "Lcom/google/android/mms/pdu/CharacterSets;", + "Lcom/google/android/mms/pdu/EncodedStringValue;", + "Lcom/google/android/mms/pdu/GenericPdu;", + "Lcom/google/android/mms/pdu/PduBody;", + "Lcom/google/android/mms/pdu/PduComposer;", + "Lcom/google/android/mms/pdu/PduContentTypes;", + "Lcom/google/android/mms/pdu/PduHeaders;", + "Lcom/google/android/mms/pdu/PduParser;", + "Lcom/google/android/mms/pdu/PduPart;", + "Lcom/google/android/mms/pdu/PduPersister;", + "Lcom/google/android/mms/pdu/QuotedPrintable;", + "Lcom/google/android/mms/util/AbstractCache;", + "Lcom/google/android/mms/util/DownloadDrmHelper;", + "Lcom/google/android/mms/util/DrmConvertSession;", + "Lcom/google/android/mms/util/PduCacheEntry;", + "Lcom/google/android/mms/util/SqliteWrapper;", + "Lcom/android/internal/util/State;", + "Lcom/google/android/mms/InvalidHeaderValueException;", + "Lcom/google/android/mms/pdu/AcknowledgeInd;", + "Lcom/google/android/mms/pdu/DeliveryInd;", + "Lcom/google/android/mms/pdu/MultimediaMessagePdu;", + "Lcom/google/android/mms/pdu/NotificationInd;", + "Lcom/google/android/mms/pdu/NotifyRespInd;", + "Lcom/google/android/mms/pdu/ReadOrigInd;", + "Lcom/google/android/mms/pdu/ReadRecInd;", + "Lcom/google/android/mms/pdu/SendConf;", + "Lcom/google/android/mms/util/PduCache;", + "Lcom/google/android/mms/pdu/RetrieveConf;", + "Lcom/google/android/mms/pdu/SendReq;" + ); + private static final ImmutableSet<String> PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST = + ImmutableSet.of( + "Lcom/android/modules/utils/build/SdkLevel;", + "Lcom/android/settingslib/RestrictedLockUtils;" + ); + // TODO: b/223837599 + private static final ImmutableSet<String> TETHERING_APK_IN_APEX_BURNDOWN_LIST = + ImmutableSet.of( + "Landroid/hidl/base/V1_0/DebugInfo;", + // /system/framework/services.jar + "Landroid/net/DataStallReportParcelable;", + "Landroid/net/DhcpResultsParcelable;", + "Landroid/net/INetd;", + "Landroid/net/INetdUnsolicitedEventListener;", + "Landroid/net/INetworkStackConnector;", + "Landroid/net/INetworkStackStatusCallback;", + "Landroid/net/InformationElementParcelable;", + "Landroid/net/InitialConfigurationParcelable;", + "Landroid/net/InterfaceConfigurationParcel;", + "Landroid/net/Layer2InformationParcelable;", + "Landroid/net/Layer2PacketParcelable;", + "Landroid/net/MarkMaskParcel;", + "Landroid/net/NativeNetworkConfig;", + "Landroid/net/NattKeepalivePacketDataParcelable;", + "Landroid/net/NetworkTestResultParcelable;", + "Landroid/net/PrivateDnsConfigParcel;", + "Landroid/net/ProvisioningConfigurationParcelable;", + "Landroid/net/RouteInfoParcel;", + "Landroid/net/ScanResultInfoParcelable;", + "Landroid/net/TcpKeepalivePacketDataParcelable;", + "Landroid/net/TetherConfigParcel;", + "Landroid/net/TetherOffloadRuleParcel;", + "Landroid/net/TetherStatsParcel;", + "Landroid/net/UidRangeParcel;", + "Landroid/net/dhcp/DhcpLeaseParcelable;", + "Landroid/net/dhcp/DhcpServingParamsParcel;", + "Landroid/net/dhcp/IDhcpEventCallbacks;", + "Landroid/net/dhcp/IDhcpServer;", + "Landroid/net/dhcp/IDhcpServerCallbacks;", + "Landroid/net/ipmemorystore/Blob;", + "Landroid/net/ipmemorystore/NetworkAttributesParcelable;", + "Landroid/net/ipmemorystore/SameL3NetworkResponseParcelable;", + "Landroid/net/ipmemorystore/StatusParcelable;", + "Landroid/net/netd/aidl/NativeUidRangeConfig;", + "Landroid/net/networkstack/aidl/NetworkMonitorParameters;", + "Landroid/net/networkstack/aidl/dhcp/DhcpOption;", + "Landroid/net/networkstack/aidl/ip/ReachabilityLossInfoParcelable;", + "Landroid/net/networkstack/aidl/quirks/IPv6ProvisioningLossQuirkParcelable;", + "Landroid/net/shared/NetdUtils;", + "Landroid/net/util/NetworkConstants;", + "Landroid/net/util/SharedLog;", + "Lcom/android/modules/utils/build/SdkLevel;", + ///system/framework/framework.jar + "Landroid/util/IndentingPrintWriter;", + "Lcom/android/internal/annotations/Keep;" + ); + // TODO: b/223836161 + private static final ImmutableSet<String> EXTSERVICES_APK_IN_APEX_BURNDOWN_LIST = + ImmutableSet.of( + ///system/framework/framework.jar + "Landroid/view/displayhash/DisplayHashResultCallback;", + "Landroid/view/displayhash/DisplayHash;", + "Landroid/view/displayhash/VerifiedDisplayHash;" + ); + // TODO: b/223836163 + private static final ImmutableSet<String> ODA_APK_IN_APEX_BURNDOWN_LIST = + ImmutableSet.of( + // /apex/com.android.ondevicepersonalization/javalib/framework-ondevicepersonalization.jar + "Landroid/ondevicepersonalization/aidl/IInitOnDevicePersonalizationCallback;", + "Landroid/ondevicepersonalization/aidl/IOnDevicePersonalizationManagerService;" + ); + // TODO: b/223837016 + private static final ImmutableSet<String> MEDIAPROVIDER_APK_IN_APEX_BURNDOWN_LIST = + ImmutableSet.of( + // /system/framework/services.jar + "Lcom/android/modules/utils/build/SdkLevel;" + ); + // TODO: b/223837017 + private static final ImmutableSet<String> CELLBROADCAST_APK_IN_APEX_BURNDOWN_LIST = + ImmutableSet.of( + // /system/framework/telephony-common.jar + "Lcom/android/cellbroadcastservice/CellBroadcastStatsLog;", + // /system/framework/framework.jar + "Lcom/android/internal/util/IState;", + "Lcom/android/internal/util/StateMachine;", + "Lcom/android/internal/util/State;" + ); + private static final ImmutableMap<String, ImmutableSet<String>> FULL_APK_IN_APEX_BURNDOWN = + new ImmutableMap.Builder<String, ImmutableSet<String>>() + .put("/apex/com.android.bluetooth/app/Bluetooth/Bluetooth.apk", + BLUETOOTH_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.permission/priv-app/PermissionController/PermissionController.apk", + PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.permission/priv-app/GooglePermissionController/GooglePermissionController.apk", + PERMISSION_CONTROLLER_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.tethering/priv-app/TetheringNextGoogle/TetheringNextGoogle.apk", + TETHERING_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.tethering/priv-app/TetheringGoogle/TetheringGoogle.apk", + TETHERING_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.tethering/priv-app/TetheringNext/TetheringNext.apk", + TETHERING_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.tethering/priv-app/Tethering/Tethering.apk", + TETHERING_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.extservices/priv-app/GoogleExtServices/GoogleExtServices.apk", + EXTSERVICES_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.extservices/priv-app/ExtServices/ExtServices.apk", + EXTSERVICES_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.ondevicepersonalization/app/OnDevicePersonalizationGoogle/OnDevicePersonalizationGoogle.apk", + ODA_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.ondevicepersonalization/app/OnDevicePersonalization/OnDevicePersonalization.apk", + ODA_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.mediaprovider/priv-app/MediaProviderGoogle/MediaProviderGoogle.apk", + MEDIAPROVIDER_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.mediaprovider/priv-app/MediaProvider/MediaProvider.apk", + MEDIAPROVIDER_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.cellbroadcast/priv-app/GoogleCellBroadcastServiceModule/GoogleCellBroadcastServiceModule.apk", + CELLBROADCAST_APK_IN_APEX_BURNDOWN_LIST) + .put("/apex/com.android.cellbroadcast/priv-app/CellBroadcastServiceModule/CellBroadcastServiceModule.apk", + CELLBROADCAST_APK_IN_APEX_BURNDOWN_LIST) + .build(); /** * Fetch all jar files in BCP, SSCP and shared libs and extract all the classes. * * <p>This method cannot be static, as there are no static equivalents for {@link #getDevice()} * and {@link #getBuild()}. */ - @Before - public void setupOnce() throws IOException, DeviceNotAvailableException { - if (getDevice() == null || getBuild() == null) { + @BeforeClassWithInfo + public static void setupOnce(TestInformation testInfo) throws Exception { + if (testInfo.getDevice() == null || testInfo.getBuildInfo() == null) { throw new RuntimeException("No device and/or build type specified!"); } - mDeviceSdkLevel = new DeviceSdkLevel(getDevice()); + DeviceSdkLevel deviceSdkLevel = new DeviceSdkLevel(testInfo.getDevice()); - synchronized (sLock) { - if (sJarsToClasses != null) { - return; - } - sBootclasspathJars = Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH); - sSystemserverclasspathJars = - Classpaths.getJarsOnClasspath(getDevice(), SYSTEMSERVERCLASSPATH); - sSharedLibs = mDeviceSdkLevel.isDeviceAtLeastS() - ? Classpaths.getSharedLibraryInfos(getDevice(), getBuild()) - : ImmutableList.of(); - sSharedLibJars = sSharedLibs.stream() - .map(sharedLibraryInfo -> sharedLibraryInfo.paths) - .flatMap(ImmutableCollection::stream) - .filter(this::doesFileExist) - .collect(ImmutableList.toImmutableList()); - - final ImmutableSetMultimap.Builder<String, String> jarsToClasses = - ImmutableSetMultimap.builder(); - Stream.of(sBootclasspathJars.stream(), - sSystemserverclasspathJars.stream(), - sSharedLibJars.stream()) - .reduce(Stream::concat).orElseGet(Stream::empty) - .parallel() - .forEach(jar -> { - try { - ImmutableSet<String> classes = - Classpaths.getClassDefsFromJar(getDevice(), jar).stream() - .map(ClassDef::getType) - // Inner classes always go with their parent. - .filter(className -> !className.contains("$")) - .collect(ImmutableSet.toImmutableSet()); - synchronized (jarsToClasses) { - jarsToClasses.putAll(jar, classes); - } - } catch (DeviceNotAvailableException | IOException e) { - throw new RuntimeException(e); + sBootclasspathJars = Classpaths.getJarsOnClasspath(testInfo.getDevice(), BOOTCLASSPATH); + sSystemserverclasspathJars = + Classpaths.getJarsOnClasspath(testInfo.getDevice(), SYSTEMSERVERCLASSPATH); + sSharedLibs = deviceSdkLevel.isDeviceAtLeastS() + ? Classpaths.getSharedLibraryInfos(testInfo.getDevice(), testInfo.getBuildInfo()) + : ImmutableList.of(); + sSharedLibJars = sSharedLibs.stream() + .map(sharedLibraryInfo -> sharedLibraryInfo.paths) + .flatMap(ImmutableCollection::stream) + .filter(file -> doesFileExist(file, testInfo.getDevice())) + // GmsCore should not contribute to *classpath. + .filter(file -> !file.contains("GmsCore")) + .collect(ImmutableList.toImmutableList()); + + final ImmutableSetMultimap.Builder<String, String> jarsToClasses = + ImmutableSetMultimap.builder(); + Stream.of(sBootclasspathJars.stream(), + sSystemserverclasspathJars.stream(), + sSharedLibJars.stream()) + .reduce(Stream::concat).orElseGet(Stream::empty) + .parallel() + .forEach(jar -> { + try { + ImmutableSet<String> classes = + Classpaths.getClassDefsFromJar(testInfo.getDevice(), jar).stream() + .map(ClassDef::getType) + // Inner classes always go with their parent. + .filter(className -> !className.contains("$")) + .collect(ImmutableSet.toImmutableSet()); + synchronized (jarsToClasses) { + jarsToClasses.putAll(jar, classes); } - }); - sJarsToClasses = jarsToClasses.build(); - } + } catch (DeviceNotAvailableException | IOException e) { + throw new RuntimeException(e); + } + }); + sJarsToClasses = jarsToClasses.build(); + } + + @Before + public void setup() { + mDeviceSdkLevel = new DeviceSdkLevel(getDevice()); } /** @@ -512,6 +945,78 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test { } /** + * Ensure that no apk-in-apex bundles classes that could be eclipsed by jars in + * BOOTCLASSPATH, SYSTEMSERVERCLASSPATH. + */ + @Test + public void testApkInApex_nonClasspathClasses() throws Exception { + HashMultimap<String, Multimap<String, String>> perApkClasspathDuplicates = + HashMultimap.create(); + Arrays.stream(collectApkInApexPaths()) + .parallel() + .forEach(apk -> { + try { + final ImmutableSet<String> apkClasses = + Classpaths.getClassDefsFromJar(getDevice(), apk).stream() + .map(ClassDef::getType) + .collect(ImmutableSet.toImmutableSet()); + // b/226559955: The directory paths containing APKs contain the build ID, + // so strip out the @BUILD_ID portion. + // e.g. /apex/com.android.bluetooth/app/Bluetooth@SC-DEV/Bluetooth.apk -> + // /apex/com.android.bluetooth/app/Bluetooth/Bluetooth.apk + apk = apk.replaceFirst("@[^/]*", ""); + final ImmutableSet<String> burndownClasses = + FULL_APK_IN_APEX_BURNDOWN.getOrDefault(apk, ImmutableSet.of()); + final Multimap<String, String> duplicates = + Multimaps.filterValues(sJarsToClasses, apkClasses::contains); + final Multimap<String, String> filteredDuplicates = + Multimaps.filterValues(duplicates, + className -> !burndownClasses.contains(className) + // TODO: b/225341497 + && !className.equals("Landroidx/annotation/Keep;")); + if (!filteredDuplicates.isEmpty()) { + synchronized (perApkClasspathDuplicates) { + perApkClasspathDuplicates.put(apk, filteredDuplicates); + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + }); + assertThat(perApkClasspathDuplicates).isEmpty(); + } + + private String[] collectApkInApexPaths() { + try { + final CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); + final String installError = getDevice().installPackage( + buildHelper.getTestFile(TEST_HELPER_APK), false); + assertWithMessage("Failed to install %s due to: %s", TEST_HELPER_APK, installError) + .that(installError).isNull(); + runDeviceTests(new DeviceTestRunOptions(TEST_HELPER_PACKAGE) + .setDevice(getDevice()) + .setTestClassName(TEST_HELPER_PACKAGE + ".ApexDeviceTest") + .setTestMethodName("testCollectApkInApexPaths")); + final String remoteFile = "/sdcard/apk-in-apex-paths.txt"; + String content; + try { + content = getDevice().pullFileContents(remoteFile); + } finally { + getDevice().deleteFile(remoteFile); + } + return content.split("\n"); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + try { + getDevice().uninstallPackage(TEST_HELPER_PACKAGE); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + /** * Gets the duplicate classes within a list of jar files. * * @param jars a list of jar files. @@ -523,10 +1028,10 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test { return Multimaps.filterKeys(allClasses, key -> allClasses.get(key).size() > 1); } - private boolean doesFileExist(String path) { + private static boolean doesFileExist(String path, ITestDevice device) { assertThat(path).isNotNull(); try { - return getDevice().doesFileExist(path); + return device.doesFileExist(path); } catch (DeviceNotAvailableException e) { throw new RuntimeException("Could not check whether " + path + " exists on device", e); } diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java index ecf82418345..5900abec4f4 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java @@ -16,17 +16,13 @@ package android.photopicker.cts; -import android.Manifest; import android.app.Instrumentation; import android.content.Context; import android.content.Intent; -import android.provider.DeviceConfig; import androidx.test.InstrumentationRegistry; import androidx.test.uiautomator.UiDevice; -import com.android.modules.utils.build.SdkLevel; - import org.junit.Before; /** @@ -46,7 +42,7 @@ public class PhotoPickerBaseTest { mDevice = UiDevice.getInstance(inst); final String setSyncDelayCommand = - "setprop persist.sys.photopicker.pickerdb.default_sync_delay_ms 0"; + "setprop persist.sys.photopicker.pickerdb.default_sync_delay_ms 0"; mDevice.executeShellCommand(setSyncDelayCommand); mContext = inst.getContext(); diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerPickImagesIntentTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerPickImagesIntentTest.java new file mode 100644 index 00000000000..802acd5e93a --- /dev/null +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerPickImagesIntentTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.photopicker.cts; + +import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPersistedGrant; +import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat; +import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess; +import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages; +import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia; +import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT; +import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait; +import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton; +import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import android.app.Activity; +import android.content.ClipData; +import android.content.Intent; +import android.net.Uri; +import android.provider.MediaStore; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.uiautomator.UiObject; +import androidx.test.uiautomator.UiSelector; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.List; + +/** + * Photo Picker tests for {@link MediaStore#ACTION_PICK_IMAGES} intent exclusively + */ +@RunWith(AndroidJUnit4.class) +public class PhotoPickerPickImagesIntentTest extends PhotoPickerBaseTest { + + private List<Uri> mUriList = new ArrayList<>(); + + @After + public void tearDown() throws Exception { + for (Uri uri : mUriList) { + deleteMedia(uri, mContext); + } + mUriList.clear(); + + if (mActivity != null) { + mActivity.finish(); + } + } + + @Test + public void testMultiSelect_invalidParam() throws Exception { + final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); + intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit() + 1); + mActivity.startActivityForResult(intent, REQUEST_CODE); + final GetResultActivity.Result res = mActivity.getResult(); + assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED); + } + + @Test + public void testMultiSelect_invalidNegativeParam() throws Exception { + final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); + intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, -1); + mActivity.startActivityForResult(intent, REQUEST_CODE); + final GetResultActivity.Result res = mActivity.getResult(); + assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED); + } + + @Test + public void testMultiSelect_returnsNotMoreThanMax() throws Exception { + final int maxCount = 2; + final int imageCount = maxCount + 1; + createImages(imageCount, mContext.getUserId(), mUriList); + final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); + intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount); + mActivity.startActivityForResult(intent, REQUEST_CODE); + + final List<UiObject> itemList = findItemList(imageCount); + final int itemCount = itemList.size(); + assertThat(itemCount).isEqualTo(imageCount); + // Select maxCount + 1 item + for (int i = 0; i < itemCount; i++) { + clickAndWait(mDevice, itemList.get(i)); + } + + UiObject snackbarTextView = mDevice.findObject(new UiSelector().text( + "Select up to 2 items")); + assertWithMessage("Timed out while waiting for snackbar to appear").that( + snackbarTextView.waitForExists(SHORT_TIMEOUT)).isTrue(); + + assertWithMessage("Timed out waiting for snackbar to disappear").that( + snackbarTextView.waitUntilGone(SHORT_TIMEOUT)).isTrue(); + + clickAndWait(mDevice, findAddButton()); + + final ClipData clipData = mActivity.getResult().data.getClipData(); + final int count = clipData.getItemCount(); + assertThat(count).isEqualTo(maxCount); + } + + @Test + public void testDoesNotRespectExtraAllowMultiple() throws Exception { + final int imageCount = 2; + createImages(imageCount, mContext.getUserId(), mUriList); + final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + mActivity.startActivityForResult(intent, REQUEST_CODE); + + final List<UiObject> itemList = findItemList(imageCount); + final int itemCount = itemList.size(); + assertThat(itemCount).isEqualTo(imageCount); + // Select 1 item + clickAndWait(mDevice, itemList.get(0)); + + final Uri uri = mActivity.getResult().data.getData(); + assertPickerUriFormat(uri, mContext.getUserId()); + assertPersistedGrant(uri, mContext.getContentResolver()); + assertRedactedReadOnlyAccess(uri); + } +} diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java index 92c96a6cadb..47ade548718 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java @@ -26,6 +26,7 @@ import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideos; import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia; import static android.photopicker.cts.util.PhotoPickerUiUtils.REGEX_PACKAGE_NAME; import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT; +import static android.photopicker.cts.util.PhotoPickerUiUtils.clickAndWait; import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton; import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList; import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddButton; @@ -34,32 +35,56 @@ import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddOrSe import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; -import android.app.Activity; import android.content.ClipData; import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.net.Uri; import android.provider.MediaStore; -import androidx.test.runner.AndroidJUnit4; +import androidx.test.InstrumentationRegistry; import androidx.test.uiautomator.UiObject; import androidx.test.uiautomator.UiObjectNotFoundException; import androidx.test.uiautomator.UiSelector; import org.junit.After; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** * Photo Picker Device only tests for common flows. */ -@RunWith(AndroidJUnit4.class) +@RunWith(Parameterized.class) public class PhotoPickerTest extends PhotoPickerBaseTest { + + @Parameter(0) + public String mAction; + + @Parameters + public static Iterable<? extends Object> data() { + return PhotoPickerTest.getTestParameters(); + } + private List<Uri> mUriList = new ArrayList<>(); + @Before + public void setUp() throws Exception { + super.setUp(); + + if (mAction.equals(Intent.ACTION_GET_CONTENT)) { + clearDocumentsUiPackageData(); + } + } + @After public void tearDown() throws Exception { for (Uri uri : mUriList) { @@ -77,11 +102,11 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final int itemCount = 1; createImages(itemCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - mActivity.startActivityForResult(intent, REQUEST_CODE); + final Intent intent = new Intent(mAction); + launchPhotoPickerForIntent(intent); final UiObject item = findItemList(itemCount).get(0); - clickAndWait(item); + clickAndWait(mDevice, item); final Uri uri = mActivity.getResult().data.getData(); assertPickerUriFormat(uri, mContext.getUserId()); @@ -94,17 +119,16 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final int itemCount = 1; createImages(itemCount, mContext.getUserId(), mUriList, true); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - mActivity.startActivityForResult(intent, REQUEST_CODE); + final Intent intent = new Intent(mAction); + launchPhotoPickerForIntent(intent); - UiObject albumsTab = mDevice.findObject(new UiSelector().text( - "Albums")); - clickAndWait(albumsTab); + UiObject albumsTab = mDevice.findObject(new UiSelector().text("Albums")); + clickAndWait(mDevice, albumsTab); final UiObject album = findItemList(1).get(0); - clickAndWait(album); + clickAndWait(mDevice, album); final UiObject item = findItemList(itemCount).get(0); - clickAndWait(item); + clickAndWait(mDevice, item); final Uri uri = mActivity.getResult().data.getData(); assertPickerUriFormat(uri, mContext.getUserId()); @@ -116,27 +140,27 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final int videoCount = 2; createVideos(videoCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); + Intent intent = new Intent(mAction); intent.setType("video/*"); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); - mActivity.startActivityForResult(intent, REQUEST_CODE); + intent = addMultipleSelectionFlag(intent); + launchPhotoPickerForIntent(intent); UiObject albumsTab = mDevice.findObject(new UiSelector().text( "Albums")); - clickAndWait(albumsTab); + clickAndWait(mDevice, albumsTab); final UiObject album = findItemList(1).get(0); - clickAndWait(album); + clickAndWait(mDevice, album); final List<UiObject> itemList = findItemList(videoCount); final int itemCount = itemList.size(); assertThat(itemCount).isEqualTo(videoCount); - for (int i = 0; i < itemCount; i++) { - clickAndWait(itemList.get(i)); + for (UiObject uiObject : itemList) { + clickAndWait(mDevice, uiObject); } - clickAndWait(findViewSelectedButton()); + clickAndWait(mDevice, findViewSelectedButton()); // Wait for playback to start. This is needed in some devices where playback // buffering -> ready state takes around 10s. @@ -149,8 +173,8 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final int itemCount = 1; createImages(itemCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - mActivity.startActivityForResult(intent, REQUEST_CODE); + final Intent intent = new Intent(mAction); + launchPhotoPickerForIntent(intent); final UiObject item = findItemList(itemCount).get(0); item.longClick(); @@ -158,7 +182,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final UiObject addButton = findPreviewAddOrSelectButton(); assertThat(addButton.waitForExists(1000)).isTrue(); - clickAndWait(addButton); + clickAndWait(mDevice, addButton); final Uri uri = mActivity.getResult().data.getData(); assertPickerUriFormat(uri, mContext.getUserId()); @@ -166,91 +190,22 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { } @Test - public void testMultiSelect_invalidParam() throws Exception { - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit() + 1); - mActivity.startActivityForResult(intent, REQUEST_CODE); - final GetResultActivity.Result res = mActivity.getResult(); - assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED); - } - - @Test - public void testMultiSelect_invalidNegativeParam() throws Exception { - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, -1); - mActivity.startActivityForResult(intent, REQUEST_CODE); - final GetResultActivity.Result res = mActivity.getResult(); - assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED); - } - - @Test - public void testMultiSelect_returnsNotMoreThanMax() throws Exception { - final int maxCount = 2; - final int imageCount = maxCount + 1; - createImages(imageCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, maxCount); - mActivity.startActivityForResult(intent, REQUEST_CODE); - - final List<UiObject> itemList = findItemList(imageCount); - final int itemCount = itemList.size(); - assertThat(itemCount).isEqualTo(imageCount); - // Select maxCount + 1 item - for (int i = 0; i < itemCount; i++) { - clickAndWait(itemList.get(i)); - } - - UiObject snackbarTextView = mDevice.findObject(new UiSelector().text( - "Select up to 2 items")); - assertWithMessage("Timed out while waiting for snackbar to appear").that( - snackbarTextView.waitForExists(SHORT_TIMEOUT)).isTrue(); - - assertWithMessage("Timed out waiting for snackbar to disappear").that( - snackbarTextView.waitUntilGone(SHORT_TIMEOUT)).isTrue(); - - clickAndWait(findAddButton()); - - final ClipData clipData = mActivity.getResult().data.getClipData(); - final int count = clipData.getItemCount(); - assertThat(count).isEqualTo(maxCount); - } - - @Test - public void testDoesNotRespectExtraAllowMultiple() throws Exception { - final int imageCount = 2; - createImages(imageCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); - mActivity.startActivityForResult(intent, REQUEST_CODE); - - final List<UiObject> itemList = findItemList(imageCount); - final int itemCount = itemList.size(); - assertThat(itemCount).isEqualTo(imageCount); - // Select 1 item - clickAndWait(itemList.get(0)); - - final Uri uri = mActivity.getResult().data.getData(); - assertPickerUriFormat(uri, mContext.getUserId()); - assertPersistedGrant(uri, mContext.getContentResolver()); - assertRedactedReadOnlyAccess(uri); - } - - @Test public void testMultiSelect() throws Exception { final int imageCount = 4; createImages(imageCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); - mActivity.startActivityForResult(intent, REQUEST_CODE); + + Intent intent = new Intent(mAction); + intent = addMultipleSelectionFlag(intent); + launchPhotoPickerForIntent(intent); final List<UiObject> itemList = findItemList(imageCount); final int itemCount = itemList.size(); assertThat(itemCount).isEqualTo(imageCount); - for (int i = 0; i < itemCount; i++) { - clickAndWait(itemList.get(i)); + for (UiObject uiObject : itemList) { + clickAndWait(mDevice, uiObject); } - clickAndWait(findAddButton()); + clickAndWait(mDevice, findAddButton()); final ClipData clipData = mActivity.getResult().data.getClipData(); final int count = clipData.getItemCount(); @@ -267,17 +222,18 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { public void testMultiSelect_longPress() throws Exception { final int videoCount = 3; createDNGVideos(videoCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); + + Intent intent = new Intent(mAction); + intent = addMultipleSelectionFlag(intent); intent.setType("video/*"); - mActivity.startActivityForResult(intent, REQUEST_CODE); + launchPhotoPickerForIntent(intent); final List<UiObject> itemList = findItemList(videoCount); final int itemCount = itemList.size(); assertThat(itemCount).isEqualTo(videoCount); // Select one item from Photo grid - clickAndWait(itemList.get(0)); + clickAndWait(mDevice, itemList.get(0)); // Preview the item UiObject item = itemList.get(1); @@ -289,14 +245,14 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { .that(addOrSelectButton.waitForExists(1000)).isTrue(); // Select the item from Preview - clickAndWait(addOrSelectButton); + clickAndWait(mDevice, addOrSelectButton); mDevice.pressBack(); // Select one more item from Photo grid - clickAndWait(itemList.get(2)); + clickAndWait(mDevice, itemList.get(2)); - clickAndWait(findAddButton()); + clickAndWait(mDevice, findAddButton()); // Verify that all 3 items are returned final ClipData clipData = mActivity.getResult().data.getClipData(); @@ -314,18 +270,19 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { public void testMultiSelect_preview() throws Exception { final int imageCount = 4; createImages(imageCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); - mActivity.startActivityForResult(intent, REQUEST_CODE); + + Intent intent = new Intent(mAction); + intent = addMultipleSelectionFlag(intent); + launchPhotoPickerForIntent(intent); final List<UiObject> itemList = findItemList(imageCount); final int itemCount = itemList.size(); assertThat(itemCount).isEqualTo(imageCount); - for (int i = 0; i < itemCount; i++) { - clickAndWait(itemList.get(i)); + for (UiObject uiObject : itemList) { + clickAndWait(mDevice, uiObject); } - clickAndWait(findViewSelectedButton()); + clickAndWait(mDevice, findViewSelectedButton()); // Swipe left three times swipeLeftAndWait(); @@ -333,10 +290,10 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { swipeLeftAndWait(); // Deselect one item - clickAndWait(findPreviewSelectedCheckButton()); + clickAndWait(mDevice, findPreviewSelectedCheckButton()); // Return selected items - clickAndWait(findPreviewAddButton()); + clickAndWait(mDevice, findPreviewAddButton()); final ClipData clipData = mActivity.getResult().data.getClipData(); final int count = clipData.getItemCount(); @@ -383,20 +340,20 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { // Test 2: Click Mute Button // Click to unmute the audio - clickAndWait(muteButton); + clickAndWait(mDevice, muteButton); // Check that mute button state is unmute, i.e., it shows `volume up` icon assertMuteButtonState(muteButton, /* isMuted */ false); // Click on the muteButton and check that mute button status is now 'mute' - clickAndWait(muteButton); + clickAndWait(mDevice, muteButton); assertMuteButtonState(muteButton, /* isMuted */ true); // Click on the muteButton and check that mute button status is now unmute - clickAndWait(muteButton); + clickAndWait(mDevice, muteButton); assertMuteButtonState(muteButton, /* isMuted */ false); // Test 3: Next preview resumes mute state // Go back and launch preview again mDevice.pressBack(); - clickAndWait(findViewSelectedButton()); + clickAndWait(mDevice, findViewSelectedButton()); // check that player controls are visible assertPlayerControlsVisible(playPauseButton, muteButton); @@ -427,7 +384,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { // Test 2: Swipe resumes mute state, with state of mute button 'volume up' / 'unmute' // Click muteButton again to check the next video resumes the previous video's mute state - clickAndWait(muteButton); + clickAndWait(mDevice, muteButton); assertMuteButtonState(muteButton, /* isMuted */ false); // check that next video resumed previous video's mute state swipeLeftAndWait(); @@ -453,7 +410,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final UiObject playerView = findPlayerView(); // Click on StyledPlayerView to make the video controls visible - clickAndWait(playerView); + clickAndWait(mDevice, playerView); assertPlayerControlsVisible(playPauseButton, muteButton); // Wait for 1s and check that controls are still visible @@ -470,7 +427,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { assertPlayerControlsHidden(playPauseButton, muteButton); // Click on the StyledPlayerView and check that controls appear - clickAndWait(playerView); + clickAndWait(mDevice, playerView); assertPlayerControlsVisible(playPauseButton, muteButton); // Swipe left to check that controls are now visible on swipe @@ -493,20 +450,20 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { final String mimeType = "video/dng"; - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); + Intent intent = new Intent(mAction); + intent = addMultipleSelectionFlag(intent); intent.setType(mimeType); - mActivity.startActivityForResult(intent, REQUEST_CODE); + launchPhotoPickerForIntent(intent); // find all items final List<UiObject> itemList = findItemList(-1); final int itemCount = itemList.size(); assertThat(itemCount).isAtLeast(videoCount); - for (int i = 0; i < itemCount; i++) { - clickAndWait(itemList.get(i)); + for (UiObject uiObject : itemList) { + clickAndWait(mDevice, uiObject); } - clickAndWait(findAddButton()); + clickAndWait(mDevice, findAddButton()); final ClipData clipData = mActivity.getResult().data.getClipData(); final int count = clipData.getItemCount(); @@ -539,37 +496,38 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { assertPlayerControlsAutoHide(playPauseButton, muteButton); // Click on StyledPlayerView to make the video controls visible - clickAndWait(findPlayerView()); + clickAndWait(mDevice, findPlayerView()); // PlayPause button is now pause button, click the button to pause the video. - clickAndWait(playPauseButton); + clickAndWait(mDevice, playPauseButton); // Wait for 1s and check that play button is not auto hidden assertPlayerControlsDontAutoHide(playPauseButton, muteButton); // PlayPause button is now play button, click the button to play the video. - clickAndWait(playPauseButton); + clickAndWait(mDevice, playPauseButton); // Check that pause button auto-hides in 1s. assertPlayerControlsAutoHide(playPauseButton, muteButton); } private void launchPreviewMultipleWithVideos(int videoCount) throws Exception { createVideos(videoCount, mContext.getUserId(), mUriList); - final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES); - intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit()); + + Intent intent = new Intent(mAction); + intent = addMultipleSelectionFlag(intent); intent.setType("video/*"); - mActivity.startActivityForResult(intent, REQUEST_CODE); + launchPhotoPickerForIntent(intent); final List<UiObject> itemList = findItemList(videoCount); final int itemCount = itemList.size(); assertThat(itemCount).isEqualTo(videoCount); - for (int i = 0; i < itemCount; i++) { - clickAndWait(itemList.get(i)); + for (UiObject uiObject : itemList) { + clickAndWait(mDevice, uiObject); } - clickAndWait(findViewSelectedButton()); + clickAndWait(mDevice, findViewSelectedButton()); // Wait for playback to start. This is needed in some devices where playback // buffering -> ready state takes around 10s. @@ -582,7 +540,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { // Wait for 1s or Play/Pause button to hide playPauseButton.waitUntilGone(1000); // Click on StyledPlayerView to make the video controls visible - clickAndWait(playerView); + clickAndWait(mDevice, playerView); assertPlayerControlsVisible(playPauseButton, muteButton); } @@ -649,15 +607,75 @@ public class PhotoPickerTest extends PhotoPickerBaseTest { REGEX_PACKAGE_NAME + ":id/preview_video_image")); } - private void clickAndWait(UiObject uiObject) throws Exception { - uiObject.click(); - mDevice.waitForIdle(); - } - private void swipeLeftAndWait() { final int width = mDevice.getDisplayWidth(); final int height = mDevice.getDisplayHeight(); mDevice.swipe(15 * width / 20, height / 2, width / 20, height / 2, 10); mDevice.waitForIdle(); } + + + static List<String> getTestParameters() { + return Arrays.asList( + MediaStore.ACTION_PICK_IMAGES, + Intent.ACTION_GET_CONTENT + ); + } + + private Intent addMultipleSelectionFlag(Intent intent) { + switch (intent.getAction()) { + case MediaStore.ACTION_PICK_IMAGES: + intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, + MediaStore.getPickImagesMaxLimit()); + break; + case Intent.ACTION_GET_CONTENT: + intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true); + break; + default: + // do nothing + } + + return intent; + } + + private void launchPhotoPickerForIntent(Intent intent) throws Exception { + switch (intent.getAction()) { + case MediaStore.ACTION_PICK_IMAGES: + mActivity.startActivityForResult(intent, REQUEST_CODE); + break; + case Intent.ACTION_GET_CONTENT: + if (intent.getType() == null) { + intent.setType("*/*"); + } + mActivity.startActivityForResult(intent, REQUEST_CODE); + findAndLaunchPicker(); + break; + default: + // do nothing + } + } + + /** + * Clears the DocumentsUI package data. + */ + private void clearDocumentsUiPackageData() throws Exception { + final PackageManager pm = mContext.getPackageManager(); + final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + final ResolveInfo ri = pm.resolveActivity(intent, 0); + InstrumentationRegistry.getInstrumentation().getUiAutomation() + .executeShellCommand("pm clear " + ri.activityInfo.packageName); + } + + private void findAndLaunchPicker() throws Exception { + mDevice.waitForIdle(); + UiObject photoPickerApp = new UiObject(new UiSelector().textMatches("Photo picker")); + + assertWithMessage("Timed out while waiting for Photo picker app to appear") + .that(photoPickerApp.waitForExists(SHORT_TIMEOUT)) + .isTrue(); + + clickAndWait(mDevice, photoPickerApp); + mDevice.waitForIdle(); + } } diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java index d20dcd6665b..9da6c9c35bd 100644 --- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java +++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertWithMessage; import android.text.format.DateUtils; +import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject; import androidx.test.uiautomator.UiObjectNotFoundException; import androidx.test.uiautomator.UiScrollable; @@ -92,4 +93,9 @@ public class PhotoPickerUiUtils { return new UiObject(new UiSelector().resourceIdMatches( REGEX_PACKAGE_NAME + ":id/profile_button")); } + + public static void clickAndWait(UiDevice uiDevice, UiObject uiObject) throws Exception { + uiObject.click(); + uiDevice.waitForIdle(); + } } diff --git a/tests/tests/mediaparser/Android.bp b/tests/tests/mediaparser/Android.bp index 138cb5ac826..d916d6198d2 100644 --- a/tests/tests/mediaparser/Android.bp +++ b/tests/tests/mediaparser/Android.bp @@ -18,7 +18,10 @@ package { android_test { name: "CtsMediaParserTestCases", - defaults: ["CtsMediaParserTestCasesDefaults", "cts_defaults"], + defaults: [ + "CtsMediaParserTestCasesDefaults", + "cts_defaults", + ], min_sdk_version: "29", test_suites: [ "cts", @@ -39,8 +42,8 @@ java_defaults { static_libs: [ "ctstestrunner-axt", "androidx.test.ext.junit", - "exoplayer2-extractor-test-utils", - "exoplayer2-extractor-tests-assets", + "exoplayer-cts_media-test_assets", + "exoplayer-cts_media-test_utils", ], libs: [ "android.test.base", diff --git a/tests/tests/netpermission/OWNERS b/tests/tests/netpermission/OWNERS deleted file mode 100644 index 370c20c10f1..00000000000 --- a/tests/tests/netpermission/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -# Bug component: 31808 -include ../net/OWNERS diff --git a/tests/tests/netpermission/internetpermission/AndroidManifest.xml b/tests/tests/netpermission/internetpermission/AndroidManifest.xml deleted file mode 100644 index 45ef5bdd5f1..00000000000 --- a/tests/tests/netpermission/internetpermission/AndroidManifest.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2019 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.networkpermission.internetpermission.cts"> - - <application> - <uses-library android:name="android.test.runner"/> - <activity android:name="android.networkpermission.internetpermission.cts.InternetPermissionTest" - android:label="InternetPermissionTest" - android:exported="true"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/> - </intent-filter> - </activity> - </application> - - <!-- - The CTS stubs package cannot be used as the target application here, - since that requires many permissions to be set. Instead, specify this - package itself as the target and include any stub activities needed. - - This test package uses the default InstrumentationTestRunner, because - the InstrumentationCtsTestRunner is only available in the stubs - package. That runner cannot be added to this package either, since it - relies on hidden APIs. - --> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.networkpermission.internetpermission.cts" - android:label="CTS tests for INTERNET permissions"> - <meta-data android:name="listener" - android:value="com.android.cts.runner.CtsTestRunListener"/> - </instrumentation> - -</manifest> diff --git a/tests/tests/netpermission/internetpermission/AndroidTest.xml b/tests/tests/netpermission/internetpermission/AndroidTest.xml deleted file mode 100644 index 3b23e72145c..00000000000 --- a/tests/tests/netpermission/internetpermission/AndroidTest.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<configuration description="Config for CTS internet permission test cases"> - <option name="test-suite-tag" value="cts" /> - <option name="config-descriptor:metadata" key="component" value="networking" /> - <option name="config-descriptor:metadata" key="parameter" value="instant_app" /> - <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> - <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> - <option name="not-shardable" value="true" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="CtsNetTestCasesInternetPermission.apk" /> - </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="android.networkpermission.internetpermission.cts" /> - <option name="runtime-hint" value="10s" /> - </test> -</configuration> diff --git a/tests/tests/netpermission/internetpermission/TEST_MAPPING b/tests/tests/netpermission/internetpermission/TEST_MAPPING deleted file mode 100644 index 60877f4a321..00000000000 --- a/tests/tests/netpermission/internetpermission/TEST_MAPPING +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presubmit": [ - { - "name": "CtsNetTestCasesInternetPermission" - } - ] -} diff --git a/tests/tests/netpermission/internetpermission/src/android/net/cts/network/permission/InternetPermissionTest.java b/tests/tests/netpermission/internetpermission/src/android/net/cts/network/permission/InternetPermissionTest.java deleted file mode 100644 index 2b7c8b5f357..00000000000 --- a/tests/tests/netpermission/internetpermission/src/android/net/cts/network/permission/InternetPermissionTest.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2019 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.net.cts.networkpermission.internetpermission; - -import static org.junit.Assert.fail; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.Socket; -/** -* Test that protected android.net.ConnectivityManager methods cannot be called without -* permissions -*/ -@RunWith(AndroidJUnit4.class) -public class InternetPermissionTest { - - /** - * Verify that create inet socket failed because of the permission is missing. - * <p>Tests Permission: - * {@link android.Manifest.permission#INTERNET}. - */ - @SmallTest - @Test - public void testCreateSocket() throws Exception { - try { - Socket socket = new Socket("example.com", 80); - fail("Ceate inet socket did not throw SecurityException as expected"); - } catch (SecurityException e) { - // expected - } - } -} diff --git a/tests/tests/netpermission/updatestatspermission/Android.bp b/tests/tests/netpermission/updatestatspermission/Android.bp deleted file mode 100644 index 7a24886e69c..00000000000 --- a/tests/tests/netpermission/updatestatspermission/Android.bp +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (C) 2019 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - default_applicable_licenses: ["Android-Apache-2.0"], -} - -android_test { - name: "CtsNetTestCasesUpdateStatsPermission", - defaults: ["cts_defaults"], - - srcs: ["src/**/*.java"], - - static_libs: ["ctstestrunner-axt"], - - // Tag this module as a cts test artifact - test_suites: [ - "cts", - "general-tests", - ], - -} diff --git a/tests/tests/netpermission/updatestatspermission/AndroidManifest.xml b/tests/tests/netpermission/updatestatspermission/AndroidManifest.xml deleted file mode 100644 index 6babe8fd554..00000000000 --- a/tests/tests/netpermission/updatestatspermission/AndroidManifest.xml +++ /dev/null @@ -1,58 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2019 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.networkpermission.updatestatspermission.cts"> - - <!-- - This CTS test is designed to test that an unprivileged app cannot get the - UPDATE_DEVICE_STATS permission even if it specified it in the manifest. the - UPDATE_DEVICE_STATS permission is a signature|privileged permission that CTS - test cannot have. - --> - <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS"/> - <uses-permission android:name="android.permission.INTERNET"/> - <application> - <uses-library android:name="android.test.runner"/> - <activity android:name="android.networkpermission.updatestatspermission.cts.UpdateStatsPermissionTest" - android:label="UpdateStatsPermissionTest" - android:exported="true"> - <intent-filter> - <action android:name="android.intent.action.MAIN"/> - <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"/> - </intent-filter> - </activity> - </application> - - <!-- - The CTS stubs package cannot be used as the target application here, - since that requires many permissions to be set. Instead, specify this - package itself as the target and include any stub activities needed. - - This test package uses the default InstrumentationTestRunner, because - the InstrumentationCtsTestRunner is only available in the stubs - package. That runner cannot be added to this package either, since it - relies on hidden APIs. - --> - <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" - android:targetPackage="android.networkpermission.updatestatspermission.cts" - android:label="CTS tests for UPDATE_DEVICE_STATS permissions"> - <meta-data android:name="listener" - android:value="com.android.cts.runner.CtsTestRunListener"/> - </instrumentation> - -</manifest> diff --git a/tests/tests/netpermission/updatestatspermission/AndroidTest.xml b/tests/tests/netpermission/updatestatspermission/AndroidTest.xml deleted file mode 100644 index c47cad97116..00000000000 --- a/tests/tests/netpermission/updatestatspermission/AndroidTest.xml +++ /dev/null @@ -1,31 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2019 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> -<configuration description="Config for CTS update stats permission test cases"> - <option name="test-suite-tag" value="cts" /> - <option name="config-descriptor:metadata" key="component" value="networking" /> - <option name="config-descriptor:metadata" key="parameter" value="instant_app" /> - <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" /> - <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> - <option name="not-shardable" value="true" /> - <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> - <option name="cleanup-apks" value="true" /> - <option name="test-file-name" value="CtsNetTestCasesUpdateStatsPermission.apk" /> - </target_preparer> - <test class="com.android.tradefed.testtype.AndroidJUnitTest" > - <option name="package" value="android.networkpermission.updatestatspermission.cts" /> - <option name="runtime-hint" value="10s" /> - </test> -</configuration> diff --git a/tests/tests/netpermission/updatestatspermission/TEST_MAPPING b/tests/tests/netpermission/updatestatspermission/TEST_MAPPING deleted file mode 100644 index 6d6dfe042bc..00000000000 --- a/tests/tests/netpermission/updatestatspermission/TEST_MAPPING +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presubmit": [ - { - "name": "CtsNetTestCasesUpdateStatsPermission" - } - ] -} diff --git a/tests/tests/netpermission/updatestatspermission/src/android/net/cts/network/permission/UpdateStatsPermissionTest.java b/tests/tests/netpermission/updatestatspermission/src/android/net/cts/network/permission/UpdateStatsPermissionTest.java deleted file mode 100644 index bea843c706c..00000000000 --- a/tests/tests/netpermission/updatestatspermission/src/android/net/cts/network/permission/UpdateStatsPermissionTest.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2019 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.net.cts.networkpermission.updatestatspermission; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import android.net.TrafficStats; -import android.os.Process; - -import androidx.test.filters.SmallTest; -import androidx.test.runner.AndroidJUnit4; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.io.OutputStream; -import java.net.Socket; - -/** -* Test that protected android.net.ConnectivityManager methods cannot be called without -* permissions -*/ -@RunWith(AndroidJUnit4.class) -public class UpdateStatsPermissionTest { - - /** - * Verify that setCounterSet for a different uid failed because of the permission cannot be - * granted to a third-party app. - * <p>Tests Permission: - * {@link android.Manifest.permission#UPDATE_DEVICE_STATS}. - */ - @SmallTest - @Test - public void testUpdateDeviceStatsPermission() throws Exception { - - // Set the current thread uid to a another uid. It should silently fail when tagging the - // socket since the current process doesn't have UPDATE_DEVICE_STATS permission. - TrafficStats.setThreadStatsTag(0); - TrafficStats.setThreadStatsUid(/*root uid*/ 0); - Socket socket = new Socket("example.com", 80); - TrafficStats.tagSocket(socket); - - // Transfer 1K of data to a remote host and verify the stats is still billed to the current - // uid. - final int byteCount = 1024; - - socket.setTcpNoDelay(true); - socket.setSoLinger(true, 0); - OutputStream out = socket.getOutputStream(); - byte[] buf = new byte[byteCount]; - final long uidTxBytesBefore = TrafficStats.getUidTxBytes(Process.myUid()); - out.write(buf); - out.close(); - socket.close(); - long uidTxBytesAfter = TrafficStats.getUidTxBytes(Process.myUid()); - long uidTxDeltaBytes = uidTxBytesAfter - uidTxBytesBefore; - assertTrue("uidtxb: " + uidTxBytesBefore + " -> " + uidTxBytesAfter + " delta=" - + uidTxDeltaBytes + " >= " + byteCount, uidTxDeltaBytes >= byteCount); - } - - static final int UNSUPPORTED = -1; - - /** - * Verify that get TrafficStats of a different uid failed because of the permission is not - * granted to a third-party app. - * <p>Tests Permission: - * {@link android.Manifest.permission#UPDATE_DEVICE_STATS}. - */ - @SmallTest - @Test - public void testGetStatsOfOtherUid() throws Exception { - // Test get stats of another uid failed since the current process does not have permission - assertEquals(UNSUPPORTED, TrafficStats.getUidRxBytes(/*root uid*/ 0)); - } -} diff --git a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java index a4f3ff5aaa7..ef52bc71881 100644 --- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java +++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java @@ -165,6 +165,7 @@ public class WifiManagerTest extends WifiJUnit3TestBase { private static final int SCAN_TEST_WAIT_DURATION_MS = 15_000; private static final int TEST_WAIT_DURATION_MS = 10_000; private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000; + private static final int WIFI_PNO_CONNECT_TIMEOUT_MILLIS = 90_000; private static final int WAIT_MSEC = 60; private static final int DURATION_SCREEN_TOGGLE = 2000; private static final int DURATION_SETTINGS_TOGGLE = 1_000; @@ -439,6 +440,10 @@ public class WifiManagerTest extends WifiJUnit3TestBase { } } + private void waitForConnection(int timeoutMillis) throws Exception { + waitForNetworkInfoState(NetworkInfo.State.CONNECTED, timeoutMillis); + } + private void waitForConnection() throws Exception { waitForNetworkInfoState(NetworkInfo.State.CONNECTED, WIFI_CONNECT_TIMEOUT_MILLIS); } @@ -2864,7 +2869,7 @@ public class WifiManagerTest extends WifiJUnit3TestBase { } // make sure we're connected - waitForConnection(); + waitForConnection(WIFI_PNO_CONNECT_TIMEOUT_MILLIS); WifiInfo currentNetwork = ShellIdentityUtils.invokeWithShellPermissions( mWifiManager::getConnectionInfo); |