Show policy transparent of "Force stop" when no DO

PackageManager.isPackageStateProtected() is moving to permission based,
so force stop button can also be protected when no DeviceOwner.

The ActivityManger side has already handled correctly, no Settings UI
side need to show a device policy transparent dialog.

Fix: 319579347
Test: manual - Force stop on AppInfo
Test: unit test
Change-Id: I4432dcb798a0cfcbb6bfc8b30c9191dd91b980a2
This commit is contained in:
Chaohui Wang
2024-01-11 17:02:55 +08:00
parent 59d67c3dc2
commit 52ebf58566
2 changed files with 98 additions and 49 deletions

View File

@@ -19,6 +19,7 @@ package com.android.settings.spa.app.appinfo
import android.app.settings.SettingsEnums import android.app.settings.SettingsEnums
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.os.UserManager import android.os.UserManager
import androidx.annotation.VisibleForTesting
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Report import androidx.compose.material.icons.outlined.Report
import androidx.compose.material3.Text import androidx.compose.material3.Text
@@ -87,9 +88,10 @@ class AppForceStopButton(
dialogPresenter.open() dialogPresenter.open()
} }
private fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when { @VisibleForTesting
fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when {
packageManager.isPackageStateProtected(app.packageName, app.userId) -> { packageManager.isPackageStateProtected(app.packageName, app.userId) -> {
RestrictedLockUtilsInternal.getDeviceOwner(context) RestrictedLockUtilsInternal.getDeviceOwner(context) ?: EnforcedAdmin()
} }
else -> RestrictedLockUtilsInternal.checkIfRestrictionEnforced( else -> RestrictedLockUtilsInternal.checkIfRestrictionEnforced(

View File

@@ -17,79 +17,82 @@
package com.android.settings.spa.app.appinfo package com.android.settings.spa.app.appinfo
import android.app.admin.DevicePolicyManager import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.UserHandle
import android.os.UserManager
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.assertIsNotEnabled
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onNodeWithText
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.widget.button.ActionButton import com.android.settings.R
import com.android.settingslib.spa.testutils.delay
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
import com.android.settingslib.spaprivileged.model.app.userId import com.android.settingslib.spaprivileged.model.app.userId
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.Mock import org.mockito.kotlin.any
import org.mockito.Spy import org.mockito.kotlin.doReturn
import org.mockito.junit.MockitoJUnit import org.mockito.kotlin.mock
import org.mockito.junit.MockitoRule import org.mockito.kotlin.spy
import org.mockito.Mockito.`when` as whenever import org.mockito.kotlin.stub
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
class AppForceStopButtonTest { class AppForceStopButtonTest {
@get:Rule @get:Rule
val composeTestRule = createComposeRule() val composeTestRule = createComposeRule()
@get:Rule private val mockPackageManager = mock<PackageManager>()
val mockito: MockitoRule = MockitoJUnit.rule()
@Spy private val mockDevicePolicyManager = mock<DevicePolicyManager>()
private val context: Context = ApplicationProvider.getApplicationContext()
@Mock private val mockUserManager = mock<UserManager> {
private lateinit var packageInfoPresenter: PackageInfoPresenter on { getUserRestrictionSources(any(), any()) } doReturn emptyList()
@Mock
private lateinit var packageManager: PackageManager
@Mock
private lateinit var devicePolicyManager: DevicePolicyManager
private lateinit var appForceStopButton: AppForceStopButton
@Before
fun setUp() {
whenever(packageInfoPresenter.context).thenReturn(context)
whenever(context.packageManager).thenReturn(packageManager)
whenever(context.devicePolicyManager).thenReturn(devicePolicyManager)
appForceStopButton = AppForceStopButton(packageInfoPresenter)
} }
@Test private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
fun getActionButton() { on { packageManager } doReturn mockPackageManager
on { devicePolicyManager } doReturn mockDevicePolicyManager
on { getSystemService(Context.DEVICE_POLICY_SERVICE) } doReturn mockDevicePolicyManager
on { getSystemService(Context.USER_SERVICE) } doReturn mockUserManager
} }
private val packageInfoPresenter = mock<PackageInfoPresenter> {
on { context } doReturn context
}
private val appForceStopButton = AppForceStopButton(packageInfoPresenter)
@Test @Test
fun getActionButton_isActiveAdmin_buttonDisabled() { fun getActionButton_isActiveAdmin_buttonDisabled() {
val app = createApp() val app = createApp()
whenever(devicePolicyManager.packageHasActiveAdmins(PACKAGE_NAME, app.userId)) mockDevicePolicyManager.stub {
.thenReturn(true) on { packageHasActiveAdmins(PACKAGE_NAME, app.userId) } doReturn true
}
val actionButton = setForceStopButton(app) setForceStopButton(app)
assertThat(actionButton.enabled).isFalse() composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
} }
@Test @Test
fun getActionButton_isUninstallInQueue_buttonDisabled() { fun getActionButton_isUninstallInQueue_buttonDisabled() {
val app = createApp() val app = createApp()
whenever(devicePolicyManager.isUninstallInQueue(PACKAGE_NAME)).thenReturn(true) mockDevicePolicyManager.stub {
on { isUninstallInQueue(PACKAGE_NAME) } doReturn true
}
val actionButton = setForceStopButton(app) setForceStopButton(app)
assertThat(actionButton.enabled).isFalse() composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
} }
@Test @Test
@@ -98,35 +101,79 @@ class AppForceStopButtonTest {
flags = ApplicationInfo.FLAG_STOPPED flags = ApplicationInfo.FLAG_STOPPED
} }
val actionButton = setForceStopButton(app) setForceStopButton(app)
assertThat(actionButton.enabled).isFalse() composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
} }
@Test @Test
fun getActionButton_regularApp_buttonEnabled() { fun getActionButton_regularApp_buttonEnabled() {
val app = createApp() val app = createApp()
val actionButton = setForceStopButton(app) setForceStopButton(app)
assertThat(actionButton.enabled).isTrue() composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsEnabled()
} }
private fun setForceStopButton(app: ApplicationInfo): ActionButton { @Test
lateinit var actionButton: ActionButton fun getAdminRestriction_packageNotProtected() {
mockPackageManager.stub {
on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn false
}
val admin = appForceStopButton.getAdminRestriction(createApp())
assertThat(admin).isNull()
}
@Test
fun getAdminRestriction_packageProtectedAndHaveOwner() {
mockPackageManager.stub {
on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn true
}
mockDevicePolicyManager.stub {
on { deviceOwnerComponentOnAnyUser } doReturn DEVICE_OWNER
}
val admin = appForceStopButton.getAdminRestriction(createApp())!!
assertThat(admin.component).isEqualTo(DEVICE_OWNER)
}
@Test
fun getAdminRestriction_packageProtectedAndNotHaveOwner() {
mockPackageManager.stub {
on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn true
}
mockDevicePolicyManager.stub {
on { deviceOwnerComponentOnAnyUser } doReturn null
}
val admin = appForceStopButton.getAdminRestriction(createApp())!!
assertThat(admin.component).isNull()
}
private fun setForceStopButton(app: ApplicationInfo) {
composeTestRule.setContent { composeTestRule.setContent {
actionButton = appForceStopButton.getActionButton(app) val actionButton = appForceStopButton.getActionButton(app)
Button(onClick = {}, enabled = actionButton.enabled) {
Text(actionButton.text)
} }
return actionButton }
composeTestRule.delay()
} }
private fun createApp(builder: ApplicationInfo.() -> Unit = {}) = private fun createApp(builder: ApplicationInfo.() -> Unit = {}) =
ApplicationInfo().apply { ApplicationInfo().apply {
packageName = PACKAGE_NAME packageName = PACKAGE_NAME
uid = UID
enabled = true enabled = true
}.apply(builder) }.apply(builder)
private companion object { private companion object {
const val PACKAGE_NAME = "package.name" const val PACKAGE_NAME = "package.name"
const val UID = 10000
val DEVICE_OWNER = ComponentName("device", "Owner")
} }
} }