diff --git a/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt b/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt index 7792da0..80cf791 100644 --- a/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt +++ b/app/src/main/java/com/bintianqi/owndroid/MainActivity.kt @@ -526,15 +526,14 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) { } composable { - UserRestrictionScreen(::navigateUp) { - navigate(it) - } + UserRestrictionScreen(vm::getUserRestrictions, ::navigateUp, ::navigate) } composable { - UserRestrictionEditorScreen(::navigateUp) + UserRestrictionEditorScreen(vm.userRestrictions, vm::setUserRestriction, ::navigateUp) } composable(mapOf(serializableNavTypePair>())) { - UserRestrictionOptionsScreen(it.toRoute(), ::navigateUp) + UserRestrictionOptionsScreen(it.toRoute(), vm.userRestrictions, + vm::setUserRestriction, ::navigateUp) } composable { UsersScreen(::navigateUp, ::navigate) } diff --git a/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt b/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt index 782dcea..c3db43e 100644 --- a/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt +++ b/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt @@ -996,6 +996,25 @@ class MyViewModel(application: Application): AndroidViewModel(application) { DPM.transferOwnership(DAR, component, null) Privilege.updateStatus() } + val userRestrictions = MutableStateFlow(emptyMap()) + @RequiresApi(24) + fun getUserRestrictions() { + val bundle = DPM.getUserRestrictions(DAR) + userRestrictions.value = bundle.keySet().associateWith { bundle.getBoolean(it) } + } + fun setUserRestriction(name: String, state: Boolean): Boolean { + return try { + if (state) { + DPM.addUserRestriction(DAR, name) + } else { + DPM.clearUserRestriction(DAR, name) + } + userRestrictions.update { it.plus(name to state) } + true + } catch (_: SecurityException) { + false + } + } } data class ThemeSettings( diff --git a/app/src/main/java/com/bintianqi/owndroid/Privilege.kt b/app/src/main/java/com/bintianqi/owndroid/Privilege.kt index 6ba405b..190f05a 100644 --- a/app/src/main/java/com/bintianqi/owndroid/Privilege.kt +++ b/app/src/main/java/com/bintianqi/owndroid/Privilege.kt @@ -24,6 +24,7 @@ object Privilege { if (dhizukuDpm != null) { DPM = dhizukuDpm DAR = Dhizuku.getOwnerComponent() + updateStatus() return } } diff --git a/app/src/main/java/com/bintianqi/owndroid/UserRestrictionsRepository.kt b/app/src/main/java/com/bintianqi/owndroid/UserRestrictionsRepository.kt new file mode 100644 index 0000000..7caee10 --- /dev/null +++ b/app/src/main/java/com/bintianqi/owndroid/UserRestrictionsRepository.kt @@ -0,0 +1,110 @@ +package com.bintianqi.owndroid + +import android.os.Build +import android.os.UserManager +import com.bintianqi.owndroid.dpm.Restriction + +@Suppress("InlinedApi") +object UserRestrictionsRepository { + val network = listOf( + Restriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, R.string.config_mobile_network, R.drawable.signal_cellular_alt_fill0), + Restriction(UserManager.DISALLOW_CONFIG_WIFI, R.string.config_wifi, R.drawable.wifi_fill0), + Restriction(UserManager.DISALLOW_DATA_ROAMING, R.string.data_roaming, R.drawable.network_cell_fill0, 24), + Restriction(UserManager.DISALLOW_CELLULAR_2G, R.string.cellular_2g, R.drawable.network_cell_fill0, 34), + Restriction(UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO, R.string.ultra_wideband_radio, R.drawable.wifi_tethering_fill0, 34), + Restriction(UserManager.DISALLOW_ADD_WIFI_CONFIG, R.string.add_wifi_conf, R.drawable.wifi_fill0, 33), + Restriction(UserManager.DISALLOW_CHANGE_WIFI_STATE, R.string.change_wifi_state, R.drawable.wifi_fill0, 33), + Restriction(UserManager.DISALLOW_WIFI_DIRECT, R.string.wifi_direct, R.drawable.wifi_tethering_fill0), + Restriction(UserManager.DISALLOW_WIFI_TETHERING, R.string.wifi_tethering, R.drawable.wifi_tethering_fill0, 33), + Restriction(UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, R.string.share_admin_wifi, R.drawable.share_fill0, 33), + Restriction(UserManager.DISALLOW_NETWORK_RESET, R.string.network_reset, R.drawable.reset_wrench_fill0, 23), + Restriction(UserManager.DISALLOW_CONFIG_TETHERING, R.string.config_tethering, R.drawable.wifi_tethering_fill0), + Restriction(UserManager.DISALLOW_CONFIG_VPN, R.string.config_vpn, R.drawable.vpn_key_fill0), + Restriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS, R.string.config_private_dns, R.drawable.dns_fill0, 29), + Restriction(UserManager.DISALLOW_AIRPLANE_MODE, R.string.airplane_mode, R.drawable.airplanemode_active_fill0, 28), + Restriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, R.string.config_cell_broadcasts, R.drawable.cell_tower_fill0), + Restriction(UserManager.DISALLOW_SMS, R.string.sms, R.drawable.sms_fill0), + Restriction(UserManager.DISALLOW_OUTGOING_CALLS, R.string.outgoing_calls, R.drawable.phone_forwarded_fill0), + Restriction(UserManager.DISALLOW_SIM_GLOBALLY, R.string.download_esim, R.drawable.sim_card_download_fill0), + Restriction(UserManager.DISALLOW_THREAD_NETWORK, R.string.thread_network, R.drawable.router_fill0, 36) + ) + val connectivity = listOf( + Restriction(UserManager.DISALLOW_BLUETOOTH, R.string.bluetooth, R.drawable.bluetooth_fill0, 26), + Restriction(UserManager.DISALLOW_BLUETOOTH_SHARING, R.string.bt_share, R.drawable.bluetooth_searching_fill0, 26), + Restriction(UserManager.DISALLOW_SHARE_LOCATION, R.string.share_location, R.drawable.location_on_fill0), + Restriction(UserManager.DISALLOW_CONFIG_LOCATION, R.string.config_location, R.drawable.location_on_fill0, 28), + Restriction(UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO, R.string.nfc, R.drawable.nfc_fill0, 35), + Restriction(UserManager.DISALLOW_OUTGOING_BEAM, R.string.outgoing_beam, R.drawable.nfc_fill0, 22), + Restriction(UserManager.DISALLOW_USB_FILE_TRANSFER, R.string.usb_file_transfer, R.drawable.usb_fill0), + Restriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, R.string.mount_physical_media, R.drawable.sd_card_fill0), + Restriction(UserManager.DISALLOW_PRINTING, R.string.printing, R.drawable.print_fill0, 28) + ) + val applications = listOf( + Restriction(UserManager.DISALLOW_INSTALL_APPS, R.string.install_app, R.drawable.android_fill0), + Restriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, R.string.install_unknown_src_globally, R.drawable.android_fill0, 29), + Restriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, R.string.inst_unknown_src, R.drawable.android_fill0), + Restriction(UserManager.DISALLOW_UNINSTALL_APPS, R.string.uninstall_app, R.drawable.delete_fill0), + Restriction(UserManager.DISALLOW_APPS_CONTROL, R.string.apps_ctrl, R.drawable.apps_fill0), + Restriction(UserManager.DISALLOW_CONFIG_DEFAULT_APPS, R.string.config_default_apps, R.drawable.apps_fill0, 34) + ) + val media = listOf( + Restriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, R.string.config_brightness, R.drawable.brightness_5_fill0, 28), + Restriction(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, R.string.config_scr_timeout, R.drawable.screen_lock_portrait_fill0, 28), + Restriction(UserManager.DISALLOW_AMBIENT_DISPLAY, R.string.ambient_display, R.drawable.brightness_5_fill0, 28), + Restriction(UserManager.DISALLOW_ADJUST_VOLUME, R.string.adjust_volume, R.drawable.volume_up_fill0), + Restriction(UserManager.DISALLOW_UNMUTE_MICROPHONE, R.string.unmute_microphone, R.drawable.mic_fill0), + Restriction(UserManager.DISALLOW_CAMERA_TOGGLE, R.string.camera_toggle, R.drawable.cameraswitch_fill0, 31), + Restriction(UserManager.DISALLOW_MICROPHONE_TOGGLE, R.string.microphone_toggle, R.drawable.mic_fill0, 31) + ) + val users = listOf( + Restriction(UserManager.DISALLOW_ADD_USER, R.string.add_user, R.drawable.account_circle_fill0), + Restriction(UserManager.DISALLOW_REMOVE_USER, R.string.remove_user, R.drawable.account_circle_fill0), + Restriction(UserManager.DISALLOW_USER_SWITCH, R.string.switch_user, R.drawable.account_circle_fill0, 28), + Restriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, R.string.create_work_profile, R.drawable.work_fill0, 26), + Restriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, R.string.delete_work_profile, R.drawable.delete_forever_fill0, 26), + Restriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, R.string.create_private_space, R.drawable.lock_fill0, 35), + Restriction(UserManager.DISALLOW_SET_USER_ICON, R.string.set_user_icon, R.drawable.account_circle_fill0, 24), + Restriction(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE, R.string.cross_profile_copy, R.drawable.content_paste_fill0), + Restriction(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, R.string.share_into_managed_profile, R.drawable.share_fill0, 28), + Restriction(UserManager.DISALLOW_UNIFIED_PASSWORD, R.string.unified_pwd, R.drawable.work_fill0, 28) + ) + val other = listOf( + Restriction(UserManager.DISALLOW_AUTOFILL, R.string.autofill, R.drawable.password_fill0, 26), + Restriction(UserManager.DISALLOW_CONFIG_CREDENTIALS, R.string.config_credentials, R.drawable.android_fill0), + Restriction(UserManager.DISALLOW_CONTENT_CAPTURE, R.string.content_capture, R.drawable.screenshot_fill0, 29), + Restriction(UserManager.DISALLOW_CONTENT_SUGGESTIONS, R.string.content_suggestions, R.drawable.sms_fill0, 29), + Restriction(UserManager.DISALLOW_ASSIST_CONTENT, R.string.assist_content, R.drawable.info_fill0, 35), + Restriction(UserManager.DISALLOW_CREATE_WINDOWS, R.string.create_windows, R.drawable.web_asset), + Restriction(UserManager.DISALLOW_SET_WALLPAPER, R.string.set_wallpaper, R.drawable.wallpaper_fill0, 24), + Restriction(UserManager.DISALLOW_GRANT_ADMIN, R.string.grant_admin, R.drawable.security_fill0, 34), + Restriction(UserManager.DISALLOW_FUN, R.string.`fun`, R.drawable.stadia_controller_fill0, 23), + Restriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, R.string.modify_accounts, R.drawable.manage_accounts_fill0), + Restriction(UserManager.DISALLOW_CONFIG_LOCALE, R.string.config_locale, R.drawable.language_fill0, 28), + Restriction(UserManager.DISALLOW_CONFIG_DATE_TIME, R.string.config_date_time, R.drawable.schedule_fill0, 28), + Restriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS, R.string.sys_err_dialog, R.drawable.warning_fill0, 28), + Restriction(UserManager.DISALLOW_FACTORY_RESET, R.string.factory_reset, R.drawable.android_fill0), + Restriction(UserManager.DISALLOW_SAFE_BOOT, R.string.safe_boot, R.drawable.security_fill0, 23), + Restriction(UserManager.DISALLOW_DEBUGGING_FEATURES, R.string.debug_features, R.drawable.adb_fill0) + ) + + fun getData(id: String): Pair> { + val category = UserRestrictionCategory.entries.find { it.id == id }!! + return category.title to when (category) { + UserRestrictionCategory.Network -> network + UserRestrictionCategory.Connectivity -> connectivity + UserRestrictionCategory.Applications -> applications + UserRestrictionCategory.Media -> media + UserRestrictionCategory.Users -> users + UserRestrictionCategory.Other -> other + }.filter { Build.VERSION.SDK_INT >= it.requiresApi } + } +} + +enum class UserRestrictionCategory(val id: String, val title: Int, val icon: Int) { + Network("network", R.string.network, R.drawable.language_fill0), + Connectivity("connectivity", R.string.connectivity, R.drawable.devices_other_fill0), + Applications("applications", R.string.applications, R.drawable.apps_fill0), + Media("media", R.string.media, R.drawable.volume_up_fill0), + Users("users", R.string.users, R.drawable.manage_accounts_fill0), + Other("other", R.string.other, R.drawable.more_horiz_fill0) +} \ No newline at end of file diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/UserRestriction.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/UserRestriction.kt index 6ba859f..e7b3dda 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/UserRestriction.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/UserRestriction.kt @@ -1,10 +1,6 @@ package com.bintianqi.owndroid.dpm -import android.os.Build -import android.os.UserManager -import androidx.annotation.DrawableRes import androidx.annotation.RequiresApi -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -12,6 +8,7 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.ime import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn @@ -39,8 +36,6 @@ import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -57,17 +52,20 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bintianqi.owndroid.HorizontalPadding import com.bintianqi.owndroid.Privilege import com.bintianqi.owndroid.R +import com.bintianqi.owndroid.UserRestrictionCategory +import com.bintianqi.owndroid.UserRestrictionsRepository import com.bintianqi.owndroid.showOperationResultToast import com.bintianqi.owndroid.ui.FunctionItem import com.bintianqi.owndroid.ui.MyLazyScaffold import com.bintianqi.owndroid.ui.NavIcon +import kotlinx.coroutines.flow.StateFlow import kotlinx.serialization.Serializable @Serializable data class Restriction( val id: String, - @StringRes val name: Int, - @DrawableRes val icon: Int, + val name: Int, + val icon: Int, val requiresApi: Int = 0 ) @@ -76,12 +74,12 @@ data class Restriction( @OptIn(ExperimentalMaterial3Api::class) @RequiresApi(24) @Composable -fun UserRestrictionScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) { +fun UserRestrictionScreen( + getRestrictions: () -> Unit,onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit +) { val privilege by Privilege.status.collectAsStateWithLifecycle() val sb = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() - fun navigateToOptions(title: Int, items: List) { - onNavigate(UserRestrictionOptions(title, items)) - } + LaunchedEffect(Unit) { getRestrictions() } Scaffold( Modifier.nestedScroll(sb.nestedScrollConnection), topBar = { @@ -114,49 +112,29 @@ fun UserRestrictionScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) { Text(text = stringResource(R.string.some_features_invalid_in_work_profile), modifier = Modifier.padding(start = 16.dp)) } Spacer(Modifier.padding(vertical = 2.dp)) - FunctionItem(R.string.network, icon = R.drawable.language_fill0) { - navigateToOptions(R.string.network, RestrictionData.internet) - } - FunctionItem(R.string.connectivity, icon = R.drawable.devices_other_fill0) { - navigateToOptions(R.string.connectivity, RestrictionData.connectivity) - } - FunctionItem(R.string.applications, icon = R.drawable.apps_fill0) { - navigateToOptions(R.string.applications, RestrictionData.applications) - } - FunctionItem(R.string.users, icon = R.drawable.account_circle_fill0) { - navigateToOptions(R.string.users, RestrictionData.users) - } - FunctionItem(R.string.media, icon = R.drawable.volume_up_fill0) { - navigateToOptions(R.string.media, RestrictionData.media) - } - FunctionItem(R.string.other, icon = R.drawable.more_horiz_fill0) { - navigateToOptions(R.string.other, RestrictionData.other) + UserRestrictionCategory.entries.forEach { + FunctionItem(it.title, icon = it.icon) { + onNavigate(UserRestrictionOptions(it.id)) + } } } } } @Serializable -data class UserRestrictionOptions( - val title: Int, val items: List -) +data class UserRestrictionOptions(val id: String) @RequiresApi(24) @Composable fun UserRestrictionOptionsScreen( - data: UserRestrictionOptions, onNavigateUp: () -> Unit + args: UserRestrictionOptions, userRestrictions: StateFlow>, + setRestriction: (String, Boolean) -> Boolean, onNavigateUp: () -> Unit ) { val context = LocalContext.current - val status = remember { mutableStateMapOf() } - fun refresh() { - val restrictions = Privilege.DPM.getUserRestrictions(Privilege.DAR) - data.items.forEach { - status.put(it.id, restrictions.getBoolean(it.id)) - } - } - LaunchedEffect(Unit) { refresh() } - MyLazyScaffold(data.title, onNavigateUp) { - items(data.items.filter { Build.VERSION.SDK_INT >= it.requiresApi }) { restriction -> + val status by userRestrictions.collectAsStateWithLifecycle() + val (title, items) = UserRestrictionsRepository.getData(args.id) + MyLazyScaffold(title, onNavigateUp) { + items(items) { restriction -> Row( Modifier.fillMaxWidth().padding(15.dp, 6.dp), Arrangement.SpaceBetween, Alignment.CenterVertically @@ -174,18 +152,11 @@ fun UserRestrictionOptionsScreen( Switch( status[restriction.id] == true, { - try { - if (it) { - Privilege.DPM.addUserRestriction(Privilege.DAR, restriction.id) - } else { - Privilege.DPM.clearUserRestriction(Privilege.DAR, restriction.id) - } - } catch (e: Exception) { - e.printStackTrace() + if (!setRestriction(restriction.id, it)) { context.showOperationResultToast(false) } - refresh() - } + }, + Modifier.padding(start = 8.dp) ) } } @@ -195,104 +166,18 @@ fun UserRestrictionOptionsScreen( } } -@Suppress("InlinedApi") -object RestrictionData { - val internet = listOf( - Restriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, R.string.config_mobile_network, R.drawable.signal_cellular_alt_fill0), - Restriction(UserManager.DISALLOW_CONFIG_WIFI, R.string.config_wifi, R.drawable.wifi_fill0), - Restriction(UserManager.DISALLOW_DATA_ROAMING, R.string.data_roaming, R.drawable.network_cell_fill0, 24), - Restriction(UserManager.DISALLOW_CELLULAR_2G, R.string.cellular_2g, R.drawable.network_cell_fill0, 34), - Restriction(UserManager.DISALLOW_ULTRA_WIDEBAND_RADIO, R.string.ultra_wideband_radio, R.drawable.wifi_tethering_fill0, 34), - Restriction(UserManager.DISALLOW_ADD_WIFI_CONFIG, R.string.add_wifi_conf, R.drawable.wifi_fill0, 33), - Restriction(UserManager.DISALLOW_CHANGE_WIFI_STATE, R.string.change_wifi_state, R.drawable.wifi_fill0, 33), - Restriction(UserManager.DISALLOW_WIFI_DIRECT, R.string.wifi_direct, R.drawable.wifi_tethering_fill0), - Restriction(UserManager.DISALLOW_WIFI_TETHERING, R.string.wifi_tethering, R.drawable.wifi_tethering_fill0, 33), - Restriction(UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI, R.string.share_admin_wifi, R.drawable.share_fill0, 33), - Restriction(UserManager.DISALLOW_NETWORK_RESET, R.string.network_reset, R.drawable.reset_wrench_fill0, 23), - Restriction(UserManager.DISALLOW_CONFIG_TETHERING, R.string.config_tethering, R.drawable.wifi_tethering_fill0), - Restriction(UserManager.DISALLOW_CONFIG_VPN, R.string.config_vpn, R.drawable.vpn_key_fill0), - Restriction(UserManager.DISALLOW_CONFIG_PRIVATE_DNS, R.string.config_private_dns, R.drawable.dns_fill0, 29), - Restriction(UserManager.DISALLOW_AIRPLANE_MODE, R.string.airplane_mode, R.drawable.airplanemode_active_fill0, 28), - Restriction(UserManager.DISALLOW_CONFIG_CELL_BROADCASTS, R.string.config_cell_broadcasts, R.drawable.cell_tower_fill0), - Restriction(UserManager.DISALLOW_SMS, R.string.sms, R.drawable.sms_fill0), - Restriction(UserManager.DISALLOW_OUTGOING_CALLS, R.string.outgoing_calls, R.drawable.phone_forwarded_fill0), - Restriction(UserManager.DISALLOW_SIM_GLOBALLY, R.string.download_esim, R.drawable.sim_card_download_fill0), - Restriction(UserManager.DISALLOW_THREAD_NETWORK, R.string.thread_network, R.drawable.router_fill0, 36) - ) - val connectivity = listOf( - Restriction(UserManager.DISALLOW_BLUETOOTH, R.string.bluetooth, R.drawable.bluetooth_fill0, 26), - Restriction(UserManager.DISALLOW_BLUETOOTH_SHARING, R.string.bt_share, R.drawable.bluetooth_searching_fill0, 26), - Restriction(UserManager.DISALLOW_SHARE_LOCATION, R.string.share_location, R.drawable.location_on_fill0), - Restriction(UserManager.DISALLOW_CONFIG_LOCATION, R.string.config_location, R.drawable.location_on_fill0, 28), - Restriction(UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO, R.string.nfc, R.drawable.nfc_fill0, 35), - Restriction(UserManager.DISALLOW_OUTGOING_BEAM, R.string.outgoing_beam, R.drawable.nfc_fill0, 22), - Restriction(UserManager.DISALLOW_USB_FILE_TRANSFER, R.string.usb_file_transfer, R.drawable.usb_fill0), - Restriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, R.string.mount_physical_media, R.drawable.sd_card_fill0), - Restriction(UserManager.DISALLOW_PRINTING, R.string.printing, R.drawable.print_fill0, 28) - ) - val applications = listOf( - Restriction(UserManager.DISALLOW_INSTALL_APPS, R.string.install_app, R.drawable.android_fill0), - Restriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY, R.string.install_unknown_src_globally, R.drawable.android_fill0, 29), - Restriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, R.string.inst_unknown_src, R.drawable.android_fill0), - Restriction(UserManager.DISALLOW_UNINSTALL_APPS, R.string.uninstall_app, R.drawable.delete_fill0), - Restriction(UserManager.DISALLOW_APPS_CONTROL, R.string.apps_ctrl, R.drawable.apps_fill0), - Restriction(UserManager.DISALLOW_CONFIG_DEFAULT_APPS, R.string.config_default_apps, R.drawable.apps_fill0, 34) - ) - val media = listOf( - Restriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, R.string.config_brightness, R.drawable.brightness_5_fill0, 28), - Restriction(UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT, R.string.config_scr_timeout, R.drawable.screen_lock_portrait_fill0, 28), - Restriction(UserManager.DISALLOW_AMBIENT_DISPLAY, R.string.ambient_display, R.drawable.brightness_5_fill0, 28), - Restriction(UserManager.DISALLOW_ADJUST_VOLUME, R.string.adjust_volume, R.drawable.volume_up_fill0), - Restriction(UserManager.DISALLOW_UNMUTE_MICROPHONE, R.string.unmute_microphone, R.drawable.mic_fill0), - Restriction(UserManager.DISALLOW_CAMERA_TOGGLE, R.string.camera_toggle, R.drawable.cameraswitch_fill0, 31), - Restriction(UserManager.DISALLOW_MICROPHONE_TOGGLE, R.string.microphone_toggle, R.drawable.mic_fill0, 31) - ) - val users = listOf( - Restriction(UserManager.DISALLOW_ADD_USER, R.string.add_user, R.drawable.account_circle_fill0), - Restriction(UserManager.DISALLOW_REMOVE_USER, R.string.remove_user, R.drawable.account_circle_fill0), - Restriction(UserManager.DISALLOW_USER_SWITCH, R.string.switch_user, R.drawable.account_circle_fill0, 28), - Restriction(UserManager.DISALLOW_ADD_MANAGED_PROFILE, R.string.create_work_profile, R.drawable.work_fill0, 26), - Restriction(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE, R.string.delete_work_profile, R.drawable.delete_forever_fill0, 26), - Restriction(UserManager.DISALLOW_ADD_PRIVATE_PROFILE, R.string.create_private_space, R.drawable.lock_fill0, 35), - Restriction(UserManager.DISALLOW_SET_USER_ICON, R.string.set_user_icon, R.drawable.account_circle_fill0, 24), - Restriction(UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE, R.string.cross_profile_copy, R.drawable.content_paste_fill0), - Restriction(UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE, R.string.share_into_managed_profile, R.drawable.share_fill0, 28), - Restriction(UserManager.DISALLOW_UNIFIED_PASSWORD, R.string.unified_pwd, R.drawable.work_fill0, 28) - ) - val other = listOf( - Restriction(UserManager.DISALLOW_AUTOFILL, R.string.autofill, R.drawable.password_fill0, 26), - Restriction(UserManager.DISALLOW_CONFIG_CREDENTIALS, R.string.config_credentials, R.drawable.android_fill0), - Restriction(UserManager.DISALLOW_CONTENT_CAPTURE, R.string.content_capture, R.drawable.screenshot_fill0, 29), - Restriction(UserManager.DISALLOW_CONTENT_SUGGESTIONS, R.string.content_suggestions, R.drawable.sms_fill0, 29), - Restriction(UserManager.DISALLOW_ASSIST_CONTENT, R.string.assist_content, R.drawable.info_fill0, 35), - Restriction(UserManager.DISALLOW_CREATE_WINDOWS, R.string.create_windows, R.drawable.web_asset), - Restriction(UserManager.DISALLOW_SET_WALLPAPER, R.string.set_wallpaper, R.drawable.wallpaper_fill0, 24), - Restriction(UserManager.DISALLOW_GRANT_ADMIN, R.string.grant_admin, R.drawable.security_fill0, 34), - Restriction(UserManager.DISALLOW_FUN, R.string.`fun`, R.drawable.stadia_controller_fill0, 23), - Restriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, R.string.modify_accounts, R.drawable.manage_accounts_fill0), - Restriction(UserManager.DISALLOW_CONFIG_LOCALE, R.string.config_locale, R.drawable.language_fill0, 28), - Restriction(UserManager.DISALLOW_CONFIG_DATE_TIME, R.string.config_date_time, R.drawable.schedule_fill0, 28), - Restriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS, R.string.sys_err_dialog, R.drawable.warning_fill0, 28), - Restriction(UserManager.DISALLOW_FACTORY_RESET, R.string.factory_reset, R.drawable.android_fill0), - Restriction(UserManager.DISALLOW_SAFE_BOOT, R.string.safe_boot, R.drawable.security_fill0, 23), - Restriction(UserManager.DISALLOW_DEBUGGING_FEATURES, R.string.debug_features, R.drawable.adb_fill0) - ) -} - @Serializable object UserRestrictionEditor @OptIn(ExperimentalMaterial3Api::class) @RequiresApi(24) @Composable -fun UserRestrictionEditorScreen(onNavigateUp: () -> Unit) { +fun UserRestrictionEditorScreen( + restrictions: StateFlow>, setRestriction: (String, Boolean) -> Boolean, + onNavigateUp: () -> Unit +) { val context = LocalContext.current - val list = remember { mutableStateListOf() } - fun refresh() { - val restrictions = Privilege.DPM.getUserRestrictions(Privilege.DAR) - list.clear() - list.addAll(restrictions.keySet().filter { restrictions.getBoolean(it) }) - } - LaunchedEffect(Unit) { refresh() } + val map by restrictions.collectAsStateWithLifecycle() + val list = map.filter { it.value }.map { it.key } Scaffold( topBar = { TopAppBar( @@ -310,13 +195,7 @@ fun UserRestrictionEditorScreen(onNavigateUp: () -> Unit) { ) { Text(it) IconButton({ - try { - Privilege.DPM.clearUserRestriction(Privilege.DAR, it) - } catch (e: Exception) { - e.printStackTrace() - context.showOperationResultToast(false) - } - refresh() + if (!setRestriction(it, false)) context.showOperationResultToast(false) }) { Icon(Icons.Outlined.Delete, null) } @@ -325,17 +204,10 @@ fun UserRestrictionEditorScreen(onNavigateUp: () -> Unit) { item { var input by remember { mutableStateOf("") } fun add() { - try { - Privilege.DPM.addUserRestriction(Privilege.DAR, input) - input = "" - } catch (e: Exception) { - e.printStackTrace() - context.showOperationResultToast(false) - } - refresh() + if (!setRestriction(input, false)) context.showOperationResultToast(false) } OutlinedTextField( - input, { input = it }, Modifier.fillMaxWidth().padding(HorizontalPadding, 20.dp), + input, { input = it }, Modifier.fillMaxWidth().padding(HorizontalPadding, 8.dp), label = { Text("id") }, trailingIcon = { IconButton(::add, enabled = input.isNotBlank()) { @@ -345,6 +217,7 @@ fun UserRestrictionEditorScreen(onNavigateUp: () -> Unit) { keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Ascii, imeAction = ImeAction.Done), keyboardActions = KeyboardActions { add() } ) + Spacer(Modifier.height(40.dp)) } } }