summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt63
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt63
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt37
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt26
4 files changed, 90 insertions, 99 deletions
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
index 7bd7fbe0c526..06b3eabfad26 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppList.kt
@@ -16,9 +16,7 @@
package com.android.settingslib.spaprivileged.template.app
-import android.app.AppOpsManager.MODE_ALLOWED
-import android.app.AppOpsManager.MODE_DEFAULT
-import android.app.AppOpsManager.MODE_ERRORED
+import android.app.AppOpsManager
import android.content.Context
import android.content.pm.ApplicationInfo
import androidx.compose.runtime.Composable
@@ -64,7 +62,7 @@ abstract class AppOpPermissionListModel(
*/
open val permissionHasAppOpFlag: Boolean = true
- open val modeForNotAllowed: Int = MODE_ERRORED
+ open val modeForNotAllowed: Int = AppOpsManager.MODE_ERRORED
/**
* Use AppOpsManager#setUidMode() instead of AppOpsManager#setMode() when set allowed.
@@ -130,27 +128,14 @@ abstract class AppOpPermissionListModel(
override fun filter(userIdFlow: Flow<Int>, recordListFlow: Flow<List<AppOpPermissionRecord>>) =
recordListFlow.filterItem(::isChangeable)
- /**
- * Defining the default behavior as permissible as long as the package requested this permission
- * (This means pre-M gets approval during install time; M apps gets approval during runtime).
- */
@Composable
- override fun isAllowed(record: AppOpPermissionRecord): () -> Boolean? {
- if (record.hasRequestBroaderPermission) {
- // Broader permission trumps the specific permission.
- return { true }
- }
-
- val mode = record.appOpsController.mode.observeAsState()
- return {
- when (mode.value) {
- null -> null
- MODE_ALLOWED -> true
- MODE_DEFAULT -> with(packageManagers) { record.app.hasGrantPermission(permission) }
- else -> false
- }
- }
- }
+ override fun isAllowed(record: AppOpPermissionRecord): () -> Boolean? =
+ isAllowed(
+ record = record,
+ appOpsController = record.appOpsController,
+ permission = permission,
+ packageManagers = packageManagers,
+ )
override fun isChangeable(record: AppOpPermissionRecord) =
record.hasRequestPermission &&
@@ -161,3 +146,33 @@ abstract class AppOpPermissionListModel(
record.appOpsController.setAllowed(newAllowed)
}
}
+
+/**
+ * Defining the default behavior as permissible as long as the package requested this permission
+ * (This means pre-M gets approval during install time; M apps gets approval during runtime).
+ */
+@Composable
+internal fun isAllowed(
+ record: AppOpPermissionRecord,
+ appOpsController: IAppOpsController,
+ permission: String,
+ packageManagers: IPackageManagers = PackageManagers,
+): () -> Boolean? {
+ if (record.hasRequestBroaderPermission) {
+ // Broader permission trumps the specific permission.
+ return { true }
+ }
+
+ val mode = appOpsController.mode.observeAsState()
+ return {
+ when (mode.value) {
+ null -> null
+ AppOpsManager.MODE_ALLOWED -> true
+ AppOpsManager.MODE_DEFAULT -> {
+ with(packageManagers) { record.app.hasGrantPermission(permission) }
+ }
+
+ else -> false
+ }
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index 3380b7db4cd0..565543614866 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -16,19 +16,16 @@
package com.android.settingslib.spaprivileged.template.app
-import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.Bundle
import androidx.annotation.VisibleForTesting
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.core.os.bundleOf
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.android.settingslib.spa.framework.common.SettingsEntry
@@ -49,6 +46,8 @@ import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProvid
import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl
import com.android.settingslib.spaprivileged.template.preference.RestrictedSwitchPreference
import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.flowOn
internal class TogglePermissionAppInfoPageProvider(
private val appListTemplate: TogglePermissionAppListTemplate,
@@ -132,7 +131,7 @@ internal fun <T : AppRecord> TogglePermissionAppListModel<T>.TogglePermissionApp
@VisibleForTesting
@Composable
-internal fun TogglePermissionAppListModel<out AppRecord>.TogglePermissionAppInfoPage(
+internal fun <T : AppRecord> TogglePermissionAppListModel<T>.TogglePermissionAppInfoPage(
packageName: String,
userId: Int,
packageManagers: IPackageManagers = PackageManagers,
@@ -145,40 +144,34 @@ internal fun TogglePermissionAppListModel<out AppRecord>.TogglePermissionAppInfo
footerContent = { AnnotatedText(footerResId) },
packageManagers = packageManagers,
) {
- val model = createSwitchModel(checkNotNull(applicationInfo))
+ val app = applicationInfo ?: return@AppInfoPage
+ val record = rememberRecord(app).value ?: return@AppInfoPage
+ val isAllowed = isAllowed(record)
+ val isChangeable by rememberIsChangeable(record)
+ val switchModel = object : SwitchPreferenceModel {
+ override val title = stringResource(switchTitleResId)
+ override val checked = isAllowed
+ override val changeable = { isChangeable }
+ override val onCheckedChange: (Boolean) -> Unit = { setAllowed(record, it) }
+ }
val restrictions = Restrictions(userId, switchRestrictionKeys)
- RestrictedSwitchPreference(model, restrictions, restrictionsProviderFactory)
+ RestrictedSwitchPreference(switchModel, restrictions, restrictionsProviderFactory)
}
}
@Composable
-private fun <T : AppRecord> TogglePermissionAppListModel<T>.createSwitchModel(
- app: ApplicationInfo,
-): TogglePermissionSwitchModel<T> {
- val context = LocalContext.current
- val record = remember(app) { transformItem(app) }
- val isAllowed = isAllowed(record)
- return remember(record) { TogglePermissionSwitchModel(context, this, record, isAllowed) }
- .also { model -> LaunchedEffect(model, Dispatchers.IO) { model.initState() } }
-}
-
-private class TogglePermissionSwitchModel<T : AppRecord>(
- context: Context,
- private val listModel: TogglePermissionAppListModel<T>,
- private val record: T,
- isAllowed: () -> Boolean?,
-) : SwitchPreferenceModel {
- private var appChangeable by mutableStateOf(true)
+private fun <T : AppRecord> TogglePermissionAppListModel<T>.rememberRecord(app: ApplicationInfo) =
+ remember(app) {
+ flow {
+ emit(transformItem(app))
+ }.flowOn(Dispatchers.Default)
+ }.collectAsStateWithLifecycle(initialValue = null)
- override val title: String = context.getString(listModel.switchTitleResId)
- override val checked = isAllowed
- override val changeable = { appChangeable }
- fun initState() {
- appChangeable = listModel.isChangeable(record)
- }
-
- override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
- listModel.setAllowed(record, newChecked)
- }
-}
+@Composable
+private fun <T : AppRecord> TogglePermissionAppListModel<T>.rememberIsChangeable(record: T) =
+ remember(record) {
+ flow {
+ emit(isChangeable(record))
+ }.flowOn(Dispatchers.Default)
+ }.collectAsStateWithLifecycle(initialValue = false)
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
index 3b2fe0f5c16b..d158a2414f85 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppOpPermissionAppListTest.kt
@@ -32,44 +32,37 @@ import com.android.settingslib.spaprivileged.test.R
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
-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
@RunWith(AndroidJUnit4::class)
class AppOpPermissionAppListTest {
- @get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
+ @get:Rule
+ val composeTestRule = createComposeRule()
- @get:Rule val composeTestRule = createComposeRule()
+ private val packageManagers = mock<IPackageManagers>()
- @Spy private val context: Context = ApplicationProvider.getApplicationContext()
+ private val appOpsManager = mock<AppOpsManager>()
- @Mock private lateinit var packageManagers: IPackageManagers
-
- @Mock private lateinit var appOpsManager: AppOpsManager
-
- @Mock private lateinit var packageManager: PackageManager
-
- private lateinit var listModel: TestAppOpPermissionAppListModel
+ private val packageManager = mock<PackageManager> {
+ doNothing().whenever(mock).updatePermissionFlags(any(), any(), any(), any(), any())
+ }
- @Before
- fun setUp() {
- whenever(context.appOpsManager).thenReturn(appOpsManager)
- whenever(context.packageManager).thenReturn(packageManager)
- doNothing().whenever(packageManager)
- .updatePermissionFlags(any(), any(), any(), any(), any())
- listModel = TestAppOpPermissionAppListModel()
+ private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+ on { appOpsManager } doReturn appOpsManager
+ on { packageManager } doReturn packageManager
}
+ private val listModel = TestAppOpPermissionAppListModel()
+
@Test
fun transformItem_recordHasCorrectApp() {
val record = listModel.transformItem(APP)
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt
index 8bfae14b3b8f..270b3faa7ec6 100644
--- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPageTest.kt
@@ -38,44 +38,34 @@ import com.android.settingslib.spaprivileged.tests.testutils.FakeRestrictionsPro
import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListModel
import com.android.settingslib.spaprivileged.tests.testutils.TestTogglePermissionAppListProvider
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.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.mockito.kotlin.whenever
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
@RunWith(AndroidJUnit4::class)
class TogglePermissionAppInfoPageTest {
@get:Rule
val composeTestRule = createComposeRule()
- @get:Rule
- val mockito: MockitoRule = MockitoJUnit.rule()
-
private val context: Context = ApplicationProvider.getApplicationContext()
- @Mock
- private lateinit var packageManagers: IPackageManagers
+ private val packageManagers = mock<IPackageManagers> {
+ on { getPackageInfoAsUser(PACKAGE_NAME, USER_ID) } doReturn PACKAGE_INFO
+ }
private val fakeNavControllerWrapper = FakeNavControllerWrapper()
- private val fakeRestrictionsProvider = FakeRestrictionsProvider()
+ private val fakeRestrictionsProvider = FakeRestrictionsProvider().apply {
+ restrictedMode = NoRestricted
+ }
private val appListTemplate =
TogglePermissionAppListTemplate(listOf(TestTogglePermissionAppListProvider))
private val appInfoPageProvider = TogglePermissionAppInfoPageProvider(appListTemplate)
- @Before
- fun setUp() {
- fakeRestrictionsProvider.restrictedMode = NoRestricted
- whenever(packageManagers.getPackageInfoAsUser(PACKAGE_NAME, USER_ID))
- .thenReturn(PACKAGE_INFO)
- }
-
@Test
fun buildEntry() {
val entryList = appInfoPageProvider.buildEntry(null)