Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 52ebf585 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

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
parent 59d67c3d
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.settings.spa.app.appinfo
import android.app.settings.SettingsEnums
import android.content.pm.ApplicationInfo
import android.os.UserManager
import androidx.annotation.VisibleForTesting
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Report
import androidx.compose.material3.Text
@@ -87,9 +88,10 @@ class AppForceStopButton(
        dialogPresenter.open()
    }

    private fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when {
    @VisibleForTesting
    fun getAdminRestriction(app: ApplicationInfo): EnforcedAdmin? = when {
        packageManager.isPackageStateProtected(app.packageName, app.userId) -> {
            RestrictedLockUtilsInternal.getDeviceOwner(context)
            RestrictedLockUtilsInternal.getDeviceOwner(context) ?: EnforcedAdmin()
        }

        else -> RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+92 −45
Original line number Diff line number Diff line
@@ -17,79 +17,82 @@
package com.android.settings.spa.app.appinfo

import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.pm.ApplicationInfo
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.onNodeWithText
import androidx.test.core.app.ApplicationProvider
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.model.app.userId
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.Mockito.`when` as whenever
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub

@RunWith(AndroidJUnit4::class)
class AppForceStopButtonTest {
    @get:Rule
    val composeTestRule = createComposeRule()

    @get:Rule
    val mockito: MockitoRule = MockitoJUnit.rule()

    @Spy
    private val context: Context = ApplicationProvider.getApplicationContext()

    @Mock
    private lateinit var packageInfoPresenter: PackageInfoPresenter

    @Mock
    private lateinit var packageManager: PackageManager
    private val mockPackageManager = mock<PackageManager>()

    @Mock
    private lateinit var devicePolicyManager: DevicePolicyManager
    private val mockDevicePolicyManager = mock<DevicePolicyManager>()

    private lateinit var appForceStopButton: AppForceStopButton
    private val mockUserManager = mock<UserManager> {
        on { getUserRestrictionSources(any(), any()) } doReturn emptyList()
    }

    @Before
    fun setUp() {
        whenever(packageInfoPresenter.context).thenReturn(context)
        whenever(context.packageManager).thenReturn(packageManager)
        whenever(context.devicePolicyManager).thenReturn(devicePolicyManager)
        appForceStopButton = AppForceStopButton(packageInfoPresenter)
    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
        on { packageManager } doReturn mockPackageManager
        on { devicePolicyManager } doReturn mockDevicePolicyManager
        on { getSystemService(Context.DEVICE_POLICY_SERVICE) } doReturn mockDevicePolicyManager
        on { getSystemService(Context.USER_SERVICE) } doReturn mockUserManager
    }

    @Test
    fun getActionButton() {
    private val packageInfoPresenter = mock<PackageInfoPresenter> {
        on { context } doReturn context
    }

    private val appForceStopButton = AppForceStopButton(packageInfoPresenter)

    @Test
    fun getActionButton_isActiveAdmin_buttonDisabled() {
        val app = createApp()
        whenever(devicePolicyManager.packageHasActiveAdmins(PACKAGE_NAME, app.userId))
            .thenReturn(true)
        mockDevicePolicyManager.stub {
            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
    fun getActionButton_isUninstallInQueue_buttonDisabled() {
        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
@@ -98,35 +101,79 @@ class AppForceStopButtonTest {
            flags = ApplicationInfo.FLAG_STOPPED
        }

        val actionButton = setForceStopButton(app)
        setForceStopButton(app)

        assertThat(actionButton.enabled).isFalse()
        composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsNotEnabled()
    }

    @Test
    fun getActionButton_regularApp_buttonEnabled() {
        val app = createApp()

        val actionButton = setForceStopButton(app)
        setForceStopButton(app)

        composeTestRule.onNodeWithText(context.getString(R.string.force_stop)).assertIsEnabled()
    }

    @Test
    fun getAdminRestriction_packageNotProtected() {
        mockPackageManager.stub {
            on { isPackageStateProtected(PACKAGE_NAME, UserHandle.getUserId(UID)) } doReturn false
        }

        val admin = appForceStopButton.getAdminRestriction(createApp())

        assertThat(actionButton.enabled).isTrue()
        assertThat(admin).isNull()
    }

    private fun setForceStopButton(app: ApplicationInfo): ActionButton {
        lateinit var actionButton: ActionButton
    @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 {
            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 = {}) =
        ApplicationInfo().apply {
            packageName = PACKAGE_NAME
            uid = UID
            enabled = true
        }.apply(builder)

    private companion object {
        const val PACKAGE_NAME = "package.name"
        const val UID = 10000
        val DEVICE_OWNER = ComponentName("device", "Owner")
    }
}