blob: dff94b8d197775ce8263b46cfd3d2af82b5061cf [file] [log] [blame]
/*
* 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.cts.packagemanager.verify.domain.device.multiuser
import android.content.ComponentName
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import com.android.bedstead.harrier.BedsteadJUnit4
import com.android.bedstead.harrier.DeviceState
import com.android.bedstead.harrier.annotations.AfterClass
import com.android.bedstead.harrier.annotations.BeforeClass
import com.android.bedstead.harrier.annotations.EnsureHasWorkProfile
import com.android.bedstead.harrier.annotations.Postsubmit
import com.android.bedstead.harrier.annotations.RequireRunOnPrimaryUser
import com.android.bedstead.harrier.annotations.RequireRunOnWorkProfile
import com.android.bedstead.nene.TestApis
import com.android.bedstead.nene.packages.Packages
import com.android.bedstead.nene.users.UserReference
import com.android.bedstead.nene.utils.ShellCommand
import com.android.compatibility.common.util.ShellUtils
import com.android.cts.packagemanager.verify.domain.android.DomainUtils.DECLARING_PKG_1_COMPONENT
import com.android.cts.packagemanager.verify.domain.android.DomainUtils.DECLARING_PKG_2_COMPONENT
import com.android.cts.packagemanager.verify.domain.android.SharedVerifications
import com.android.cts.packagemanager.verify.domain.java.DomainUtils
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DECLARING_PKG_APK_1
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DECLARING_PKG_APK_2
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DECLARING_PKG_NAME_1
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DECLARING_PKG_NAME_2
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DOMAIN_1
import com.android.cts.packagemanager.verify.domain.java.DomainUtils.DOMAIN_UNHANDLED
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@EnsureHasWorkProfile(forUser = DeviceState.UserType.PRIMARY_USER)
@RunWith(BedsteadJUnit4::class)
abstract class DomainVerificationWorkProfileTestsBase {
companion object {
@JvmField
@ClassRule
@Rule
val deviceState = DeviceState()
private val TARGET_INTENT = Intent(Intent.ACTION_VIEW, Uri.parse("https://$DOMAIN_1"))
private val BROWSER_INTENT =
Intent(Intent.ACTION_VIEW, Uri.parse("https://$DOMAIN_UNHANDLED"))
@JvmStatic
protected val FORWARD_TO_PARENT =
ComponentName("android", "com.android.internal.app.ForwardIntentToParent")
@JvmStatic
protected val FORWARD_TO_MANAGED =
ComponentName("android", "com.android.internal.app.ForwardIntentToManagedProfile")
@JvmStatic
protected val PERSONAL_APP = DECLARING_PKG_NAME_1
@JvmStatic
protected val WORK_APP = DECLARING_PKG_NAME_2
@JvmStatic
protected val PERSONAL_COMPONENT = DECLARING_PKG_1_COMPONENT
@JvmStatic
protected val WORK_COMPONENT = DECLARING_PKG_2_COMPONENT
@JvmStatic
protected lateinit var personalBrowsers: Collection<ComponentName>
@JvmStatic
protected lateinit var workBrowsers: Collection<ComponentName>
private lateinit var personalUser: UserReference
private lateinit var workUser: UserReference
@JvmStatic
@BeforeClass
fun installApks() {
personalUser = deviceState.primaryUser()
workUser = deviceState.workProfile(DeviceState.UserType.PRIMARY_USER)
personalBrowsers = collectBrowsers(personalUser)
workBrowsers = collectBrowsers(workUser)
TestApis.packages().run {
install(personalUser, Packages.JavaResource.javaResource(DECLARING_PKG_APK_1.value))
install(workUser, Packages.JavaResource.javaResource(DECLARING_PKG_APK_2.value))
}
}
@JvmStatic
@AfterClass
fun uninstallApks() {
TestApis.packages().run {
find(PERSONAL_APP).uninstallFromAllUsers()
find(WORK_APP).uninstallFromAllUsers()
}
}
private fun collectBrowsers(user: UserReference) =
withUserContext(user) { context ->
context.packageManager
.queryIntentActivities(BROWSER_INTENT, PackageManager.MATCH_DEFAULT_ONLY)
.map { it.activityInfo }
.map { ComponentName(it.packageName, it.name) }
.also { assumeTrue(it.isNotEmpty()) }
}
@JvmStatic
protected fun assertResolvesTo(vararg components: ComponentName) =
assertResolvesTo(components.toList())
@JvmStatic
protected fun assertResolvesTo(components: Collection<ComponentName>) {
val results = TestApis.context()
.instrumentedContext()
.packageManager
.queryIntentActivities(TARGET_INTENT, PackageManager.MATCH_DEFAULT_ONLY)
.map { it.activityInfo }
.map { ComponentName(it.packageName, it.name) }
assertThat(results).containsExactlyElementsIn(components)
}
@JvmStatic
protected fun verify(vararg packageNames: String) = packageNames.forEach {
assertWithMessage("pm set-app-links should be empty on success").that(
ShellUtils.runShellCommand(DomainUtils.setAppLinks(it, "STATE_APPROVED", DOMAIN_1))
).isEmpty()
}
}
@Before
@After
fun resetState() {
listOf(personalUser, workUser).forEach {
withUserContext(it) {
SharedVerifications.reset(it, resetEnable = true)
}
}
}
@RequireRunOnPrimaryUser
@Postsubmit(reason = "New test")
@Test
fun inPersonal_unverified() {
assertResolvesTo(personalBrowsers)
}
@RequireRunOnPrimaryUser
@Postsubmit(reason = "New test")
@Test
fun inPersonal_verifiedInCurrentProfile() {
verify(PERSONAL_APP)
assertResolvesTo(PERSONAL_COMPONENT)
}
// The assertion for this method varies based on general versus specific cross profile config
abstract fun inPersonal_verifiedInOtherProfile()
@RequireRunOnPrimaryUser
@Postsubmit(reason = "New test")
@Test
fun inPersonal_verifiedInBothProfiles() {
verify(PERSONAL_APP, WORK_APP)
assertResolvesTo(PERSONAL_COMPONENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_unverified() {
assertResolvesTo(workBrowsers)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInCurrentProfile() {
verify(WORK_APP)
assertResolvesTo(WORK_COMPONENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInOtherProfile() {
verify(PERSONAL_APP)
assertResolvesTo(workBrowsers + FORWARD_TO_PARENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInOtherProfileDisabledApp() {
verify(PERSONAL_APP)
disableApp(personalUser, PERSONAL_APP)
assertResolvesTo(workBrowsers)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInOtherProfileDisabledComponent() {
verify(PERSONAL_APP)
disableComponent(personalUser, PERSONAL_COMPONENT)
assertResolvesTo(workBrowsers)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfiles() {
verify(PERSONAL_APP, WORK_APP)
assertResolvesTo(WORK_COMPONENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfilesDisabledAppInOther() {
verify(PERSONAL_APP, WORK_APP)
disableApp(personalUser, PERSONAL_APP)
assertResolvesTo(WORK_COMPONENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfilesDisabledComponentInOther() {
verify(PERSONAL_APP, WORK_APP)
disableComponent(personalUser, PERSONAL_COMPONENT)
assertResolvesTo(WORK_COMPONENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfilesDisabledAppInCurrent() {
verify(PERSONAL_APP, WORK_APP)
disableApp(workUser, WORK_APP)
assertResolvesTo(workBrowsers + FORWARD_TO_PARENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfilesDisabledComponentInCurrent() {
verify(PERSONAL_APP, WORK_APP)
disableComponent(workUser, WORK_COMPONENT)
assertResolvesTo(workBrowsers + FORWARD_TO_PARENT)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfilesDisabledAppInBoth() {
verify(PERSONAL_APP, WORK_APP)
disableApp(personalUser, PERSONAL_APP)
disableApp(workUser, WORK_APP)
assertResolvesTo(workBrowsers)
}
@RequireRunOnWorkProfile
@Postsubmit(reason = "New test")
@Test
fun inWork_verifiedInBothProfilesDisabledComponentInBoth() {
verify(PERSONAL_APP, WORK_APP)
disableComponent(personalUser, PERSONAL_COMPONENT)
disableComponent(workUser, WORK_COMPONENT)
assertResolvesTo(workBrowsers)
}
private fun disableApp(user: UserReference, packageName: String) {
ShellCommand.builderForUser(user, "pm disable-user")
.addOperand(packageName)
.validate { it.trim().endsWith("new state: disabled-user") }
.execute()
}
private fun disableComponent(user: UserReference, component: ComponentName) {
ShellCommand.builderForUser(user, "pm disable")
.addOperand(component.flattenToString())
.validate { it.trim().endsWith("new state: disabled") }
.execute()
}
}