summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp38
-rw-r--r--services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml42
-rw-r--r--services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml32
-rw-r--r--services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt20
-rw-r--r--services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt254
5 files changed, 386 insertions, 0 deletions
diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp b/services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp
new file mode 100644
index 000000000000..39ef50112cba
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/preverifieddomains/Android.bp
@@ -0,0 +1,38 @@
+// 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 {
+ default_team: "trendy_team_framework_android_packages",
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "PreVerifiedDomainsTests",
+ srcs: [
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "compatibility-device-util-axt",
+ "androidx.test.runner",
+ "truth",
+ ],
+ platform_apis: true,
+ certificate: "platform",
+ test_suites: ["device-tests"],
+}
diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml
new file mode 100644
index 000000000000..ad731fc1a61c
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidManifest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.server.pm.test.preverifieddomains">
+
+ <application android:label="PreVerified Domains Tests">
+ <activity
+ android:name="com.android.server.pm.test.preverifieddomains.FakeInstantAppInstallerActivity"
+ android:enabled="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.INSTALL_INSTANT_APP_PACKAGE_TEST" />
+ <category android:name="android.intent.category.DEFAULT"/>
+ <data android:scheme="file"/>
+ <data android:mimeType="application/vnd.android.package-archive"/>
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.pm.test.preverifieddomains"
+ android:label="Package Manager Service Tests for pre-verified domains">
+ </instrumentation>
+
+</manifest>
+
diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml
new file mode 100644
index 000000000000..45e193b03e36
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/preverifieddomains/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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.
+ -->
+
+<configuration description="Runs Package Manager Service Pre-Verified Domains Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="test-file-name" value="PreVerifiedDomainsTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="PreVerifiedDomainsTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest">
+ <option name="package" value="com.android.server.pm.test.preverifieddomains" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false" />
+ </test>
+</configuration>
diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt
new file mode 100644
index 000000000000..d330490516f4
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/FakeInstantAppInstallerActivity.kt
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+package com.android.server.pm.test.preverifieddomains
+
+import android.app.Activity
+
+class FakeInstantAppInstallerActivity : Activity()
diff --git a/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt
new file mode 100644
index 000000000000..70432168ca5c
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/preverifieddomains/src/com/android/server/pm/test/preverifieddomains/PreVerifiedDomainsTests.kt
@@ -0,0 +1,254 @@
+/*
+ * 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 com.android.server.pm.test.preverifieddomains
+
+import android.app.UiAutomation
+import android.content.ComponentName
+import android.content.Context
+import android.content.pm.Flags
+import android.content.pm.PackageInstaller
+import android.content.pm.PackageInstaller.SessionParams.MODE_FULL_INSTALL
+import android.content.pm.PackageManager
+import android.os.Build
+import android.platform.test.annotations.RequiresFlagsEnabled
+import android.platform.test.flag.junit.CheckFlagsRule
+import android.platform.test.flag.junit.DeviceFlagsValueProvider
+import android.provider.DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.compatibility.common.util.DeviceConfigStateManager
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.AfterClass
+import org.junit.Assert.assertThrows
+import org.junit.Assume.assumeTrue
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.Rule
+import org.junit.Test
+import org.junit.function.ThrowingRunnable
+import org.junit.runner.RunWith
+
+/**
+ * Pre-verified domains API tests. These tests require the device's default instant app
+ * installer to be disabled temporarily and is only able to run on ENG builds.
+ */
+@RunWith(AndroidJUnit4::class)
+class PreVerifiedDomainsTests {
+ companion object {
+ private const val PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT =
+ "pre_verified_domains_count_limit"
+ private const val PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT =
+ "pre_verified_domain_length_limit"
+ private const val TEMP_COUNT_LIMIT = 10
+ private const val TEMP_LENGTH_LIMIT = 15
+ private val testDomains = setOf("com.foo", "com.bar")
+
+ private val uiAutomation: UiAutomation =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation()
+ private lateinit var packageManager: PackageManager
+ private var defaultInstantAppInstaller: ComponentName? = null
+ private lateinit var fakeInstantAppInstaller: ComponentName
+
+ @JvmStatic
+ @BeforeClass
+ fun setupBeforeClass() {
+ val context = InstrumentationRegistry.getInstrumentation().getContext()
+ packageManager = context.packageManager
+ defaultInstantAppInstaller = packageManager.getInstantAppInstallerComponent()
+ fakeInstantAppInstaller = ComponentName(
+ context.packageName,
+ context.packageName + ".FakeInstantAppInstallerActivity")
+ // By disabling the original instant app installer, this test app becomes the instant
+ // app installer
+ uiAutomation.adoptShellPermissionIdentity()
+ try {
+ // Enable the fake instant app installer before disabling the default one
+ packageManager.setComponentEnabledSetting(
+ fakeInstantAppInstaller,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP
+ )
+ if (defaultInstantAppInstaller != null) {
+ packageManager.setComponentEnabledSetting(
+ defaultInstantAppInstaller!!,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ 0
+ )
+ }
+ } finally {
+ uiAutomation.dropShellPermissionIdentity()
+ }
+ assertThat(fakeInstantAppInstaller).isEqualTo(
+ packageManager.getInstantAppInstallerComponent())
+ }
+
+ @JvmStatic
+ @AfterClass
+ fun restoreInstantAppInstaller() {
+ uiAutomation.adoptShellPermissionIdentity()
+ try {
+ // Enable the original instant app installer before disabling the temporary one, so
+ // there won't be a time when the device doesn't have a valid instant app installer
+ if (defaultInstantAppInstaller != null) {
+ packageManager.setComponentEnabledSetting(
+ defaultInstantAppInstaller!!,
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ 0
+ )
+ }
+ // Be careful not to let this test process killed, or the test will be considered
+ // as failed
+ packageManager.setComponentEnabledSetting(
+ fakeInstantAppInstaller,
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP
+ )
+ } finally {
+ uiAutomation.dropShellPermissionIdentity()
+ }
+ }
+ }
+
+ private lateinit var packageInstaller: PackageInstaller
+ private lateinit var context: Context
+ private lateinit var packageManager: PackageManager
+ private var mDefaultCountLimit: String? = null
+ private var mDefaultLengthLimit: String? = null
+
+ @JvmField
+ @Rule
+ val mCheckFlagsRule: CheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule()
+
+ @Before
+ fun setUp() {
+ context = InstrumentationRegistry.getInstrumentation().getContext()
+ packageManager = context.packageManager
+ packageInstaller = packageManager.packageInstaller
+ mDefaultCountLimit = getLimitFromDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT)
+ mDefaultLengthLimit = getLimitFromDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT)
+ }
+
+ @After
+ fun cleanUp() {
+ setLimitInDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT, mDefaultCountLimit)
+ setLimitInDeviceConfig(PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT, mDefaultLengthLimit)
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS)
+ @Test
+ fun testSetPreVerifiedDomainsExceedsCountLimit() {
+ // Temporarily change the count limit to a much smaller number so the test can exceed it
+ setLimitInDeviceConfig(
+ PROPERTY_PRE_VERIFIED_DOMAINS_COUNT_LIMIT,
+ TEMP_COUNT_LIMIT.toString()
+ )
+ val domains = mutableSetOf<String>()
+ for (i in 0 until(TEMP_COUNT_LIMIT + 1)) {
+ domains.add("domain$i")
+ }
+
+ uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.ACCESS_INSTANT_APPS)
+ try {
+ assertThrows(
+ IllegalArgumentException::class.java,
+ ThrowingRunnable {
+ createSessionWithPreVerifiedDomains(domains)
+ }
+ )
+ } finally {
+ uiAutomation.dropShellPermissionIdentity()
+ }
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS)
+ @Test
+ fun testSetPreVerifiedDomainsExceedsLengthLimit() {
+ // Temporarily change the count limit to a much smaller number so the test can exceed it
+ setLimitInDeviceConfig(
+ PROPERTY_PRE_VERIFIED_DOMAIN_LENGTH_LIMIT,
+ TEMP_LENGTH_LIMIT.toString()
+ )
+ val invalidDomain = "a".repeat(TEMP_LENGTH_LIMIT + 1)
+
+ uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.ACCESS_INSTANT_APPS)
+ try {
+ assertThrows(
+ "Pre-verified domain: [" +
+ invalidDomain + " ] exceeds maximum length allowed: " +
+ TEMP_LENGTH_LIMIT,
+ IllegalArgumentException::class.java,
+ ThrowingRunnable {
+ createSessionWithPreVerifiedDomains(setOf(invalidDomain))
+ }
+ )
+ } finally {
+ uiAutomation.dropShellPermissionIdentity()
+ }
+ }
+
+ @RequiresFlagsEnabled(Flags.FLAG_SET_PRE_VERIFIED_DOMAINS)
+ @Test
+ fun testSetAndGetPreVerifiedDomains() {
+ // Fake instant app installers can only work on ENG builds
+ assumeTrue("eng" == Build.TYPE)
+ var session: PackageInstaller.Session? = null
+ uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.ACCESS_INSTANT_APPS)
+ try {
+ val sessionId = createSessionWithPreVerifiedDomains(testDomains)
+ session = packageInstaller.openSession(sessionId)
+ assertThat(session.getPreVerifiedDomains()).isEqualTo(testDomains)
+ } finally {
+ uiAutomation.dropShellPermissionIdentity()
+ session?.abandon()
+ }
+ }
+
+ private fun createSessionWithPreVerifiedDomains(domains: Set<String>): Int {
+ val sessionParam = PackageInstaller.SessionParams(MODE_FULL_INSTALL)
+ val sessionId = packageInstaller.createSession(sessionParam)
+ val session = packageInstaller.openSession(sessionId)
+ try {
+ session.setPreVerifiedDomains(domains)
+ } catch (e: Exception) {
+ session.abandon()
+ throw e
+ }
+ return sessionId
+ }
+
+ private fun getLimitFromDeviceConfig(propertyName: String): String? {
+ val stateManager = DeviceConfigStateManager(
+ context,
+ NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ propertyName
+ )
+ return stateManager.get()
+ }
+
+ private fun setLimitInDeviceConfig(propertyName: String, value: String?) {
+ val stateManager = DeviceConfigStateManager(
+ context,
+ NAMESPACE_PACKAGE_MANAGER_SERVICE,
+ propertyName
+ )
+ val currentValue = stateManager.get()
+ if (currentValue != value) {
+ // Only change the value if the current value is different
+ stateManager.set(value)
+ }
+ }
+}