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

Commit 38b7bbad authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Add setModeByUid for AppOpPermissionListModel

Default false, if true, use AppOpsManager#setUidMode instead of #setMode

This follows Change: I261953ff88bc049cf0a2f04f8caac00b8cc6f704
Reason:
Security related app-ops should be set with AppOpsManager#setUidMode
instead of AppOpsManager#setMode.

Bug: 235727273
Test: Unit test
Change-Id: I1e0892fd933945833d7c2f4af7dcb49084fa18f6
parent 384234e2
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ class AppOpsController(
    context: Context,
    private val app: ApplicationInfo,
    private val op: Int,
    private val setModeByUid: Boolean = false,
) : IAppOpsController {
    private val appOpsManager = context.appOpsManager

@@ -49,7 +50,11 @@ class AppOpsController(

    override fun setAllowed(allowed: Boolean) {
        val mode = if (allowed) MODE_ALLOWED else MODE_ERRORED
        if (setModeByUid) {
            appOpsManager.setUidMode(op, app.uid, mode)
        } else {
            appOpsManager.setMode(op, app.uid, app.packageName, mode)
        }
        _mode.postValue(mode)
    }

+16 −2
Original line number Diff line number Diff line
@@ -49,6 +49,13 @@ abstract class AppOpPermissionListModel(
    abstract val appOp: Int
    abstract val permission: String

    /**
     * Use AppOpsManager#setUidMode() instead of AppOpsManager#setMode() when set allowed.
     *
     * Security 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)
@@ -61,7 +68,7 @@ abstract class AppOpPermissionListModel(
                AppOpPermissionRecord(
                    app = app,
                    hasRequestPermission = app.packageName in packageNames,
                    appOpsController = AppOpsController(context = context, app = app, op = appOp),
                    appOpsController = createAppOpsController(app),
                )
            }
        }
@@ -69,7 +76,14 @@ abstract class AppOpPermissionListModel(
    override fun transformItem(app: ApplicationInfo) = AppOpPermissionRecord(
        app = app,
        hasRequestPermission = with(packageManagers) { app.hasRequestPermission(permission) },
        appOpsController = AppOpsController(context = context, app = app, op = appOp),
        appOpsController = createAppOpsController(app),
    )

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

    override fun filter(userIdFlow: Flow<Int>, recordListFlow: Flow<List<AppOpPermissionRecord>>) =
+112 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.settingslib.spaprivileged.model.app

import android.app.AppOpsManager
import android.app.AppOpsManager.MODE_ALLOWED
import android.app.AppOpsManager.MODE_ERRORED
import android.content.Context
import android.content.pm.ApplicationInfo
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.Mockito.verify
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.Mockito.`when` as whenever

@RunWith(AndroidJUnit4::class)
class AppOpsControllerTest {
    @get:Rule
    val mockito: MockitoRule = MockitoJUnit.rule()

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

    @Mock
    private lateinit var appOpsManager: AppOpsManager

    @Before
    fun setUp() {
        whenever(context.appOpsManager).thenReturn(appOpsManager)
    }

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

        controller.setAllowed(true)

        verify(appOpsManager).setMode(OP, APP.uid, APP.packageName, MODE_ALLOWED)
    }

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

        controller.setAllowed(false)

        verify(appOpsManager).setMode(OP, APP.uid, APP.packageName, MODE_ERRORED)
    }

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

        controller.setAllowed(true)

        verify(appOpsManager).setUidMode(OP, APP.uid, MODE_ALLOWED)
    }

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

        controller.setAllowed(false)

        verify(appOpsManager).setUidMode(OP, APP.uid, MODE_ERRORED)
    }

    @Test
    fun getMode() {
        whenever(
            appOpsManager.checkOpNoThrow(OP, APP.uid, APP.packageName)
        ).thenReturn(MODE_ALLOWED)
        val controller = AppOpsController(context = context, app = APP, op = OP)

        val mode = controller.getMode()

        assertThat(mode).isEqualTo(MODE_ALLOWED)
    }

    private companion object {
        const val OP = 1
        val APP = ApplicationInfo().apply {
            packageName = "package.name"
            uid = 123
        }
    }
}
 No newline at end of file
+20 −3
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import androidx.lifecycle.liveData
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.IAppOpsController
import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.test.R
@@ -37,6 +38,8 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Spy
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.Mockito.`when` as whenever
@@ -50,17 +53,20 @@ class AppOpPermissionAppListTest {
    @get:Rule
    val composeTestRule = createComposeRule()

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

    @Mock
    private lateinit var packageManagers: IPackageManagers

    @Mock
    private lateinit var appOpsManager: AppOpsManager

    private lateinit var listModel: TestAppOpPermissionAppListModel

    @Before
    fun setUp() = runTest {
        whenever(packageManagers.getAppOpPermissionPackages(USER_ID, PERMISSION))
            .thenReturn(emptySet())
    fun setUp() {
        whenever(context.appOpsManager).thenReturn(appOpsManager)
        listModel = TestAppOpPermissionAppListModel()
    }

@@ -221,6 +227,16 @@ 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: State<Boolean?>
        composeTestRule.setContent {
@@ -236,6 +252,7 @@ class AppOpPermissionAppListTest {
        override val footerResId = R.string.test_app_op_permission_footer
        override val appOp = AppOpsManager.OP_MANAGE_MEDIA
        override val permission = PERMISSION
        override var setModeByUid = false
    }

    private companion object {