mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
916 lines
47 KiB
Kotlin
916 lines
47 KiB
Kotlin
package com.bintianqi.owndroid.dpm
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.app.admin.DevicePolicyManager
|
|
import android.app.admin.DevicePolicyManager.*
|
|
import android.app.admin.SystemUpdateInfo
|
|
import android.app.admin.SystemUpdatePolicy
|
|
import android.app.admin.SystemUpdatePolicy.TYPE_INSTALL_AUTOMATIC
|
|
import android.app.admin.SystemUpdatePolicy.TYPE_INSTALL_WINDOWED
|
|
import android.app.admin.SystemUpdatePolicy.TYPE_POSTPONE
|
|
import android.content.ComponentName
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.os.Binder
|
|
import android.os.Build.VERSION
|
|
import android.os.UserManager
|
|
import android.util.Log
|
|
import android.widget.Toast
|
|
import androidx.activity.ComponentActivity
|
|
import androidx.compose.animation.AnimatedVisibility
|
|
import androidx.compose.animation.animateContentSize
|
|
import androidx.compose.foundation.*
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.foundation.text.selection.SelectionContainer
|
|
import androidx.compose.material3.*
|
|
import androidx.compose.material3.MaterialTheme.colorScheme
|
|
import androidx.compose.material3.MaterialTheme.typography
|
|
import androidx.compose.runtime.*
|
|
import androidx.compose.ui.Modifier
|
|
import androidx.compose.ui.draw.alpha
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
import androidx.compose.ui.res.stringResource
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.KeyboardType
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.navigation.NavHostController
|
|
import androidx.navigation.compose.NavHost
|
|
import androidx.navigation.compose.composable
|
|
import androidx.navigation.compose.currentBackStackEntryAsState
|
|
import androidx.navigation.compose.rememberNavController
|
|
import com.bintianqi.owndroid.R
|
|
import com.bintianqi.owndroid.Receiver
|
|
import com.bintianqi.owndroid.toText
|
|
import com.bintianqi.owndroid.ui.*
|
|
import com.bintianqi.owndroid.ui.theme.bgColor
|
|
import kotlinx.coroutines.delay
|
|
import java.util.Date
|
|
|
|
@Composable
|
|
fun SystemManage(navCtrl:NavHostController){
|
|
val localNavCtrl = rememberNavController()
|
|
val backStackEntry by localNavCtrl.currentBackStackEntryAsState()
|
|
val scrollState = rememberScrollState()
|
|
/*val titleMap = mapOf(
|
|
"Switches" to R.string.options,
|
|
"Keyguard" to R.string.keyguard,
|
|
"BugReport" to R.string.request_bug_report,
|
|
"Reboot" to R.string.reboot,
|
|
"EditTime" to R.string.edit_time,
|
|
"PermissionPolicy" to R.string.permission_policy,
|
|
"MTEPolicy" to R.string.mte_policy,
|
|
"NearbyStreamingPolicy" to R.string.nearby_streaming_policy,
|
|
"LockTaskFeatures" to R.string.lock_task_feature,
|
|
"CaCert" to R.string.ca_cert,
|
|
"SecurityLogs" to R.string.security_logs,
|
|
"SystemUpdatePolicy" to R.string.system_update_policy,
|
|
"WipeData" to R.string.wipe_data
|
|
)*/
|
|
Scaffold(
|
|
topBar = {
|
|
/*TopAppBar(
|
|
title = {Text(text = stringResource(titleMap[backStackEntry?.destination?.route]?:R.string.device_ctrl))},
|
|
navigationIcon = {NavIcon{if(backStackEntry?.destination?.route=="Home"){navCtrl.navigateUp()}else{localNavCtrl.navigateUp()}}},
|
|
colors = TopAppBarDefaults.topAppBarColors(containerColor = colorScheme.surfaceVariant)
|
|
)*/
|
|
TopBar(backStackEntry,navCtrl,localNavCtrl){
|
|
if(backStackEntry?.destination?.route=="Home"&&scrollState.maxValue>80){
|
|
Text(
|
|
text = stringResource(R.string.system_manage),
|
|
modifier = Modifier.alpha((maxOf(scrollState.value-30,0)).toFloat()/80)
|
|
)
|
|
}
|
|
}
|
|
}
|
|
){
|
|
NavHost(
|
|
navController = localNavCtrl, startDestination = "Home",
|
|
enterTransition = Animations.navHostEnterTransition,
|
|
exitTransition = Animations.navHostExitTransition,
|
|
popEnterTransition = Animations.navHostPopEnterTransition,
|
|
popExitTransition = Animations.navHostPopExitTransition,
|
|
modifier = Modifier.background(bgColor).padding(top = it.calculateTopPadding())
|
|
){
|
|
composable(route = "Home"){Home(localNavCtrl,scrollState)}
|
|
composable(route = "Switches"){Switches()}
|
|
composable(route = "Keyguard"){Keyguard()}
|
|
composable(route = "BugReport"){BugReport()}
|
|
composable(route = "Reboot"){Reboot()}
|
|
composable(route = "EditTime"){EditTime()}
|
|
composable(route = "PermissionPolicy"){PermissionPolicy()}
|
|
composable(route = "MTEPolicy"){MTEPolicy()}
|
|
composable(route = "NearbyStreamingPolicy"){NearbyStreamingPolicy()}
|
|
composable(route = "LockTaskFeatures"){LockTaskFeatures()}
|
|
composable(route = "CaCert"){CaCert()}
|
|
composable(route = "SecurityLogs"){SecurityLogs()}
|
|
composable(route = "SystemUpdatePolicy"){SysUpdatePolicy()}
|
|
composable(route = "WipeData"){WipeData()}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun Home(navCtrl: NavHostController,scrollState: ScrollState){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(scrollState)){
|
|
Text(text = stringResource(R.string.system_manage), style = typography.headlineLarge, modifier = Modifier.padding(top = 8.dp, bottom = 5.dp, start = 15.dp))
|
|
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
|
SubPageItem(R.string.options,"",R.drawable.tune_fill0){navCtrl.navigate("Switches")}
|
|
}
|
|
SubPageItem(R.string.keyguard,"",R.drawable.screen_lock_portrait_fill0){navCtrl.navigate("Keyguard")}
|
|
if(VERSION.SDK_INT>=24){
|
|
SubPageItem(R.string.request_bug_report,"",R.drawable.bug_report_fill0){navCtrl.navigate("BugReport")}
|
|
SubPageItem(R.string.reboot,"",R.drawable.restart_alt_fill0){navCtrl.navigate("Reboot")}
|
|
}
|
|
if(VERSION.SDK_INT>=28){
|
|
SubPageItem(R.string.edit_time,"",R.drawable.schedule_fill0){navCtrl.navigate("EditTime")}
|
|
}
|
|
if(VERSION.SDK_INT>=23&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
|
|
SubPageItem(R.string.permission_policy,"",R.drawable.key_fill0){navCtrl.navigate("PermissionPolicy")}
|
|
}
|
|
if(VERSION.SDK_INT>=34&&isDeviceOwner(myDpm)){
|
|
SubPageItem(R.string.mte_policy,"",R.drawable.memory_fill0){navCtrl.navigate("MTEPolicy")}
|
|
}
|
|
if(VERSION.SDK_INT>=31&&(isDeviceOwner(myDpm)||isProfileOwner(myDpm))){
|
|
SubPageItem(R.string.nearby_streaming_policy,"",R.drawable.share_fill0){navCtrl.navigate("NearbyStreamingPolicy")}
|
|
}
|
|
if(VERSION.SDK_INT>=28&&isDeviceOwner(myDpm)){
|
|
SubPageItem(R.string.lock_task_feature,"",R.drawable.lock_fill0){navCtrl.navigate("LockTaskFeatures")}
|
|
}
|
|
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
|
SubPageItem(R.string.ca_cert,"",R.drawable.license_fill0){navCtrl.navigate("CaCert")}
|
|
}
|
|
if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){
|
|
SubPageItem(R.string.security_logs,"",R.drawable.description_fill0){navCtrl.navigate("SecurityLogs")}
|
|
}
|
|
if(VERSION.SDK_INT>=23&&isDeviceOwner(myDpm)){
|
|
SubPageItem(R.string.system_update_policy,"",R.drawable.system_update_fill0){navCtrl.navigate("SystemUpdatePolicy")}
|
|
}
|
|
SubPageItem(R.string.wipe_data,"",R.drawable.warning_fill0){navCtrl.navigate("WipeData")}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
LaunchedEffect(Unit){caCert =byteArrayOf()}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun Switches(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext, Receiver::class.java)
|
|
Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
|
SwitchItem(R.string.disable_cam,"", R.drawable.photo_camera_fill0,
|
|
{myDpm.getCameraDisabled(null)},{myDpm.setCameraDisabled(myComponent,it)}
|
|
)
|
|
}
|
|
if(isDeviceOwner(myDpm)||isProfileOwner(myDpm)){
|
|
SwitchItem(R.string.disable_screenshot, stringResource(R.string.also_disable_aosp_screen_record),R.drawable.screenshot_fill0,
|
|
{myDpm.getScreenCaptureDisabled(null)},{myDpm.setScreenCaptureDisabled(myComponent,it) }
|
|
)
|
|
}
|
|
if(VERSION.SDK_INT>=34&&(isDeviceOwner(myDpm)|| (isProfileOwner(myDpm)&&myDpm.isAffiliatedUser))){
|
|
SwitchItem(R.string.disable_status_bar,"",R.drawable.notifications_fill0,
|
|
{myDpm.isStatusBarDisabled},{myDpm.setStatusBarDisabled(myComponent,it) }
|
|
)
|
|
}
|
|
if(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile)){
|
|
if(VERSION.SDK_INT>=30){
|
|
SwitchItem(R.string.auto_time,"",R.drawable.schedule_fill0,
|
|
{myDpm.getAutoTimeEnabled(myComponent)},{myDpm.setAutoTimeEnabled(myComponent,it) }
|
|
)
|
|
SwitchItem(R.string.auto_timezone,"",R.drawable.globe_fill0,
|
|
{myDpm.getAutoTimeZoneEnabled(myComponent)},{myDpm.setAutoTimeZoneEnabled(myComponent,it) }
|
|
)
|
|
}else{
|
|
SwitchItem(R.string.auto_time,"",R.drawable.schedule_fill0,{myDpm.autoTimeRequired},{myDpm.setAutoTimeRequired(myComponent,it)})
|
|
}
|
|
}
|
|
if(isDeviceOwner(myDpm)|| isProfileOwner(myDpm)){
|
|
SwitchItem(R.string.master_mute,"",R.drawable.volume_up_fill0,
|
|
{myDpm.isMasterVolumeMuted(myComponent)},{myDpm.setMasterVolumeMuted(myComponent,it) }
|
|
)
|
|
}
|
|
if(VERSION.SDK_INT>=26&&(isDeviceOwner(myDpm)|| isProfileOwner(myDpm))){
|
|
SwitchItem(R.string.backup_service,"",R.drawable.backup_fill0,
|
|
{myDpm.isBackupServiceEnabled(myComponent)},{myDpm.setBackupServiceEnabled(myComponent,it) }
|
|
)
|
|
}
|
|
if(VERSION.SDK_INT>=23&&(isDeviceOwner(myDpm)|| isProfileOwner(myDpm))){
|
|
SwitchItem(R.string.disable_bt_contact_share,"",R.drawable.account_circle_fill0,
|
|
{myDpm.getBluetoothContactSharingDisabled(myComponent)},{myDpm.setBluetoothContactSharingDisabled(myComponent,it)}
|
|
)
|
|
}
|
|
if(VERSION.SDK_INT>=30&&isDeviceOwner(myDpm)){
|
|
SwitchItem(R.string.common_criteria_mode, stringResource(R.string.common_criteria_mode_desc),R.drawable.security_fill0,
|
|
{myDpm.isCommonCriteriaModeEnabled(myComponent)},{myDpm.setCommonCriteriaModeEnabled(myComponent,it)}
|
|
)
|
|
}
|
|
if(VERSION.SDK_INT>=31&&(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))){
|
|
SwitchItem(
|
|
R.string.usb_signal,"",R.drawable.usb_fill0, {myDpm.isUsbDataSignalingEnabled},
|
|
{
|
|
if(myDpm.canUsbDataSignalingBeDisabled()){
|
|
myDpm.isUsbDataSignalingEnabled = it
|
|
}else{
|
|
Toast.makeText(myContext,myContext.getString(R.string.unsupported),Toast.LENGTH_SHORT).show()
|
|
}
|
|
}
|
|
)
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun Keyguard(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.keyguard), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if(VERSION.SDK_INT>=23){
|
|
Button(
|
|
onClick = {
|
|
Toast.makeText(myContext,
|
|
myContext.getString(if(myDpm.setKeyguardDisabled(myComponent,true)){R.string.success}else{R.string.fail}), Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(myDpm)|| (VERSION.SDK_INT>=28&&isProfileOwner(myDpm)&&myDpm.isAffiliatedUser),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.disable))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
Toast.makeText(myContext,
|
|
myContext.getString(if(myDpm.setKeyguardDisabled(myComponent,false)){R.string.success}else{R.string.fail}), Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(myDpm)|| (VERSION.SDK_INT>=28&&isProfileOwner(myDpm)&&myDpm.isAffiliatedUser),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.enable))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
Information{Text(text = stringResource(R.string.require_no_password_to_disable))}
|
|
Spacer(Modifier.padding(vertical = 8.dp))
|
|
}
|
|
var flag by remember{mutableIntStateOf(0)}
|
|
Button(
|
|
onClick = {myDpm.lockNow()},
|
|
enabled = myDpm.isAdminActive(myComponent),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.lock_now))
|
|
}
|
|
if(VERSION.SDK_INT>=26){ CheckBoxItem(stringResource(R.string.require_enter_password_again),{flag==FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY},{flag = if(flag==0){1}else{0} }) }
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun BugReport(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp)){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Button(
|
|
onClick = {
|
|
val result = myDpm.requestBugreport(myComponent)
|
|
Toast.makeText(myContext, if(result){"成功"}else{"失败"}, Toast.LENGTH_SHORT).show()
|
|
},
|
|
modifier = Modifier.fillMaxWidth(),
|
|
enabled = isDeviceOwner(myDpm)
|
|
) {
|
|
Text(stringResource(R.string.request_bug_report))
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun Reboot(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp)){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Button(
|
|
onClick = {myDpm.reboot(myComponent)},
|
|
enabled = isDeviceOwner(myDpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.reboot))
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun EditTime(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.edit_time), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
var inputTime by remember{mutableStateOf("")}
|
|
Text(text = stringResource(R.string.from_epoch_to_target_time))
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
OutlinedTextField(
|
|
value = inputTime,
|
|
label = { Text(stringResource(R.string.time_unit_ms))},
|
|
onValueChange = {inputTime = it},
|
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
enabled = isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile),
|
|
modifier = Modifier.focusable().fillMaxWidth()
|
|
)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {myDpm.setTime(myComponent,inputTime.toLong())},
|
|
modifier = Modifier.fillMaxWidth(),
|
|
enabled = inputTime!=""&&(isDeviceOwner(myDpm)||(VERSION.SDK_INT>=30&&isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))
|
|
) {
|
|
Text("应用")
|
|
}
|
|
Button(
|
|
onClick = {inputTime = System.currentTimeMillis().toString()},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.get_current_time))
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun PermissionPolicy(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
var selectedPolicy by remember{mutableIntStateOf(myDpm.getPermissionPolicy(myComponent))}
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.permission_policy), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
RadioButtonItem(stringResource(R.string.default_stringres), {selectedPolicy==PERMISSION_POLICY_PROMPT}, {selectedPolicy= PERMISSION_POLICY_PROMPT})
|
|
RadioButtonItem(stringResource(R.string.auto_grant), {selectedPolicy==PERMISSION_POLICY_AUTO_GRANT}, {selectedPolicy= PERMISSION_POLICY_AUTO_GRANT})
|
|
RadioButtonItem(stringResource(R.string.auto_deny), {selectedPolicy==PERMISSION_POLICY_AUTO_DENY}, {selectedPolicy= PERMISSION_POLICY_AUTO_DENY})
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
myDpm.setPermissionPolicy(myComponent,selectedPolicy)
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun MTEPolicy(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.mte_policy), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
var selectedMtePolicy by remember{mutableIntStateOf(myDpm.mtePolicy)}
|
|
RadioButtonItem(stringResource(R.string.decide_by_user), {selectedMtePolicy==MTE_NOT_CONTROLLED_BY_POLICY}, {selectedMtePolicy= MTE_NOT_CONTROLLED_BY_POLICY})
|
|
RadioButtonItem(stringResource(R.string.enabled), {selectedMtePolicy==MTE_ENABLED}, {selectedMtePolicy=MTE_ENABLED})
|
|
RadioButtonItem(stringResource(R.string.disabled), {selectedMtePolicy==MTE_DISABLED}, {selectedMtePolicy=MTE_DISABLED})
|
|
Button(
|
|
onClick = {
|
|
try {
|
|
myDpm.mtePolicy = selectedMtePolicy
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
}catch(e:java.lang.UnsupportedOperationException){
|
|
Toast.makeText(myContext, myContext.getString(R.string.unsupported), Toast.LENGTH_SHORT).show()
|
|
}
|
|
selectedMtePolicy = myDpm.mtePolicy
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Information{Text(stringResource(R.string.mte_policy_desc))}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun NearbyStreamingPolicy(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
var appPolicy by remember{mutableIntStateOf(myDpm.nearbyAppStreamingPolicy)}
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.nearby_app_streaming), style = typography.titleLarge)
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
RadioButtonItem(stringResource(R.string.decide_by_user),{appPolicy == NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY},{appPolicy = NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY})
|
|
RadioButtonItem(stringResource(R.string.enabled),{appPolicy == NEARBY_STREAMING_ENABLED},{appPolicy = NEARBY_STREAMING_ENABLED})
|
|
RadioButtonItem(stringResource(R.string.disabled),{appPolicy == NEARBY_STREAMING_DISABLED},{appPolicy = NEARBY_STREAMING_DISABLED})
|
|
RadioButtonItem(stringResource(R.string.enable_if_secure_enough),{appPolicy == NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY},{appPolicy = NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY})
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
Button(
|
|
onClick = {
|
|
myDpm.nearbyAppStreamingPolicy = appPolicy
|
|
Toast.makeText(myContext, "成功", Toast.LENGTH_SHORT).show()
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text("应用")
|
|
}
|
|
var notificationPolicy by remember{mutableIntStateOf(myDpm.nearbyNotificationStreamingPolicy)}
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.nearby_notification_streaming), style = typography.titleLarge)
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
RadioButtonItem(stringResource(R.string.decide_by_user),{notificationPolicy == NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY},{notificationPolicy = NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY})
|
|
RadioButtonItem(stringResource(R.string.enabled),{notificationPolicy == NEARBY_STREAMING_ENABLED},{notificationPolicy = NEARBY_STREAMING_ENABLED})
|
|
RadioButtonItem(stringResource(R.string.disabled),{notificationPolicy == NEARBY_STREAMING_DISABLED},{notificationPolicy = NEARBY_STREAMING_DISABLED})
|
|
RadioButtonItem(stringResource(R.string.enable_if_secure_enough),{notificationPolicy == NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY},{notificationPolicy = NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY})
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
Button(
|
|
onClick = {
|
|
myDpm.nearbyNotificationStreamingPolicy = notificationPolicy
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun LockTaskFeatures(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
val lockTaskPolicyList = mutableListOf(
|
|
LOCK_TASK_FEATURE_NONE,
|
|
LOCK_TASK_FEATURE_SYSTEM_INFO,
|
|
LOCK_TASK_FEATURE_NOTIFICATIONS,
|
|
LOCK_TASK_FEATURE_HOME,
|
|
LOCK_TASK_FEATURE_OVERVIEW,
|
|
LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
|
|
LOCK_TASK_FEATURE_KEYGUARD
|
|
)
|
|
var sysInfo by remember{mutableStateOf(false)}
|
|
var notifications by remember{mutableStateOf(false)}
|
|
var home by remember{mutableStateOf(false)}
|
|
var overview by remember{mutableStateOf(false)}
|
|
var globalAction by remember{mutableStateOf(false)}
|
|
var keyGuard by remember{mutableStateOf(false)}
|
|
var blockAct by remember{mutableStateOf(false)}
|
|
if(VERSION.SDK_INT>=30){lockTaskPolicyList.add(LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK)}
|
|
var inited by remember{mutableStateOf(false)}
|
|
var custom by remember{mutableStateOf(false)}
|
|
val refreshFeature = {
|
|
var calculate = myDpm.getLockTaskFeatures(myComponent)
|
|
if(calculate!=0){
|
|
if(VERSION.SDK_INT>=30&&calculate-lockTaskPolicyList[7]>=0){blockAct=true;calculate-=lockTaskPolicyList[7]}
|
|
if(calculate-lockTaskPolicyList[6]>=0){keyGuard=true;calculate-=lockTaskPolicyList[6]}
|
|
if(calculate-lockTaskPolicyList[5]>=0){globalAction=true;calculate-=lockTaskPolicyList[5]}
|
|
if(calculate-lockTaskPolicyList[4]>=0){overview=true;calculate-=lockTaskPolicyList[4]}
|
|
if(calculate-lockTaskPolicyList[3]>=0){home=true;calculate-=lockTaskPolicyList[3]}
|
|
if(calculate-lockTaskPolicyList[2]>=0){notifications=true;calculate-=lockTaskPolicyList[2]}
|
|
if(calculate-lockTaskPolicyList[1]>=0){sysInfo=true;calculate-=lockTaskPolicyList[1]}
|
|
}else{
|
|
custom = false
|
|
}
|
|
}
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.lock_task_feature), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if(!inited){ refreshFeature();custom=myDpm.getLockTaskFeatures(myComponent)!=0;inited=true }
|
|
RadioButtonItem(stringResource(R.string.disable_all),{!custom},{custom=false})
|
|
RadioButtonItem(stringResource(R.string.custom),{custom},{custom=true})
|
|
AnimatedVisibility(custom) {
|
|
Column {
|
|
CheckBoxItem(stringResource(R.string.ltf_sys_info),{sysInfo},{sysInfo=!sysInfo})
|
|
CheckBoxItem(stringResource(R.string.ltf_notifications),{notifications},{notifications=!notifications})
|
|
CheckBoxItem(stringResource(R.string.ltf_home),{home},{home=!home})
|
|
CheckBoxItem(stringResource(R.string.ltf_overview),{overview},{overview=!overview})
|
|
CheckBoxItem(stringResource(R.string.ltf_global_actions),{globalAction},{globalAction=!globalAction})
|
|
CheckBoxItem(stringResource(R.string.ltf_keyguard),{keyGuard},{keyGuard=!keyGuard})
|
|
if(VERSION.SDK_INT>=30){ CheckBoxItem(stringResource(R.string.ltf_block_activity_start_in_task),{blockAct},{blockAct=!blockAct}) }
|
|
}
|
|
}
|
|
Button(
|
|
modifier = Modifier.fillMaxWidth(),
|
|
onClick = {
|
|
var result = lockTaskPolicyList[0]
|
|
if(custom){
|
|
if(blockAct&&VERSION.SDK_INT>=30){result+=lockTaskPolicyList[7]}
|
|
if(keyGuard){result+=lockTaskPolicyList[6]}
|
|
if(globalAction){result+=lockTaskPolicyList[5]}
|
|
if(overview){result+=lockTaskPolicyList[4]}
|
|
if(home){result+=lockTaskPolicyList[3]}
|
|
if(notifications){result+=lockTaskPolicyList[2]}
|
|
if(sysInfo){result+=lockTaskPolicyList[1]}
|
|
}
|
|
myDpm.setLockTaskFeatures(myComponent,result)
|
|
refreshFeature()
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
}
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
val whitelist = myDpm.getLockTaskPackages(myComponent).toMutableList()
|
|
var listText by remember{mutableStateOf("")}
|
|
var inputPkg by remember{mutableStateOf("")}
|
|
val refreshWhitelist = {
|
|
inputPkg=""
|
|
listText=""
|
|
listText = whitelist.toText()
|
|
}
|
|
LaunchedEffect(Unit){refreshWhitelist()}
|
|
Text(text = stringResource(R.string.whitelist_app), style = typography.titleLarge)
|
|
SelectionContainer(modifier = Modifier.animateContentSize()){
|
|
Text(text = if(listText==""){ stringResource(R.string.none) }else{listText})
|
|
}
|
|
OutlinedTextField(
|
|
value = inputPkg,
|
|
onValueChange = {inputPkg=it},
|
|
label = {Text(stringResource(R.string.package_name))},
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
modifier = Modifier.focusable().fillMaxWidth().padding(vertical = 3.dp)
|
|
)
|
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
whitelist.add(inputPkg)
|
|
myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
refreshWhitelist()
|
|
},
|
|
modifier = Modifier.fillMaxWidth(0.49F)
|
|
) {
|
|
Text(stringResource(R.string.add))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
if(inputPkg in whitelist){
|
|
whitelist.remove(inputPkg)
|
|
myDpm.setLockTaskPackages(myComponent,whitelist.toTypedArray())
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
}else{
|
|
Toast.makeText(myContext, myContext.getString(R.string.not_exist), Toast.LENGTH_SHORT).show()
|
|
}
|
|
refreshWhitelist()
|
|
},
|
|
modifier = Modifier.fillMaxWidth(0.96F)
|
|
) {
|
|
Text(stringResource(R.string.remove))
|
|
}
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun CaCert(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
var exist by remember{mutableStateOf(false)}
|
|
var isEmpty by remember{mutableStateOf(true)}
|
|
val refresh = {
|
|
isEmpty = caCert.isEmpty()
|
|
exist = if(!isEmpty){ myDpm.hasCaCertInstalled(myComponent, caCert) }else{ false }
|
|
}
|
|
LaunchedEffect(exist){ while(true){ refresh();delay(600) } }
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.ca_cert), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Text(text = if(isEmpty){stringResource(R.string.please_select_ca_cert)}else{stringResource(R.string.cacert_installed, exist)}, modifier = Modifier.animateContentSize())
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
val caCertIntent = Intent(Intent.ACTION_GET_CONTENT)
|
|
caCertIntent.setType("*/*")
|
|
caCertIntent.addCategory(Intent.CATEGORY_OPENABLE)
|
|
getCaCert.launch(caCertIntent)
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.select_ca_cert))
|
|
}
|
|
AnimatedVisibility(!isEmpty) {
|
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween){
|
|
Button(
|
|
onClick = {
|
|
val result = myDpm.installCaCert(myComponent, caCert)
|
|
Toast.makeText(myContext, myContext.getString(if(result){R.string.success}else{R.string.fail}), Toast.LENGTH_SHORT).show()
|
|
refresh()
|
|
},
|
|
modifier = Modifier.fillMaxWidth(0.49F)
|
|
) {
|
|
Text(stringResource(R.string.install))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
if(exist){
|
|
myDpm.uninstallCaCert(myComponent, caCert)
|
|
exist = myDpm.hasCaCertInstalled(myComponent, caCert)
|
|
Toast.makeText(myContext, myContext.getString(if(exist){R.string.fail}else{R.string.success}), Toast.LENGTH_SHORT).show()
|
|
}else{ Toast.makeText(myContext, myContext.getString(R.string.not_exist), Toast.LENGTH_SHORT).show() }
|
|
},
|
|
modifier = Modifier.fillMaxWidth(0.96F)
|
|
) {
|
|
Text(stringResource(R.string.uninstall))
|
|
}
|
|
}
|
|
}
|
|
Button(
|
|
onClick = {
|
|
myDpm.uninstallAllUserCaCerts(myComponent)
|
|
Toast.makeText(myContext, myContext.getString(R.string.success), Toast.LENGTH_SHORT).show()
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
){
|
|
Text(stringResource(R.string.uninstall_all_user_ca_cert))
|
|
}
|
|
}
|
|
}
|
|
|
|
@SuppressLint("NewApi")
|
|
@Composable
|
|
private fun SecurityLogs(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.security_logs), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Text(text = stringResource(R.string.developing))
|
|
SwitchItem(R.string.enable,"",null,{myDpm.isSecurityLoggingEnabled(myComponent)},{myDpm.setSecurityLoggingEnabled(myComponent,it)})
|
|
Button(
|
|
onClick = {
|
|
val log = myDpm.retrieveSecurityLogs(myComponent)
|
|
if(log!=null){
|
|
for(i in log){ Log.d("SecureLog",i.toString()) }
|
|
Toast.makeText(myContext,myContext.getString(R.string.success),Toast.LENGTH_SHORT).show()
|
|
}else{
|
|
Log.d("SecureLog",myContext.getString(R.string.none))
|
|
Toast.makeText(myContext, myContext.getString(R.string.no_logs),Toast.LENGTH_SHORT).show()
|
|
}
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.security_logs))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
val log = myDpm.retrievePreRebootSecurityLogs(myComponent)
|
|
if(log!=null){
|
|
for(i in log){ Log.d("SecureLog",i.toString()) }
|
|
Toast.makeText(myContext,myContext.getString(R.string.success),Toast.LENGTH_SHORT).show()
|
|
}else{
|
|
Log.d("SecureLog",myContext.getString(R.string.none))
|
|
Toast.makeText(myContext,myContext.getString(R.string.no_logs),Toast.LENGTH_SHORT).show()
|
|
}
|
|
},
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.pre_reboot_security_logs))
|
|
}
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun WipeData(){
|
|
val myContext = LocalContext.current
|
|
val userManager = myContext.getSystemService(Context.USER_SERVICE) as UserManager
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
var flag by remember{ mutableIntStateOf(0) }
|
|
var confirmed by remember{ mutableStateOf(false) }
|
|
var externalStorage by remember{mutableStateOf(false)}
|
|
var protectionData by remember{mutableStateOf(false)}
|
|
var euicc by remember{mutableStateOf(false)}
|
|
var silent by remember{mutableStateOf(false)}
|
|
var reason by remember{mutableStateOf("")}
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
Text(text = stringResource(R.string.wipe_data),style = typography.headlineLarge,modifier = Modifier.padding(6.dp),color = colorScheme.error)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
CheckBoxItem(stringResource(R.string.wipe_external_storage),{externalStorage},{externalStorage=!externalStorage;confirmed=false})
|
|
if(VERSION.SDK_INT>=22&&isDeviceOwner(myDpm)){
|
|
CheckBoxItem(stringResource(R.string.wipe_reset_protection_data),{protectionData},{protectionData=!protectionData;confirmed=false})
|
|
}
|
|
if(VERSION.SDK_INT>=28){ CheckBoxItem(stringResource(R.string.wipe_euicc),{euicc},{euicc=!euicc;confirmed=false}) }
|
|
if(VERSION.SDK_INT>=29){ CheckBoxItem(stringResource(R.string.wipe_silently),{silent},{silent=!silent;confirmed=false}) }
|
|
AnimatedVisibility(!silent&&VERSION.SDK_INT>=28) {
|
|
OutlinedTextField(
|
|
value = reason, onValueChange = {reason=it},
|
|
label = {Text(stringResource(R.string.reason))},
|
|
enabled = !confirmed,
|
|
modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp)
|
|
)
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
Button(
|
|
onClick = {
|
|
focusMgr.clearFocus()
|
|
flag = 0
|
|
if(externalStorage){flag += WIPE_EXTERNAL_STORAGE}
|
|
if(protectionData&&VERSION.SDK_INT>=22){flag += WIPE_RESET_PROTECTION_DATA}
|
|
if(euicc&&VERSION.SDK_INT>=28){flag += WIPE_EUICC}
|
|
if(reason==""){silent = true}
|
|
if(silent&&VERSION.SDK_INT>=29){flag += WIPE_SILENTLY}
|
|
confirmed=!confirmed
|
|
},
|
|
colors = ButtonDefaults.buttonColors(
|
|
containerColor = if(confirmed){ colorScheme.primary }else{ colorScheme.error },
|
|
contentColor = if(confirmed){ colorScheme.onPrimary }else{ colorScheme.onError }
|
|
),
|
|
enabled = myDpm.isAdminActive(myComponent),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(text = stringResource(if(confirmed){ R.string.cancel }else{ R.string.confirm }))
|
|
}
|
|
Button(
|
|
onClick = {
|
|
if(VERSION.SDK_INT>=28&&reason!=""){
|
|
myDpm.wipeData(flag,reason)
|
|
}else{
|
|
myDpm.wipeData(flag)
|
|
}
|
|
},
|
|
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
|
enabled = confirmed&&(VERSION.SDK_INT<34||(VERSION.SDK_INT>=34&&!userManager.isSystemUser)),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text("WipeData")
|
|
}
|
|
if (VERSION.SDK_INT >= 34&&(isDeviceOwner(myDpm)||(isProfileOwner(myDpm)&&myDpm.isOrganizationOwnedDeviceWithManagedProfile))) {
|
|
Button(
|
|
onClick = {myDpm.wipeDevice(flag)},
|
|
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
|
enabled = confirmed,
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text("WipeDevice")
|
|
}
|
|
}
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
if(VERSION.SDK_INT>=24&&isProfileOwner(myDpm)&&myDpm.isManagedProfile(myComponent)){
|
|
Information{Text(text = stringResource(R.string.will_delete_work_profile))}
|
|
}
|
|
if(VERSION.SDK_INT>=34&&Binder.getCallingUid()/100000==0){
|
|
Information{Text(text = stringResource(R.string.api34_or_above_wipedata_cannot_in_system_user))}
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
}
|
|
}
|
|
|
|
@Composable
|
|
private fun SysUpdatePolicy(){
|
|
val myContext = LocalContext.current
|
|
val myDpm = myContext.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
val myComponent = ComponentName(myContext,Receiver::class.java)
|
|
val focusMgr = LocalFocusManager.current
|
|
val sharedPref = myContext.getSharedPreferences("data", Context.MODE_PRIVATE)
|
|
val isWear = sharedPref.getBoolean("isWear",false)
|
|
val bodyTextStyle = if(isWear){ typography.bodyMedium}else{typography.bodyLarge}
|
|
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp).verticalScroll(rememberScrollState())){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
if(VERSION.SDK_INT>=23){
|
|
Column {
|
|
var selectedPolicy by remember{ mutableStateOf(myDpm.systemUpdatePolicy?.policyType) }
|
|
Text(text = stringResource(R.string.system_update_policy), style = typography.headlineLarge)
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
RadioButtonItem(stringResource(R.string.system_update_policy_automatic),{selectedPolicy==TYPE_INSTALL_AUTOMATIC},{selectedPolicy= TYPE_INSTALL_AUTOMATIC})
|
|
RadioButtonItem(stringResource(R.string.system_update_policy_install_windowed),{selectedPolicy==TYPE_INSTALL_WINDOWED},{selectedPolicy= TYPE_INSTALL_WINDOWED})
|
|
RadioButtonItem(stringResource(R.string.system_update_policy_postpone),{selectedPolicy==TYPE_POSTPONE},{selectedPolicy= TYPE_POSTPONE})
|
|
RadioButtonItem(stringResource(R.string.none),{selectedPolicy == null},{selectedPolicy=null})
|
|
var windowedPolicyStart by remember{ mutableStateOf("") }
|
|
var windowedPolicyEnd by remember{ mutableStateOf("") }
|
|
if(selectedPolicy==2){
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
OutlinedTextField(
|
|
value = windowedPolicyStart,
|
|
label = { Text(stringResource(R.string.start_time))},
|
|
onValueChange = {windowedPolicyStart=it},
|
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
modifier = Modifier.focusable().fillMaxWidth(0.5F)
|
|
)
|
|
Spacer(Modifier.padding(horizontal = 3.dp))
|
|
OutlinedTextField(
|
|
value = windowedPolicyEnd,
|
|
onValueChange = {windowedPolicyEnd=it},
|
|
label = {Text(stringResource(R.string.end_time))},
|
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
|
keyboardActions = KeyboardActions(onDone = {focusMgr.clearFocus()}),
|
|
modifier = Modifier.focusable().fillMaxWidth()
|
|
)
|
|
Spacer(Modifier.padding(vertical = 3.dp))
|
|
Text(text = stringResource(R.string.minutes_in_one_day), style = bodyTextStyle)
|
|
}
|
|
Button(
|
|
onClick = {
|
|
val policy =
|
|
when(selectedPolicy){
|
|
TYPE_INSTALL_AUTOMATIC-> SystemUpdatePolicy.createAutomaticInstallPolicy()
|
|
TYPE_INSTALL_WINDOWED-> SystemUpdatePolicy.createWindowedInstallPolicy(windowedPolicyStart.toInt(),windowedPolicyEnd.toInt())
|
|
TYPE_POSTPONE-> SystemUpdatePolicy.createPostponeInstallPolicy()
|
|
else->null
|
|
}
|
|
myDpm.setSystemUpdatePolicy(myComponent,policy)
|
|
Toast.makeText(myContext, "成功!", Toast.LENGTH_SHORT).show()
|
|
},
|
|
enabled = isDeviceOwner(myDpm),
|
|
modifier = Modifier.fillMaxWidth()
|
|
) {
|
|
Text(stringResource(R.string.apply))
|
|
}
|
|
}
|
|
}
|
|
if(VERSION.SDK_INT>=26){
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
val sysUpdateInfo = myDpm.getPendingSystemUpdate(myComponent)
|
|
Column {
|
|
if(sysUpdateInfo!=null){
|
|
Text(text = stringResource(R.string.update_received_time, Date(sysUpdateInfo.receivedTime)), style = bodyTextStyle)
|
|
val securityStateDesc = when(sysUpdateInfo.securityPatchState){
|
|
SystemUpdateInfo.SECURITY_PATCH_STATE_UNKNOWN-> stringResource(R.string.unknown)
|
|
SystemUpdateInfo.SECURITY_PATCH_STATE_TRUE->"true"
|
|
else->"false"
|
|
}
|
|
Text(text = stringResource(R.string.is_security_patch, securityStateDesc), style = bodyTextStyle)
|
|
}else{
|
|
Text(text = stringResource(R.string.no_system_update), style = bodyTextStyle)
|
|
}
|
|
}
|
|
}
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
/*if(VERSION.SDK_INT>=29){
|
|
Column(modifier = sections()){
|
|
var resultUri by remember{mutableStateOf(otaUri)}
|
|
Text(text = "安装系统更新", style = typography.titleLarge)
|
|
Button(
|
|
onClick = {
|
|
val getUri = Intent(Intent.ACTION_GET_CONTENT)
|
|
getUri.setType("application/zip")
|
|
getUri.addCategory(Intent.CATEGORY_OPENABLE)
|
|
getOtaPackage.launch(getUri)
|
|
},
|
|
modifier = Modifier.fillMaxWidth(),
|
|
enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm)
|
|
) {
|
|
Text("选择OTA包")
|
|
}
|
|
Button(
|
|
onClick = {resultUri = otaUri},
|
|
modifier = Modifier.fillMaxWidth(),
|
|
enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm)
|
|
) {
|
|
Text("查看OTA包详情")
|
|
}
|
|
Text("URI: $resultUri")
|
|
if(installOta){
|
|
Button(
|
|
onClick = {
|
|
val sysUpdateExecutor = Executors.newCachedThreadPool()
|
|
val sysUpdateCallback:InstallSystemUpdateCallback = InstallSystemUpdateCallback
|
|
myDpm.installSystemUpdate(myComponent,resultUri,sysUpdateExecutor,sysUpdateCallback)
|
|
},
|
|
enabled = isDeviceOwner(myDpm)||isProfileOwner(myDpm)
|
|
){
|
|
Text("安装")
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
}
|
|
}
|