summaryrefslogtreecommitdiff
path: root/hostsidetests
diff options
context:
space:
mode:
Diffstat (limited to 'hostsidetests')
-rw-r--r--hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java7
-rw-r--r--hostsidetests/compilation/Android.bp87
-rw-r--r--hostsidetests/compilation/scripts/generate_dm.sh34
-rw-r--r--hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java45
-rw-r--r--hostsidetests/devicepolicy/Android.bp43
-rw-r--r--hostsidetests/devicepolicy/TEST_MAPPING6
-rw-r--r--hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp1
-rw-r--r--hostsidetests/devicepolicy/app/StartInfoApp/OWNERS5
-rw-r--r--hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java13
-rw-r--r--hostsidetests/gwp_asan/Android.bp2
-rw-r--r--hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java46
-rw-r--r--hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java37
-rw-r--r--hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java6
-rw-r--r--hostsidetests/gwp_asan/default/Android.bp (renamed from hostsidetests/gwp_asan/recoverable/Android.bp)2
-rw-r--r--hostsidetests/gwp_asan/default/AndroidManifest.xml (renamed from hostsidetests/gwp_asan/recoverable/AndroidManifest.xml)0
-rw-r--r--hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java50
-rw-r--r--hostsidetests/gwp_asan/src/android/cts/gwp_asan/NonRecoverableTest.java72
-rw-r--r--hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java75
-rw-r--r--hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java13
-rw-r--r--hostsidetests/incrementalinstall/OWNERS3
-rw-r--r--hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java115
-rw-r--r--hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java14
-rw-r--r--hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java16
-rw-r--r--hostsidetests/rollback/OWNERS6
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java13
-rw-r--r--hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java5
-rw-r--r--hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java186
-rw-r--r--hostsidetests/scopedstorage/libs/ScopedStorageTestLib/src/android/scopedstorage/cts/lib/TestUtils.java3
-rw-r--r--hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java27
-rw-r--r--hostsidetests/security/Android.bp12
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxHostTest.java108
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxNeverallowRule.java184
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesParserTest.java16
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java191
-rw-r--r--hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTestVendor.java155
-rwxr-xr-xhostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c21
-rw-r--r--hostsidetests/shortcuts/hostside/AndroidTest.xml2
-rw-r--r--hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaCapabilitiesTests.java8
-rw-r--r--hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java21
39 files changed, 1085 insertions, 565 deletions
diff --git a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
index 71c8bc19b6a..a3d7e6ea431 100644
--- a/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
+++ b/hostsidetests/appsecurity/src/android/appsecurity/cts/AdoptableHostTest.java
@@ -51,6 +51,7 @@ import java.util.concurrent.TimeUnit;
public class AdoptableHostTest extends BaseHostJUnit4Test {
public static final String FEATURE_ADOPTABLE_STORAGE = "feature:android.software.adoptable_storage";
+ private static final int ANDROID_API_LEVEL_R = 30;
private String mListVolumesInitialState;
@@ -400,7 +401,11 @@ public class AdoptableHostTest extends BaseHostJUnit4Test {
}
private boolean isSupportedDevice() throws Exception {
- return hasFeature() || hasFstab();
+ return hasCasefoldSupport() && (hasFeature() || hasFstab());
+ }
+
+ private boolean hasCasefoldSupport() throws Exception {
+ return getDevice().getLaunchApiLevel() >= ANDROID_API_LEVEL_R;
}
private boolean hasFeature() throws Exception {
diff --git a/hostsidetests/compilation/Android.bp b/hostsidetests/compilation/Android.bp
index b80a17dfe80..bac1ac298ba 100644
--- a/hostsidetests/compilation/Android.bp
+++ b/hostsidetests/compilation/Android.bp
@@ -14,6 +14,7 @@
package {
default_applicable_licenses: ["Android-Apache-2.0"],
+ default_team: "trendy_team_art_mainline",
}
java_defaults {
@@ -25,15 +26,18 @@ java_defaults {
java_resource_dirs: ["assets/"],
java_resources: [
":AppUsedByOtherApp",
+ ":AppUsedByOtherApp_1_disable_embedded_profile_dm",
":AppUsedByOtherApp_1_dm",
":AppUsedByOtherApp_2_prof",
":AppUsingOtherApp",
- ":CompilationTestCases_package-dex-usage",
+ ":CompilationTestCases-package-dex-usage",
":CtsCompilationApp",
":CtsCompilationApp_profile",
":CtsCompilationApp_dm",
":CtsCompilationApp_with_bad_profile",
":CtsCompilationApp_with_good_profile",
+ ":disable_embedded_profile_dm",
+ ":empty_config_dm",
],
libs: [
"cts-tradefed",
@@ -78,15 +82,22 @@ genrule_defaults {
"--reference-profile-file=$(out)",
}
-// Generates a DM file from a binary profile.
-// The input must be the binary profile.
+sh_binary {
+ name: "generate_dm",
+ host_supported: true,
+ src: "scripts/generate_dm.sh",
+}
+
+// Generates a DM file.
+// Each input must be a binary profile or a config file in binary protobuf
+// format.
genrule_defaults {
name: "dm_defaults",
- tools: ["soong_zip"],
- cmd: "cp $(in) $(genDir)/primary.prof && " +
- "$(location soong_zip) " +
- "-j -f $(genDir)/primary.prof " +
- "-o $(out)",
+ tools: [
+ "generate_dm",
+ "soong_zip",
+ ],
+ cmd: "$(location generate_dm) $(location soong_zip) $(out) $(in)",
}
genrule {
@@ -138,15 +149,69 @@ genrule {
}
genrule {
- name: "CompilationTestCases_package-dex-usage",
+ name: "CompilationTestCases-package-dex-usage",
+ srcs: [
+ ":libartservice_protos",
+ "assets/package-dex-usage.textproto",
+ ],
tools: ["aprotoc"],
cmd: "$(location aprotoc) " +
"--encode=com.android.server.art.proto.DexUseProto " +
"$(locations :libartservice_protos) " +
"< $(location assets/package-dex-usage.textproto) > $(out)",
+ out: ["package-dex-usage.pb"],
+}
+
+genrule {
+ name: "CompilationTestCases-config-empty",
srcs: [
":libartservice_protos",
- "assets/package-dex-usage.textproto",
],
- out: ["package-dex-usage.pb"],
+ tools: ["aprotoc"],
+ cmd: "$(location aprotoc) " +
+ "--encode=com.android.server.art.proto.DexMetadataConfig " +
+ "$(locations :libartservice_protos) " +
+ "<<<'' > $(out)",
+ out: ["config-empty.pb"],
+}
+
+genrule {
+ name: "empty_config_dm",
+ defaults: ["dm_defaults"],
+ srcs: [
+ ":CompilationTestCases-config-empty",
+ ],
+ out: ["empty_config.dm"],
+}
+
+genrule {
+ name: "CompilationTestCases-config-disable_embedded_profile",
+ srcs: [
+ ":libartservice_protos",
+ ],
+ tools: ["aprotoc"],
+ cmd: "$(location aprotoc) " +
+ "--encode=com.android.server.art.proto.DexMetadataConfig " +
+ "$(locations :libartservice_protos) " +
+ "<<<'enable_embedded_profile: false' > $(out)",
+ out: ["config-disable_embedded_profile.pb"],
+}
+
+genrule {
+ name: "disable_embedded_profile_dm",
+ defaults: ["dm_defaults"],
+ srcs: [
+ ":CompilationTestCases-config-disable_embedded_profile",
+ ],
+ out: ["disable_embedded_profile.dm"],
+}
+
+genrule {
+ name: "AppUsedByOtherApp_1_disable_embedded_profile_dm",
+ defaults: ["dm_defaults"],
+ srcs: [
+ ":AppUsedByOtherApp_1_prof",
+ ":CompilationTestCases-config-disable_embedded_profile",
+ ],
+ out: ["AppUsedByOtherApp_1_disable_embedded_profile.dm"],
}
diff --git a/hostsidetests/compilation/scripts/generate_dm.sh b/hostsidetests/compilation/scripts/generate_dm.sh
new file mode 100644
index 00000000000..7be9bfdcbea
--- /dev/null
+++ b/hostsidetests/compilation/scripts/generate_dm.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+#
+# Copyright 2024 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.
+
+# A tool to generate a dm file from inputs.
+# Usage: SCRIPT SOONG_ZIP OUTPUT INPUTS...
+
+soong_zip=$1
+output=$2
+shift 2
+
+args="${soong_zip} -o ${output}"
+for input in $@; do
+ if [[ $input =~ \.prof$ ]]; then
+ args+=" -e primary.prof -f $input"
+ fi
+ if [[ $input =~ \.pb$ ]]; then
+ args+=" -e config.pb -f $input"
+ fi
+done
+
+$args
diff --git a/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java b/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
index 1f7dfb04fbe..c01dec9588b 100644
--- a/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
+++ b/hostsidetests/compilation/src/android/compilation/cts/CompilationTest.java
@@ -56,6 +56,10 @@ public class CompilationTest extends BaseHostJUnit4Test {
private static final String TEST_APP_2_PKG = "android.compilation.cts.appusedbyotherapp";
private static final String TEST_APP_2_APK_RES = "/AppUsedByOtherApp.apk";
private static final String TEST_APP_2_DM_RES = "/AppUsedByOtherApp_1.dm";
+ private static final String TEST_APP_2_DISABLE_EMBEDDED_PROFILE_DM_RES =
+ "/AppUsedByOtherApp_1_disable_embedded_profile.dm";
+ private static final String DISABLE_EMBEDDED_PROFILE_DM_RES = "/disable_embedded_profile.dm";
+ private static final String EMPTY_CONFIG_DM_RES = "/empty_config.dm";
private Utils mUtils;
@@ -269,6 +273,24 @@ public class CompilationTest extends BaseHostJUnit4Test {
"Error occurred during dexopt when processing external profiles:");
}
+ @Test
+ public void testEmbeddedProfileEmptyConfig() throws Exception {
+ // A DM with a config file is provided, but it's empty, so it should have no impact on the
+ // embedded profile.
+ mUtils.installFromResources(getAbi(), TEST_APP_WITH_GOOD_PROFILE_RES, EMPTY_CONFIG_DM_RES);
+ String dump = mUtils.assertCommandSucceeds("pm art dump " + TEST_APP_PKG);
+ checkDexoptStatus(dump, Pattern.quote("base.apk"), "speed-profile");
+ }
+
+ @Test
+ public void testEmbeddedProfileConfigDisabledByConfig() throws Exception {
+ // A DM with a config file is provided, and it disables embedded profile.
+ mUtils.installFromResources(
+ getAbi(), TEST_APP_WITH_GOOD_PROFILE_RES, DISABLE_EMBEDDED_PROFILE_DM_RES);
+ String dump = mUtils.assertCommandSucceeds("pm art dump " + TEST_APP_PKG);
+ checkDexoptStatus(dump, Pattern.quote("base.apk"), "verify");
+ }
+
/**
* Verifies that adb install-multi-package fails with multiple error messages when multiple
* APK-DM mismatches happen.
@@ -304,6 +326,29 @@ public class CompilationTest extends BaseHostJUnit4Test {
checkDexoptStatus(dump, Pattern.quote("base.apk"), "verify");
}
+ @Test
+ public void testFallBackToEmbeddedProfile() throws Exception {
+ // The DM has a bad profile, so ART Service should fall back to the embedded profile.
+ assertThrows(Throwable.class, () -> {
+ mUtils.installFromResources(
+ getAbi(), TEST_APP_WITH_GOOD_PROFILE_RES, TEST_APP_2_DM_RES);
+ });
+ String dump = mUtils.assertCommandSucceeds("pm art dump " + TEST_APP_PKG);
+ checkDexoptStatus(dump, Pattern.quote("base.apk"), "speed-profile");
+ }
+
+ @Test
+ public void testNoFallBackToEmbeddedProfile() throws Exception {
+ // The DM has a bad profile, but it also has a config that disables embedded profile, so ART
+ // Service should not fall back to the embedded profile.
+ assertThrows(Throwable.class, () -> {
+ mUtils.installFromResources(getAbi(), TEST_APP_WITH_GOOD_PROFILE_RES,
+ TEST_APP_2_DISABLE_EMBEDDED_PROFILE_DM_RES);
+ });
+ String dump = mUtils.assertCommandSucceeds("pm art dump " + TEST_APP_PKG);
+ checkDexoptStatus(dump, Pattern.quote("base.apk"), "verify");
+ }
+
private void checkDexoptStatus(String dump, String dexfilePattern, String statusPattern) {
// Matches the dump output typically being:
// /data/user/0/android.compilation.cts.statuscheckerapp/secondary.jar
diff --git a/hostsidetests/devicepolicy/Android.bp b/hostsidetests/devicepolicy/Android.bp
index 1efdf960622..eb0eb3d8916 100644
--- a/hostsidetests/devicepolicy/Android.bp
+++ b/hostsidetests/devicepolicy/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
@@ -33,6 +34,7 @@ java_test_host {
"cts",
"general-tests",
"mts-permission",
+ "mcts-permission",
],
static_libs: [
"cts-statsd-atom-host-test-utils",
@@ -99,3 +101,44 @@ java_test_host {
],
per_testcase_directory: true,
}
+
+test_module_config_host {
+ name: "CtsDevicePolicyManagerTestCases_Permissions",
+ base: "CtsDevicePolicyManagerTestCases",
+ test_suites: ["general-tests"],
+ include_annotations: ["com.android.cts.devicepolicy.annotations.PermissionsTest"],
+}
+
+test_module_config_host {
+ name: "CtsDevicePolicyManagerTestCases_Permissions_NoFlakes",
+ base: "CtsDevicePolicyManagerTestCases",
+ test_suites: ["general-tests"],
+ include_annotations: ["com.android.cts.devicepolicy.annotations.PermissionsTest"],
+ exclude_annotations: ["android.platform.test.annotations.FlakyTest"],
+}
+
+// Currently, there are no tests marked flaky or large in CtsDevicePolicyManagerTestCases
+test_module_config_host {
+ name: "CtsDevicePolicyManagerTestCases_NoFlakes_NoLarge",
+ base: "CtsDevicePolicyManagerTestCases",
+ test_suites: ["general-tests"],
+ exclude_annotations: [
+ "android.platform.test.annotations.FlakyTest",
+ "android.platform.test.annotations.LargeTest",
+ ],
+}
+
+test_module_config_host {
+ name: "CtsDevicePolicyManagerTestCases_LockSettings_NoFlakes",
+ base: "CtsDevicePolicyManagerTestCases",
+ test_suites: ["general-tests"],
+ include_annotations: ["com.android.cts.devicepolicy.annotations.LockSettingsTest"],
+ exclude_annotations: ["android.platform.test.annotations.FlakyTest"],
+}
+
+test_module_config_host {
+ name: "CtsDevicePolicyManagerTestCases_ParentProfileApiDisabled",
+ base: "CtsDevicePolicyManagerTestCases",
+ test_suites: ["general-tests"],
+ include_filters: ["com.android.cts.devicepolicy.ManagedProfileTest#testParentProfileApiDisabled"],
+}
diff --git a/hostsidetests/devicepolicy/TEST_MAPPING b/hostsidetests/devicepolicy/TEST_MAPPING
index 7275f80ee70..189a2244011 100644
--- a/hostsidetests/devicepolicy/TEST_MAPPING
+++ b/hostsidetests/devicepolicy/TEST_MAPPING
@@ -27,5 +27,11 @@
{
"name": "CtsDevicePolicyManagerTestCases"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "CtsDevicePolicyManagerTestCases_Permissions_NoFlakes",
+ "name": "CtsDevicePolicyManagerTestCases_LockSettings_NoFlakes"
+ }
]
}
diff --git a/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp b/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp
index 05c8016dc0e..04efba21856 100644
--- a/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp
+++ b/hostsidetests/devicepolicy/app/SimpleSmsApp/Android.bp
@@ -13,6 +13,7 @@
// limitations under the License.
package {
+ default_team: "trendy_team_enterprise",
default_applicable_licenses: ["Android-Apache-2.0"],
}
diff --git a/hostsidetests/devicepolicy/app/StartInfoApp/OWNERS b/hostsidetests/devicepolicy/app/StartInfoApp/OWNERS
new file mode 100644
index 00000000000..24bb8f97b2f
--- /dev/null
+++ b/hostsidetests/devicepolicy/app/StartInfoApp/OWNERS
@@ -0,0 +1,5 @@
+carmenjackson@google.com
+edgararriaga@google.com
+haiping@google.com
+steventerrell@google.com
+yforta@google.com
diff --git a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
index 2c6332e727f..d2a075abaaf 100644
--- a/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
+++ b/hostsidetests/devicepolicy/src/com/android/cts/devicepolicy/BaseDevicePolicyTest.java
@@ -124,15 +124,9 @@ public abstract class BaseDevicePolicyTest extends BaseHostJUnit4Test {
private static final long DEFAULT_TEST_TIMEOUT_MILLIS = TimeUnit.MINUTES.toMillis(10);
/**
- * The amount of milliseconds to wait for the remove user calls in {@link #tearDown}.
- * This is a temporary measure until b/114057686 is fixed.
- */
- private static final long USER_REMOVE_WAIT = TimeUnit.SECONDS.toMillis(5);
-
- /**
* The amount of milliseconds to wait for the switch user calls in {@link #tearDown}.
*/
- private static final long USER_SWITCH_WAIT = TimeUnit.SECONDS.toMillis(5);
+ private static final long USER_SWITCH_WAIT = TimeUnit.SECONDS.toMillis(1);
// From the UserInfo class
protected static final int FLAG_GUEST = 0x00000004;
@@ -426,7 +420,7 @@ public abstract class BaseDevicePolicyTest extends BaseHostJUnit4Test {
*/
protected void switchUser(int userId) throws Exception {
// TODO Move this logic to ITestDevice
- int retries = 10;
+ int retries = 15;
CLog.i("switching to user %d", userId);
executeShellCommand("am switch-user " + userId);
RunUtil.getDefault().sleep(USER_SWITCH_WAIT);
@@ -527,12 +521,9 @@ public abstract class BaseDevicePolicyTest extends BaseHostJUnit4Test {
String stopUserCommand = "am stop-user -w -f " + userId;
CLog.d("stopping and removing user " + userId);
getDevice().executeShellCommand(stopUserCommand);
- // TODO: Remove both sleeps and USER_REMOVE_WAIT constant when b/114057686 is fixed.
- RunUtil.getDefault().sleep(USER_REMOVE_WAIT);
// Ephemeral users may have already been removed after being stopped.
if (listUsers().contains(userId)) {
assertTrue("Couldn't remove user", getDevice().removeUser(userId));
- RunUtil.getDefault().sleep(USER_REMOVE_WAIT);
}
}
}
diff --git a/hostsidetests/gwp_asan/Android.bp b/hostsidetests/gwp_asan/Android.bp
index 1ed34b94a0b..81932b420e5 100644
--- a/hostsidetests/gwp_asan/Android.bp
+++ b/hostsidetests/gwp_asan/Android.bp
@@ -30,7 +30,7 @@ java_test_host {
],
data: [
":CtsGwpAsanEnabled",
- ":CtsGwpAsanRecoverable",
+ ":CtsGwpAsanDefault",
],
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
index 609af0df575..e6029185feb 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanActivityTest.java
@@ -59,42 +59,40 @@ public class GwpAsanActivityTest {
GwpAsanDisabledActivity.class, Utils.TEST_IS_GWP_ASAN_DISABLED);
}
- @Test
- public void testCrashToDropboxRecoverableEnabled() throws Exception {
+ public void testCrash(Class<?> cls, String processNameSuffix, String crashTag,
+ boolean shouldRecover) throws Exception {
TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
- DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
- activity.callActivity(GwpAsanEnabledActivity.class, Utils.TEST_USE_AFTER_FREE);
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, processNameSuffix, crashTag);
+ if (shouldRecover) {
+ activity.callActivityAndCheckSuccess(cls, Utils.TEST_USE_AFTER_FREE);
+ } else {
+ activity.callActivity(cls, Utils.TEST_USE_AFTER_FREE);
+ }
Assert.assertTrue(receiver.await());
}
@Test
+ public void testCrashToDropboxRecoverableEnabled() throws Exception {
+ testCrash(GwpAsanEnabledActivity.class, "gwp_asan_enabled", Utils.DROPBOX_RECOVERABLE_TAG,
+ /*shouldRecover=*/true);
+ }
+
+ @Test
public void testCrashToDropboxRecoverableDefault() throws Exception {
- TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
- DropBoxReceiver receiver =
- Utils.getDropboxReceiver(
- mContext, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG);
- // Ensure the recoverable mode recovers, and returns success.
- activity.callActivityAndCheckSuccess(
- GwpAsanDefaultActivity.class, Utils.TEST_USE_AFTER_FREE);
- Assert.assertTrue(receiver.await());
+ testCrash(GwpAsanDefaultActivity.class, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG,
+ /*shouldRecover=*/true);
}
@Test
- public void testCrashToDropboxEnabled() throws Exception {
- TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
- DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
- activity.callActivity(GwpAsanEnabledActivity.class, Utils.TEST_USE_AFTER_FREE);
- Assert.assertTrue(receiver.await());
+ public void testCrashToDropboxNonRecoverableEnabled() throws Exception {
+ testCrash(GwpAsanEnabledActivity.class, "gwp_asan_enabled",
+ Utils.DROPBOX_NON_RECOVERABLE_TAG, /*shouldRecover=*/false);
}
@Test
- public void testCrashToDropboxDefault() throws Exception {
- TestActivityLauncher activity = mTestActivityRule.launchActivity(null);
- DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_default");
- // Inherits from the app-wide property, which was `gwpAsanMode=always`. So, this should
- // crash.
- activity.callActivity(GwpAsanDefaultActivity.class, Utils.TEST_USE_AFTER_FREE);
- Assert.assertTrue(receiver.await());
+ public void testCrashToDropboxNonRecoverableDefault() throws Exception {
+ testCrash(GwpAsanDefaultActivity.class, "gwp_asan_default",
+ Utils.DROPBOX_NON_RECOVERABLE_TAG, /*shouldRecover=*/false);
}
@Test
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
index 4a6236cade5..add3ad3108b 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/GwpAsanServiceTest.java
@@ -73,33 +73,38 @@ public class GwpAsanServiceTest {
runServiceAndCheckSuccess(GwpAsanDisabledService.class, Utils.TEST_IS_GWP_ASAN_DISABLED);
}
- @Test
- public void testCrashToDropboxEnabled() throws Exception {
- DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
- runService(GwpAsanEnabledService.class, Utils.TEST_USE_AFTER_FREE);
+ public void testCrash(Class<?> cls, String processNameSuffix, String crashTag,
+ boolean shouldRecover) throws Exception {
+ DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, processNameSuffix, crashTag);
+ if (shouldRecover) {
+ runServiceAndCheckSuccess(cls, Utils.TEST_USE_AFTER_FREE);
+ } else {
+ runService(cls, Utils.TEST_USE_AFTER_FREE);
+ }
assertTrue(receiver.await());
}
@Test
- public void testCrashToDropboxDefault() throws Exception {
- DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_default");
- runService(GwpAsanDefaultService.class, Utils.TEST_USE_AFTER_FREE);
- assertTrue(receiver.await());
+ public void testCrashToDropboxNonRecoverableEnabled() throws Exception {
+ testCrash(GwpAsanEnabledService.class, "gwp_asan_enabled",
+ Utils.DROPBOX_NON_RECOVERABLE_TAG, /*shouldRecover=*/false);
+ }
+
+ @Test
+ public void testCrashToDropboxNonRecoverableDefault() throws Exception {
+ testCrash(GwpAsanDefaultService.class, "gwp_asan_default",
+ Utils.DROPBOX_NON_RECOVERABLE_TAG, /*shouldRecover=*/false);
}
@Test
public void testCrashToDropboxRecoverableEnabled() throws Exception {
- DropBoxReceiver receiver = Utils.getDropboxReceiver(mContext, "gwp_asan_enabled");
- runService(GwpAsanEnabledService.class, Utils.TEST_USE_AFTER_FREE);
- assertTrue(receiver.await());
+ testCrash(GwpAsanEnabledService.class, "gwp_asan_enabled", Utils.DROPBOX_RECOVERABLE_TAG,
+ /*shouldRecover=*/true);
}
@Test
public void testCrashToDropboxRecoverableDefault() throws Exception {
- DropBoxReceiver receiver =
- Utils.getDropboxReceiver(
- mContext, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG);
- runServiceAndCheckSuccess(GwpAsanDefaultService.class, Utils.TEST_USE_AFTER_FREE);
- assertTrue(receiver.await());
+ testCrash(GwpAsanDefaultService.class, "gwp_asan_default", Utils.DROPBOX_RECOVERABLE_TAG,
+ /*shouldRecover=*/true);
}
}
diff --git a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
index eee4a83c0d3..2a1e0e4d220 100644
--- a/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
+++ b/hostsidetests/gwp_asan/common/android/cts/gwp_asan/Utils.java
@@ -44,7 +44,7 @@ public class Utils {
public static final int TEST_IS_GWP_ASAN_DISABLED = 43;
public static final int TEST_USE_AFTER_FREE = 44;
- public static final String DROPBOX_TAG = "data_app_native_crash";
+ public static final String DROPBOX_NON_RECOVERABLE_TAG = "data_app_native_crash";
public static final String DROPBOX_RECOVERABLE_TAG = "data_app_native_recoverable_crash";
// Check that GWP-ASan is enabled by allocating a whole bunch of heap pointers and making sure
@@ -102,10 +102,6 @@ public class Utils {
"backtrace:");
}
- public static DropBoxReceiver getDropboxReceiver(Context context, String processNameSuffix) {
- return getDropboxReceiver(context, processNameSuffix, DROPBOX_TAG);
- }
-
public static boolean appExitInfoHasReport(Context context, String processNameSuffix)
throws Exception {
ActivityManager am = context.getSystemService(ActivityManager.class);
diff --git a/hostsidetests/gwp_asan/recoverable/Android.bp b/hostsidetests/gwp_asan/default/Android.bp
index 466944f9a23..e0a25a76bc6 100644
--- a/hostsidetests/gwp_asan/recoverable/Android.bp
+++ b/hostsidetests/gwp_asan/default/Android.bp
@@ -17,7 +17,7 @@ package {
}
android_test_helper_app {
- name: "CtsGwpAsanRecoverable",
+ name: "CtsGwpAsanDefault",
defaults: ["cts_gwp_asan_app_defaults"],
use_embedded_native_libs: false,
}
diff --git a/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml b/hostsidetests/gwp_asan/default/AndroidManifest.xml
index ab0c632cf79..ab0c632cf79 100644
--- a/hostsidetests/gwp_asan/recoverable/AndroidManifest.xml
+++ b/hostsidetests/gwp_asan/default/AndroidManifest.xml
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
deleted file mode 100644
index 8fa57a7311a..00000000000
--- a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/EnabledTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.cts.gwp_asan;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class EnabledTest extends GwpAsanBaseTest {
- protected String getTestApk() {
- return "CtsGwpAsanEnabled.apk";
- }
-
- @Test
- public void testGwpAsanEnabled() throws Exception {
- runTest(".GwpAsanActivityTest", "testEnablement");
- runTest(".GwpAsanServiceTest", "testEnablement");
- }
-
- @Test
- public void testCrashToDropbox() throws Exception {
- runTest(".GwpAsanActivityTest", "testCrashToDropboxEnabled");
- runTest(".GwpAsanActivityTest", "testCrashToDropboxDefault");
- runTest(".GwpAsanServiceTest", "testCrashToDropboxEnabled");
- runTest(".GwpAsanServiceTest", "testCrashToDropboxDefault");
- }
-
- @Test
- public void testAppExitInfo() throws Exception {
- resetAppExitInfo();
- runTest(".GwpAsanActivityTest", "testCrashToDropboxDefault");
- runTest(".GwpAsanActivityTest", "checkAppExitInfo");
- }
-}
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/NonRecoverableTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/NonRecoverableTest.java
new file mode 100644
index 00000000000..47f8784265e
--- /dev/null
+++ b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/NonRecoverableTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.cts.gwp_asan;
+
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class NonRecoverableTest extends GwpAsanBaseTest {
+ private static final String RECOVERABLE_SYSPROP = "libc.debug.gwp_asan.recoverable.";
+
+ protected String getTestApk() {
+ return "CtsGwpAsanEnabled.apk";
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ // Android 15+ uses recoverable GWP-ASan for all apps. This test suite expects crashes, so
+ // let's disable the recovery.
+ mDevice.setProperty(RECOVERABLE_SYSPROP + TEST_PKG, "false");
+ mDevice.setProperty(RECOVERABLE_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "false");
+ mDevice.setProperty(RECOVERABLE_SYSPROP + TEST_PKG + ":gwp_asan_default", "false");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ mDevice.setProperty(RECOVERABLE_SYSPROP + TEST_PKG, "");
+ mDevice.setProperty(RECOVERABLE_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "");
+ mDevice.setProperty(RECOVERABLE_SYSPROP + TEST_PKG + ":gwp_asan_default", "");
+ }
+
+ @Test
+ public void testGwpAsanEnabled() throws Exception {
+ runTest(".GwpAsanActivityTest", "testEnablement");
+ runTest(".GwpAsanServiceTest", "testEnablement");
+ }
+
+ @Test
+ public void testCrashToDropbox() throws Exception {
+ runTest(".GwpAsanActivityTest", "testCrashToDropboxNonRecoverableEnabled");
+ runTest(".GwpAsanActivityTest", "testCrashToDropboxNonRecoverableDefault");
+ runTest(".GwpAsanServiceTest", "testCrashToDropboxNonRecoverableEnabled");
+ runTest(".GwpAsanServiceTest", "testCrashToDropboxNonRecoverableDefault");
+ }
+
+ @Test
+ public void testAppExitInfo() throws Exception {
+ resetAppExitInfo();
+ runTest(".GwpAsanActivityTest", "testCrashToDropboxNonRecoverableDefault");
+ runTest(".GwpAsanActivityTest", "checkAppExitInfo");
+ }
+}
diff --git a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java b/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java
deleted file mode 100644
index e6cadfec82f..00000000000
--- a/hostsidetests/gwp_asan/src/android/cts/gwp_asan/RecoverableTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.cts.gwp_asan;
-
-import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(DeviceJUnit4ClassRunner.class)
-public class RecoverableTest extends GwpAsanBaseTest {
- private static final String PROCESS_SAMPLING_SYSPROP = "libc.debug.gwp_asan.process_sampling.";
-
- protected String getTestApk() {
- return "CtsGwpAsanRecoverable.apk";
- }
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- // Recoverable mode uses process sampling, which only enables GWP-ASan a fraction of the
- // time (to preserve system-wide memory overhead). Make sure that our test app doesn't use
- // process sampling, and enables GWP-ASan, when requested, every time. Note: We don't set
- // the property on the ":gwp_asan_disabled" subprocess, because libc will enable GWP-ASan
- // because a GWP-ASan property was overwritten.
- mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG, "1");
- mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "1");
- mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_default", "1");
- }
-
- @After
- public void tearDown() throws Exception {
- super.tearDown();
- mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG, "");
- mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_enabled", "");
- mDevice.setProperty(PROCESS_SAMPLING_SYSPROP + TEST_PKG + ":gwp_asan_default", "");
- }
-
- @Test
- public void testGwpAsanRecoverable() throws Exception {
- runTest(".GwpAsanActivityTest", "testEnablement");
- runTest(".GwpAsanServiceTest", "testEnablement");
- }
-
- @Test
- public void testCrashToDropboxRecoverable() throws Exception {
- runTest(".GwpAsanActivityTest", "testCrashToDropboxRecoverableEnabled");
- runTest(".GwpAsanActivityTest", "testCrashToDropboxRecoverableDefault");
- runTest(".GwpAsanServiceTest", "testCrashToDropboxRecoverableEnabled");
- runTest(".GwpAsanServiceTest", "testCrashToDropboxRecoverableDefault");
- }
-
- @Test
- public void testAppExitInfo() throws Exception {
- resetAppExitInfo();
- runTest(".GwpAsanActivityTest", "testCrashToDropboxRecoverableDefault");
- runTest(".GwpAsanActivityTest", "checkAppExitInfo");
- }
-}
diff --git a/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java b/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
index 296284bfcd9..eb25c1b73b1 100644
--- a/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
+++ b/hostsidetests/hdmicec/src/android/hdmicec/cts/RemoteControlPassthrough.java
@@ -342,6 +342,19 @@ public final class RemoteControlPassthrough {
hdmiCecClient.sendUserControlPressAndRelease(
sourceDevice, dutLogicalAddress, cecKeycode, false);
+ // KEYCODE_SETUP_MENU might trigger the notification panel quitting the activity
+ // HdmiCecKeyEventCapture.
+ if (cecKeycode == HdmiCecConstants.CEC_KEYCODE_SETUP_MENU) {
+ try {
+ LogHelper.waitForLog(device, "ActivityTaskManager", 5,
+ "TOGGLE_NOTIFICATION_HANDLER_PANEL");
+ return;
+ } catch (Exception e) {
+ // We have to send the key again since logcat was cleared.
+ hdmiCecClient.sendUserControlPressAndRelease(
+ sourceDevice, dutLogicalAddress, cecKeycode, false);
+ }
+ }
LogHelper.assertLog(device, CLASS, "Short press KEYCODE_" + androidKeycode);
}
}
diff --git a/hostsidetests/incrementalinstall/OWNERS b/hostsidetests/incrementalinstall/OWNERS
index 9a71abdce8a..8031a5dee1b 100644
--- a/hostsidetests/incrementalinstall/OWNERS
+++ b/hostsidetests/incrementalinstall/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 554432
dimuthu@google.com
-alexbuy@google.com
schfan@google.com
patb@google.com
-zyy@google.com \ No newline at end of file
+zyy@google.com
diff --git a/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java b/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
index 66e4953b03d..9961273349c 100644
--- a/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
+++ b/hostsidetests/jdwptunnel/src/android/jdwptunnel/cts/JdwpTunnelTest.java
@@ -32,6 +32,7 @@ import com.android.tradefed.util.RunUtil;
import com.sun.jdi.Bootstrap;
import com.sun.jdi.ReferenceType;
+import com.sun.jdi.ThreadReference;
import com.sun.jdi.VirtualMachine;
import com.sun.jdi.VirtualMachineManager;
import com.sun.jdi.connect.AttachingConnector;
@@ -70,13 +71,13 @@ import java.util.Map;
@RunWith(DeviceJUnit4ClassRunner.class)
public class JdwpTunnelTest extends BaseHostJUnit4Test {
private static final String DEBUGGABLE_TEST_APP_PACKAGE_NAME =
- "android.jdwptunnel.sampleapp.debuggable";
+ "android.jdwptunnel.sampleapp.debuggable";
private static final String DEBUGGABLE_TEST_APP_ACTIVITY_CLASS_NAME =
- "DebuggableSampleDeviceActivity";
+ "DebuggableSampleDeviceActivity";
private static final String PROFILEABLE_TEST_APP_PACKAGE_NAME =
- "android.jdwptunnel.sampleapp.profileable";
+ "android.jdwptunnel.sampleapp.profileable";
private static final String PROFILEABLE_TEST_APP_ACTIVITY_CLASS_NAME =
- "ProfileableSampleDeviceActivity";
+ "ProfileableSampleDeviceActivity";
private static final String DDMS_TEST_APP_PACKAGE_NAME = "android.jdwptunnel.sampleapp.ddms";
private static final String DDMS_TEST_APP_ACTIVITY_CLASS_NAME = "DdmsSampleDeviceActivity";
@@ -100,11 +101,11 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
private VirtualMachine getDebuggerConnection(String port) throws Exception {
VirtualMachineManager vmm = Bootstrap.virtualMachineManager();
AttachingConnector conn =
- vmm.attachingConnectors().stream()
+ vmm.attachingConnectors()
+ .stream()
.filter((x) -> x.transport().name().equals("dt_socket"))
.findFirst()
- .orElseThrow(
- () -> new Error("Could not find dt_socket connector!"));
+ .orElseThrow(() -> new Error("Could not find dt_socket connector!"));
Map<String, Connector.Argument> params = conn.defaultArguments();
params.get("port").setValue(port);
params.get("hostname").setValue("localhost");
@@ -129,17 +130,20 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
}
private String startupForwarding(String packageName, String shortClassName, boolean debug)
- throws Exception {
+ throws Exception {
+ return startupForwarding(packageName, shortClassName, debug, false);
+ }
+
+ private String startupForwarding(String packageName, String shortClassName, boolean debug,
+ boolean startSuspended) throws Exception {
moveToHomeScreen();
new Thread(() -> {
try {
- mDevice.executeShellCommand(
- "cmd activity start-activity "
- + (debug ? "-D" : "")
- + " -W -n "
- + packageName
- + "/."
- + shortClassName);
+ String cmd = "cmd activity start-activity " + (debug ? "-D" : "")
+ + (startSuspended ? " --suspend" : "") + " -W -n " + packageName + "/."
+ + shortClassName;
+ CLog.i(cmd);
+ mDevice.executeShellCommand(cmd);
} catch (DeviceNotAvailableException e) {
CLog.i("Failed to start activity for package: " + packageName, e);
}
@@ -148,8 +152,7 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
// Don't keep trying after a minute.
final Instant deadline = Instant.now().plusSeconds(60);
String pid = "";
- while ((pid = mDevice.executeShellCommand(
- "pidof " + packageName).trim()).equals("")) {
+ while ((pid = mDevice.executeShellCommand("pidof " + packageName).trim()).equals("")) {
if (Instant.now().isAfter(deadline)) {
fail("Unable to find PID of " + packageName + " process!");
}
@@ -162,7 +165,13 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
}
private VirtualMachine startupTest(String packageName, String shortClassName) throws Exception {
- return getDebuggerConnection(startupForwarding(packageName, shortClassName, true));
+ return getDebuggerConnection(startupForwarding(packageName, shortClassName, true, false));
+ }
+
+ private VirtualMachine startupTest(String packageName, String shortClassName, boolean debug,
+ boolean startSuspended) throws Exception {
+ return getDebuggerConnection(
+ startupForwarding(packageName, shortClassName, debug, startSuspended));
}
/**
@@ -174,7 +183,7 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
* TODO: We should expand this to more functions.
*/
private void testAttachDebugger(String packageName, String shortClassName)
- throws DeviceNotAvailableException, Exception {
+ throws DeviceNotAvailableException, Exception {
String fullClassName = packageName + "." + shortClassName;
VirtualMachine vm = startupTest(packageName, shortClassName);
@@ -186,8 +195,7 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
final Instant deadline = Instant.now().plusSeconds(120);
// Check the test-activity class is not already loaded.
assertTrue(shortClassName + " is not yet loaded!",
- vm.allClasses().stream()
- .noneMatch(x -> x.name().equals(fullClassName)));
+ vm.allClasses().stream().noneMatch(x -> x.name().equals(fullClassName)));
// Wait for the class to load.
ClassPrepareRequest cpr = erm.createClassPrepareRequest();
@@ -200,11 +208,13 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
if (Instant.now().isAfter(deadline)) {
fail(fullClassName + " did not load within timeout!");
}
- activityType = vm.eventQueue().remove().stream()
- .filter(e -> cpr == e.request())
- .findFirst()
- .map(e -> ((ClassPrepareEvent) e).referenceType())
- .orElse(null);
+ activityType = vm.eventQueue()
+ .remove()
+ .stream()
+ .filter(e -> cpr == e.request())
+ .findFirst()
+ .map(e -> ((ClassPrepareEvent) e).referenceType())
+ .orElse(null);
}
cpr.disable();
// Set a breakpoint on the onCreate method at the first line.
@@ -237,8 +247,8 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
*/
@Test
public void testAttachDebuggerToDebuggableApp() throws DeviceNotAvailableException, Exception {
- testAttachDebugger(DEBUGGABLE_TEST_APP_PACKAGE_NAME,
- DEBUGGABLE_TEST_APP_ACTIVITY_CLASS_NAME);
+ testAttachDebugger(
+ DEBUGGABLE_TEST_APP_PACKAGE_NAME, DEBUGGABLE_TEST_APP_ACTIVITY_CLASS_NAME);
}
/**
@@ -251,8 +261,8 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
public void testAttachDebuggerToProfileableApp() throws DeviceNotAvailableException, Exception {
java.io.IOException thrownException = null;
try {
- testAttachDebugger(PROFILEABLE_TEST_APP_PACKAGE_NAME,
- PROFILEABLE_TEST_APP_ACTIVITY_CLASS_NAME);
+ testAttachDebugger(
+ PROFILEABLE_TEST_APP_PACKAGE_NAME, PROFILEABLE_TEST_APP_ACTIVITY_CLASS_NAME);
} catch (java.io.IOException e) {
thrownException = e;
}
@@ -271,13 +281,17 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
// when it calls the "attach" method from class AttachingConnector or its subclass.
// In other words, the callstack is expected to look like
//
- // at jdk.jdi/com.sun.tools.jdi.SocketAttachingConnector.attach(SocketAttachingConnector.java:83)
- // at android.jdwptunnel.cts.JdwpTunnelTest.getDebuggerConnection(JdwpTunnelTest.java:96)
+ // at
+ // jdk.jdi/com.sun.tools.jdi.SocketAttachingConnector.attach
+ // (SocketAttachingConnector.java:83)
+ // at
+ // android.jdwptunnel.cts.JdwpTunnelTest.getDebuggerConnection
+ // (JdwpTunnelTest.java:96)
boolean thrownByGetDebuggerConnection = false;
StackTraceElement[] stack = thrownException.getStackTrace();
for (int i = 0; i < stack.length; i++) {
- if (stack[i].getClassName().equals("android.jdwptunnel.cts.JdwpTunnelTest") &&
- stack[i].getMethodName().equals("getDebuggerConnection")) {
+ if (stack[i].getClassName().equals("android.jdwptunnel.cts.JdwpTunnelTest")
+ && stack[i].getMethodName().equals("getDebuggerConnection")) {
thrownByGetDebuggerConnection = true;
assertTrue(i > 0);
assertEquals("attach", stack[i - 1].getMethodName());
@@ -306,8 +320,8 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
String deviceArch = getDeviceBaseArch();
Assume.assumeTrue(testingArch.equals(deviceArch));
- String port =
- startupForwarding(DDMS_TEST_APP_PACKAGE_NAME, DDMS_TEST_APP_ACTIVITY_CLASS_NAME, false);
+ String port = startupForwarding(
+ DDMS_TEST_APP_PACKAGE_NAME, DDMS_TEST_APP_ACTIVITY_CLASS_NAME, false);
Socket sock = new Socket("localhost", Integer.decode(port).intValue());
OutputStream os = sock.getOutputStream();
// Let the test spin a bit. Try to lose any race with the app.
@@ -330,4 +344,33 @@ public class JdwpTunnelTest extends BaseHostJUnit4Test {
// Data sent big-endian so first byte has sign bit.
assertTrue((is.read() & 0x80) == 0x80);
}
+
+ private void assertThreadSuspensionState(VirtualMachine vm, boolean expected) {
+ for (ThreadReference tr : vm.allThreads()) {
+ boolean isSuspended = tr.isSuspended();
+ if (isSuspended != expected) {
+ fail("Thread in unexpected state '" + tr.name() + "' isSuspended=" + isSuspended);
+ }
+ }
+ }
+
+ // App can be started "suspended" which means all its threads will be suspended shorty after
+ // zygote specializes.
+ @Test
+ public void testSuspendStartup() throws DeviceNotAvailableException, Exception {
+
+ VirtualMachine vm = startupTest(DEBUGGABLE_TEST_APP_PACKAGE_NAME,
+ DEBUGGABLE_TEST_APP_ACTIVITY_CLASS_NAME, true, true);
+
+ try {
+ // The VM was started in suspended mode.
+ assertThreadSuspensionState(vm, true);
+
+ // Let's go!
+ vm.resume();
+ assertThreadSuspensionState(vm, false);
+ } finally {
+ vm.dispose();
+ }
+ }
}
diff --git a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
index c4ed6bdfbe0..689a93d19dc 100644
--- a/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
+++ b/hostsidetests/media/src/android/media/cts/BaseMultiUserTest.java
@@ -52,6 +52,7 @@ public class BaseMultiUserTest extends BaseMediaHostSideTest {
private String mPackageVerifier;
+ private int mInitialUserId;
private Set<String> mExistingPackages;
private List<Integer> mExistingUsers;
private HashSet<String> mAvailableFeatures;
@@ -75,9 +76,17 @@ public class BaseMultiUserTest extends BaseMediaHostSideTest {
"0",
USER_ALL);
+ mInitialUserId = getDevice().getCurrentUser();
mExistingUsers = getDevice().listUsers();
+ Integer mainUserId = getDevice().getMainUserId();
Integer primaryUserId = getDevice().getPrimaryUserId();
- executeShellCommand("am switch-user " + primaryUserId);
+ if (primaryUserId != null) {
+ getDevice().switchUser(primaryUserId);
+ } else if (mainUserId != null) {
+ getDevice().switchUser(mainUserId);
+ } else {
+ // Neither a primary nor a main user exists. Just use the current one.
+ }
executeShellCommand("wm dismiss-keyguard");
}
@@ -117,6 +126,9 @@ public class BaseMultiUserTest extends BaseMediaHostSideTest {
lastTearDownError = t;
}
}
+ if (getDevice().getCurrentUser() != mInitialUserId) {
+ getDevice().switchUser(mInitialUserId);
+ }
super.tearDown();
if (lastTearDownError != null) {
throw new AssertionError("Something went wrong while cleaning up.", lastTearDownError);
diff --git a/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java b/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
index 5c30bf97333..df220112773 100644
--- a/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
+++ b/hostsidetests/mediapc/videoencodingquality/src/CtsVideoEncodingQualityHostTest.java
@@ -22,6 +22,7 @@ import android.platform.test.annotations.AppModeFull;
import com.android.compatibility.common.util.CddTest;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -498,17 +499,24 @@ public class CtsVideoEncodingQualityHostTest implements IDeviceTest {
+ testRunResult.getName() + ": " + testRunResult.getRunFailureMessage());
}
if (testRunResult.getNumTests() != testRunResult.getPassedTests().size()) {
- StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
for (Map.Entry<TestDescription, TestResult> resultEntry :
testRunResult.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus()
- .equals(com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
+ if (resultEntry.getValue().getStatus().equals(TestStatus.FAILURE)) {
+ StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
errorBuilder.append(resultEntry.getKey().toString());
errorBuilder.append(":\n");
errorBuilder.append(resultEntry.getValue().getStackTrace());
+ throw new AssertionError(errorBuilder.toString());
+ }
+ if (resultEntry.getValue().getStatus().equals(TestStatus.ASSUMPTION_FAILURE)) {
+ StringBuilder errorBuilder =
+ new StringBuilder("On-device tests assumption failed:\n");
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ Assume.assumeTrue(errorBuilder.toString(), false);
}
}
- throw new AssertionError(errorBuilder.toString());
}
}
}
diff --git a/hostsidetests/rollback/OWNERS b/hostsidetests/rollback/OWNERS
index b8578eb6794..ca6897c0d60 100644
--- a/hostsidetests/rollback/OWNERS
+++ b/hostsidetests/rollback/OWNERS
@@ -1,5 +1,3 @@
# Bug component: 557916
-olilan@google.com
-wangchun@google.com
-gavincorkery@google.com
-*
+ancr@google.com
+harshitmahajan@google.com
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 e0dc9463ee1..fb7fd3f236a 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/LegacyStorageHostTest.java
@@ -18,6 +18,8 @@ package android.scopedstorage.cts.host;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AppModeFull;
import com.android.tradefed.device.contentprovider.ContentProviderHandler;
@@ -40,7 +42,7 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
private ContentProviderHandler mContentProviderHandler;
/**
- * Runs the given phase of LegacyFileAccessTest by calling into the device.
+ * Runs the given phase of LegacyStorageTest by calling into the device.
* Throws an exception if the test phase fails.
*/
void runDeviceTest(String phase) throws Exception {
@@ -86,6 +88,9 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
@Before
public void setup() throws Exception {
+ // Ignore tests on automotive devices b/319785789
+ assumeFalse(hasDeviceFeature("android.hardware.type.automotive"));
+
mContentProviderHandler = new ContentProviderHandler(getDevice());
mContentProviderHandler.setUp();
setupExternalStorage();
@@ -98,7 +103,9 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
@After
public void tearDown() throws Exception {
- mContentProviderHandler.tearDown();
+ if (mContentProviderHandler != null) {
+ mContentProviderHandler.tearDown();
+ }
revokePermissions("android.permission.WRITE_EXTERNAL_STORAGE",
"android.permission.READ_EXTERNAL_STORAGE");
}
@@ -260,7 +267,7 @@ public class LegacyStorageHostTest extends BaseHostTestCase {
}
/**
- * (b/205673506): Test that legacy System Gallery can update() media file's releative_path to a
+ * (b/205673506): Test that legacy System Gallery can update() media file's relative_path to a
* non default top level directory.
*/
@Test
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 37f8ee7faf3..6c2b836b98f 100644
--- a/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
+++ b/hostsidetests/scopedstorage/host/src/android/scopedstorage/cts/host/ScopedStorageHostTest.java
@@ -18,6 +18,8 @@ package android.scopedstorage.cts.host;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
+
import android.platform.test.annotations.AppModeFull;
import com.android.modules.utils.build.testing.DeviceSdkLevel;
@@ -71,6 +73,9 @@ public class ScopedStorageHostTest extends BaseHostTestCase {
@Before
public void setup() throws Exception {
+ // Ignore tests on automotive devices b/319785789
+ assumeFalse(hasDeviceFeature("android.hardware.type.automotive"));
+
setupExternalStorage();
executeShellCommand("mkdir /sdcard/Android/data/com.android.shell -m 2770");
executeShellCommand("mkdir /sdcard/Android/data/com.android.shell/files -m 2770");
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 33a838ed42d..4517e646b1f 100644
--- a/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
+++ b/hostsidetests/scopedstorage/legacy/src/android/scopedstorage/cts/legacy/LegacyStorageTest.java
@@ -64,8 +64,6 @@ import static android.scopedstorage.cts.lib.TestUtils.verifyInsertFromExternalPr
import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalMediaDirViaRelativePath_allowed;
import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalPrivateDirsViaRelativePath_denied;
-import static androidx.test.InstrumentationRegistry.getContext;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -93,8 +91,8 @@ import android.system.OsConstants;
import android.text.TextUtils;
import android.util.Log;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.cts.install.lib.TestApp;
@@ -116,7 +114,7 @@ import java.util.Arrays;
/**
* Test app targeting Q and requesting legacy storage - tests legacy file path access.
- * Designed to be run by LegacyAccessHostTest.
+ * Designed to be run by LegacyStorageHostTest.
*
* <p> Test cases that assume we have WRITE_EXTERNAL_STORAGE only are appended with hasW,
* those that assume we have READ_EXTERNAL_STORAGE only are appended with hasR, those who assume we
@@ -126,22 +124,23 @@ import java.util.Arrays;
*/
@RunWith(AndroidJUnit4.class)
public class LegacyStorageTest {
- private static final String TAG = "LegacyFileAccessTest";
- static final String THIS_PACKAGE_NAME = InstrumentationRegistry.getContext().getPackageName();
+ private static final String TAG = "LegacyStorageTest";
+ private static final String THIS_PACKAGE_NAME =
+ InstrumentationRegistry.getInstrumentation().getContext().getPackageName();
/**
* To help avoid flaky tests, give ourselves a unique nonce to be used for
* all filesystem paths, so that we don't risk conflicting with previous
* test runs.
*/
- static final String NONCE = String.valueOf(System.nanoTime());
- static final String TEST_DIRECTORY_NAME = "ScopedStorageTestDirectory" + NONCE;
+ private static final String NONCE = String.valueOf(System.nanoTime());
+ private static final String TEST_DIRECTORY_NAME = "LegacyStorageTestDirectory" + 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";
+ private static final String IMAGE_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".jpg";
+ private static final String VIDEO_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".mp4";
+ private static final String NONMEDIA_FILE_NAME = "LegacyStorageTest_file_" + NONCE + ".pdf";
- static final String CONTENT_PROVIDER_URL = "content://android.tradefed.contentprovider";
+ private 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.
@@ -194,18 +193,18 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ false);
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
// Can create file under root dir
- assertCanCreateFile(new File(TestUtils.getExternalStorageDir(), "LegacyFileAccessTest.txt"));
+ assertCanCreateFile(new File(TestUtils.getExternalStorageDir(), "LegacyStorageTest.txt"));
// Can create music file under DCIM
- assertCanCreateFile(new File(TestUtils.getDcimDir(), "LegacyFileAccessTest.mp3"));
+ assertCanCreateFile(new File(TestUtils.getDcimDir(), "LegacyStorageTest.mp3"));
// Can create random file under external files dir
assertCanCreateFile(new File(TestUtils.getExternalFilesDir(),
- "LegacyFileAccessTest"));
+ "LegacyStorageTest"));
// However, even legacy apps can't create files under other app's directories
final File otherAppDir = new File(TestUtils.getAndroidDataDir(), "com.android.shell");
- final File file = new File(otherAppDir, "LegacyFileAccessTest.txt");
+ final File file = new File(otherAppDir, "LegacyStorageTest.txt");
// otherAppDir was already created by the host test
try {
@@ -223,14 +222,14 @@ public class LegacyStorageTest {
public void testMkdirInRandomPlaces_hasW() throws Exception {
pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ false);
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
- // Can create a top-level direcotry
- final File topLevelDir = new File(TestUtils.getExternalStorageDir(), "LegacyFileAccessTest");
+ // Can create a top-level directory
+ final File topLevelDir = new File(TestUtils.getExternalStorageDir(), "LegacyStorageTest");
assertCanCreateDir(topLevelDir);
final File otherAppDir = new File(TestUtils.getAndroidDataDir(), "com.android.shell");
// However, even legacy apps can't create dirs under other app's directories
- final File subDir = new File(otherAppDir, "LegacyFileAccessTest");
+ final File subDir = new File(otherAppDir, "LegacyStorageTest");
// otherAppDir was already created by the host test
assertThat(subDir.mkdir()).isFalse();
@@ -247,7 +246,7 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ false);
// Can't create file under root dir
final File newTxtFile = new File(TestUtils.getExternalStorageDir(),
- "LegacyFileAccessTest.txt");
+ "LegacyStorageTest.txt");
try {
newTxtFile.createNewFile();
fail("File creation expected to fail: " + newTxtFile);
@@ -255,15 +254,15 @@ public class LegacyStorageTest {
}
// Can't create music file under /MUSIC
- final File newMusicFile = new File(TestUtils.getMusicDir(), "LegacyFileAccessTest.mp3");
+ final File newMusicFile = new File(TestUtils.getMusicDir(), "LegacyStorageTest.mp3");
try {
newMusicFile.createNewFile();
fail("File creation expected to fail: " + newMusicFile);
} catch (IOException expected) {
}
- // Can't create a top-level direcotry
- final File topLevelDir = new File(TestUtils.getExternalStorageDir(), "LegacyFileAccessTest");
+ // Can't create a top-level directory
+ final File topLevelDir = new File(TestUtils.getExternalStorageDir(), "LegacyStorageTest");
assertThat(topLevelDir.mkdir()).isFalse();
// Can't read existing file
@@ -287,11 +286,11 @@ public class LegacyStorageTest {
// However, even without permissions, we can access our own external dir
final File fileInDataDir =
new File(TestUtils.getExternalFilesDir(),
- "LegacyFileAccessTest");
+ "LegacyStorageTest");
try {
assertThat(fileInDataDir.createNewFile()).isTrue();
assertThat(Arrays.asList(fileInDataDir.getParentFile().list()))
- .contains("LegacyFileAccessTest");
+ .contains("LegacyStorageTest");
} finally {
fileInDataDir.delete();
}
@@ -299,11 +298,11 @@ public class LegacyStorageTest {
// we can access our own external media directory without permissions.
final File fileInMediaDir =
new File(TestUtils.getExternalMediaDir(),
- "LegacyFileAccessTest");
+ "LegacyStorageTest");
try {
assertThat(fileInMediaDir.createNewFile()).isTrue();
assertThat(Arrays.asList(fileInMediaDir.getParentFile().list()))
- .contains("LegacyFileAccessTest");
+ .contains("LegacyStorageTest");
} finally {
fileInMediaDir.delete();
}
@@ -340,7 +339,7 @@ public class LegacyStorageTest {
}
// try to create file and fail, because it requires WRITE
- final File newFile = new File(TestUtils.getMusicDir(), "LegacyFileAccessTest.mp3");
+ final File newFile = new File(TestUtils.getMusicDir(), "LegacyStorageTest.mp3");
try {
newFile.createNewFile();
fail("Creating file expected to fail: " + newFile);
@@ -348,7 +347,7 @@ public class LegacyStorageTest {
}
// try to mkdir and fail, because it requires WRITE
- final File newDir = new File(TestUtils.getExternalStorageDir(), "LegacyFileAccessTest");
+ final File newDir = new File(TestUtils.getExternalStorageDir(), "LegacyStorageTest");
try {
assertThat(newDir.mkdir()).isFalse();
} finally {
@@ -408,15 +407,15 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ true);
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
- final File musicFile1 = new File(TestUtils.getDcimDir(), "LegacyFileAccessTest.mp3");
+ final File musicFile1 = new File(TestUtils.getDcimDir(), "LegacyStorageTest.mp3");
final File musicFile2 = new File(TestUtils.getExternalStorageDir(),
- "LegacyFileAccessTest.mp3");
- final File musicFile3 = new File(TestUtils.getMoviesDir(), "LegacyFileAccessTest.mp3");
- final File nonMediaDir1 = new File(TestUtils.getDcimDir(), "LegacyFileAccessTest");
+ "LegacyStorageTest.mp3");
+ final File musicFile3 = new File(TestUtils.getMoviesDir(), "LegacyStorageTest.mp3");
+ final File nonMediaDir1 = new File(TestUtils.getDcimDir(), "LegacyStorageTest");
final File nonMediaDir2 = new File(TestUtils.getExternalStorageDir(),
- "LegacyFileAccessTest");
- final File pdfFile1 = new File(nonMediaDir1, "LegacyFileAccessTest.pdf");
- final File pdfFile2 = new File(nonMediaDir2, "LegacyFileAccessTest.pdf");
+ "LegacyStorageTest");
+ final File pdfFile1 = new File(nonMediaDir1, "LegacyStorageTest.pdf");
+ final File pdfFile2 = new File(nonMediaDir2, "LegacyStorageTest.pdf");
try {
// can rename a file to root directory.
assertThat(musicFile1.createNewFile()).isTrue();
@@ -429,7 +428,7 @@ public class LegacyStorageTest {
assertThat(pdfFile1.createNewFile()).isTrue();
// can rename directory to root directory.
assertCanRenameDirectory(
- nonMediaDir1, nonMediaDir2, new File[] {pdfFile1}, new File[] {pdfFile2});
+ nonMediaDir1, nonMediaDir2, new File[]{pdfFile1}, new File[]{pdfFile2});
} finally {
musicFile1.delete();
musicFile2.delete();
@@ -469,13 +468,13 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ false);
final File shellFile1 = getShellFile();
- final File shellFile2 = new File(TestUtils.getDownloadDir(), "LegacyFileAccessTest_shell");
+ final File shellFile2 = new File(TestUtils.getDownloadDir(), "LegacyStorageTest_shell");
final File mediaFile1 =
new File(TestUtils.getExternalMediaDir(),
- "LegacyFileAccessTest1");
+ "LegacyStorageTest1");
final File mediaFile2 =
new File(TestUtils.getExternalMediaDir(),
- "LegacyFileAccessTest2");
+ "LegacyStorageTest2");
try {
createFileInExternalDir(shellFile1);
MediaStore.scanFile(getContentResolver(), shellFile1);
@@ -504,13 +503,13 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ false);
final File shellFile1 = getShellFile();
- final File shellFile2 = new File(TestUtils.getDownloadDir(), "LegacyFileAccessTest_shell");
+ final File shellFile2 = new File(TestUtils.getDownloadDir(), "LegacyStorageTest_shell");
final File mediaFile1 =
new File(TestUtils.getExternalMediaDir(),
- "LegacyFileAccessTest1");
+ "LegacyStorageTest1");
final File mediaFile2 =
new File(TestUtils.getExternalMediaDir(),
- "LegacyFileAccessTest2");
+ "LegacyStorageTest2");
try {
createFileInExternalDir(shellFile1);
MediaStore.scanFile(getContentResolver(), shellFile1);
@@ -535,7 +534,7 @@ public class LegacyStorageTest {
*/
@Test
public void testRenameDirectoryAndUpdateDB_hasW() throws Exception {
- final String testDirectoryName = "LegacyFileAccessTestDirectory";
+ final String testDirectoryName = "LegacyStorageTestDirectory";
File directoryOldPath = new File(TestUtils.getDcimDir(), testDirectoryName);
File directoryNewPath = new File(TestUtils.getMoviesDir(), testDirectoryName);
try {
@@ -625,7 +624,8 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
final File videoFile = new File(TestUtils.getDcimDir(), VIDEO_FILE_NAME);
- final File renamedVideoFile = new File(TestUtils.getDcimDir(), "Renamed_" + VIDEO_FILE_NAME);
+ final File renamedVideoFile = new File(TestUtils.getDcimDir(),
+ "Renamed_" + VIDEO_FILE_NAME);
final ContentResolver cr = getContentResolver();
try {
@@ -747,7 +747,7 @@ public class LegacyStorageTest {
assertTrue(file.createNewFile());
try (Cursor c = TestUtils.queryFile(file,
- new String[] {MediaStore.MediaColumns.IS_PENDING})) {
+ new String[]{MediaStore.MediaColumns.IS_PENDING})) {
// This file will not have IS_PENDING=1 because create didn't set IS_PENDING.
assertTrue(c.moveToFirst());
assertEquals(c.getInt(0), 0);
@@ -809,45 +809,49 @@ public class LegacyStorageTest {
pollForPermission(Manifest.permission.READ_EXTERNAL_STORAGE, /*granted*/ true);
pollForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, /*granted*/ true);
- final String IMAGE_FILE_DISPLAY_NAME = "LegacyStorageTest_file_" + NONCE;
- final File imageFile = new File(TestUtils.getDcimDir(), IMAGE_FILE_DISPLAY_NAME + ".jpg");
-
- for (String mimeType : new String[] {
- "image/*", "", null, "foo/bar"
- }) {
- Uri uri = null;
- try {
- ContentValues values = new ContentValues();
- values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
- if (TextUtils.isEmpty(mimeType)) {
- values.put(MediaStore.MediaColumns.DISPLAY_NAME, imageFile.getName());
- } else {
- values.put(MediaStore.MediaColumns.DISPLAY_NAME, IMAGE_FILE_DISPLAY_NAME);
- }
- values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
-
- uri = getContentResolver().insert(getImageContentUri(), values, Bundle.EMPTY);
- assertNotNull(uri);
-
- try (final OutputStream fos = getContentResolver().openOutputStream(uri, "rw")) {
- fos.write(BYTES_DATA1);
- }
-
- // Closing the file should trigger a scan, we still scan again to ensure MIME type
- // is extracted from file extension
- assertNotNull(MediaStore.scanFile(getContentResolver(), imageFile));
-
- final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME,
- MediaStore.MediaColumns.MIME_TYPE};
- try (Cursor c = getContentResolver().query(uri, projection, null, null, null)) {
- assertTrue(c.moveToFirst());
- assertEquals(c.getCount(), 1);
- assertEquals(c.getString(0), imageFile.getName());
- assertTrue("image/jpeg".equalsIgnoreCase(c.getString(1)));
- }
- } finally {
- deleteWithMediaProviderNoThrow(uri);
+ final String imageFileDisplayName = "LegacyStorageTest_file_" + NONCE;
+ final String[] mimeTypes = {"image/*", "", null, "foo/bar"};
+ for (int i = 0; i < mimeTypes.length; i++) {
+ // b/288337808 Creating files with different names to avoid potential name reassignments
+ assertFileInsertWithMimeType(imageFileDisplayName + "_" + i, mimeTypes[i]);
+ }
+ }
+
+ private void assertFileInsertWithMimeType(String filename, String mimeType)
+ throws IOException {
+ Uri uri = null;
+ final File imageFile = new File(TestUtils.getDcimDir(), filename + ".jpg");
+ try {
+ ContentValues values = new ContentValues();
+ values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
+ if (TextUtils.isEmpty(mimeType)) {
+ values.put(MediaStore.MediaColumns.DISPLAY_NAME, imageFile.getName());
+ } else {
+ values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename);
+ }
+ values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
+
+ uri = getContentResolver().insert(getImageContentUri(), values, Bundle.EMPTY);
+ assertNotNull(uri);
+
+ try (OutputStream fos = getContentResolver().openOutputStream(uri, "rw")) {
+ fos.write(BYTES_DATA1);
+ }
+
+ // Closing the file should trigger a scan, we still scan again to ensure MIME type
+ // is extracted from file extension
+ assertNotNull(MediaStore.scanFile(getContentResolver(), imageFile));
+
+ final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME,
+ MediaStore.MediaColumns.MIME_TYPE};
+ try (Cursor c = getContentResolver().query(uri, projection, null, null, null)) {
+ assertTrue(c.moveToFirst());
+ assertEquals(c.getCount(), 1);
+ assertEquals(c.getString(0), imageFile.getName());
+ assertTrue("image/jpeg".equalsIgnoreCase(c.getString(1)));
}
+ } finally {
+ deleteWithMediaProviderNoThrow(uri);
}
}
@@ -881,7 +885,7 @@ public class LegacyStorageTest {
}
/**
- * (b/205673506): Test that legacy System Gallery can update() media file's releative_path to a
+ * (b/205673506): Test that legacy System Gallery can update() media file's relative_path to a
* non default top level directory.
*/
@Test
@@ -968,8 +972,8 @@ public class LegacyStorageTest {
final File jpgFile = new File(getPicturesDir(), IMAGE_FILE_NAME);
try {
// Copy the image content to jpgFile
- try (InputStream in =
- getContext().getResources().openRawResource(R.raw.img_with_metadata);
+ try (InputStream in = InstrumentationRegistry.getInstrumentation().getContext()
+ .getResources().openRawResource(R.raw.img_with_metadata);
FileOutputStream out = new FileOutputStream(jpgFile)) {
FileUtils.copy(in, out);
out.getFD().sync();
@@ -1208,11 +1212,11 @@ public class LegacyStorageTest {
final String selection = "is_pending = 0 AND is_trashed = 0 AND "
+ "(media_type = ? OR media_type = ?)";
final String[] selectionArgs =
- new String[] {String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),
+ new String[]{String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE),
String.valueOf(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)};
try (Cursor c = getContentResolver().query(TestUtils.getTestVolumeFileUri(),
- /* projection */ new String[] {MediaStore.MediaColumns.DISPLAY_NAME},
+ /* projection */ new String[]{MediaStore.MediaColumns.DISPLAY_NAME},
selection, selectionArgs, null)) {
while (c.moveToNext()) {
mediaFiles.add(c.getString(0));
@@ -1223,7 +1227,7 @@ public class LegacyStorageTest {
private File getShellFile() throws Exception {
return new File(TestUtils.getExternalStorageDir(),
- "LegacyAccessHostTest_shell");
+ "LegacyStorageHostTest_shell");
}
private void createFileInExternalDir(File file) throws Exception {
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 9c0b577269b..b337265999c 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
@@ -1023,7 +1023,8 @@ public class TestUtils {
try {
getContentResolver().delete(uri, Bundle.EMPTY);
- } catch (Exception ignored) {
+ } catch (Exception exception) {
+ Log.e("Exception while deleting files", exception.getMessage());
}
}
}
diff --git a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
index 01792e7213c..89b207b52b2 100644
--- a/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
+++ b/hostsidetests/scopedstorage/src/android/scopedstorage/cts/ScopedStorageTest.java
@@ -71,8 +71,6 @@ import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalDirs
import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalMediaDirViaRelativePath_allowed;
import static android.scopedstorage.cts.lib.TestUtils.verifyUpdateToExternalPrivateDirsViaRelativePath_denied;
-import static androidx.test.InstrumentationRegistry.getContext;
-
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -84,6 +82,7 @@ import static org.junit.Assume.assumeTrue;
import android.Manifest;
import android.content.ContentValues;
+import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@@ -95,7 +94,8 @@ import android.provider.MediaStore;
import android.scopedstorage.cts.lib.RedactionTestHelper;
import android.util.Log;
-import androidx.test.runner.AndroidJUnit4;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
import com.android.cts.install.lib.TestApp;
import com.android.modules.utils.build.SdkLevel;
@@ -117,7 +117,8 @@ import java.io.IOException;
@RunWith(AndroidJUnit4.class)
public class ScopedStorageTest {
static final String TAG = "ScopedStorageTest";
- static final String THIS_PACKAGE_NAME = getContext().getPackageName();
+ static final String THIS_PACKAGE_NAME =
+ InstrumentationRegistry.getInstrumentation().getContext().getPackageName();
static final int USER_SYSTEM = 0;
/**
@@ -165,11 +166,12 @@ public class ScopedStorageTest {
@Before
public void setup() throws Exception {
- if (!getContext().getPackageManager().isInstantApp()) {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ if (!context.getPackageManager().isInstantApp()) {
pollForExternalStorageState();
getExternalFilesDir().mkdirs();
}
- MediaStore.waitForIdle(getContext().getContentResolver());
+ MediaStore.waitForIdle(context.getContentResolver());
}
/**
@@ -187,7 +189,8 @@ public class ScopedStorageTest {
public void testCheckInstallerAppAccessToObbDirs() throws Exception {
assertCanAccessPrivateAppAndroidObbDir(true /*canAccess*/, APP_B_NO_PERMS,
THIS_PACKAGE_NAME, NONMEDIA_FILE_NAME);
- final int uid = getContext().getPackageManager().getPackageUid(THIS_PACKAGE_NAME, 0);
+ final int uid = InstrumentationRegistry.getInstrumentation().getContext()
+ .getPackageManager().getPackageUid(THIS_PACKAGE_NAME, 0);
if (isAtLeastS()) {
assertMountMode(THIS_PACKAGE_NAME, uid, StorageManager.MOUNT_MODE_EXTERNAL_INSTALLER);
}
@@ -200,7 +203,8 @@ public class ScopedStorageTest {
public void testCheckInstallerAppCannotAccessDataDirs() throws Exception {
assertCanAccessPrivateAppAndroidDataDir(false /*canAccess*/, APP_B_NO_PERMS,
THIS_PACKAGE_NAME, NONMEDIA_FILE_NAME);
- final int uid = getContext().getPackageManager().getPackageUid(THIS_PACKAGE_NAME, 0);
+ final int uid = InstrumentationRegistry.getInstrumentation().getContext()
+ .getPackageManager().getPackageUid(THIS_PACKAGE_NAME, 0);
if (isAtLeastS()) {
assertMountMode(THIS_PACKAGE_NAME, uid, StorageManager.MOUNT_MODE_EXTERNAL_INSTALLER);
}
@@ -577,7 +581,7 @@ public class ScopedStorageTest {
assertAccess(new File("/storage/emulated"), true, false, false);
// Verify we can enter "/storage/emulated/<userId>" and read
- int userId = getContext().getUserId();
+ int userId = InstrumentationRegistry.getInstrumentation().getContext().getUserId();
assertAccess(new File("/storage/emulated/" + userId), true, true, false);
// Verify we can't get another userId
@@ -1138,9 +1142,10 @@ public class ScopedStorageTest {
@Test
@AppModeInstant
public void testInstantAppsCantAccessExternalStorage() throws Exception {
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
assumeTrue("This test requires that the test runs as an Instant app",
- getContext().getPackageManager().isInstantApp());
- assertThat(getContext().getPackageManager().isInstantApp()).isTrue();
+ context.getPackageManager().isInstantApp());
+ assertThat(context.getPackageManager().isInstantApp()).isTrue();
// Check that the app does not have legacy external storage access
assertThat(Environment.isExternalStorageLegacy()).isFalse();
diff --git a/hostsidetests/security/Android.bp b/hostsidetests/security/Android.bp
index d4e9d215cc2..f42b9b434ed 100644
--- a/hostsidetests/security/Android.bp
+++ b/hostsidetests/security/Android.bp
@@ -61,6 +61,11 @@ java_test_host {
target_required: ["CtsDeviceInfo"],
}
+filegroup {
+ name: "prebuilt_sepolicy_cts_data",
+ srcs: [":202404_sepolicy_cts_data"],
+}
+
java_genrule_host {
name: "CtsSecurityHostTestCases_StaticLibs",
tools: [
@@ -75,9 +80,11 @@ java_genrule_host {
],
tool_files: [
":general_sepolicy.conf",
+ ":prebuilt_sepolicy_cts_data",
],
out: ["CtsSecurityHostTestCases_StaticLibs.jar"],
- cmd: "$(location soong_zip) -jar -o $(location CtsSecurityHostTestCases_StaticLibs.jar) -j " +
+ cmd: "echo $(locations :prebuilt_sepolicy_cts_data) > $(out).prebuilt_list.txt && " +
+ "$(location soong_zip) -jar -o $(location CtsSecurityHostTestCases_StaticLibs.jar) -j " +
"-f $(location checkseapp) " +
"-f $(location checkfc) " +
"-f $(location property_info_checker) " +
@@ -85,5 +92,6 @@ java_genrule_host {
"-f $(location secilc) " +
"-f $(location sepolicy-analyze) " +
"-f $(location sepolicy_tests) " +
- "-f $(location :general_sepolicy.conf)",
+ "-f $(location :general_sepolicy.conf) " +
+ "-l $(out).prebuilt_list.txt",
}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
index 341024c5f28..2ffcfce38c6 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxHostTest.java
@@ -92,12 +92,13 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
private static final String SEPOLICY_VERSION_JSON_KEY = "sepolicy_version";
private static final String PLATFORM_SEPOLICY_VERSION_JSON_KEY = "platform_sepolicy_version";
- private static final Map<ITestDevice, File> cachedDevicePolicyFiles = new HashMap<>(1);
- private static final Map<ITestDevice, File> cachedDevicePlatFcFiles = new HashMap<>(1);
- private static final Map<ITestDevice, File> cachedDeviceVendorFcFiles = new HashMap<>(1);
- private static final Map<ITestDevice, File> cachedDeviceVendorManifest = new HashMap<>(1);
- private static final Map<ITestDevice, File> cachedDeviceVintfJson = new HashMap<>(1);
- private static final Map<ITestDevice, File> cachedDeviceSystemPolicy = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDevicePolicyFiles = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDevicePlatFcFiles = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDeviceVendorFcFiles = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDeviceVendorManifest = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDeviceVendorPolicy = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDeviceVintfJson = new HashMap<>(1);
+ private static final Map<ITestDevice, File> sCachedDeviceSystemPolicy = new HashMap<>(1);
private File mSepolicyAnalyze;
private File checkSeapp;
@@ -163,16 +164,16 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
devicePolicyFile = getDevicePolicyFile(mDevice);
if (isSepolicySplit(mDevice)) {
- devicePlatFcFile = getDeviceFile(mDevice, cachedDevicePlatFcFiles,
+ devicePlatFcFile = getDeviceFile(mDevice, sCachedDevicePlatFcFiles,
"/system/etc/selinux/plat_file_contexts", "plat_file_contexts");
- deviceVendorFcFile = getDeviceFile(mDevice, cachedDeviceVendorFcFiles,
+ deviceVendorFcFile = getDeviceFile(mDevice, sCachedDeviceVendorFcFiles,
"/vendor/etc/selinux/vendor_file_contexts", "vendor_file_contexts");
deviceSystemPolicyFile =
android.security.cts.SELinuxHostTest.getDeviceSystemPolicyFile(mDevice);
} else {
- devicePlatFcFile = getDeviceFile(mDevice, cachedDevicePlatFcFiles,
+ devicePlatFcFile = getDeviceFile(mDevice, sCachedDevicePlatFcFiles,
"/plat_file_contexts", "plat_file_contexts");
- deviceVendorFcFile = getDeviceFile(mDevice, cachedDeviceVendorFcFiles,
+ deviceVendorFcFile = getDeviceFile(mDevice, sCachedDeviceVendorFcFiles,
"/vendor_file_contexts", "vendor_file_contexts");
}
}
@@ -204,7 +205,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
Map<ITestDevice, File> cache, String deviceFilePath,
String tmpFileName) throws Exception {
if (!device.doesFileExist(deviceFilePath)){
- throw new Exception();
+ throw new Exception("File not found on the device: " + deviceFilePath);
}
File file;
synchronized (cache) {
@@ -271,18 +272,86 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
return builtPolicyFile;
}
+ private static File buildVendorPolicy(IBuildInfo build, ITestDevice device,
+ Map<ITestDevice, File> cache, String tmpFileName) throws Exception {
+ File builtPolicyFile;
+ synchronized (cache) {
+ builtPolicyFile = cache.get(device);
+ }
+ if (builtPolicyFile != null) {
+ return builtPolicyFile;
+ }
+
+ builtPolicyFile = createTempFile(tmpFileName, ".tmp");
+
+ File secilc = copyResourceToTempFile("/secilc");
+ secilc.setExecutable(true);
+
+ int vendorVersion = getVendorSepolicyVersion(build, device);
+
+ File platSepolicyFile = copyResourceToTempFile("/" + vendorVersion + "_plat_sepolicy.cil");
+ File platMappingFile = copyResourceToTempFile("/" + vendorVersion + "_mapping.cil");
+ File vendorSepolicyCilFile = createTempFile("vendor_sepolicy", ".cil");
+ File platPubVersionedCilFile = createTempFile("plat_pub_versioned", ".cil");
+ File odmSepolicyCilFile = createTempFile("odm_sepolicy", ".cil");
+ File fileContextsFile = createTempFile("file_contexts", ".txt");
+
+ assertTrue(device.pullFile("/vendor/etc/selinux/vendor_sepolicy.cil",
+ vendorSepolicyCilFile));
+ assertTrue(device.pullFile("/vendor/etc/selinux/plat_pub_versioned.cil",
+ platPubVersionedCilFile));
+
+ List<String> command = new ArrayList<>(Arrays.asList(
+ secilc.getAbsolutePath(),
+ "-m",
+ "-M",
+ "true",
+ "-c",
+ "30",
+ "-N",
+ "-o",
+ builtPolicyFile.getAbsolutePath(),
+ "-f",
+ fileContextsFile.getAbsolutePath(),
+ platSepolicyFile.getAbsolutePath(),
+ platMappingFile.getAbsolutePath(),
+ vendorSepolicyCilFile.getAbsolutePath(),
+ platPubVersionedCilFile.getAbsolutePath()));
+
+ if (device.pullFile("/odm/etc/selinux/odm_sepolicy.cil", odmSepolicyCilFile)) {
+ command.add(odmSepolicyCilFile.getAbsolutePath());
+ }
+
+ String errorString = tryRunCommand(command.toArray(new String[0]));
+ assertTrue(errorString, errorString.length() == 0);
+
+ synchronized (cache) {
+ cache.put(device, builtPolicyFile);
+ }
+ return builtPolicyFile;
+ }
+
/**
* Returns the host-side file containing the SELinux policy of the device under test.
*/
public static File getDevicePolicyFile(ITestDevice device) throws Exception {
- return getDeviceFile(device, cachedDevicePolicyFiles, "/sys/fs/selinux/policy", "sepolicy");
+ return getDeviceFile(device, sCachedDevicePolicyFiles, "/sys/fs/selinux/policy",
+ "sepolicy");
}
/**
* Returns the host-side file containing the system SELinux policy of the device under test.
*/
public static File getDeviceSystemPolicyFile(ITestDevice device) throws Exception {
- return buildSystemPolicy(device, cachedDeviceSystemPolicy, "system_sepolicy");
+ return buildSystemPolicy(device, sCachedDeviceSystemPolicy, "system_sepolicy");
+ }
+
+ /**
+ * Returns the host-side file containing the vendor SELinux policy of the device under test.
+ */
+ public static File getDeviceVendorPolicyFile(IBuildInfo build, ITestDevice device)
+ throws Exception {
+ return buildVendorPolicy(build, device, sCachedDeviceVendorPolicy, "vendor_sepolicy");
}
/**
@@ -303,19 +372,20 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
try {
return getVendorSepolicyVersionFromBuildInfo(build);
} catch (Exception ex) {
- CLog.e("getVendorSepolicyVersionFromBuildInfo failed: ", ex);
+ CLog.e("getVendorSepolicyVersionFromBuildInfo failed: " + ex);
buildInfoEx = ex;
}
try {
return getVendorSepolicyVersionFromDeviceJson(device);
} catch (Exception ex) {
- CLog.e("getVendorSepolicyVersionFromDeviceJson failed: ", ex);
+ CLog.e("getVendorSepolicyVersionFromDeviceJson failed: " + ex);
}
try {
return getVendorSepolicyVersionFromManifests(device);
} catch (Exception ex) {
- CLog.e("getVendorSepolicyVersionFromManifests failed: ", ex);
- throw buildInfoEx;
+ CLog.e("getVendorSepolicyVersionFromManifests failed: " + ex);
+ throw new Exception("Unable to get the vendor policy version from the device:",
+ buildInfoEx);
}
}
@@ -347,7 +417,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
* VintfDeviceInfo.
*/
private static int getVendorSepolicyVersionFromDeviceJson(ITestDevice device) throws Exception {
- File vintfJson = getDeviceFile(device, cachedDeviceVintfJson,
+ File vintfJson = getDeviceFile(device, sCachedDeviceVintfJson,
DEVICE_INFO_DEVICE_DIR + VINTF_DEVICE_JSON, VINTF_DEVICE_JSON);
return getVendorSepolicyVersionFromJsonFile(vintfJson);
}
@@ -374,7 +444,7 @@ public class SELinuxHostTest extends BaseHostJUnit4Test {
(device.doesFileExist("/vendor/etc/vintf/manifest.xml")) ?
"/vendor/etc/vintf/manifest.xml" :
"/vendor/manifest.xml";
- File vendorManifestFile = getDeviceFile(device, cachedDeviceVendorManifest,
+ File vendorManifestFile = getDeviceFile(device, sCachedDeviceVendorManifest,
deviceManifestPath, "manifest.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRule.java b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRule.java
new file mode 100644
index 00000000000..e2335da64c7
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRule.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2024 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 com.android.compatibility.common.util.PropertyUtil;
+import com.android.tradefed.device.ITestDevice;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class SELinuxNeverallowRule {
+ private static String[] sConditions = {
+ "TREBLE_ONLY",
+ "COMPATIBLE_PROPERTY_ONLY",
+ "LAUNCHING_WITH_R_ONLY",
+ "LAUNCHING_WITH_S_ONLY",
+ };
+
+ public String mText;
+ public boolean fullTrebleOnly;
+ public boolean launchingWithROnly;
+ public boolean launchingWithSOnly;
+ public boolean compatiblePropertyOnly;
+
+ private SELinuxNeverallowRule(String text, Map<String, Integer> conditions) {
+ mText = text;
+ if (conditions.getOrDefault("TREBLE_ONLY", 0) > 0) {
+ fullTrebleOnly = true;
+ }
+ if (conditions.getOrDefault("COMPATIBLE_PROPERTY_ONLY", 0) > 0) {
+ compatiblePropertyOnly = true;
+ }
+ if (conditions.getOrDefault("LAUNCHING_WITH_R_ONLY", 0) > 0) {
+ launchingWithROnly = true;
+ }
+ if (conditions.getOrDefault("LAUNCHING_WITH_S_ONLY", 0) > 0) {
+ launchingWithSOnly = true;
+ }
+ }
+
+ public String toString() {
+ return "Rule [text= " + mText
+ + ", fullTrebleOnly=" + fullTrebleOnly
+ + ", compatiblePropertyOnly=" + compatiblePropertyOnly
+ + ", launchingWithROnly=" + launchingWithROnly
+ + ", launchingWithSOnly=" + launchingWithSOnly
+ + "]";
+ }
+
+ private boolean isFullTrebleDevice(ITestDevice device) throws Exception {
+ return SELinuxHostTest.isFullTrebleDevice(device);
+ }
+
+ private boolean isDeviceLaunchingWithR(ITestDevice device) throws Exception {
+ return PropertyUtil.getFirstApiLevel(device) > 29;
+ }
+
+ private boolean isDeviceLaunchingWithS(ITestDevice device) throws Exception {
+ return PropertyUtil.getFirstApiLevel(device) > 30;
+ }
+
+ private boolean isCompatiblePropertyEnforcedDevice(ITestDevice device) throws Exception {
+ return SELinuxHostTest.isCompatiblePropertyEnforcedDevice(device);
+ }
+
+ public boolean isCompatible(ITestDevice device) throws Exception {
+ if ((fullTrebleOnly) && (!isFullTrebleDevice(device))) {
+ // This test applies only to Treble devices but this device isn't one
+ return false;
+ }
+ if ((launchingWithROnly) && (!isDeviceLaunchingWithR(device))) {
+ // This test applies only to devices launching with R or later but this device isn't one
+ return false;
+ }
+ if ((launchingWithSOnly) && (!isDeviceLaunchingWithS(device))) {
+ // This test applies only to devices launching with S or later but this device isn't one
+ return false;
+ }
+ if ((compatiblePropertyOnly) && (!isCompatiblePropertyEnforcedDevice(device))) {
+ // This test applies only to devices on which compatible property is enforced but this
+ // device isn't one
+ return false;
+ }
+ return true;
+ }
+
+ public static List<SELinuxNeverallowRule> parsePolicy(String policy) throws Exception {
+ String patternConditions = Arrays.stream(sConditions)
+ .flatMap(condition -> Stream.of("BEGIN_" + condition, "END_" + condition))
+ .collect(Collectors.joining("|"));
+
+ /* Uncomment conditions delimiter lines. */
+ Pattern uncommentConditions = Pattern.compile("^\\s*#\\s*(" + patternConditions + ")\\s*$",
+ Pattern.MULTILINE);
+ Matcher matcher = uncommentConditions.matcher(policy);
+ policy = matcher.replaceAll("$1");
+
+ /* Remove all comments. */
+ Pattern comments = Pattern.compile("#.*?$", Pattern.MULTILINE);
+ matcher = comments.matcher(policy);
+ policy = matcher.replaceAll("");
+
+ /* Use a pattern to match all the neverallow rules or a condition. */
+ Pattern neverAllowPattern = Pattern.compile(
+ "(neverallow\\s[^;]+?;|" + patternConditions + ")",
+ Pattern.MULTILINE);
+
+ List<SELinuxNeverallowRule> rules = new ArrayList();
+ Map<String, Integer> conditions = new HashMap();
+
+ matcher = neverAllowPattern.matcher(policy);
+ while (matcher.find()) {
+ String rule = matcher.group(1).replace("\n", " ");
+ if (rule.startsWith("BEGIN_")) {
+ String section = rule.substring(6);
+ conditions.put(section, conditions.getOrDefault(section, 0) + 1);
+ } else if (rule.startsWith("END_")) {
+ String section = rule.substring(4);
+ Integer v = conditions.getOrDefault(section, 0);
+ assertTrue("Condition " + rule + " found without BEGIN", v > 0);
+ conditions.put(section, v - 1);
+ } else if (rule.startsWith("neverallow")) {
+ rules.add(new SELinuxNeverallowRule(rule, conditions));
+ } else {
+ throw new Exception("Unknown rule: " + rule);
+ }
+ }
+
+ for (Map.Entry<String, Integer> condition : conditions.entrySet()) {
+ if (condition.getValue() != 0) {
+ throw new Exception("End of input while inside " + condition.getKey() + " section");
+ }
+ }
+
+ return rules;
+ }
+
+ public void testNeverallowRule(File sepolicyAnalyze, File policyFile) throws Exception {
+ /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ policyFile.getAbsolutePath(), "neverallow", "-n",
+ mText);
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\n");
+ }
+ p.waitFor();
+ assertTrue("The following errors were encountered when validating the SELinux"
+ + "neverallow rule:\n" + mText + "\n" + errorString,
+ errorString.length() == 0);
+ }
+}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesParserTest.java b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesParserTest.java
index b7f5aefbcdf..def1f8182f0 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesParserTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesParserTest.java
@@ -19,15 +19,13 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
-import android.security.cts.SELinuxNeverallowRulesTest.NeverAllowRule;
-
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
+import java.util.List;
@RunWith(DeviceJUnit4ClassRunner.class)
public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
@@ -35,7 +33,7 @@ public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
@Test
public void testParsingEmpty() throws Exception {
String policy = "allow s t:c p;";
- ArrayList<NeverAllowRule> rules = SELinuxNeverallowRulesTest.parsePolicy(policy);
+ List<SELinuxNeverallowRule> rules = SELinuxNeverallowRule.parsePolicy(policy);
assertTrue(rules.isEmpty());
}
@@ -44,7 +42,7 @@ public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
String policy = "# A comment, no big deal\n"
+ "neverallow d1 d2:c1 p;\n"
+ "neverallow d2 d3:c2 p2;\n";
- ArrayList<NeverAllowRule> rules = SELinuxNeverallowRulesTest.parsePolicy(policy);
+ List<SELinuxNeverallowRule> rules = SELinuxNeverallowRule.parsePolicy(policy);
assertEquals(2, rules.size());
assertEquals("neverallow d1 d2:c1 p;", rules.get(0).mText);
assertEquals(false, rules.get(0).fullTrebleOnly);
@@ -62,7 +60,7 @@ public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
public void testParsingMultiNeverallowOnOneLine() throws Exception {
String policy = "# A comment\n"
+ "neverallow d1 d2:c1 p; neverallow d2 d3:c2 p2;\n";
- ArrayList<NeverAllowRule> rules = SELinuxNeverallowRulesTest.parsePolicy(policy);
+ List<SELinuxNeverallowRule> rules = SELinuxNeverallowRule.parsePolicy(policy);
assertEquals(2, rules.size());
}
@@ -76,7 +74,7 @@ public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
+ " p1\n"
+ " p2\n"
+ "};\n";
- ArrayList<NeverAllowRule> rules = SELinuxNeverallowRulesTest.parsePolicy(policy);
+ List<SELinuxNeverallowRule> rules = SELinuxNeverallowRule.parsePolicy(policy);
assertEquals(1, rules.size());
assertEquals(rules.get(0).mText, "neverallow d1 { d2 d3 }:file { p1 p2 };");
}
@@ -87,7 +85,7 @@ public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
+ "neverallow d1 d2:c1 p;\n"
+ "# END_TREBLE_ONLY\n"
+ "neverallow d2 d3:c2 p2;\n";
- ArrayList<NeverAllowRule> rules = SELinuxNeverallowRulesTest.parsePolicy(policy);
+ List<SELinuxNeverallowRule> rules = SELinuxNeverallowRule.parsePolicy(policy);
assertEquals(2, rules.size());
assertEquals(true, rules.get(0).fullTrebleOnly);
assertEquals(false, rules.get(1).fullTrebleOnly);
@@ -97,6 +95,6 @@ public class SELinuxNeverallowRulesParserTest extends BaseHostJUnit4Test {
public void testParsingMissingConditions() throws Exception {
String policy = "# BEGIN_LAUNCHING_WITH_S_ONLY\n"
+ "neverallow d1 d2:c1 p;\n";
- assertThrows(Exception.class, () -> SELinuxNeverallowRulesTest.parsePolicy(policy));
+ assertThrows(Exception.class, () -> SELinuxNeverallowRule.parsePolicy(policy));
}
}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java
index 6ea35c0a5e7..10da2544e66 100644
--- a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java
+++ b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java
@@ -17,13 +17,12 @@
package android.security.cts;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assume.assumeTrue;
import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
import android.cts.host.utils.DeviceJUnit4Parameterized;
import android.platform.test.annotations.RestrictedBuildTest;
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.compatibility.common.util.PropertyUtil;
import com.android.tradefed.build.IBuildInfo;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
@@ -36,18 +35,9 @@ import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.Parameterized.UseParametersRunnerFactory;
-import java.io.BufferedReader;
import java.io.File;
-import java.io.InputStreamReader;
import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
+import java.util.List;
/**
* Neverallow Rules SELinux tests.
@@ -58,7 +48,8 @@ import java.util.stream.Stream;
* policy.
*
* A set of criteria can be used in the platform policy to skip the test
- * depending on the device (e.g., launching version). See sConditions below.
+ * depending on the device (e.g., launching version). See
+ * SELinuxNeverallowRule.sConditions.
*
*/
@RunWith(DeviceJUnit4Parameterized.class)
@@ -77,106 +68,15 @@ public class SELinuxNeverallowRulesTest extends BaseHostJUnit4Test {
*/
private ITestDevice mDevice;
- private static String[] sConditions = {
- "TREBLE_ONLY",
- "COMPATIBLE_PROPERTY_ONLY",
- "LAUNCHING_WITH_R_ONLY",
- "LAUNCHING_WITH_S_ONLY",
- };
-
- protected static class NeverAllowRule {
- public String mText;
- public boolean fullTrebleOnly;
- public boolean launchingWithROnly;
- public boolean launchingWithSOnly;
- public boolean compatiblePropertyOnly;
-
- NeverAllowRule(String text, HashMap<String, Integer> conditions) {
- mText = text;
- if (conditions.getOrDefault("TREBLE_ONLY", 0) > 0) {
- fullTrebleOnly = true;
- }
- if (conditions.getOrDefault("COMPATIBLE_PROPERTY_ONLY", 0) > 0) {
- compatiblePropertyOnly = true;
- }
- if (conditions.getOrDefault("LAUNCHING_WITH_R_ONLY", 0) > 0) {
- launchingWithROnly = true;
- }
- if (conditions.getOrDefault("LAUNCHING_WITH_S_ONLY", 0) > 0) {
- launchingWithSOnly = true;
- }
- }
-
- public String toString() {
- return "Rule [text= " + mText
- + ", fullTrebleOnly=" + fullTrebleOnly
- + ", compatiblePropertyOnly=" + compatiblePropertyOnly
- + ", launchingWithROnly=" + launchingWithROnly
- + ", launchingWithSOnly=" + launchingWithSOnly
- + "]";
- }
- }
-
- public static ArrayList<NeverAllowRule> parsePolicy(String policy) throws Exception {
- String patternConditions = Arrays.stream(sConditions)
- .flatMap(condition -> Stream.of("BEGIN_" + condition, "END_" + condition))
- .collect(Collectors.joining("|"));
-
- /* Uncomment conditions delimiter lines. */
- Pattern uncommentConditions = Pattern.compile("^\\s*#\\s*(" + patternConditions + ")\\s*$",
- Pattern.MULTILINE);
- Matcher matcher = uncommentConditions.matcher(policy);
- policy = matcher.replaceAll("$1");
-
- /* Remove all comments. */
- Pattern comments = Pattern.compile("#.*?$", Pattern.MULTILINE);
- matcher = comments.matcher(policy);
- policy = matcher.replaceAll("");
-
- /* Use a pattern to match all the neverallow rules or a condition. */
- Pattern neverAllowPattern = Pattern.compile(
- "(neverallow\\s[^;]+?;|" + patternConditions + ")",
- Pattern.MULTILINE);
-
- ArrayList<NeverAllowRule> rules = new ArrayList();
- HashMap<String, Integer> conditions = new HashMap();
-
- matcher = neverAllowPattern.matcher(policy);
- while (matcher.find()) {
- String rule = matcher.group(1).replace("\n", " ");
- if (rule.startsWith("BEGIN_")) {
- String section = rule.substring(6);
- conditions.put(section, conditions.getOrDefault(section, 0) + 1);
- } else if (rule.startsWith("END_")) {
- String section = rule.substring(4);
- Integer v = conditions.getOrDefault(section, 0);
- assertTrue("Condition " + rule + " found without BEGIN", v > 0);
- conditions.put(section, v - 1);
- } else if (rule.startsWith("neverallow")) {
- rules.add(new NeverAllowRule(rule, conditions));
- } else {
- throw new Exception("Unknown rule: " + rule);
- }
- }
-
- for (Map.Entry<String, Integer> condition : conditions.entrySet()) {
- if (condition.getValue() != 0) {
- throw new Exception("End of input while inside " + condition.getKey() + " section");
- }
- }
-
- return rules;
- }
-
/**
* Generate the test parameters based on the embedded policy (general_sepolicy.conf).
*/
@Parameters
- public static Iterable<NeverAllowRule> generateRules() throws Exception {
+ public static Iterable<SELinuxNeverallowRule> generateRules() throws Exception {
File publicPolicy = SELinuxHostTest.copyResourceToTempFile("/general_sepolicy.conf");
String policy = Files.readString(publicPolicy.toPath());
- ArrayList<NeverAllowRule> rules = parsePolicy(policy);
+ List<SELinuxNeverallowRule> rules = SELinuxNeverallowRule.parsePolicy(policy);
assertTrue("No test generated from the CTS-embedded policy", !rules.isEmpty());
return rules;
@@ -184,20 +84,23 @@ public class SELinuxNeverallowRulesTest extends BaseHostJUnit4Test {
/* Parameter generated by generateRules() and available to testNeverallowRules */
@Parameter
- public NeverAllowRule mRule;
+ public SELinuxNeverallowRule mRule;
@Before
public void setUp() throws Exception {
mDevice = getDevice();
mBuild = getBuild();
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
- sepolicyAnalyze = SELinuxHostTest.copyResourceToTempFile("/sepolicy-analyze");
- sepolicyAnalyze.setExecutable(true);
+ assumeTrue("skipping not compatible rule", mRule.isCompatible(mDevice));
+
+ if (sepolicyAnalyze == null) {
+ sepolicyAnalyze = SELinuxHostTest.copyResourceToTempFile("/sepolicy-analyze");
+ sepolicyAnalyze.setExecutable(true);
+ }
devicePolicyFile = SELinuxHostTest.getDevicePolicyFile(mDevice);
- if (isSepolicySplit()) {
+ if (SELinuxHostTest.isSepolicySplit(mDevice)) {
deviceSystemPolicyFile =
SELinuxHostTest.getDeviceSystemPolicyFile(mDevice);
@@ -215,74 +118,22 @@ public class SELinuxNeverallowRulesTest extends BaseHostJUnit4Test {
@After
public void tearDown() throws Exception {
- sepolicyAnalyze.delete();
- }
-
- private boolean isFullTrebleDevice() throws Exception {
- return SELinuxHostTest.isFullTrebleDevice(mDevice);
- }
-
- private boolean isDeviceLaunchingWithR() throws Exception {
- return PropertyUtil.getFirstApiLevel(mDevice) > 29;
- }
-
- private boolean isDeviceLaunchingWithS() throws Exception {
- return PropertyUtil.getFirstApiLevel(mDevice) > 30;
- }
-
- private boolean isCompatiblePropertyEnforcedDevice() throws Exception {
- return SELinuxHostTest.isCompatiblePropertyEnforcedDevice(mDevice);
- }
-
- private boolean isSepolicySplit() throws Exception {
- return SELinuxHostTest.isSepolicySplit(mDevice);
+ if (sepolicyAnalyze != null) {
+ sepolicyAnalyze.delete();
+ sepolicyAnalyze = null;
+ }
}
@Test
@RestrictedBuildTest
public void testNeverallowRules() throws Exception {
-
- if ((mRule.fullTrebleOnly) && (!isFullTrebleDevice())) {
- // This test applies only to Treble devices but this device isn't one
- return;
- }
- if ((mRule.launchingWithROnly) && (!isDeviceLaunchingWithR())) {
- // This test applies only to devices launching with R or later but this device isn't one
- return;
- }
- if ((mRule.launchingWithSOnly) && (!isDeviceLaunchingWithS())) {
- // This test applies only to devices launching with S or later but this device isn't one
- return;
- }
- if ((mRule.compatiblePropertyOnly) && (!isCompatiblePropertyEnforcedDevice())) {
- // This test applies only to devices on which compatible property is enforced but this
- // device isn't one
- return;
- }
-
// If sepolicy is split and vendor sepolicy version is behind platform's,
// only test against platform policy.
File policyFile =
- (isSepolicySplit() && mVendorSepolicyVersion < mSystemSepolicyVersion)
+ (SELinuxHostTest.isSepolicySplit(mDevice)
+ && mVendorSepolicyVersion < mSystemSepolicyVersion)
? deviceSystemPolicyFile : devicePolicyFile;
- /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
- ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- policyFile.getAbsolutePath(), "neverallow", "-n",
- mRule.mText);
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- p.waitFor();
- assertTrue("The following errors were encountered when validating the SELinux"
- + "neverallow rule:\n" + mRule.mText + "\n" + errorString,
- errorString.length() == 0);
+ mRule.testNeverallowRule(sepolicyAnalyze, policyFile);
}
}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTestVendor.java b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTestVendor.java
new file mode 100644
index 00000000000..7e4ae2ccbf7
--- /dev/null
+++ b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTestVendor.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2024 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.assumeTrue;
+
+import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
+import android.cts.host.utils.DeviceJUnit4Parameterized;
+import android.platform.test.annotations.RestrictedBuildTest;
+
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+import org.junit.runners.Parameterized.UseParametersRunnerFactory;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarFile;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Neverallow Rules SELinux tests on vendor.
+ *
+ * This is a parametrised test. It extracts the neverallow rules from the
+ * platform policy which is embedded in the CTS distribution. Each rule
+ * generates its own test to ensure that it is not violated by the device
+ * policy.
+ *
+ * A set of criteria can be used in the platform policy to skip the test
+ * depending on the device (e.g., launching version). See
+ * SELinuxNeverallowRule.sConditions.
+ *
+ */
+@RunWith(DeviceJUnit4Parameterized.class)
+@UseParametersRunnerFactory(DeviceJUnit4ClassRunnerWithParameters.RunnerFactory.class)
+public class SELinuxNeverallowRulesTestVendor extends BaseHostJUnit4Test {
+ private File mSepolicyAnalyze;
+ private File mDeviceVendorPolicyFile;
+
+ private IBuildInfo mBuild;
+ private int mVendorSepolicyVersion = -1;
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private static final Pattern VENDOR_POLICY_PATTERN = Pattern.compile(
+ "^([0-9]{6})_general_sepolicy.conf$");
+
+ /**
+ * Generate the test parameters based on the embedded policy ({ver}_general_sepolicy.conf).
+ */
+ @Parameters(name = "ver={0,number,#};idx={1,number,#}")
+ public static Iterable<Object[]> generateRules() throws Exception {
+ List<Object[]> rules = new ArrayList<>();
+ JarFile jarFile = new JarFile(SELinuxHostTest.class
+ .getProtectionDomain()
+ .getCodeSource()
+ .getLocation()
+ .getPath());
+ jarFile.stream().forEach(entry -> {
+ try {
+ String name = entry.getName();
+ Matcher m = VENDOR_POLICY_PATTERN.matcher(name);
+ if (m.matches()) {
+ int ver = Integer.parseInt(m.group(1));
+ File publicPolicy = SELinuxHostTest.copyResourceToTempFile("/" + name);
+ String policy = Files.readString(publicPolicy.toPath());
+ List<SELinuxNeverallowRule> parsedRules =
+ SELinuxNeverallowRule.parsePolicy(policy);
+
+ for (int idx = 0; idx < parsedRules.size(); ++idx) {
+ rules.add(new Object[]{ver, idx, parsedRules.get(idx)});
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ jarFile.close();
+
+ assertTrue("No test generated from the CTS-embedded policy", !rules.isEmpty());
+ return rules;
+ }
+
+ @Parameter(0)
+ public int mVersion;
+
+ @Parameter(1)
+ public int mIndex;
+
+ /* Parameter generated by generateRules() and available to testNeverallowRules */
+ @Parameter(2)
+ public SELinuxNeverallowRule mRule;
+
+ @Before
+ public void setUp() throws Exception {
+ mDevice = getDevice();
+ mBuild = getBuild();
+
+ if (mVendorSepolicyVersion == -1) {
+ mVendorSepolicyVersion =
+ SELinuxHostTest.getVendorSepolicyVersion(mBuild, mDevice);
+ }
+
+ assumeTrue("skipping not matching vendor", mVendorSepolicyVersion == mVersion);
+ assumeTrue("skipping not compatible rule", mRule.isCompatible(mDevice));
+
+ if (mSepolicyAnalyze == null) {
+ mSepolicyAnalyze = SELinuxHostTest.copyResourceToTempFile("/sepolicy-analyze");
+ mSepolicyAnalyze.setExecutable(true);
+ }
+ mDeviceVendorPolicyFile = SELinuxHostTest.getDeviceVendorPolicyFile(mBuild, mDevice);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mSepolicyAnalyze != null) {
+ mSepolicyAnalyze.delete();
+ mSepolicyAnalyze = null;
+ }
+ }
+
+ @Test
+ @RestrictedBuildTest
+ public void testNeverallowRules() throws Exception {
+ mRule.testNeverallowRule(mSepolicyAnalyze, mDeviceVendorPolicyFile);
+ }
+}
diff --git a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c
index 67ed5c7fc14..cb4b3c6c9fe 100755
--- a/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c
+++ b/hostsidetests/securitybulletin/securityPatch/CVE-2017-0386/poc.c
@@ -17,16 +17,25 @@
#define LOG_TAG "CVE-2017-0386"
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <stdio.h>
#include <log/log.h>
+#include <netlink/attr.h>
#include <netlink/msg.h>
#include <netlink/netlink.h>
-#include <netlink-private/object-api.h>
-#include <netlink-private/types.h>
+#include <netlink/object-api.h>
#include <netlink/object.h>
-#include <netlink/attr.h>
+#include <netlink/types.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+// These are private headers from libnl and make this code fragile.
+#if __has_include(<netlink-private/types.h>)
+// Old libnl private header.
+#include <netlink-private/types.h>
+#else
+#include <base/nl-base-utils.h>
+#include <nl-priv-dynamic-core/nl-core.h>
+#endif
#include "../includes/common.h"
diff --git a/hostsidetests/shortcuts/hostside/AndroidTest.xml b/hostsidetests/shortcuts/hostside/AndroidTest.xml
index 36a08763c15..f7d2931b600 100644
--- a/hostsidetests/shortcuts/hostside/AndroidTest.xml
+++ b/hostsidetests/shortcuts/hostside/AndroidTest.xml
@@ -16,7 +16,7 @@
<configuration description="Config for the CTS ShortcutManager host tests">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="framework" />
- <option name="config-descriptor:metadata" key="parameter" value="all_foldable_states" />
+ <option name="config-descriptor:metadata" key="parameter" value="no_foldable_states" />
<!-- Instant apps can't access ShortcutManager -->
<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/statsdatom/src/android/cts/statsdatom/media/MediaCapabilitiesTests.java b/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaCapabilitiesTests.java
index 20d7872783c..5490627d5ff 100644
--- a/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaCapabilitiesTests.java
+++ b/hostsidetests/statsdatom/src/android/cts/statsdatom/media/MediaCapabilitiesTests.java
@@ -80,9 +80,9 @@ public class MediaCapabilitiesTests extends DeviceTestCase implements IBuildRece
// Setting the values of audio setting via shell commands
getDevice().executeShellCommand(
- "cmd audio set-surround-format-enabled 7 true");
+ "cmd audio set-surround-format-enabled 5 true");
getDevice().executeShellCommand(
- "cmd audio set-surround-format-enabled 14 false");
+ "cmd audio set-surround-format-enabled 6 false");
getDevice().executeShellCommand("cmd audio set-encoded-surround-mode 2");
RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_SHORT);
@@ -98,10 +98,10 @@ public class MediaCapabilitiesTests extends DeviceTestCase implements IBuildRece
.isAtLeast(1);
assertEquals(Mediametrics.EncodedSurroundOutputMode.ENCODED_SURROUND_OUTPUT_NEVER,
atom.getMediaCapabilities().getSurroundOutputMode());
- assertThat(Mediametrics.AudioEncoding.ENCODING_DTS).isIn(
+ assertThat(Mediametrics.AudioEncoding.ENCODING_AC3).isIn(
atom.getMediaCapabilities()
.getUserEnabledSurroundEncodings().getAudioEncodingsList());
- assertThat(Mediametrics.AudioEncoding.ENCODING_DOLBY_TRUEHD).isNotIn(
+ assertThat(Mediametrics.AudioEncoding.ENCODING_E_AC3).isNotIn(
atom.getMediaCapabilities()
.getUserEnabledSurroundEncodings().getAudioEncodingsList());
}
diff --git a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
index 32107f57bae..ded3568ef08 100644
--- a/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
+++ b/hostsidetests/videoencodingminimum/src/android/videoqualityfloor/cts/CtsVideoQualityFloorHostTest.java
@@ -21,6 +21,7 @@ import android.cts.host.utils.DeviceJUnit4Parameterized;
import android.platform.test.annotations.AppModeFull;
import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
+import com.android.ddmlib.testrunner.TestResult.TestStatus;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
@@ -230,7 +231,8 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
JSONArray codecConfigs = obj.getJSONArray("CodecConfigs");
int th = Runtime.getRuntime().availableProcessors() / 2;
th = Math.min(Math.max(1, th), 8);
- String filter = "libvmaf=feature=name=psnr:model=version=vmaf_v0.6.1:n_threads=" + th;
+ String filter = "feature=name=psnr:model=version=vmaf_v0.6.1\\\\:enable_transform=true"
+ + ":n_threads=" + th;
for (int i = 0; i < codecConfigs.length(); i++) {
JSONObject codecConfig = codecConfigs.getJSONObject(i);
String outputName = codecConfig.getString("EncodedFileName");
@@ -240,7 +242,7 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
cmd += " -hide_banner";
cmd += " -i " + outDir + "/" + outputName + ".mp4" + " -an";
cmd += " -i " + "samples/" + refFileName + " -an";
- cmd += " -filter_complex " + "\"" + filter + "\"";
+ cmd += " -lavfi libvmaf=" + "\'" + filter + "\'";
cmd += " -f null -";
cmd += " > " + outputVmafPath + " 2>&1";
LogUtil.CLog.i("ffmpeg command : " + cmd);
@@ -346,17 +348,24 @@ public class CtsVideoQualityFloorHostTest implements IDeviceTest {
+ testRunResult.getName() + ": " + testRunResult.getRunFailureMessage());
}
if (testRunResult.getNumTests() != testRunResult.getPassedTests().size()) {
- StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
for (Map.Entry<TestDescription, TestResult> resultEntry :
testRunResult.getTestResults().entrySet()) {
- if (!resultEntry.getValue().getStatus()
- .equals(com.android.ddmlib.testrunner.TestResult.TestStatus.PASSED)) {
+ if (resultEntry.getValue().getStatus().equals(TestStatus.FAILURE)) {
+ StringBuilder errorBuilder = new StringBuilder("On-device tests failed:\n");
errorBuilder.append(resultEntry.getKey().toString());
errorBuilder.append(":\n");
errorBuilder.append(resultEntry.getValue().getStackTrace());
+ throw new AssertionError(errorBuilder.toString());
+ }
+ if (resultEntry.getValue().getStatus().equals(TestStatus.ASSUMPTION_FAILURE)) {
+ StringBuilder errorBuilder =
+ new StringBuilder("On-device tests assumption failed:\n");
+ errorBuilder.append(resultEntry.getKey().toString());
+ errorBuilder.append(":\n");
+ errorBuilder.append(resultEntry.getValue().getStackTrace());
+ Assume.assumeTrue(errorBuilder.toString(), false);
}
}
- throw new AssertionError(errorBuilder.toString());
}
}
}