mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 11:05:59 +00:00
feat: change global & secure settings (#237)
This commit is contained in:
@@ -101,6 +101,8 @@ import com.bintianqi.owndroid.dpm.CrossProfileIntentFilter
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileIntentFilterScreen
|
||||
import com.bintianqi.owndroid.dpm.CrossProfilePackages
|
||||
import com.bintianqi.owndroid.dpm.CrossProfileWidgetProviders
|
||||
import com.bintianqi.owndroid.dpm.DefaultInputMethod
|
||||
import com.bintianqi.owndroid.dpm.DefaultInputMethodScreen
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdmins
|
||||
import com.bintianqi.owndroid.dpm.DelegatedAdminsScreen
|
||||
import com.bintianqi.owndroid.dpm.DeleteWorkProfile
|
||||
@@ -363,6 +365,10 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
||||
HardwareMonitorScreen(vm.hardwareProperties, vm::getHardwareProperties,
|
||||
vm::setHpRefreshInterval, ::navigateUp)
|
||||
}
|
||||
composable<DefaultInputMethod> {
|
||||
DefaultInputMethodScreen(vm::getCurrentInputMethod, vm.inputMethodList,
|
||||
vm::getInputMethods, vm::setDefaultInputMethod, ::navigateUp)
|
||||
}
|
||||
composable<ChangeTime> { ChangeTimeScreen(vm::setTime, ::navigateUp) }
|
||||
composable<ChangeTimeZone> { ChangeTimeZoneScreen(vm::setTimeZone, ::navigateUp) }
|
||||
composable<AutoTimePolicy> {
|
||||
|
||||
@@ -45,7 +45,9 @@ import android.os.Bundle
|
||||
import android.os.HardwarePropertiesManager
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings
|
||||
import android.telephony.data.ApnSetting
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
@@ -103,10 +105,12 @@ import com.bintianqi.owndroid.dpm.activateOrgProfileCommand
|
||||
import com.bintianqi.owndroid.dpm.delegatedScopesList
|
||||
import com.bintianqi.owndroid.dpm.doUserOperationWithContext
|
||||
import com.bintianqi.owndroid.dpm.getPackageInstaller
|
||||
import com.bintianqi.owndroid.dpm.globalSettings
|
||||
import com.bintianqi.owndroid.dpm.handlePrivilegeChange
|
||||
import com.bintianqi.owndroid.dpm.isValidPackageName
|
||||
import com.bintianqi.owndroid.dpm.parsePackageInstallerMessage
|
||||
import com.bintianqi.owndroid.dpm.runtimePermissions
|
||||
import com.bintianqi.owndroid.dpm.secureSettings
|
||||
import com.bintianqi.owndroid.dpm.temperatureTypes
|
||||
import com.rosan.dhizuku.api.Dhizuku
|
||||
import com.rosan.dhizuku.api.DhizukuRequestPermissionListener
|
||||
@@ -717,7 +721,9 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
commonCriteriaMode = if (VERSION.SDK_INT >= 30 && (privilege.device || privilege.org))
|
||||
DPM.isCommonCriteriaModeEnabled(DAR) else false,
|
||||
usbSignalEnabled = if (VERSION.SDK_INT >= 31) DPM.isUsbDataSignalingEnabled else false,
|
||||
canDisableUsbSignal = if (VERSION.SDK_INT >= 31) DPM.canUsbDataSignalingBeDisabled() else false
|
||||
canDisableUsbSignal = if (VERSION.SDK_INT >= 31) DPM.canUsbDataSignalingBeDisabled() else false,
|
||||
stayOnWhilePluggedIn = Settings.Global.getInt(
|
||||
application.contentResolver, Settings.Global.STAY_ON_WHILE_PLUGGED_IN) != 0
|
||||
)
|
||||
}
|
||||
fun setCameraDisabled(disabled: Boolean) {
|
||||
@@ -782,6 +788,28 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
DPM.isUsbDataSignalingEnabled = enabled
|
||||
systemOptionsStatus.update { it.copy(usbSignalEnabled = DPM.isUsbDataSignalingEnabled) }
|
||||
}
|
||||
fun setStayOnWhilePluggedIn(status: Boolean) {
|
||||
DPM.setGlobalSetting(
|
||||
DAR, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, if (status) "15" else "0"
|
||||
)
|
||||
systemOptionsStatus.update { it.copy(stayOnWhilePluggedIn = status) }
|
||||
}
|
||||
fun getGlobalSettings(): Map<String, Boolean> {
|
||||
return globalSettings.associate {
|
||||
it.setting to (Settings.Global.getInt(application.contentResolver, it.setting, 0) == 1)
|
||||
}
|
||||
}
|
||||
fun setGlobalSetting(name: String, status: Boolean) {
|
||||
DPM.setGlobalSetting(DAR, name, if (status) "1" else "0")
|
||||
}
|
||||
fun getSecureSettings(): Map<String, Boolean> {
|
||||
return secureSettings.associate {
|
||||
it.setting to (Settings.Secure.getInt(application.contentResolver, it.setting, 0) == 1)
|
||||
}
|
||||
}
|
||||
fun setSecureSetting(name: String, status: Boolean) {
|
||||
DPM.setSecureSetting(DAR, name, if (status) "1" else "0")
|
||||
}
|
||||
fun setKeyguardDisabled(disabled: Boolean): Boolean {
|
||||
return DPM.setKeyguardDisabled(DAR, disabled)
|
||||
}
|
||||
@@ -816,6 +844,21 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
delay(hpRefreshInterval)
|
||||
}
|
||||
}
|
||||
fun getCurrentInputMethod(): String {
|
||||
return Settings.Secure.getString(
|
||||
application.contentResolver, Settings.Secure.DEFAULT_INPUT_METHOD)
|
||||
}
|
||||
val inputMethodList = MutableStateFlow(listOf<Pair<String, AppInfo>>())
|
||||
fun getInputMethods() {
|
||||
val imm = application.getSystemService(InputMethodManager::class.java)
|
||||
inputMethodList.value = imm.inputMethodList.map {
|
||||
it.id to getAppInfo(it.packageName)
|
||||
}
|
||||
}
|
||||
fun setDefaultInputMethod(id: String) {
|
||||
DPM.setSecureSetting(DAR, Settings.Secure.DEFAULT_INPUT_METHOD, id)
|
||||
getCurrentInputMethod()
|
||||
}
|
||||
@RequiresApi(28)
|
||||
fun setTime(time: Long, useCurrentTz: Boolean): Boolean {
|
||||
val offset = if (useCurrentTz) {
|
||||
|
||||
@@ -24,11 +24,13 @@ import android.net.Uri
|
||||
import android.os.Build.VERSION
|
||||
import android.os.HardwarePropertiesManager
|
||||
import android.os.UserManager
|
||||
import android.provider.Settings
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.animateContentSize
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@@ -39,6 +41,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
@@ -69,6 +72,7 @@ import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
import androidx.compose.material3.MaterialTheme.typography
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.PrimaryTabRow
|
||||
import androidx.compose.material3.RadioButton
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Tab
|
||||
@@ -86,6 +90,7 @@ import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
@@ -93,6 +98,7 @@ import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
@@ -120,12 +126,14 @@ import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
||||
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
||||
import com.bintianqi.owndroid.ui.FunctionItem
|
||||
import com.bintianqi.owndroid.ui.ListItem
|
||||
import com.bintianqi.owndroid.ui.MyLazyScaffold
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.MySmallTitleScaffold
|
||||
import com.bintianqi.owndroid.ui.NavIcon
|
||||
import com.bintianqi.owndroid.ui.Notes
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -153,6 +161,9 @@ fun SystemManagerScreen(
|
||||
FunctionItem(R.string.keyguard, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(Keyguard) }
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device && !privilege.dhizuku)
|
||||
FunctionItem(R.string.hardware_monitor, icon = R.drawable.memory_fill0) { onNavigate(HardwareMonitor) }
|
||||
FunctionItem(R.string.default_input_method, icon = R.drawable.keyboard_fill0) {
|
||||
onNavigate(DefaultInputMethod)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device) {
|
||||
FunctionItem(R.string.reboot, icon = R.drawable.restart_alt_fill0) { dialog = 1 }
|
||||
}
|
||||
@@ -314,17 +325,41 @@ data class SystemOptionsStatus(
|
||||
val btContactSharingDisabled: Boolean = false,
|
||||
val commonCriteriaMode: Boolean = false,
|
||||
val usbSignalEnabled: Boolean = true,
|
||||
val canDisableUsbSignal: Boolean = true
|
||||
val canDisableUsbSignal: Boolean = true,
|
||||
val stayOnWhilePluggedIn: Boolean = false
|
||||
)
|
||||
|
||||
@Serializable object SystemOptions
|
||||
|
||||
class GlobalSetting(val icon: Int, val name: Int, val setting: String) // also for secure settings
|
||||
|
||||
// STAY_ON_WHILE_PLUGGED_IN is set separately
|
||||
val globalSettings = listOf(
|
||||
GlobalSetting(R.drawable.cell_tower_fill0, R.string.data_roaming, Settings.Global.DATA_ROAMING),
|
||||
GlobalSetting(R.drawable.adb_fill0, R.string.enable_adb, Settings.Global.ADB_ENABLED),
|
||||
GlobalSetting(R.drawable.usb_fill0, R.string.enable_usb_mass_storage,
|
||||
Settings.Global.USB_MASS_STORAGE_ENABLED),
|
||||
GlobalSetting(R.drawable.wifi_password_fill0, R.string.lockdown_admin_configured_network,
|
||||
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN)
|
||||
)
|
||||
|
||||
val secureSettings = listOf(
|
||||
GlobalSetting(R.drawable.light_off_fill0, R.string.skip_first_use_hints,
|
||||
Settings.Secure.SKIP_FIRST_USE_HINTS)
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SystemOptionsScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||
val privilege by Privilege.status.collectAsStateWithLifecycle()
|
||||
var dialog by rememberSaveable { mutableIntStateOf(0) }
|
||||
val status by vm.systemOptionsStatus.collectAsStateWithLifecycle()
|
||||
LaunchedEffect(Unit) { vm.getSystemOptionsStatus() }
|
||||
val globalSettingsStatus = remember { mutableStateMapOf<String, Boolean>() }
|
||||
val secureSettingsStatus = remember { mutableStateMapOf<String, Boolean>() }
|
||||
LaunchedEffect(Unit) {
|
||||
vm.getSystemOptionsStatus()
|
||||
globalSettingsStatus.putAll(vm.getGlobalSettings())
|
||||
secureSettingsStatus.putAll(vm.getSecureSettings())
|
||||
}
|
||||
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
||||
SwitchItem(R.string.disable_cam, status.cameraDisabled, vm::setCameraDisabled,
|
||||
R.drawable.no_photography_fill0)
|
||||
@@ -366,6 +401,20 @@ fun SystemOptionsScreen(vm: MyViewModel, onNavigateUp: () -> Unit) {
|
||||
SwitchItem(R.string.enable_usb_signal, status.usbSignalEnabled,
|
||||
vm::setUsbSignalEnabled, R.drawable.usb_fill0)
|
||||
}
|
||||
SwitchItem(R.string.stay_on_while_plugged_in, status.stayOnWhilePluggedIn,
|
||||
vm::setStayOnWhilePluggedIn, R.drawable.mobile_phone_fill0)
|
||||
globalSettings.forEach {
|
||||
SwitchItem(it.name, globalSettingsStatus[it.setting] ?: false, { state ->
|
||||
vm.setGlobalSetting(it.setting, state)
|
||||
globalSettingsStatus[it.setting] = state
|
||||
}, it.icon)
|
||||
}
|
||||
secureSettings.forEach {
|
||||
SwitchItem(it.name, secureSettingsStatus[it.setting] ?: false, { state ->
|
||||
vm.setSecureSetting(it.setting, state)
|
||||
secureSettingsStatus[it.setting] = state
|
||||
}, it.icon)
|
||||
}
|
||||
if (VERSION.SDK_INT < 34) {
|
||||
Row(
|
||||
Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding),
|
||||
@@ -531,6 +580,47 @@ fun HardwareMonitorScreen(
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object DefaultInputMethod
|
||||
|
||||
@Composable
|
||||
fun DefaultInputMethodScreen(
|
||||
getCurrentIm: () -> String, imListState: StateFlow<List<Pair<String, AppInfo>>>,
|
||||
getImList: () -> Unit, setIm: (String) -> Unit, navigateUp: () -> Unit
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val imList by imListState.collectAsStateWithLifecycle()
|
||||
var selectedIm by remember { mutableStateOf("") }
|
||||
LaunchedEffect(Unit) {
|
||||
selectedIm = getCurrentIm()
|
||||
getImList()
|
||||
}
|
||||
MyLazyScaffold(R.string.default_input_method, navigateUp) {
|
||||
items(imList) { (id, info) ->
|
||||
Row(
|
||||
Modifier.fillMaxWidth().clickable { selectedIm = id }.padding(8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(selectedIm == id, { selectedIm = id })
|
||||
Image(rememberDrawablePainter(info.icon), null, Modifier.size(40.dp))
|
||||
Column(Modifier.padding(start = 8.dp)) {
|
||||
Text(info.label)
|
||||
Text(id, Modifier.alpha(0.7F), style = typography.bodyMedium)
|
||||
}
|
||||
}
|
||||
}
|
||||
item {
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Button({
|
||||
setIm(selectedIm)
|
||||
context.showOperationResultToast(true)
|
||||
}, Modifier.fillMaxWidth().padding(horizontal = HorizontalPadding)) {
|
||||
Text(stringResource(R.string.apply))
|
||||
}
|
||||
Spacer(Modifier.height(BottomPadding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ChangeTime
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
9
app/src/main/res/drawable/light_off_fill0.xml
Normal file
9
app/src/main/res/drawable/light_off_fill0.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M423.5,856.5Q400,833 400,800h160q0,33 -23.5,56.5T480,880q-33,0 -56.5,-23.5ZM480,160q-44,0 -81.5,15.5T332,218l-58,-56q41,-38 93.5,-60T480,80q125,0 212.5,87.5T780,380q0,71 -25,121.5T698,584l-56,-56q21,-23 39.5,-59t18.5,-89q0,-92 -64,-156t-156,-64ZM848,848 L791,905 526,640L330,640q-69,-41 -109.5,-110T180,380q0,-20 2.5,-39t7.5,-37L56,168l56,-56 736,736ZM354,560h92L260,374v6q0,54 24.5,101t69.5,79ZM348,462ZM482,368ZM646,680v80L320,760v-80h326Z"
|
||||
android:fillColor="#000000"/>
|
||||
</vector>
|
||||
@@ -134,6 +134,10 @@
|
||||
<string name="disable_bt_contact_share">禁止蓝牙分享联系人</string>
|
||||
<string name="common_criteria_mode">通用标准模式</string>
|
||||
<string name="enable_usb_signal">启用USB信号</string>
|
||||
<string name="stay_on_while_plugged_in">充电时保持亮屏</string>
|
||||
<string name="enable_adb">启用ADB</string>
|
||||
<string name="enable_usb_mass_storage">启用USB大容量存储</string>
|
||||
<string name="skip_first_use_hints">跳过首次使用提示</string>
|
||||
<string name="keyguard">锁屏</string>
|
||||
<string name="lock_now">立即锁屏</string>
|
||||
<string name="lock_screen">锁屏</string>
|
||||
@@ -148,7 +152,8 @@
|
||||
<string name="cpu_usages">CPU使用情况</string>
|
||||
<string name="active">活动</string>
|
||||
<string name="total">总计</string>
|
||||
<string name="fan_speeds">Fan speeds</string>
|
||||
<string name="fan_speeds">风扇速度</string>
|
||||
<string name="default_input_method">默认输入法</string>
|
||||
<string name="bug_report">错误报告</string>
|
||||
<string name="confirm_bug_report">请求错误报告?</string>
|
||||
<string name="reboot">重启</string>
|
||||
|
||||
@@ -143,6 +143,10 @@
|
||||
<string name="disable_bt_contact_share">Disable bluetooth contact sharing</string>
|
||||
<string name="common_criteria_mode">Common criteria mode</string>
|
||||
<string name="enable_usb_signal">Enable USB signal</string>
|
||||
<string name="stay_on_while_plugged_in">Stay on while plugged in</string>
|
||||
<string name="enable_adb">Enable ADB</string>
|
||||
<string name="enable_usb_mass_storage">Enable USB mass storage</string>
|
||||
<string name="skip_first_use_hints">Skip first use hints</string>
|
||||
<string name="keyguard">Keyguard</string>
|
||||
<string name="lock_now">Lock screen now</string>
|
||||
<string name="lock_screen">Lock screen</string>
|
||||
@@ -158,6 +162,7 @@
|
||||
<string name="active">Active</string>
|
||||
<string name="total">Total</string>
|
||||
<string name="fan_speeds">Fan speeds</string>
|
||||
<string name="default_input_method">Default input method</string>
|
||||
<string name="bug_report">Bug report</string>
|
||||
<string name="confirm_bug_report">Request bug report?</string>
|
||||
<string name="reboot">Reboot</string>
|
||||
|
||||
Reference in New Issue
Block a user