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
This commit is contained in:
@@ -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
|
||||
appOpsManager.setMode(op, app.uid, app.packageName, mode)
|
||||
if (setModeByUid) {
|
||||
appOpsManager.setUidMode(op, app.uid, mode)
|
||||
} else {
|
||||
appOpsManager.setMode(op, app.uid, app.packageName, mode)
|
||||
}
|
||||
_mode.postValue(mode)
|
||||
}
|
||||
|
||||
|
||||
@@ -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>>) =
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user