start lock task mode (#36)

This commit is contained in:
BinTianqi
2024-07-17 11:58:20 +08:00
parent 7156e1ebeb
commit 8f8ed1ec57
5 changed files with 141 additions and 74 deletions

View File

@@ -55,6 +55,10 @@ fun Set<Any>.toText(): String{
return output
}
fun MutableList<Int>.toggle(status: Boolean, element: Int) {
if(status) add(element) else remove(element)
}
fun writeClipBoard(context: Context, string: String):Boolean{
val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
try {

View File

@@ -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)
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] }
lockTaskFeatures.clear()
if(calculate != 0) {
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)
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()
}
dpm.setLockTaskFeatures(receiver,result)
refreshFeature()
Toast.makeText(context, R.string.success, Toast.LENGTH_SHORT).show()
}
) {
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))
}
}

View File

@@ -151,7 +151,11 @@
<string name="nearby_streaming_policy">Yakındaki akış politikası</string>
<string name="nearby_notification_streaming">Yakındaki bildirim akış politikası</string>
<string name="enable_if_secure_enough">Yalnızca aynı yönetilen hesap</string>
<string name="lock_task_mode">Lock task mode</string> <!--TODO-->
<string name="lock_task_feature">Görev kilitleme özelliği</string>
<string name="lock_task_packages">Lock task packages</string> <!--TODO-->
<string name="start_lock_task_mode">Start lock task mode</string> <!--TODO-->
<string name="app_not_allowed">App not allowed</string> <!--TODO-->
<string name="disable_all">Hepsini devre dışı bırak</string>
<!--ltf: lock task feature-->

View File

@@ -146,7 +146,11 @@
<string name="nearby_streaming_policy">附近流式传输策略</string>
<string name="nearby_notification_streaming">附近通知传输</string>
<string name="enable_if_secure_enough">在足够安全时启用</string>
<string name="lock_task_mode">锁定任务模式</string>
<string name="lock_task_feature">锁定任务功能</string>
<string name="lock_task_packages">锁定任务应用</string>
<string name="start_lock_task_mode">启动锁定任务模式</string>
<string name="app_not_allowed">应用未被允许</string>
<string name="disable_all">禁用全部</string>
<string name="ltf_sys_info">允许状态栏信息</string>
<string name="ltf_notifications">允许通知</string>

View File

@@ -157,7 +157,11 @@
<string name="nearby_streaming_policy">Nearby streaming policy</string>
<string name="nearby_notification_streaming">Nearby notification streaming policy</string>
<string name="enable_if_secure_enough">Same managed account only</string>
<string name="lock_task_mode">Lock task mode</string>
<string name="lock_task_feature">Lock task feature</string>
<string name="lock_task_packages">Lock task packages</string>
<string name="start_lock_task_mode">Start lock task mode</string>
<string name="app_not_allowed">App not allowed</string>
<string name="disable_all">Disable all</string>
<!--ltf: lock task feature-->
<string name="ltf_sys_info">Allow system info</string>