Loading packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt +16 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.os.UserHandle import android.os.UserManager import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settingslib.RestrictedLockUtils import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin Loading @@ -32,15 +34,15 @@ import kotlinx.coroutines.flow.flowOn import com.android.settingslib.widget.restricted.R data class Restrictions( val userId: Int, val userId: Int = UserHandle.myUserId(), val keys: List<String>, ) sealed interface RestrictedMode object NoRestricted : RestrictedMode data object NoRestricted : RestrictedMode object BaseUserRestricted : RestrictedMode data object BaseUserRestricted : RestrictedMode interface BlockedByAdmin : RestrictedMode { fun getSummary(checked: Boolean?): String Loading Loading @@ -79,6 +81,17 @@ interface RestrictionsProvider { typealias RestrictionsProviderFactory = (Context, Restrictions) -> RestrictionsProvider @Composable internal fun RestrictionsProviderFactory.rememberRestrictedMode( restrictions: Restrictions, ): State<RestrictedMode?> { val context = LocalContext.current val restrictionsProvider = remember(restrictions) { this(context, restrictions) } return restrictionsProvider.restrictedModeState() } internal class RestrictionsProviderImpl( private val context: Context, private val restrictions: Restrictions, Loading packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt +4 −4 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.settingslib.spaprivileged.model.app.userId import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode import com.android.settingslib.spaprivileged.template.preference.RestrictedSwitchPreference import kotlinx.coroutines.flow.Flow Loading Loading @@ -149,14 +150,13 @@ internal class TogglePermissionInternalAppListModel<T : AppRecord>( @Composable fun getSummary(record: T): State<String> { val restrictionsProvider = remember(record.app.userId) { val restrictions = Restrictions( val restrictions = remember(record.app.userId) { Restrictions( userId = record.app.userId, keys = listModel.switchRestrictionKeys, ) restrictionsProviderFactory(context, restrictions) } val restrictedMode = restrictionsProvider.restrictedModeState() val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions) val allowed = listModel.isAllowed(record) return remember { derivedStateOf { Loading packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedPreference.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.template.preference import androidx.annotation.VisibleForTesting import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import com.android.settingslib.spa.framework.compose.stateOf import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode @Composable fun RestrictedPreference( model: PreferenceModel, restrictions: Restrictions, ) { RestrictedPreference(model, restrictions, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun RestrictedPreference( model: PreferenceModel, restrictions: Restrictions, restrictionsProviderFactory: RestrictionsProviderFactory, ) { if (restrictions.keys.isEmpty()) { Preference(model) return } val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value val restrictedSwitchModel = remember(restrictedMode) { RestrictedPreferenceModel(model, restrictedMode) } restrictedSwitchModel.RestrictionWrapper { Preference(restrictedSwitchModel) } } private class RestrictedPreferenceModel( model: PreferenceModel, private val restrictedMode: RestrictedMode?, ) : PreferenceModel { override val title = model.title override val summary = model.summary override val icon = model.icon override val enabled = when (restrictedMode) { NoRestricted -> model.enabled else -> stateOf(false) } override val onClick = when (restrictedMode) { NoRestricted -> model.onClick // Need to passthrough onClick for clickable semantics, although since enabled is false so // this will not be called. BaseUserRestricted -> model.onClick else -> null } @Composable fun RestrictionWrapper(content: @Composable () -> Unit) { if (restrictedMode !is BlockedByAdmin) { content() return } Box( Modifier .clickable( role = Role.Button, onClick = { restrictedMode.sendShowAdminSupportDetailsIntent() }, ) ) { content() } } } packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt +15 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.settingslib.spaprivileged.template.preference import android.content.Context import androidx.annotation.VisibleForTesting import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable Loading @@ -40,22 +41,29 @@ import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode @Composable fun RestrictedSwitchPreference( model: SwitchPreferenceModel, restrictions: Restrictions, restrictionsProviderFactory: RestrictionsProviderFactory = ::RestrictionsProviderImpl, ) { RestrictedSwitchPreference(model, restrictions, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun RestrictedSwitchPreference( model: SwitchPreferenceModel, restrictions: Restrictions, restrictionsProviderFactory: RestrictionsProviderFactory, ) { if (restrictions.keys.isEmpty()) { SwitchPreference(model) return } val context = LocalContext.current val restrictionsProvider = remember(restrictions) { restrictionsProviderFactory(context, restrictions) } val restrictedMode = restrictionsProvider.restrictedModeState().value val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value val restrictedSwitchModel = remember(restrictedMode) { RestrictedSwitchPreferenceModel(context, model, restrictedMode) } Loading Loading @@ -112,8 +120,8 @@ private class RestrictedSwitchPreferenceModel( override val onCheckedChange = when (restrictedMode) { null -> null is NoRestricted -> model.onCheckedChange // Need to pass a non null onCheckedChange to enable semantics ToggleableState, although // since changeable is false this will not be called. // Need to passthrough onCheckedChange for toggleable semantics, although since changeable // is false so this will not be called. is BaseUserRestricted -> model.onCheckedChange // Pass null since semantics ToggleableState is provided in RestrictionWrapper. is BlockedByAdmin -> null Loading packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt +5 −8 Original line number Diff line number Diff line Loading @@ -16,15 +16,15 @@ package com.android.settingslib.spaprivileged.template.scaffold import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import com.android.settingslib.spa.widget.scaffold.MoreOptionsScope import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode @Composable fun MoreOptionsScope.RestrictedMenuItem( Loading @@ -35,6 +35,7 @@ fun MoreOptionsScope.RestrictedMenuItem( RestrictedMenuItemImpl(text, restrictions, onClick, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun MoreOptionsScope.RestrictedMenuItemImpl( text: String, Loading @@ -42,12 +43,8 @@ internal fun MoreOptionsScope.RestrictedMenuItemImpl( onClick: () -> Unit, restrictionsProviderFactory: RestrictionsProviderFactory, ) { val context = LocalContext.current val restrictionsProvider = remember(restrictions) { restrictionsProviderFactory(context, restrictions) } val restrictedMode = restrictionsProvider.restrictedModeState().value MenuItem(text = text, enabled = restrictedMode !is BaseUserRestricted) { val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value MenuItem(text = text, enabled = restrictedMode !== BaseUserRestricted) { when (restrictedMode) { is BlockedByAdmin -> restrictedMode.sendShowAdminSupportDetailsIntent() else -> onClick() Loading Loading
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/enterprise/RestrictionsProvider.kt +16 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,8 @@ import android.os.UserHandle import android.os.UserManager import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.settingslib.RestrictedLockUtils import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin Loading @@ -32,15 +34,15 @@ import kotlinx.coroutines.flow.flowOn import com.android.settingslib.widget.restricted.R data class Restrictions( val userId: Int, val userId: Int = UserHandle.myUserId(), val keys: List<String>, ) sealed interface RestrictedMode object NoRestricted : RestrictedMode data object NoRestricted : RestrictedMode object BaseUserRestricted : RestrictedMode data object BaseUserRestricted : RestrictedMode interface BlockedByAdmin : RestrictedMode { fun getSummary(checked: Boolean?): String Loading Loading @@ -79,6 +81,17 @@ interface RestrictionsProvider { typealias RestrictionsProviderFactory = (Context, Restrictions) -> RestrictionsProvider @Composable internal fun RestrictionsProviderFactory.rememberRestrictedMode( restrictions: Restrictions, ): State<RestrictedMode?> { val context = LocalContext.current val restrictionsProvider = remember(restrictions) { this(context, restrictions) } return restrictionsProvider.restrictedModeState() } internal class RestrictionsProviderImpl( private val context: Context, private val restrictions: Restrictions, Loading
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt +4 −4 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.settingslib.spaprivileged.model.app.userId import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode import com.android.settingslib.spaprivileged.template.preference.RestrictedSwitchPreference import kotlinx.coroutines.flow.Flow Loading Loading @@ -149,14 +150,13 @@ internal class TogglePermissionInternalAppListModel<T : AppRecord>( @Composable fun getSummary(record: T): State<String> { val restrictionsProvider = remember(record.app.userId) { val restrictions = Restrictions( val restrictions = remember(record.app.userId) { Restrictions( userId = record.app.userId, keys = listModel.switchRestrictionKeys, ) restrictionsProviderFactory(context, restrictions) } val restrictedMode = restrictionsProvider.restrictedModeState() val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions) val allowed = listModel.isAllowed(record) return remember { derivedStateOf { Loading
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedPreference.kt 0 → 100644 +101 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.template.preference import androidx.annotation.VisibleForTesting import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import com.android.settingslib.spa.framework.compose.stateOf import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin import com.android.settingslib.spaprivileged.model.enterprise.NoRestricted import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode @Composable fun RestrictedPreference( model: PreferenceModel, restrictions: Restrictions, ) { RestrictedPreference(model, restrictions, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun RestrictedPreference( model: PreferenceModel, restrictions: Restrictions, restrictionsProviderFactory: RestrictionsProviderFactory, ) { if (restrictions.keys.isEmpty()) { Preference(model) return } val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value val restrictedSwitchModel = remember(restrictedMode) { RestrictedPreferenceModel(model, restrictedMode) } restrictedSwitchModel.RestrictionWrapper { Preference(restrictedSwitchModel) } } private class RestrictedPreferenceModel( model: PreferenceModel, private val restrictedMode: RestrictedMode?, ) : PreferenceModel { override val title = model.title override val summary = model.summary override val icon = model.icon override val enabled = when (restrictedMode) { NoRestricted -> model.enabled else -> stateOf(false) } override val onClick = when (restrictedMode) { NoRestricted -> model.onClick // Need to passthrough onClick for clickable semantics, although since enabled is false so // this will not be called. BaseUserRestricted -> model.onClick else -> null } @Composable fun RestrictionWrapper(content: @Composable () -> Unit) { if (restrictedMode !is BlockedByAdmin) { content() return } Box( Modifier .clickable( role = Role.Button, onClick = { restrictedMode.sendShowAdminSupportDetailsIntent() }, ) ) { content() } } }
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/preference/RestrictedSwitchPreference.kt +15 −7 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.settingslib.spaprivileged.template.preference import android.content.Context import androidx.annotation.VisibleForTesting import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.runtime.Composable Loading @@ -40,22 +41,29 @@ import com.android.settingslib.spaprivileged.model.enterprise.RestrictedMode import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode @Composable fun RestrictedSwitchPreference( model: SwitchPreferenceModel, restrictions: Restrictions, restrictionsProviderFactory: RestrictionsProviderFactory = ::RestrictionsProviderImpl, ) { RestrictedSwitchPreference(model, restrictions, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun RestrictedSwitchPreference( model: SwitchPreferenceModel, restrictions: Restrictions, restrictionsProviderFactory: RestrictionsProviderFactory, ) { if (restrictions.keys.isEmpty()) { SwitchPreference(model) return } val context = LocalContext.current val restrictionsProvider = remember(restrictions) { restrictionsProviderFactory(context, restrictions) } val restrictedMode = restrictionsProvider.restrictedModeState().value val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value val restrictedSwitchModel = remember(restrictedMode) { RestrictedSwitchPreferenceModel(context, model, restrictedMode) } Loading Loading @@ -112,8 +120,8 @@ private class RestrictedSwitchPreferenceModel( override val onCheckedChange = when (restrictedMode) { null -> null is NoRestricted -> model.onCheckedChange // Need to pass a non null onCheckedChange to enable semantics ToggleableState, although // since changeable is false this will not be called. // Need to passthrough onCheckedChange for toggleable semantics, although since changeable // is false so this will not be called. is BaseUserRestricted -> model.onCheckedChange // Pass null since semantics ToggleableState is provided in RestrictionWrapper. is BlockedByAdmin -> null Loading
packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/scaffold/RestrictedMenuItem.kt +5 −8 Original line number Diff line number Diff line Loading @@ -16,15 +16,15 @@ package com.android.settingslib.spaprivileged.template.scaffold import androidx.annotation.VisibleForTesting import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import com.android.settingslib.spa.widget.scaffold.MoreOptionsScope import com.android.settingslib.spaprivileged.model.enterprise.BaseUserRestricted import com.android.settingslib.spaprivileged.model.enterprise.BlockedByAdmin import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderFactory import com.android.settingslib.spaprivileged.model.enterprise.RestrictionsProviderImpl import com.android.settingslib.spaprivileged.model.enterprise.rememberRestrictedMode @Composable fun MoreOptionsScope.RestrictedMenuItem( Loading @@ -35,6 +35,7 @@ fun MoreOptionsScope.RestrictedMenuItem( RestrictedMenuItemImpl(text, restrictions, onClick, ::RestrictionsProviderImpl) } @VisibleForTesting @Composable internal fun MoreOptionsScope.RestrictedMenuItemImpl( text: String, Loading @@ -42,12 +43,8 @@ internal fun MoreOptionsScope.RestrictedMenuItemImpl( onClick: () -> Unit, restrictionsProviderFactory: RestrictionsProviderFactory, ) { val context = LocalContext.current val restrictionsProvider = remember(restrictions) { restrictionsProviderFactory(context, restrictions) } val restrictedMode = restrictionsProvider.restrictedModeState().value MenuItem(text = text, enabled = restrictedMode !is BaseUserRestricted) { val restrictedMode = restrictionsProviderFactory.rememberRestrictedMode(restrictions).value MenuItem(text = text, enabled = restrictedMode !== BaseUserRestricted) { when (restrictedMode) { is BlockedByAdmin -> restrictedMode.sendShowAdminSupportDetailsIntent() else -> onClick() Loading