summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java7
-rw-r--r--services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt271
2 files changed, 276 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index 8f191580e2c9..e24e5bbfa4f6 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -542,8 +542,6 @@ public class DomainVerificationService extends SystemService
userState.removeHosts(domains);
}
}
-
- mConnection.scheduleWriteSettings();
}
@Nullable
@@ -849,6 +847,7 @@ public class DomainVerificationService extends SystemService
public void setLegacyUserState(@NonNull String packageName, @UserIdInt int userId, int state) {
mEnforcer.callerIsLegacyUserSelector(mConnection.getCallingUid());
mLegacySettings.add(packageName, userId, state);
+ mConnection.scheduleWriteSettings();
}
@Override
@@ -1067,6 +1066,8 @@ public class DomainVerificationService extends SystemService
}
}
}
+
+ mConnection.scheduleWriteSettings();
}
/**
@@ -1124,6 +1125,8 @@ public class DomainVerificationService extends SystemService
}
}
}
+
+ mConnection.scheduleWriteSettings();
}
@Override
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
new file mode 100644
index 000000000000..5792e02e37a2
--- /dev/null
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/verify/domain/DomainVerificationSettingsMutationTest.kt
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.test.verify.domain
+
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.content.pm.PackageUserState
+import android.content.pm.verify.domain.DomainVerificationManager
+import android.content.pm.parsing.component.ParsedActivity
+import android.content.pm.parsing.component.ParsedIntentInfo
+import android.os.Build
+import android.os.Process
+import android.util.ArraySet
+import android.util.SparseArray
+import com.android.server.pm.PackageSetting
+import com.android.server.pm.verify.domain.DomainVerificationManagerInternal
+import com.android.server.pm.verify.domain.DomainVerificationService
+import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.testutils.mockThrowOnUnmocked
+import com.android.server.testutils.spyThrowOnUnmocked
+import com.android.server.testutils.whenever
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.verify
+import java.io.File
+import java.util.UUID
+
+@RunWith(Parameterized::class)
+class DomainVerificationSettingsMutationTest {
+
+ companion object {
+ private const val TEST_PKG = "com.test"
+
+ // Pretend to be the system. This class doesn't verify any enforcement behavior.
+ private const val TEST_UID = Process.SYSTEM_UID
+ private const val TEST_USER_ID = 10
+ private val TEST_UUID = UUID.fromString("5168e42e-327e-432b-b562-cfb553518a70")
+
+ @JvmStatic
+ @Parameterized.Parameters(name = "{0}")
+ fun parameters(): Array<Any> {
+ val context: Context = mockThrowOnUnmocked {
+ whenever(
+ enforcePermission(
+ eq(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT),
+ anyInt(), anyInt(), anyString()
+ )
+ )
+ whenever(
+ enforcePermission(
+ eq(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION),
+ anyInt(), anyInt(), anyString()
+ )
+ )
+ whenever(
+ enforcePermission(
+ eq(android.Manifest.permission.INTERACT_ACROSS_USERS),
+ anyInt(), anyInt(), anyString()
+ )
+ )
+ whenever(
+ enforcePermission(
+ eq(android.Manifest.permission.SET_PREFERRED_APPLICATIONS),
+ anyInt(), anyInt(), anyString()
+ )
+ )
+ }
+ val proxy: DomainVerificationProxy = mockThrowOnUnmocked {
+ whenever(isCallerVerifier(anyInt())) { true }
+ whenever(sendBroadcastForPackages(any()))
+ }
+
+ val makeService: (DomainVerificationManagerInternal.Connection) -> DomainVerificationService =
+ { connection ->
+ DomainVerificationService(
+ context,
+ mockThrowOnUnmocked { whenever(linkedApps) { ArraySet<String>() } },
+ mockThrowOnUnmocked {
+ whenever(isChangeEnabled(anyLong(),any())) { true }
+ }).apply {
+ setConnection(connection)
+ }
+ }
+
+ fun service(name: String, block: DomainVerificationService.() -> Unit) =
+ Params(makeService, name) { service ->
+ service.proxy = proxy
+ service.addPackage(mockPkgSetting())
+ service.block()
+ }
+
+ return arrayOf(
+ service("clearPackage") {
+ clearPackage(TEST_PKG)
+ },
+ service("clearUser") {
+ clearUser(TEST_USER_ID)
+ },
+ service("clearState") {
+ clearDomainVerificationState(listOf(TEST_PKG))
+ },
+ service("clearUserSelections") {
+ clearUserSelections(listOf(TEST_PKG), TEST_USER_ID)
+ },
+ service("setStatus") {
+ setDomainVerificationStatus(
+ TEST_UUID,
+ setOf("example.com"),
+ DomainVerificationManager.STATE_SUCCESS
+ )
+ },
+ service("setStatusInternalPackageName") {
+ setDomainVerificationStatusInternal(
+ TEST_PKG,
+ DomainVerificationManager.STATE_SUCCESS,
+ ArraySet(setOf("example.com"))
+ )
+ },
+ service("setStatusInternalUid") {
+ setDomainVerificationStatusInternal(
+ TEST_UID,
+ TEST_UUID,
+ setOf("example.com"),
+ DomainVerificationManager.STATE_SUCCESS
+ )
+ },
+ service("setLinkHandlingAllowed") {
+ setDomainVerificationLinkHandlingAllowed(TEST_PKG, true)
+ },
+ service("setLinkHandlingAllowedUserId") {
+ setDomainVerificationLinkHandlingAllowed(TEST_PKG, true, TEST_USER_ID)
+ },
+ service("setLinkHandlingAllowedInternal") {
+ setDomainVerificationLinkHandlingAllowedInternal(TEST_PKG, true, TEST_USER_ID)
+ },
+ service("setUserSelection") {
+ setDomainVerificationUserSelection(TEST_UUID, setOf("example.com"), true)
+ },
+ service("setUserSelectionUserId") {
+ setDomainVerificationUserSelection(
+ TEST_UUID,
+ setOf("example.com"),
+ true,
+ TEST_USER_ID
+ )
+ },
+ service("setUserSelectionInternal") {
+ setDomainVerificationUserSelectionInternal(
+ TEST_USER_ID,
+ TEST_PKG,
+ true,
+ ArraySet(setOf("example.com")),
+ )
+ },
+ service("setLegacyUserState") {
+ setLegacyUserState(
+ TEST_PKG,
+ TEST_USER_ID,
+ PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER
+ )
+ },
+ )
+ }
+
+ data class Params(
+ val construct: (
+ DomainVerificationManagerInternal.Connection
+ ) -> DomainVerificationService,
+ val name: String,
+ val method: (DomainVerificationService) -> Unit
+ ) {
+ override fun toString() = name
+ }
+
+
+ fun mockPkg() = mockThrowOnUnmocked<AndroidPackage> {
+ whenever(packageName) { TEST_PKG }
+ whenever(targetSdkVersion) { Build.VERSION_CODES.S }
+ whenever(activities) {
+ listOf(
+ ParsedActivity().apply {
+ addIntent(
+ ParsedIntentInfo().apply {
+ autoVerify = true
+ addAction(Intent.ACTION_VIEW)
+ addCategory(Intent.CATEGORY_BROWSABLE)
+ addCategory(Intent.CATEGORY_DEFAULT)
+ addDataScheme("https")
+ addDataAuthority("example.com", null)
+ }
+ )
+ }
+ )
+ }
+ }
+
+ // TODO: PackageSetting field encapsulation to move to whenever(name)
+ fun mockPkgSetting() = spyThrowOnUnmocked(
+ PackageSetting(
+ TEST_PKG,
+ TEST_PKG,
+ File("/test"),
+ null,
+ null,
+ null,
+ null,
+ 1,
+ 0,
+ 0,
+ 0,
+ null,
+ null,
+ null,
+ TEST_UUID
+ )
+ ) {
+ whenever(getPkg()) { mockPkg() }
+ whenever(domainSetId) { TEST_UUID }
+ whenever(userState) {
+ SparseArray<PackageUserState>().apply {
+ this[0] = PackageUserState()
+ }
+ }
+ }
+ }
+
+ @Parameterized.Parameter(0)
+ lateinit var params: Params
+
+ @Test
+ fun writeScheduled() {
+ val connection = mockConnection()
+ val service = params.construct(connection)
+ params.method(service)
+
+ verify(connection).scheduleWriteSettings()
+ }
+
+ private fun mockConnection(): DomainVerificationManagerInternal.Connection =
+ mockThrowOnUnmocked {
+ whenever(callingUid) { TEST_UID }
+ whenever(callingUserId) { TEST_USER_ID }
+ whenever(getPackageSettingLocked(TEST_PKG)) { mockPkgSetting() }
+ whenever(getPackageLocked(TEST_PKG)) { mockPkg() }
+ whenever(schedule(anyInt(), any()))
+ whenever(scheduleWriteSettings())
+ }
+}