Fix default mode for AlarmsAndRemindersAppList

When app ops permission's app ops mode is default, should check if
permission is grant.

Fix: 339846642
Test: manual - on AlarmsAndRemindersAppList
Test: unit test
Change-Id: Ia0f05211f5774637304502ead79dd98a1cf89886
This commit is contained in:
Chaohui Wang
2024-05-16 17:15:37 +08:00
parent 7a8d8fd091
commit 83aeb45f3c
3 changed files with 42 additions and 49 deletions

View File

@@ -29,7 +29,7 @@ import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
import com.android.settingslib.R import com.android.settingslib.R
import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle import com.android.settingslib.spa.lifecycle.collectAsCallbackWithLifecycle
import com.android.settingslib.spaprivileged.model.app.AppOps import com.android.settingslib.spaprivileged.model.app.AppOps
import com.android.settingslib.spaprivileged.model.app.AppOpsController import com.android.settingslib.spaprivileged.model.app.AppOpsPermissionController
import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.model.app.PackageManagers import com.android.settingslib.spaprivileged.model.app.PackageManagers
@@ -49,7 +49,7 @@ data class AlarmsAndRemindersAppRecord(
override val app: ApplicationInfo, override val app: ApplicationInfo,
val isTrumped: Boolean, val isTrumped: Boolean,
val isChangeable: Boolean, val isChangeable: Boolean,
var controller: AppOpsController, val controller: AppOpsPermissionController,
) : AppRecord ) : AppRecord
class AlarmsAndRemindersAppListModel( class AlarmsAndRemindersAppListModel(
@@ -84,7 +84,7 @@ class AlarmsAndRemindersAppListModel(
@Composable @Composable
override fun isAllowed(record: AlarmsAndRemindersAppRecord): () -> Boolean? = when { override fun isAllowed(record: AlarmsAndRemindersAppRecord): () -> Boolean? = when {
record.isTrumped -> ({ true }) record.isTrumped -> ({ true })
else -> record.controller.isAllowed.collectAsCallbackWithLifecycle() else -> record.controller.isAllowedFlow.collectAsCallbackWithLifecycle()
} }
override fun isChangeable(record: AlarmsAndRemindersAppRecord) = record.isChangeable override fun isChangeable(record: AlarmsAndRemindersAppRecord) = record.isChangeable
@@ -114,10 +114,11 @@ class AlarmsAndRemindersAppListModel(
app = app, app = app,
isTrumped = isTrumped, isTrumped = isTrumped,
isChangeable = hasRequestPermission && !isTrumped, isChangeable = hasRequestPermission && !isTrumped,
controller = AppOpsController( controller = AppOpsPermissionController(
context = context, context = context,
app = app, app = app,
appOps = APP_OPS, appOps = APP_OPS,
permission = PERMISSION,
), ),
) )
} }

View File

@@ -17,14 +17,13 @@
package com.android.settings.spa.app.specialaccess package com.android.settings.spa.app.specialaccess
import android.Manifest import android.Manifest
import android.app.AppOpsManager
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import androidx.compose.ui.test.junit4.createComposeRule import androidx.compose.ui.test.junit4.createComposeRule
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.testutils.firstWithTimeoutOrNull import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
import com.android.settingslib.spaprivileged.model.app.IAppOpsController import com.android.settingslib.spaprivileged.model.app.IAppOpsPermissionController
import com.android.settingslib.spaprivileged.model.app.IPackageManagers import com.android.settingslib.spaprivileged.model.app.IPackageManagers
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
@@ -117,14 +116,14 @@ class WifiControlAppListModelTest {
app = APP_NOT_REQUEST_PERMISSION, app = APP_NOT_REQUEST_PERMISSION,
hasRequestPermission = false, hasRequestPermission = false,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT), appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val appRequestedNetworkSettingsRecord = val appRequestedNetworkSettingsRecord =
AppOpPermissionRecord( AppOpPermissionRecord(
app = APP_REQUESTED_NETWORK_SETTINGS, app = APP_REQUESTED_NETWORK_SETTINGS,
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT) appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val recordListFlow = val recordListFlow =
@@ -144,7 +143,7 @@ class WifiControlAppListModelTest {
app = APP, app = APP,
hasRequestPermission = false, hasRequestPermission = false,
hasRequestBroaderPermission = true, hasRequestBroaderPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT), appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val isAllowed = getIsAllowed(record) val isAllowed = getIsAllowed(record)
@@ -159,7 +158,7 @@ class WifiControlAppListModelTest {
app = APP, app = APP,
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_ALLOWED), appOpsPermissionController = FakeAppOpsPermissionController(true),
) )
val isAllowed = getIsAllowed(record) val isAllowed = getIsAllowed(record)
@@ -174,7 +173,7 @@ class WifiControlAppListModelTest {
app = APP, app = APP,
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_IGNORED), appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val isAllowed = getIsAllowed(record) val isAllowed = getIsAllowed(record)
@@ -189,7 +188,7 @@ class WifiControlAppListModelTest {
app = APP, app = APP,
hasRequestPermission = false, hasRequestPermission = false,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT), appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val isChangeable = listModel.isChangeable(record) val isChangeable = listModel.isChangeable(record)
@@ -198,13 +197,13 @@ class WifiControlAppListModelTest {
} }
@Test @Test
fun isChangeable_notChangableWhenRequestedNetworkSettingPermissions() { fun isChangeable_notChangeableWhenRequestedNetworkSettingPermissions() {
val record = val record =
AppOpPermissionRecord( AppOpPermissionRecord(
app = APP, app = APP,
hasRequestPermission = false, hasRequestPermission = false,
hasRequestBroaderPermission = true, hasRequestBroaderPermission = true,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT), appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val isChangeable = listModel.isChangeable(record) val isChangeable = listModel.isChangeable(record)
@@ -213,13 +212,13 @@ class WifiControlAppListModelTest {
} }
@Test @Test
fun isChangeable_changableWhenRequestedChangeWifiStatePermission() { fun isChangeable_changeableWhenRequestedChangeWifiStatePermission() {
val record = val record =
AppOpPermissionRecord( AppOpPermissionRecord(
app = APP, app = APP,
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT), appOpsPermissionController = FakeAppOpsPermissionController(false),
) )
val isChangeable = listModel.isChangeable(record) val isChangeable = listModel.isChangeable(record)
@@ -229,18 +228,18 @@ class WifiControlAppListModelTest {
@Test @Test
fun setAllowed_shouldCallController() { fun setAllowed_shouldCallController() {
val appOpsController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT) val appOpsPermissionController = FakeAppOpsPermissionController(false)
val record = val record =
AppOpPermissionRecord( AppOpPermissionRecord(
app = APP, app = APP,
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = appOpsController, appOpsPermissionController = appOpsPermissionController,
) )
listModel.setAllowed(record = record, newAllowed = true) listModel.setAllowed(record = record, newAllowed = true)
assertThat(appOpsController.setAllowedCalledWith).isTrue() assertThat(appOpsPermissionController.setAllowedCalledWith).isTrue()
} }
private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? { private fun getIsAllowed(record: AppOpPermissionRecord): Boolean? {
@@ -266,14 +265,12 @@ class WifiControlAppListModelTest {
} }
} }
private class FakeAppOpsController(private val fakeMode: Int) : IAppOpsController { private class FakeAppOpsPermissionController(allowed: Boolean) : IAppOpsPermissionController {
var setAllowedCalledWith: Boolean? = null var setAllowedCalledWith: Boolean? = null
override val modeFlow = flowOf(fakeMode) override val isAllowedFlow = flowOf(allowed)
override fun setAllowed(allowed: Boolean) { override fun setAllowed(allowed: Boolean) {
setAllowedCalledWith = allowed setAllowedCalledWith = allowed
} }
override fun getMode() = fakeMode
} }

View File

@@ -30,10 +30,10 @@ import com.android.media.flags.Flags
import com.android.settings.R import com.android.settings.R
import com.android.settings.testutils.FakeFeatureFactory import com.android.settings.testutils.FakeFeatureFactory
import com.android.settingslib.spaprivileged.model.app.AppOps import com.android.settingslib.spaprivileged.model.app.AppOps
import com.android.settingslib.spaprivileged.model.app.IAppOpsController import com.android.settingslib.spaprivileged.model.app.IAppOpsPermissionController
import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord import com.android.settingslib.spaprivileged.template.app.AppOpPermissionRecord
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.flowOf
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
@@ -50,7 +50,7 @@ class MediaRoutingControlTest {
@get:Rule @get:Rule
val mockito: MockitoRule = MockitoJUnit.rule() val mockito: MockitoRule = MockitoJUnit.rule()
@get:Rule val setFlagsRule: SetFlagsRule = SetFlagsRule(); @get:Rule val setFlagsRule: SetFlagsRule = SetFlagsRule()
@Spy @Spy
private val context: Context = ApplicationProvider.getApplicationContext() private val context: Context = ApplicationProvider.getApplicationContext()
@@ -86,29 +86,29 @@ class MediaRoutingControlTest {
@Test @Test
fun setAllowed_callWithNewStatusAsTrue_shouldChangeAppControllerModeToAllowed() { fun setAllowed_callWithNewStatusAsTrue_shouldChangeAppControllerModeToAllowed() {
val fakeAppOpController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT) val fakeAppOpsPermissionController = FakeAppOpsPermissionController(false)
val permissionRequestedRecord = val permissionRequestedRecord =
AppOpPermissionRecord( AppOpPermissionRecord(
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = fakeAppOpController, appOpsPermissionController = fakeAppOpsPermissionController,
) )
listModel.setAllowed(permissionRequestedRecord, true) listModel.setAllowed(permissionRequestedRecord, true)
assertThat(fakeAppOpController.getMode()).isEqualTo(AppOpsManager.MODE_ALLOWED) assertThat(fakeAppOpsPermissionController.setAllowedCalledWith).isTrue()
} }
@Test @Test
fun setAllowed_callWithNewStatusAsTrue_shouldLogPermissionToggleActionAsAllowed() { fun setAllowed_callWithNewStatusAsTrue_shouldLogPermissionToggleActionAsAllowed() {
val fakeAppOpController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT) val fakeAppOpsPermissionController = FakeAppOpsPermissionController(false)
val permissionRequestedRecord = val permissionRequestedRecord =
AppOpPermissionRecord( AppOpPermissionRecord(
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = fakeAppOpController, appOpsPermissionController = fakeAppOpsPermissionController,
) )
listModel.setAllowed(permissionRequestedRecord, true) listModel.setAllowed(permissionRequestedRecord, true)
@@ -119,29 +119,29 @@ class MediaRoutingControlTest {
@Test @Test
fun setAllowed_callWithNewStatusAsFalse_shouldChangeAppControllerModeToErrored() { fun setAllowed_callWithNewStatusAsFalse_shouldChangeAppControllerModeToErrored() {
val fakeAppOpController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT) val fakeAppOpsPermissionController = FakeAppOpsPermissionController(false)
val permissionRequestedRecord = val permissionRequestedRecord =
AppOpPermissionRecord( AppOpPermissionRecord(
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = fakeAppOpController, appOpsPermissionController = fakeAppOpsPermissionController,
) )
listModel.setAllowed(permissionRequestedRecord, false) listModel.setAllowed(permissionRequestedRecord, false)
assertThat(fakeAppOpController.getMode()).isEqualTo(AppOpsManager.MODE_ERRORED) assertThat(fakeAppOpsPermissionController.setAllowedCalledWith).isFalse()
} }
@Test @Test
fun setAllowed_callWithNewStatusAsFalse_shouldLogPermissionToggleActionAsDenied() { fun setAllowed_callWithNewStatusAsFalse_shouldLogPermissionToggleActionAsDenied() {
val fakeAppOpController = FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT) val fakeAppOpsPermissionController = FakeAppOpsPermissionController(false)
val permissionRequestedRecord = val permissionRequestedRecord =
AppOpPermissionRecord( AppOpPermissionRecord(
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = fakeAppOpController, appOpsPermissionController = fakeAppOpsPermissionController,
) )
listModel.setAllowed(permissionRequestedRecord, false) listModel.setAllowed(permissionRequestedRecord, false)
@@ -158,8 +158,7 @@ class MediaRoutingControlTest {
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = appOpsPermissionController = FakeAppOpsPermissionController(false),
FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
) )
whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH)) whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH))
.thenReturn(listOf(PACKAGE_NAME)) .thenReturn(listOf(PACKAGE_NAME))
@@ -177,8 +176,7 @@ class MediaRoutingControlTest {
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = false, hasRequestPermission = false,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = appOpsPermissionController = FakeAppOpsPermissionController(false),
FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
) )
whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH)) whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH))
.thenReturn(listOf(PACKAGE_NAME)) .thenReturn(listOf(PACKAGE_NAME))
@@ -196,8 +194,7 @@ class MediaRoutingControlTest {
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = appOpsPermissionController = FakeAppOpsPermissionController(false),
FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
) )
whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH)) whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH))
.thenReturn(listOf("other.package.name")) .thenReturn(listOf("other.package.name"))
@@ -215,8 +212,7 @@ class MediaRoutingControlTest {
app = ApplicationInfo().apply { packageName = PACKAGE_NAME }, app = ApplicationInfo().apply { packageName = PACKAGE_NAME },
hasRequestPermission = true, hasRequestPermission = true,
hasRequestBroaderPermission = false, hasRequestBroaderPermission = false,
appOpsController = appOpsPermissionController = FakeAppOpsPermissionController(false),
FakeAppOpsController(fakeMode = AppOpsManager.MODE_DEFAULT),
) )
whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH)) whenever(mockRoleManager.getRoleHolders(AssociationRequest.DEVICE_PROFILE_WATCH))
.thenReturn(listOf(PACKAGE_NAME)) .thenReturn(listOf(PACKAGE_NAME))
@@ -226,15 +222,14 @@ class MediaRoutingControlTest {
assertThat(isSpecialAccessChangeable).isFalse() assertThat(isSpecialAccessChangeable).isFalse()
} }
private class FakeAppOpsController(fakeMode: Int) : IAppOpsController { private class FakeAppOpsPermissionController(allowed: Boolean) : IAppOpsPermissionController {
var setAllowedCalledWith: Boolean? = null
override val modeFlow = MutableStateFlow(fakeMode) override val isAllowedFlow = flowOf(allowed)
override fun setAllowed(allowed: Boolean) { override fun setAllowed(allowed: Boolean) {
modeFlow.value = if (allowed) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED setAllowedCalledWith = allowed
} }
override fun getMode(): Int = modeFlow.value
} }
companion object { companion object {