|
|
|
|
@@ -1,6 +1,8 @@
|
|
|
|
|
package com.bintianqi.owndroid.dpm
|
|
|
|
|
|
|
|
|
|
import android.annotation.SuppressLint
|
|
|
|
|
import android.app.ActivityOptions
|
|
|
|
|
import android.app.AlertDialog
|
|
|
|
|
import android.app.admin.DevicePolicyManager
|
|
|
|
|
import android.app.admin.DevicePolicyManager.FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY
|
|
|
|
|
import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback
|
|
|
|
|
@@ -8,7 +10,6 @@ import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_ST
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW
|
|
|
|
|
import android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO
|
|
|
|
|
@@ -97,6 +98,7 @@ import com.bintianqi.owndroid.Receiver
|
|
|
|
|
import com.bintianqi.owndroid.fileUriFlow
|
|
|
|
|
import com.bintianqi.owndroid.getFile
|
|
|
|
|
import com.bintianqi.owndroid.toText
|
|
|
|
|
import com.bintianqi.owndroid.toggle
|
|
|
|
|
import com.bintianqi.owndroid.ui.Animations
|
|
|
|
|
import com.bintianqi.owndroid.ui.CheckBoxItem
|
|
|
|
|
import com.bintianqi.owndroid.ui.Information
|
|
|
|
|
@@ -108,6 +110,7 @@ import com.bintianqi.owndroid.uriToStream
|
|
|
|
|
import java.util.Date
|
|
|
|
|
import java.util.TimeZone
|
|
|
|
|
import java.util.concurrent.Executors
|
|
|
|
|
import kotlin.math.pow
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
fun SystemManage(navCtrl:NavHostController) {
|
|
|
|
|
@@ -144,7 +147,7 @@ fun SystemManage(navCtrl:NavHostController) {
|
|
|
|
|
composable(route = "PermissionPolicy") { PermissionPolicy() }
|
|
|
|
|
composable(route = "MTEPolicy") { MTEPolicy() }
|
|
|
|
|
composable(route = "NearbyStreamingPolicy") { NearbyStreamingPolicy() }
|
|
|
|
|
composable(route = "LockTaskFeatures") { LockTaskFeatures() }
|
|
|
|
|
composable(route = "LockTaskMode") { LockTaskMode() }
|
|
|
|
|
composable(route = "CaCert") { CaCert() }
|
|
|
|
|
composable(route = "SecurityLogs") { SecurityLogs() }
|
|
|
|
|
composable(route = "SystemUpdatePolicy") { SysUpdatePolicy() }
|
|
|
|
|
@@ -196,7 +199,7 @@ private fun Home(navCtrl: NavHostController, scrollState: ScrollState, rebootDia
|
|
|
|
|
SubPageItem(R.string.nearby_streaming_policy, "", R.drawable.share_fill0) { navCtrl.navigate("NearbyStreamingPolicy") }
|
|
|
|
|
}
|
|
|
|
|
if(VERSION.SDK_INT >= 28 && isDeviceOwner(dpm)) {
|
|
|
|
|
SubPageItem(R.string.lock_task_feature, "", R.drawable.lock_fill0) { navCtrl.navigate("LockTaskFeatures") }
|
|
|
|
|
SubPageItem(R.string.lock_task_mode, "", R.drawable.lock_fill0) { navCtrl.navigate("LockTaskMode") }
|
|
|
|
|
}
|
|
|
|
|
if(isDeviceOwner(dpm) || isProfileOwner(dpm)) {
|
|
|
|
|
SubPageItem(R.string.ca_cert, "", R.drawable.license_fill0) { navCtrl.navigate("CaCert") }
|
|
|
|
|
@@ -642,41 +645,29 @@ private fun NearbyStreamingPolicy() {
|
|
|
|
|
|
|
|
|
|
@SuppressLint("NewApi")
|
|
|
|
|
@Composable
|
|
|
|
|
private fun LockTaskFeatures() {
|
|
|
|
|
private fun LockTaskMode() {
|
|
|
|
|
val context = LocalContext.current
|
|
|
|
|
val dpm = context.getSystemService(ComponentActivity.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
|
|
|
|
val receiver = ComponentName(context,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) }
|
|
|
|
|
val lockTaskFeatures = remember { mutableStateListOf<Int>() }
|
|
|
|
|
var custom by remember { mutableStateOf(false) }
|
|
|
|
|
val refreshFeature = {
|
|
|
|
|
var calculate = dpm.getLockTaskFeatures(receiver)
|
|
|
|
|
lockTaskFeatures.clear()
|
|
|
|
|
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] }
|
|
|
|
|
var sq = 10
|
|
|
|
|
while(sq >= 1) {
|
|
|
|
|
val current = (2).toDouble().pow(sq.toDouble()).toInt()
|
|
|
|
|
if(calculate - current >= 0) {
|
|
|
|
|
lockTaskFeatures += current
|
|
|
|
|
calculate -= current
|
|
|
|
|
}
|
|
|
|
|
sq--
|
|
|
|
|
}
|
|
|
|
|
if(calculate - 1 >= 0) { lockTaskFeatures += 1 }
|
|
|
|
|
custom = true
|
|
|
|
|
}else{
|
|
|
|
|
custom = false
|
|
|
|
|
}
|
|
|
|
|
@@ -684,57 +675,87 @@ private fun LockTaskFeatures() {
|
|
|
|
|
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=dpm.getLockTaskFeatures(receiver)!=0; inited= true }
|
|
|
|
|
LaunchedEffect(Unit) { refreshFeature() }
|
|
|
|
|
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 = it })
|
|
|
|
|
CheckBoxItem(stringResource(R.string.ltf_notifications), notifications, { notifications = it })
|
|
|
|
|
CheckBoxItem(stringResource(R.string.ltf_home), home, { home = it })
|
|
|
|
|
CheckBoxItem(stringResource(R.string.ltf_overview), overview, { overview = it })
|
|
|
|
|
CheckBoxItem(stringResource(R.string.ltf_global_actions), globalAction, { globalAction = it })
|
|
|
|
|
CheckBoxItem(stringResource(R.string.ltf_keyguard), keyGuard, { keyGuard = it })
|
|
|
|
|
if(VERSION.SDK_INT >= 30) { CheckBoxItem(stringResource(R.string.ltf_block_activity_start_in_task), blockAct, { blockAct = it }) }
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_sys_info),
|
|
|
|
|
LOCK_TASK_FEATURE_SYSTEM_INFO in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_SYSTEM_INFO) }
|
|
|
|
|
)
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_notifications),
|
|
|
|
|
LOCK_TASK_FEATURE_NOTIFICATIONS in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_NOTIFICATIONS) }
|
|
|
|
|
)
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_home),
|
|
|
|
|
LOCK_TASK_FEATURE_HOME in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_HOME) }
|
|
|
|
|
)
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_overview),
|
|
|
|
|
LOCK_TASK_FEATURE_OVERVIEW in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_OVERVIEW) }
|
|
|
|
|
)
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_global_actions),
|
|
|
|
|
LOCK_TASK_FEATURE_GLOBAL_ACTIONS in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_GLOBAL_ACTIONS) }
|
|
|
|
|
)
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_keyguard),
|
|
|
|
|
LOCK_TASK_FEATURE_KEYGUARD in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_KEYGUARD) }
|
|
|
|
|
)
|
|
|
|
|
if(VERSION.SDK_INT >= 30) {
|
|
|
|
|
CheckBoxItem(
|
|
|
|
|
stringResource(R.string.ltf_block_activity_start_in_task),
|
|
|
|
|
LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK in lockTaskFeatures,
|
|
|
|
|
{ lockTaskFeatures.toggle(it, LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK) }
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Button(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
onClick = {
|
|
|
|
|
var result = lockTaskPolicyList[0]
|
|
|
|
|
var result = 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] }
|
|
|
|
|
lockTaskFeatures.forEach { result += it }
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
dpm.setLockTaskFeatures(receiver,result)
|
|
|
|
|
refreshFeature()
|
|
|
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
|
|
|
} catch (e: IllegalArgumentException) {
|
|
|
|
|
AlertDialog.Builder(context)
|
|
|
|
|
.setTitle("Error")
|
|
|
|
|
.setMessage(e.message)
|
|
|
|
|
.setPositiveButton(R.string.confirm) { dialog, _ -> dialog.dismiss() }
|
|
|
|
|
.show()
|
|
|
|
|
}
|
|
|
|
|
refreshFeature()
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
Text(stringResource(R.string.apply))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val lockTaskPackages = remember { mutableStateListOf<String>() }
|
|
|
|
|
var inputLockTaskPkg by remember { mutableStateOf("") }
|
|
|
|
|
LaunchedEffect(Unit) { lockTaskPackages.addAll(dpm.getLockTaskPackages(receiver)) }
|
|
|
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
|
|
|
Text(text = stringResource(R.string.lock_task_packages), style = typography.headlineLarge)
|
|
|
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
|
|
|
val whitelist = dpm.getLockTaskPackages(receiver).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)
|
|
|
|
|
var listText = ""
|
|
|
|
|
lockTaskPackages.forEach { listText += "\n" + it }
|
|
|
|
|
Text(text = stringResource(R.string.app_list_is) + if(listText == "") stringResource(R.string.none) else listText)
|
|
|
|
|
}
|
|
|
|
|
OutlinedTextField(
|
|
|
|
|
value = inputPkg,
|
|
|
|
|
onValueChange = { inputPkg = it },
|
|
|
|
|
value = inputLockTaskPkg,
|
|
|
|
|
onValueChange = { inputLockTaskPkg = it },
|
|
|
|
|
label = { Text(stringResource(R.string.package_name)) },
|
|
|
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
|
|
|
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
|
|
|
|
@@ -743,11 +764,8 @@ private fun LockTaskFeatures() {
|
|
|
|
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
|
|
|
|
Button(
|
|
|
|
|
onClick = {
|
|
|
|
|
focusMgr.clearFocus()
|
|
|
|
|
whitelist.add(inputPkg)
|
|
|
|
|
dpm.setLockTaskPackages(receiver,whitelist.toTypedArray())
|
|
|
|
|
lockTaskPackages.add(inputLockTaskPkg)
|
|
|
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
|
|
|
refreshWhitelist()
|
|
|
|
|
},
|
|
|
|
|
modifier = Modifier.fillMaxWidth(0.49F)
|
|
|
|
|
) {
|
|
|
|
|
@@ -755,21 +773,54 @@ private fun LockTaskFeatures() {
|
|
|
|
|
}
|
|
|
|
|
Button(
|
|
|
|
|
onClick = {
|
|
|
|
|
focusMgr.clearFocus()
|
|
|
|
|
if(inputPkg in whitelist) {
|
|
|
|
|
whitelist.remove(inputPkg)
|
|
|
|
|
dpm.setLockTaskPackages(receiver,whitelist.toTypedArray())
|
|
|
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
|
|
|
} else {
|
|
|
|
|
Toast.makeText(context, R.string.not_exist, Toast.LENGTH_SHORT).show()
|
|
|
|
|
}
|
|
|
|
|
refreshWhitelist()
|
|
|
|
|
Toast.makeText(context, if(lockTaskPackages.remove(inputLockTaskPkg)) R.string.success else R.string.not_exist, Toast.LENGTH_SHORT).show()
|
|
|
|
|
},
|
|
|
|
|
modifier = Modifier.fillMaxWidth(0.96F)
|
|
|
|
|
) {
|
|
|
|
|
Text(stringResource(R.string.remove))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Button(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
onClick = {
|
|
|
|
|
dpm.setLockTaskPackages(receiver, lockTaskPackages.toTypedArray())
|
|
|
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
Text(stringResource(R.string.apply))
|
|
|
|
|
}
|
|
|
|
|
var startLockTaskApp by remember { mutableStateOf("") }
|
|
|
|
|
Spacer(Modifier.padding(vertical = 10.dp))
|
|
|
|
|
Text(text = stringResource(R.string.start_lock_task_mode), style = typography.headlineLarge)
|
|
|
|
|
Spacer(Modifier.padding(vertical = 5.dp))
|
|
|
|
|
OutlinedTextField(
|
|
|
|
|
value = startLockTaskApp,
|
|
|
|
|
onValueChange = { startLockTaskApp = it },
|
|
|
|
|
label = { Text(stringResource(R.string.package_name)) },
|
|
|
|
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
|
|
|
|
keyboardActions = KeyboardActions(onDone = { focusMgr.clearFocus() }),
|
|
|
|
|
modifier = Modifier.fillMaxWidth().padding(vertical = 3.dp)
|
|
|
|
|
)
|
|
|
|
|
Button(
|
|
|
|
|
modifier = Modifier.fillMaxWidth(),
|
|
|
|
|
onClick = {
|
|
|
|
|
if(!dpm.getLockTaskPackages(receiver).contains(startLockTaskApp)) {
|
|
|
|
|
Toast.makeText(context, R.string.app_not_allowed, Toast.LENGTH_SHORT).show()
|
|
|
|
|
return@Button
|
|
|
|
|
}
|
|
|
|
|
val options = ActivityOptions.makeBasic().setLockTaskEnabled(true)
|
|
|
|
|
val packageManager = context.packageManager
|
|
|
|
|
val launchIntent = packageManager.getLaunchIntentForPackage(startLockTaskApp)
|
|
|
|
|
if (launchIntent != null) {
|
|
|
|
|
context.startActivity(launchIntent, options.toBundle())
|
|
|
|
|
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
|
|
|
|
|
} else {
|
|
|
|
|
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
) {
|
|
|
|
|
Text(stringResource(R.string.start))
|
|
|
|
|
}
|
|
|
|
|
Spacer(Modifier.padding(vertical = 30.dp))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|