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

Commit d61ea334 authored by Chaohui Wang's avatar Chaohui Wang Committed by Automerger Merge Worker
Browse files

Refactor: Group AppOps related info together am: 5aabbae3

parents 4a1521ad 5aabbae3
Loading
Loading
Loading
Loading
+23 −12
Original line number Diff line number Diff line
@@ -29,36 +29,46 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

interface IAppOpsController {
    val mode: Flow<Int>
    val modeFlow: Flow<Int>
    val isAllowed: Flow<Boolean>
        get() = mode.map { it == MODE_ALLOWED }
        get() = modeFlow.map { it == MODE_ALLOWED }

    fun setAllowed(allowed: Boolean)

    @Mode fun getMode(): Int
}

data class AppOps(
    val op: Int,
    val modeForNotAllowed: Int = MODE_ERRORED,

    /**
     * Use AppOpsManager#setUidMode() instead of AppOpsManager#setMode() when set allowed.
     *
     * Security or privacy related app-ops should be set with setUidMode() instead of setMode().
     */
    val setModeByUid: Boolean = false,
)

class AppOpsController(
    context: Context,
    private val app: ApplicationInfo,
    private val op: Int,
    private val modeForNotAllowed: Int = MODE_ERRORED,
    private val setModeByUid: Boolean = false,
    private val appOps: AppOps,
) : IAppOpsController {
    private val appOpsManager = context.appOpsManager
    private val packageManager = context.packageManager
    override val mode = appOpsManager.opModeFlow(op, app)
    override val modeFlow = appOpsManager.opModeFlow(appOps.op, app)

    override fun setAllowed(allowed: Boolean) {
        val mode = if (allowed) MODE_ALLOWED else modeForNotAllowed
        val mode = if (allowed) MODE_ALLOWED else appOps.modeForNotAllowed

        if (setModeByUid) {
            appOpsManager.setUidMode(op, app.uid, mode)
        if (appOps.setModeByUid) {
            appOpsManager.setUidMode(appOps.op, app.uid, mode)
        } else {
            appOpsManager.setMode(op, app.uid, app.packageName, mode)
            appOpsManager.setMode(appOps.op, app.uid, app.packageName, mode)
        }

        val permission = AppOpsManager.opToPermission(op)
        val permission = AppOpsManager.opToPermission(appOps.op)
        if (permission != null) {
            packageManager.updatePermissionFlags(permission, app.packageName,
                    PackageManager.FLAG_PERMISSION_USER_SET,
@@ -67,5 +77,6 @@ class AppOpsController(
        }
    }

    @Mode override fun getMode(): Int = appOpsManager.getOpMode(op, app)
    @Mode
    override fun getMode(): Int = appOpsManager.getOpMode(appOps.op, app)
}
+5 −19
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import androidx.compose.runtime.Composable
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settingslib.spa.framework.util.asyncMapItem
import com.android.settingslib.spa.framework.util.filterItem
import com.android.settingslib.spaprivileged.model.app.AppOps
import com.android.settingslib.spaprivileged.model.app.AppOpsController
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IAppOpsController
@@ -44,11 +45,11 @@ abstract class AppOpPermissionListModel(
    private val packageManagers: IPackageManagers = PackageManagers,
) : TogglePermissionAppListModel<AppOpPermissionRecord> {

    abstract val appOp: Int
    abstract val appOps: AppOps
    abstract val permission: String

    override val enhancedConfirmationKey: String?
        get() = AppOpsManager.opToPublicName(appOp)
        get() = AppOpsManager.opToPublicName(appOps.op)

    /**
     * When set, specifies the broader permission who trumps the [permission].
@@ -65,27 +66,12 @@ abstract class AppOpPermissionListModel(
     */
    open val permissionHasAppOpFlag: Boolean = true

    open val modeForNotAllowed: Int = AppOpsManager.MODE_ERRORED

    /**
     * Use AppOpsManager#setUidMode() instead of AppOpsManager#setMode() when set allowed.
     *
     * Security or privacy related app-ops should be set with setUidMode() instead of setMode().
     */
    open val setModeByUid = false

    /** These not changeable packages will also be hidden from app list. */
    private val notChangeablePackages =
        setOf("android", "com.android.systemui", context.packageName)

    private fun createAppOpsController(app: ApplicationInfo) =
        AppOpsController(
            context = context,
            app = app,
            op = appOp,
            setModeByUid = setModeByUid,
            modeForNotAllowed = modeForNotAllowed,
        )
        AppOpsController(context, app, appOps)

    private fun createRecord(
        app: ApplicationInfo,
@@ -166,7 +152,7 @@ internal fun isAllowed(
        return { true }
    }

    val mode = appOpsController.mode.collectAsStateWithLifecycle(initialValue = null)
    val mode = appOpsController.modeFlow.collectAsStateWithLifecycle(initialValue = null)
    return {
        when (mode.value) {
            null -> null
+26 −54
Original line number Diff line number Diff line
@@ -27,16 +27,14 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spaprivileged.framework.common.appOpsManager
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.kotlin.any
import org.mockito.kotlin.doNothing
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@@ -44,28 +42,18 @@ import org.mockito.kotlin.whenever
class AppOpsControllerTest {
    @get:Rule val mockito: MockitoRule = MockitoJUnit.rule()

    @Spy private val context: Context = ApplicationProvider.getApplicationContext()
    private val appOpsManager = mock<AppOpsManager>()

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

    @Mock private lateinit var packageManager: PackageManager

    @Before
    fun setUp() {
        whenever(context.appOpsManager).thenReturn(appOpsManager)
        whenever(context.packageManager).thenReturn(packageManager)
        doNothing().whenever(packageManager)
                .updatePermissionFlags(any(), any(), any(), any(), any())
    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
        on { appOpsManager } doReturn appOpsManager
        on { packageManager } doReturn packageManager
    }

    @Test
    fun setAllowed_setToTrue() {
        val controller =
            AppOpsController(
                context = context,
                app = APP,
                op = OP,
            )
        val controller = AppOpsController(context = context, app = APP, appOps = AppOps(OP))

        controller.setAllowed(true)

@@ -74,12 +62,7 @@ class AppOpsControllerTest {

    @Test
    fun setAllowed_setToFalse() {
        val controller =
            AppOpsController(
                context = context,
                app = APP,
                op = OP,
            )
        val controller = AppOpsController(context = context, app = APP, appOps = AppOps(OP))

        controller.setAllowed(false)

@@ -88,12 +71,10 @@ class AppOpsControllerTest {

    @Test
    fun setAllowed_setToFalseWithModeForNotAllowed() {
        val controller =
            AppOpsController(
        val controller = AppOpsController(
            context = context,
            app = APP,
                op = OP,
                modeForNotAllowed = MODE_IGNORED,
            appOps = AppOps(op = OP, modeForNotAllowed = MODE_IGNORED),
        )

        controller.setAllowed(false)
@@ -103,12 +84,10 @@ class AppOpsControllerTest {

    @Test
    fun setAllowed_setToTrueByUid() {
        val controller =
            AppOpsController(
        val controller = AppOpsController(
            context = context,
            app = APP,
                op = OP,
                setModeByUid = true,
            appOps = AppOps(op = OP, setModeByUid = true),
        )

        controller.setAllowed(true)
@@ -118,12 +97,10 @@ class AppOpsControllerTest {

    @Test
    fun setAllowed_setToFalseByUid() {
        val controller =
            AppOpsController(
        val controller = AppOpsController(
            context = context,
            app = APP,
                op = OP,
                setModeByUid = true,
            appOps = AppOps(op = OP, setModeByUid = true),
        )

        controller.setAllowed(false)
@@ -135,12 +112,7 @@ class AppOpsControllerTest {
    fun getMode() {
        whenever(appOpsManager.checkOpNoThrow(OP, APP.uid, APP.packageName))
            .thenReturn(MODE_ALLOWED)
        val controller =
            AppOpsController(
                context = context,
                app = APP,
                op = OP,
            )
        val controller = AppOpsController(context = context, app = APP, appOps = AppOps(OP))

        val mode = controller.getMode()

+3 −15
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
import com.android.settingslib.spaprivileged.framework.common.appOpsManager
import com.android.settingslib.spaprivileged.model.app.AppOps
import com.android.settingslib.spaprivileged.model.app.IAppOpsController
import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.test.R
@@ -39,7 +40,6 @@ import org.mockito.kotlin.doNothing
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

@RunWith(AndroidJUnit4::class)
@@ -287,16 +287,6 @@ class AppOpPermissionAppListTest {
        assertThat(appOpsController.setAllowedCalledWith).isTrue()
    }

    @Test
    fun setAllowed_setModeByUid() {
        listModel.setModeByUid = true
        val record = listModel.transformItem(APP)

        listModel.setAllowed(record = record, newAllowed = true)

        verify(appOpsManager).setUidMode(listModel.appOp, APP.uid, AppOpsManager.MODE_ALLOWED)
    }

    private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? {
        lateinit var isAllowedState: () -> Boolean?
        composeTestRule.setContent { isAllowedState = listModel.isAllowed(record) }
@@ -309,11 +299,9 @@ class AppOpPermissionAppListTest {
        override val switchTitleResId = R.string.test_app_op_permission_switch_title
        override val footerResId = R.string.test_app_op_permission_footer

        override val appOp = AppOpsManager.OP_MANAGE_MEDIA
        override val appOps = AppOps(AppOpsManager.OP_MANAGE_MEDIA)
        override val permission = PERMISSION
        override var broaderPermission: String? = null

        override var setModeByUid = false
    }

    private companion object {
@@ -329,7 +317,7 @@ class AppOpPermissionAppListTest {
private class FakeAppOpsController(private val fakeMode: Int) : IAppOpsController {
    var setAllowedCalledWith: Boolean? = null

    override val mode = flowOf(fakeMode)
    override val modeFlow = flowOf(fakeMode)

    override fun setAllowed(allowed: Boolean) {
        setAllowedCalledWith = allowed