mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-26 03:56:00 +00:00
Add Privilege class
This commit is contained in:
@@ -76,6 +76,7 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.AppInfo
|
||||
import com.bintianqi.owndroid.AppInstallerActivity
|
||||
import com.bintianqi.owndroid.AppInstallerViewModel
|
||||
@@ -84,6 +85,7 @@ import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.getInstalledAppsFlags
|
||||
import com.bintianqi.owndroid.installedApps
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.ErrorDialog
|
||||
import com.bintianqi.owndroid.ui.FullWidthRadioButtonItem
|
||||
@@ -179,14 +181,11 @@ fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Un
|
||||
.verticalScroll(rememberScrollState())
|
||||
.padding(bottom = 80.dp)
|
||||
) {
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
if(VERSION.SDK_INT >= 24) FunctionItem(R.string.suspend, icon = R.drawable.block_fill0) { onNavigate(Suspend) }
|
||||
FunctionItem(R.string.hide, icon = R.drawable.visibility_off_fill0) { onNavigate(Hide) }
|
||||
FunctionItem(R.string.block_uninstall, icon = R.drawable.delete_forever_fill0) { onNavigate(BlockUninstall) }
|
||||
if(VERSION.SDK_INT >= 30 && (deviceOwner || (VERSION.SDK_INT >= 33 && profileOwner))) {
|
||||
if(VERSION.SDK_INT >= 30 && (privilege.device || (VERSION.SDK_INT >= 33 && privilege.profile))) {
|
||||
FunctionItem(R.string.disable_user_control, icon = R.drawable.do_not_touch_fill0) { onNavigate(DisableUserControl) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
@@ -202,19 +201,19 @@ fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Un
|
||||
context.startActivity(Intent(context, AppInstallerActivity::class.java))
|
||||
}
|
||||
FunctionItem(R.string.uninstall_app, icon = R.drawable.delete_fill0) { onNavigate(UninstallApp) }
|
||||
if(VERSION.SDK_INT >= 28 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.keep_uninstalled_packages, icon = R.drawable.delete_fill0) { onNavigate(KeepUninstalledPackages) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28) FunctionItem(R.string.install_existing_app, icon = R.drawable.install_mobile_fill0) {
|
||||
onNavigate(InstallExistingApp)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 30 && profileOwner && dpm.isManagedProfile(receiver)) {
|
||||
if(VERSION.SDK_INT >= 30 && privilege.work) {
|
||||
FunctionItem(R.string.cross_profile_apps, icon = R.drawable.work_fill0) { onNavigate(CrossProfilePackages) }
|
||||
}
|
||||
if(profileOwner) {
|
||||
if(privilege.work) {
|
||||
FunctionItem(R.string.cross_profile_widget, icon = R.drawable.widgets_fill0) { onNavigate(CrossProfileWidgetProviders) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 34 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 34 && privilege.device) {
|
||||
FunctionItem(R.string.credential_manager_policy, icon = R.drawable.license_fill0) { onNavigate(CredentialManagerPolicy) }
|
||||
}
|
||||
FunctionItem(R.string.permitted_accessibility_services, icon = R.drawable.settings_accessibility_fill0) {
|
||||
@@ -222,7 +221,7 @@ fun ApplicationsFeaturesScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Un
|
||||
}
|
||||
FunctionItem(R.string.permitted_ime, icon = R.drawable.keyboard_fill0) { onNavigate(PermittedInputMethods) }
|
||||
FunctionItem(R.string.enable_system_app, icon = R.drawable.enable_fill0) { onNavigate(EnableSystemApp) }
|
||||
if(VERSION.SDK_INT >= 34 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT >= 34 && (privilege.device || privilege.work)) {
|
||||
FunctionItem(R.string.set_default_dialer, icon = R.drawable.call_fill0) { onNavigate(SetDefaultDialer) }
|
||||
}
|
||||
}
|
||||
@@ -445,9 +444,9 @@ fun DisableUserControlScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
LaunchedEffect(Unit) { refresh() }
|
||||
MyLazyScaffold(R.string.disable_user_control, onNavigateUp) {
|
||||
items(packages, { it.name }) {
|
||||
ApplicationItem(it) {
|
||||
dpm.setUserControlDisabledPackages(receiver, packages.minus(it).map { it.name })
|
||||
items(packages, { it.name }) { info ->
|
||||
ApplicationItem(info) {
|
||||
dpm.setUserControlDisabledPackages(receiver, packages.minus(info).map { it.name })
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
@@ -477,6 +476,7 @@ fun PermissionsManagerScreen(onNavigateUp: () -> Unit, param: PermissionsManager
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var packageName by remember { mutableStateOf(packageNameParam ?: "") }
|
||||
var selectedPermission by remember { mutableStateOf<PermissionItem?>(null) }
|
||||
val statusMap = remember { mutableStateMapOf<String, Int>() }
|
||||
@@ -551,7 +551,7 @@ fun PermissionsManagerScreen(onNavigateUp: () -> Unit, param: PermissionsManager
|
||||
Column {
|
||||
Text(selectedPermission!!.permission)
|
||||
Spacer(Modifier.padding(vertical = 4.dp))
|
||||
if(!(VERSION.SDK_INT >= 31 && selectedPermission!!.profileOwnerRestricted && context.isProfileOwner)) {
|
||||
if(!(VERSION.SDK_INT >= 31 && selectedPermission!!.profileOwnerRestricted && privilege.profile)) {
|
||||
GrantPermissionItem(R.string.granted, PERMISSION_GRANT_STATE_GRANTED)
|
||||
}
|
||||
GrantPermissionItem(R.string.denied, PERMISSION_GRANT_STATE_DENIED)
|
||||
@@ -581,9 +581,9 @@ fun DisableMeteredDataScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
LaunchedEffect(Unit) { refresh() }
|
||||
MyLazyScaffold(R.string.disable_metered_data, onNavigateUp) {
|
||||
items(packages, { it.name }) {
|
||||
ApplicationItem(it) {
|
||||
dpm.setMeteredDataDisabledPackages(receiver, packages.minus(it).map { it.name })
|
||||
items(packages, { it.name }) { info ->
|
||||
ApplicationItem(info) {
|
||||
dpm.setMeteredDataDisabledPackages(receiver, packages.minus(info).map { it.name })
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
@@ -732,9 +732,9 @@ fun KeepUninstalledPackagesScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
LaunchedEffect(Unit) { refresh() }
|
||||
MyLazyScaffold(R.string.keep_uninstalled_packages, onNavigateUp) {
|
||||
items(packages, { it.name }) {
|
||||
ApplicationItem(it) {
|
||||
dpm.setKeepUninstalledPackages(receiver, packages.minus(it).map { it.name })
|
||||
items(packages, { it.name }) { info ->
|
||||
ApplicationItem(info) {
|
||||
dpm.setKeepUninstalledPackages(receiver, packages.minus(info).map { it.name })
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
@@ -798,9 +798,9 @@ fun CrossProfilePackagesScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
LaunchedEffect(Unit) { refresh() }
|
||||
MyLazyScaffold(R.string.cross_profile_apps, onNavigateUp) {
|
||||
items(packages, { it.name }) {
|
||||
ApplicationItem(it) {
|
||||
dpm.setCrossProfilePackages(receiver, packages.minus(it).map { it.name }.toSet())
|
||||
items(packages, { it.name }) { info ->
|
||||
ApplicationItem(info) {
|
||||
dpm.setCrossProfilePackages(receiver, packages.minus(info).map { it.name }.toSet())
|
||||
refresh()
|
||||
}
|
||||
}
|
||||
@@ -1062,6 +1062,7 @@ fun EnableSystemAppScreen(onNavigateUp: () -> Unit) {
|
||||
) {
|
||||
Text(stringResource(R.string.enable))
|
||||
}
|
||||
Notes(R.string.enable_system_app)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,17 +14,21 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.IPackageInstaller
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.graphics.drawable.Icon
|
||||
import android.os.Build.VERSION
|
||||
import android.os.UserManager
|
||||
import android.util.Log
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.graphics.drawable.toBitmap
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.Receiver
|
||||
import com.bintianqi.owndroid.SharedPrefs
|
||||
import com.bintianqi.owndroid.ShortcutsReceiverActivity
|
||||
import com.bintianqi.owndroid.backToHomeStateFlow
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.rosan.dhizuku.api.Dhizuku
|
||||
import com.rosan.dhizuku.api.Dhizuku.binderWrapper
|
||||
import com.rosan.dhizuku.api.DhizukuBinderWrapper
|
||||
@@ -39,8 +43,6 @@ import kotlinx.serialization.json.put
|
||||
import kotlinx.serialization.json.putJsonArray
|
||||
import java.io.OutputStream
|
||||
|
||||
lateinit var addDeviceAdmin: ActivityResultLauncher<Intent>
|
||||
|
||||
val Context.isDeviceOwner: Boolean
|
||||
get() {
|
||||
val dpm = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
|
||||
@@ -59,11 +61,6 @@ val Context.isProfileOwner: Boolean
|
||||
return dpm.isProfileOwnerApp("com.bintianqi.owndroid")
|
||||
}
|
||||
|
||||
val Context.isDeviceAdmin: Boolean
|
||||
get() {
|
||||
return getDPM().isAdminActive(getReceiver())
|
||||
}
|
||||
|
||||
val Context.dpcPackageName: String
|
||||
get() {
|
||||
return if(SharedPrefs(this).dhizuku) {
|
||||
@@ -73,10 +70,6 @@ val Context.dpcPackageName: String
|
||||
}
|
||||
}
|
||||
|
||||
fun DevicePolicyManager.isOrgProfile(receiver: ComponentName): Boolean {
|
||||
return VERSION.SDK_INT >= 30 && this.isProfileOwnerApp("com.bintianqi.owndroid") && isManagedProfile(receiver) && isOrganizationOwnedDeviceWithManagedProfile
|
||||
}
|
||||
|
||||
@SuppressLint("PrivateApi")
|
||||
private fun binderWrapperDevicePolicyManager(appContext: Context): DevicePolicyManager? {
|
||||
try {
|
||||
@@ -544,10 +537,10 @@ fun parseSecurityEventData(event: SecurityLog.SecurityEvent): JsonElement? {
|
||||
fun setDefaultAffiliationID(context: Context) {
|
||||
if(VERSION.SDK_INT < 26) return
|
||||
val sp = SharedPrefs(context)
|
||||
val privilege = myPrivilege.value
|
||||
if(!sp.isDefaultAffiliationIdSet) {
|
||||
try {
|
||||
val um = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
if(context.isDeviceOwner || (!um.isSystemUser && context.isProfileOwner)) {
|
||||
if(privilege.device || (!privilege.primary && privilege.profile)) {
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val affiliationIDs = dpm.getAffiliationIds(receiver)
|
||||
@@ -596,3 +589,31 @@ fun parsePackageInstallerMessage(context: Context, result: Intent): String {
|
||||
else -> ""
|
||||
} + statusMessage.let { if(it == null) "" else "\n$it" }
|
||||
}
|
||||
|
||||
|
||||
fun handlePrivilegeChange(context: Context) {
|
||||
val privilege = myPrivilege.value
|
||||
val activated = privilege.device || privilege.profile
|
||||
if(activated) {
|
||||
if(!privilege.dhizuku) {
|
||||
setDefaultAffiliationID(context)
|
||||
if(VERSION.SDK_INT >= 25) {
|
||||
val sm = context.getSystemService(ShortcutManager::class.java)
|
||||
val lockIntent = Intent("com.bintianqi.owndroid.action.LOCK")
|
||||
.setComponent(ComponentName(context, ShortcutsReceiverActivity::class.java))
|
||||
val shortcut = ShortcutInfo.Builder(context, "LockScreen")
|
||||
.setShortLabel(context.getString(R.string.lock_now))
|
||||
.setIcon(Icon.createWithBitmap(context.getDrawable(R.drawable.screen_lock_portrait_fill0)?.toBitmap()))
|
||||
.setIntent(lockIntent)
|
||||
sm.addDynamicShortcuts(listOf(shortcut.build()))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SharedPrefs(context).isDefaultAffiliationIdSet = false
|
||||
if(VERSION.SDK_INT >= 25) {
|
||||
val sm = context.getSystemService(ShortcutManager::class.java)
|
||||
sm.removeDynamicShortcuts(listOf("LockScreen"))
|
||||
}
|
||||
SharedPrefs(context).isApiEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import android.net.IpConfiguration
|
||||
import android.net.LinkAddress
|
||||
import android.net.ProxyInfo
|
||||
import android.net.StaticIpConfiguration
|
||||
import android.net.Uri
|
||||
import android.net.wifi.WifiConfiguration
|
||||
import android.net.wifi.WifiManager
|
||||
import android.net.wifi.WifiSsid
|
||||
@@ -124,14 +123,16 @@ import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.ChoosePackageContract
|
||||
import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SharedPrefs
|
||||
import com.bintianqi.owndroid.formatDate
|
||||
import com.bintianqi.owndroid.formatFileSize
|
||||
import com.bintianqi.owndroid.humanReadableDate
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||
import com.bintianqi.owndroid.ui.ErrorDialog
|
||||
@@ -163,29 +164,24 @@ import kotlin.reflect.jvm.jvmErasure
|
||||
|
||||
@Composable
|
||||
fun NetworkScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val dhizuku = SharedPrefs(context).dhizuku
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.network, onNavigateUp, 0.dp) {
|
||||
if(!dhizuku) FunctionItem(R.string.wifi, icon = R.drawable.wifi_fill0) { onNavigate(WiFi) }
|
||||
if(!privilege.dhizuku) FunctionItem(R.string.wifi, icon = R.drawable.wifi_fill0) { onNavigate(WiFi) }
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(NetworkOptions) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 23 && !dhizuku && (deviceOwner || profileOwner))
|
||||
if(VERSION.SDK_INT >= 23 && !privilege.dhizuku && (privilege.device || privilege.profile))
|
||||
FunctionItem(R.string.network_stats, icon = R.drawable.query_stats_fill0) { onNavigate(QueryNetworkStats) }
|
||||
if(VERSION.SDK_INT >= 29 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 29 && privilege.device) {
|
||||
FunctionItem(R.string.private_dns, icon = R.drawable.dns_fill0) { onNavigate(PrivateDns) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24) {
|
||||
FunctionItem(R.string.always_on_vpn, icon = R.drawable.vpn_key_fill0) { onNavigate(AlwaysOnVpnPackage) }
|
||||
}
|
||||
if(deviceOwner) {
|
||||
if(privilege.device) {
|
||||
FunctionItem(R.string.recommended_global_proxy, icon = R.drawable.vpn_key_fill0) { onNavigate(RecommendedGlobalProxy) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && !dhizuku && (deviceOwner || (profileOwner && dpm.isManagedProfile(receiver)))) {
|
||||
if(VERSION.SDK_INT >= 26 && !privilege.dhizuku && (privilege.device || privilege.work)) {
|
||||
FunctionItem(R.string.network_logging, icon = R.drawable.description_fill0) { onNavigate(NetworkLogging) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
@@ -194,7 +190,7 @@ fun NetworkScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
if(VERSION.SDK_INT >= 33) {
|
||||
FunctionItem(R.string.preferential_network_service, icon = R.drawable.globe_fill0) { onNavigate(PreferentialNetworkService) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.override_apn, icon = R.drawable.cell_tower_fill0) { onNavigate(OverrideApn) }
|
||||
}
|
||||
}
|
||||
@@ -207,10 +203,10 @@ fun NetworkOptionsScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
||||
if(VERSION.SDK_INT>=30 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT >= 30 && (privilege.device || privilege.org)) {
|
||||
SwitchItem(R.string.lockdown_admin_configured_network, icon = R.drawable.wifi_password_fill0,
|
||||
getState = { dpm.hasLockdownAdminConfiguredNetworks(receiver) }, onCheckedChange = { dpm.setConfiguredNetworksLockdownState(receiver,it) },
|
||||
onClickBlank = { dialog = 1 }
|
||||
@@ -265,9 +261,8 @@ fun WifiScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNavigateTo
|
||||
}
|
||||
HorizontalPager(state = pagerState, verticalAlignment = Alignment.Top) { page ->
|
||||
if(page == 0) {
|
||||
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val orgProfileOwner = context.getDPM().isOrgProfile(context.getReceiver())
|
||||
val wm = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
@Suppress("DEPRECATION") Column(
|
||||
modifier = Modifier.fillMaxSize().padding(top = 12.dp)
|
||||
) {
|
||||
@@ -299,10 +294,10 @@ fun WifiScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNavigateTo
|
||||
Text(stringResource(R.string.reconnect))
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && (deviceOwner || orgProfileOwner)) {
|
||||
if(VERSION.SDK_INT >= 24 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.wifi_mac_address) { wifiMacDialog = true }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 33 && (deviceOwner || orgProfileOwner)) {
|
||||
if(VERSION.SDK_INT >= 33 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.min_wifi_security_level) { onNavigate(WifiSecurityLevel) }
|
||||
FunctionItem(R.string.wifi_ssid_policy) { onNavigate(WifiSsidPolicyScreen) }
|
||||
}
|
||||
@@ -315,7 +310,6 @@ fun WifiScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNavigateTo
|
||||
}
|
||||
}
|
||||
if(wifiMacDialog && VERSION.SDK_INT >= 24) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
AlertDialog(
|
||||
@@ -344,7 +338,7 @@ fun WifiScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNavigateTo
|
||||
@Composable
|
||||
private fun SavedNetworks(onNavigateToUpdateNetwork: (Bundle) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
val wm = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
val configuredNetworks = remember { mutableStateListOf<WifiConfiguration>() }
|
||||
var networkDetailsDialog by remember { mutableIntStateOf(-1) } // -1:Hidden, 0+:Index of configuredNetworks
|
||||
val coroutine = rememberCoroutineScope()
|
||||
@@ -688,7 +682,7 @@ private fun AddNetworkScreen(wifiConfig: WifiConfiguration? = null, onNavigateUp
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
val wm = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
val wm = context.applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
try {
|
||||
val config = WifiConfiguration()
|
||||
config.status = status
|
||||
@@ -899,7 +893,7 @@ fun NetworkStats.toBucketList(): List<NetworkStats.Bucket> {
|
||||
@Composable
|
||||
fun NetworkStatsScreen(onNavigateUp: () -> Unit, onNavigateToViewer: (NetworkStatsViewer) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val fm = LocalFocusManager.current
|
||||
val nsm = context.getSystemService(NetworkStatsManager::class.java)
|
||||
val coroutine = rememberCoroutineScope()
|
||||
@@ -971,7 +965,7 @@ fun NetworkStatsScreen(onNavigateUp: () -> Unit, onNavigateToViewer: (NetworkSta
|
||||
NetworkStatsTarget.entries.forEach {
|
||||
if(
|
||||
VERSION.SDK_INT >= it.minApi &&
|
||||
(deviceOwner || it != NetworkStatsTarget.Device) &&
|
||||
(privilege.device || it != NetworkStatsTarget.Device) &&
|
||||
((queryType == 1 && (it == NetworkStatsTarget.Device || it == NetworkStatsTarget.User)) ||
|
||||
(queryType == 2 && (it == NetworkStatsTarget.Uid || it == NetworkStatsTarget.UidTag || it == NetworkStatsTarget.UidTagState)))
|
||||
) DropdownMenuItem(
|
||||
@@ -1120,7 +1114,7 @@ fun NetworkStatsScreen(onNavigateUp: () -> Unit, onNavigateToViewer: (NetworkSta
|
||||
if(VERSION.SDK_INT >= 24 && (target == NetworkStatsTarget.UidTag || target == NetworkStatsTarget.UidTagState))
|
||||
ExposedDropdownMenuBox(
|
||||
activeTextField == NetworkStatsActiveTextField.Tag,
|
||||
{ activeTextField == if(it) NetworkStatsActiveTextField.Tag else NetworkStatsActiveTextField.None }
|
||||
{ activeTextField = if(it) NetworkStatsActiveTextField.Tag else NetworkStatsActiveTextField.None }
|
||||
) {
|
||||
var tagText by rememberSaveable { mutableStateOf(context.getString(R.string.all)) }
|
||||
var readOnly by rememberSaveable { mutableStateOf(true) }
|
||||
@@ -1596,7 +1590,7 @@ fun RecommendedGlobalProxyScreen(onNavigateUp: () -> Unit) {
|
||||
Toast.makeText(context, R.string.invalid_config, Toast.LENGTH_SHORT).show()
|
||||
return@Button
|
||||
}
|
||||
val uri = Uri.parse(proxyUri)
|
||||
val uri = proxyUri.toUri()
|
||||
val port: Int
|
||||
try {
|
||||
port = proxyPort.toInt()
|
||||
@@ -1827,8 +1821,8 @@ fun AddPreferentialNetworkServiceConfigScreen(route: AddPreferentialNetworkServi
|
||||
title = R.string.block_non_matching_networks,
|
||||
state = blockNonMatching, onCheckedChange = { blockNonMatching = it }, padding = false
|
||||
)
|
||||
val includedUidsLegal = includedUids.lines().filter { it.isNotBlank() }.let {
|
||||
it.isEmpty() || (it.all { it.toIntOrNull() != null } && excludedUids.isBlank())
|
||||
val includedUidsLegal = includedUids.lines().filter { it.isNotBlank() }.let { uid ->
|
||||
uid.isEmpty() || (uid.all { it.toIntOrNull() != null } && excludedUids.isBlank())
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = includedUids, onValueChange = { includedUids = it }, minLines = 2,
|
||||
@@ -1837,8 +1831,8 @@ fun AddPreferentialNetworkServiceConfigScreen(route: AddPreferentialNetworkServi
|
||||
isError = !includedUidsLegal,
|
||||
modifier = Modifier.fillMaxWidth().padding(bottom = 6.dp)
|
||||
)
|
||||
val excludedUidsLegal = excludedUids.lines().filter { it.isNotBlank() }.let {
|
||||
it.isEmpty() || (it.all { it.toIntOrNull() != null } && includedUids.isBlank())
|
||||
val excludedUidsLegal = excludedUids.lines().filter { it.isNotBlank() }.let { uid ->
|
||||
uid.isEmpty() || (uid.all { it.toIntOrNull() != null } && includedUids.isBlank())
|
||||
}
|
||||
OutlinedTextField(
|
||||
value = excludedUids, onValueChange = { excludedUids = it }, minLines = 2,
|
||||
@@ -1852,7 +1846,7 @@ fun AddPreferentialNetworkServiceConfigScreen(route: AddPreferentialNetworkServi
|
||||
try {
|
||||
val config = PreferentialNetworkServiceConfig.Builder().apply {
|
||||
setEnabled(enabled)
|
||||
if(enabled) setNetworkId(id.toInt())
|
||||
if(enabled) setNetworkId(id)
|
||||
setFallbackToDefaultConnectionAllowed(allowFallback)
|
||||
setExcludedUids(excludedUids.lines().filter { it.isNotBlank() }.map { it.toInt() }.toIntArray())
|
||||
setIncludedUids(includedUids.lines().filter { it.isNotBlank() }.map { it.toInt() }.toIntArray())
|
||||
@@ -1957,7 +1951,7 @@ private val apnTypes = listOf(
|
||||
|
||||
@Serializable object AddApnSetting
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@RequiresApi(28)
|
||||
@Composable
|
||||
fun AddApnSettingScreen(origin: ApnSetting?, onNavigateUp: () -> Unit) {
|
||||
@@ -2099,14 +2093,14 @@ fun AddApnSettingScreen(origin: ApnSetting?, onNavigateUp: () -> Unit) {
|
||||
OutlinedTextField(
|
||||
mtuV4, { mtuV4 = it }, Modifier.fillMaxWidth(0.49F),
|
||||
label = { Text("MTU (IPv4)") },
|
||||
isError = !mtuV4.isEmpty() && mtuV4.toIntOrNull() == null,
|
||||
isError = mtuV4.isNotEmpty() && mtuV4.toIntOrNull() == null,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Next),
|
||||
keyboardActions = KeyboardActions { fr.requestFocus() }
|
||||
)
|
||||
OutlinedTextField(
|
||||
mtuV6, { mtuV6 = it }, Modifier.focusRequester(fr).fillMaxWidth(0.96F),
|
||||
label = { Text("MTU (IPv6)") },
|
||||
isError = !mtuV6.isEmpty() && mtuV6.toIntOrNull() == null,
|
||||
isError = mtuV6.isNotEmpty() && mtuV6.toIntOrNull() == null,
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { fm.clearFocus() }
|
||||
)
|
||||
@@ -2194,7 +2188,7 @@ fun AddApnSettingScreen(origin: ApnSetting?, onNavigateUp: () -> Unit) {
|
||||
setMmsProxyAddress(mmsProxyAddress)
|
||||
mmsProxyPort.toIntOrNull()?.let { setMmsProxyPort(it) }
|
||||
}
|
||||
setMmsc(Uri.parse(mmsc))
|
||||
setMmsc(mmsc.toUri())
|
||||
if(VERSION.SDK_INT >= 33) {
|
||||
mtuV4.toIntOrNull()?.let { setMtuV4(it) }
|
||||
mtuV6.toIntOrNull()?.let { setMtuV6(it) }
|
||||
@@ -2238,7 +2232,7 @@ fun AddApnSettingScreen(origin: ApnSetting?, onNavigateUp: () -> Unit) {
|
||||
AlertDialog(
|
||||
title = { Text(if(dialog == 1) "Proxy" else "MMS proxy") },
|
||||
text = {
|
||||
val fm = LocalFocusManager.current
|
||||
val focusManager = LocalFocusManager.current
|
||||
Column {
|
||||
OutlinedTextField(
|
||||
address, { address = it }, Modifier.fillMaxWidth().padding(bottom = 4.dp),
|
||||
@@ -2253,7 +2247,7 @@ fun AddApnSettingScreen(origin: ApnSetting?, onNavigateUp: () -> Unit) {
|
||||
isError = port.isNotEmpty() && port.toIntOrNull() == null,
|
||||
label = { Text(stringResource(R.string.port)) },
|
||||
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, imeAction = ImeAction.Done),
|
||||
keyboardActions = KeyboardActions { fm.clearFocus() }
|
||||
keyboardActions = KeyboardActions { focusManager.clearFocus() }
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@@ -65,9 +65,11 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat.startActivity
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SharedPrefs
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
||||
@@ -86,38 +88,30 @@ import kotlinx.serialization.Serializable
|
||||
@Composable
|
||||
fun PasswordScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val deviceAdmin = context.isDeviceAdmin
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.password_and_keyguard, onNavigateUp, 0.dp) {
|
||||
FunctionItem(R.string.password_info, icon = R.drawable.info_fill0) { onNavigate(PasswordInfo) }
|
||||
if(SharedPrefs(context).displayDangerousFeatures) {
|
||||
if(VERSION.SDK_INT >= 26 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FunctionItem(R.string.reset_password_token, icon = R.drawable.key_vertical_fill0) { onNavigate(ResetPasswordToken) }
|
||||
}
|
||||
if(deviceAdmin || deviceOwner || profileOwner) {
|
||||
FunctionItem(R.string.reset_password, icon = R.drawable.lock_reset_fill0) { onNavigate(ResetPassword) }
|
||||
}
|
||||
FunctionItem(R.string.reset_password, icon = R.drawable.lock_reset_fill0) { onNavigate(ResetPassword) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
FunctionItem(R.string.required_password_complexity, icon = R.drawable.password_fill0) { onNavigate(RequiredPasswordComplexity) }
|
||||
}
|
||||
if(deviceAdmin) {
|
||||
FunctionItem(R.string.disable_keyguard_features, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(KeyguardDisabledFeatures) }
|
||||
}
|
||||
if(deviceOwner) {
|
||||
FunctionItem(R.string.disable_keyguard_features, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(KeyguardDisabledFeatures) }
|
||||
if(privilege.device) {
|
||||
FunctionItem(R.string.max_time_to_lock, icon = R.drawable.schedule_fill0) { dialog = 1 }
|
||||
FunctionItem(R.string.pwd_expiration_timeout, icon = R.drawable.lock_clock_fill0) { dialog = 3 }
|
||||
FunctionItem(R.string.max_pwd_fail, icon = R.drawable.no_encryption_fill0) { dialog = 4 }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FunctionItem(R.string.required_strong_auth_timeout, icon = R.drawable.fingerprint_off_fill0) { dialog = 2 }
|
||||
}
|
||||
if(deviceAdmin){
|
||||
FunctionItem(R.string.pwd_history, icon = R.drawable.history_fill0) { dialog = 5 }
|
||||
}
|
||||
if(VERSION.SDK_INT < 31 && (deviceOwner || profileOwner)) {
|
||||
FunctionItem(R.string.pwd_history, icon = R.drawable.history_fill0) { dialog = 5 }
|
||||
if(VERSION.SDK_INT < 31) {
|
||||
FunctionItem(R.string.required_password_quality, icon = R.drawable.password_fill0) { onNavigate(RequiredPasswordQuality) }
|
||||
}
|
||||
}
|
||||
@@ -217,8 +211,7 @@ fun PasswordInfoScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) } // 0:none, 1:password complexity
|
||||
MyScaffold(R.string.password_info, onNavigateUp, 0.dp) {
|
||||
if(VERSION.SDK_INT >= 29) {
|
||||
@@ -231,10 +224,8 @@ fun PasswordInfoScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
InfoItem(R.string.current_password_complexity, text, true) { dialog = 1 }
|
||||
}
|
||||
if(deviceOwner || profileOwner) {
|
||||
InfoItem(R.string.password_sufficient, dpm.isActivePasswordSufficient.yesOrNo)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && profileOwner && dpm.isManagedProfile(receiver)) {
|
||||
InfoItem(R.string.password_sufficient, dpm.isActivePasswordSufficient.yesOrNo)
|
||||
if(VERSION.SDK_INT >= 28 && privilege.work) {
|
||||
InfoItem(R.string.unified_password, dpm.isUsingUnifiedPassword(receiver).yesOrNo)
|
||||
}
|
||||
}
|
||||
@@ -367,7 +358,7 @@ fun ResetPasswordScreen(onNavigateUp: () -> Unit) {
|
||||
focusMgr.clearFocus()
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError),
|
||||
enabled = tokenByteArray.size >=32 && password.length !in 1..3 && (context.isDeviceOwner || context.isProfileOwner),
|
||||
enabled = tokenByteArray.size >=32 && password.length !in 1..3,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.reset_password_with_token))
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
package com.bintianqi.owndroid.dpm
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Binder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.os.RemoteException
|
||||
import android.os.UserManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
import androidx.annotation.Keep
|
||||
@@ -21,7 +17,6 @@ import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
@@ -43,13 +38,16 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.ChoosePackageContract
|
||||
import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SharedPrefs
|
||||
import com.bintianqi.owndroid.backToHomeStateFlow
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.*
|
||||
import com.bintianqi.owndroid.updatePrivilege
|
||||
import com.bintianqi.owndroid.writeClipBoard
|
||||
import com.bintianqi.owndroid.yesOrNo
|
||||
import com.rosan.dhizuku.api.Dhizuku
|
||||
@@ -61,19 +59,15 @@ import rikka.sui.Sui
|
||||
|
||||
@Serializable object Permissions
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Composable
|
||||
fun PermissionsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNavigateToShizuku: (Bundle) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceAdmin = context.isDeviceAdmin
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
var bindingShizuku by remember { mutableStateOf(false) }
|
||||
val enrollmentSpecificId = if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) dpm.enrollmentSpecificId else ""
|
||||
val enrollmentSpecificId = if(VERSION.SDK_INT >= 31 && (privilege.device || privilege.profile)) dpm.enrollmentSpecificId else ""
|
||||
MyScaffold(R.string.permissions, onNavigateUp, 0.dp) {
|
||||
if(!dpm.isDeviceOwnerApp(context.packageName)) {
|
||||
SwitchItem(
|
||||
@@ -83,19 +77,15 @@ fun PermissionsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNav
|
||||
onClickBlank = { dialog = 4 }
|
||||
)
|
||||
}
|
||||
FunctionItem(
|
||||
R.string.device_admin, stringResource(if(deviceAdmin) R.string.activated else R.string.deactivated),
|
||||
operation = { onNavigate(DeviceAdmin) }
|
||||
)
|
||||
if(profileOwner || !userManager.isSystemUser) {
|
||||
if(privilege.profile || !privilege.primary) {
|
||||
FunctionItem(
|
||||
R.string.profile_owner, stringResource(if(profileOwner) R.string.activated else R.string.deactivated),
|
||||
R.string.profile_owner, stringResource(if(privilege.profile) R.string.activated else R.string.deactivated),
|
||||
operation = { onNavigate(ProfileOwner) }
|
||||
)
|
||||
}
|
||||
if(!profileOwner && userManager.isSystemUser) {
|
||||
if(!privilege.profile && privilege.primary) {
|
||||
FunctionItem(
|
||||
R.string.device_owner, stringResource(if(deviceOwner) R.string.activated else R.string.deactivated),
|
||||
R.string.device_owner, stringResource(if(privilege.device) R.string.activated else R.string.deactivated),
|
||||
operation = { onNavigate(DeviceOwner) }
|
||||
)
|
||||
}
|
||||
@@ -130,25 +120,24 @@ fun PermissionsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNav
|
||||
Toast.makeText(context, R.string.shizuku_not_started, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && (deviceOwner || profileOwner))
|
||||
FunctionItem(R.string.delegated_admins) { onNavigate(DelegatedAdmins) }
|
||||
if(VERSION.SDK_INT >= 26) FunctionItem(R.string.delegated_admins) { onNavigate(DelegatedAdmins) }
|
||||
FunctionItem(R.string.device_info, icon = R.drawable.perm_device_information_fill0) { onNavigate(DeviceInfo) }
|
||||
if(VERSION.SDK_INT >= 24 && (profileOwner || (VERSION.SDK_INT >= 26 && deviceOwner))) {
|
||||
if(VERSION.SDK_INT >= 24 && (privilege.profile || (VERSION.SDK_INT >= 26 && privilege.device))) {
|
||||
FunctionItem(R.string.org_name, icon = R.drawable.corporate_fare_fill0) { dialog = 2 }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31 && (profileOwner || deviceOwner)) {
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
FunctionItem(R.string.org_id, icon = R.drawable.corporate_fare_fill0) { dialog = 3 }
|
||||
}
|
||||
if(enrollmentSpecificId != "") {
|
||||
FunctionItem(R.string.enrollment_specific_id, icon = R.drawable.id_card_fill0) { dialog = 1 }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT >= 24 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.lock_screen_info, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(LockScreenInfo) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && deviceAdmin) {
|
||||
if(VERSION.SDK_INT >= 24) {
|
||||
FunctionItem(R.string.support_messages, icon = R.drawable.chat_fill0) { onNavigate(SupportMessage) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 28) {
|
||||
FunctionItem(R.string.transfer_ownership, icon = R.drawable.admin_panel_settings_fill0) { onNavigate(TransferOwnership) }
|
||||
}
|
||||
}
|
||||
@@ -174,7 +163,7 @@ fun PermissionsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNav
|
||||
text = {
|
||||
val focusMgr = LocalFocusManager.current
|
||||
LaunchedEffect(Unit) {
|
||||
if(dialog == 1) input = dpm.enrollmentSpecificId
|
||||
if(dialog == 1 && VERSION.SDK_INT >= 31) input = dpm.enrollmentSpecificId
|
||||
}
|
||||
Column {
|
||||
if(dialog != 4) OutlinedTextField(
|
||||
@@ -220,8 +209,8 @@ fun PermissionsScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit, onNav
|
||||
TextButton(
|
||||
onClick = {
|
||||
try {
|
||||
if(dialog == 2) dpm.setOrganizationName(receiver, input)
|
||||
if(dialog == 3) dpm.setOrganizationId(input)
|
||||
if(dialog == 2 && VERSION.SDK_INT >= 24) dpm.setOrganizationName(receiver, input)
|
||||
if(dialog == 3 && VERSION.SDK_INT >= 31) dpm.setOrganizationId(input)
|
||||
dialog = 0
|
||||
} catch(_: IllegalStateException) {
|
||||
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
|
||||
@@ -250,6 +239,7 @@ private fun toggleDhizukuMode(status: Boolean, context: Context) {
|
||||
if(dhizukuPermissionGranted()) {
|
||||
sp.dhizuku = true
|
||||
Dhizuku.init(context)
|
||||
updatePrivilege(context)
|
||||
backToHomeStateFlow.value = true
|
||||
} else {
|
||||
Dhizuku.requestPermission(object: DhizukuRequestPermissionListener() {
|
||||
@@ -258,6 +248,7 @@ private fun toggleDhizukuMode(status: Boolean, context: Context) {
|
||||
if(grantResult == PackageManager.PERMISSION_GRANTED) {
|
||||
sp.dhizuku = true
|
||||
Dhizuku.init(context)
|
||||
updatePrivilege(context)
|
||||
backToHomeStateFlow.value = true
|
||||
} else {
|
||||
dhizukuErrorStatus.value = 2
|
||||
@@ -311,65 +302,6 @@ fun LockScreenInfoScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object DeviceAdmin
|
||||
|
||||
@Composable
|
||||
fun DeviceAdminScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
var deactivateDialog by remember { mutableStateOf(false) }
|
||||
val deviceAdmin = context.isDeviceAdmin
|
||||
MyScaffold(R.string.device_admin, onNavigateUp) {
|
||||
Text(text = stringResource(if(context.isDeviceAdmin) R.string.activated else R.string.deactivated), style = typography.titleLarge)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
AnimatedVisibility(deviceAdmin) {
|
||||
Button(
|
||||
onClick = { deactivateDialog = true },
|
||||
enabled = !context.isProfileOwner && !context.isDeviceOwner,
|
||||
colors = ButtonDefaults.buttonColors(containerColor = colorScheme.error, contentColor = colorScheme.onError)
|
||||
) {
|
||||
Text(stringResource(R.string.deactivate))
|
||||
}
|
||||
}
|
||||
AnimatedVisibility(!deviceAdmin) {
|
||||
Column {
|
||||
Button(onClick = { activateDeviceAdmin(context, receiver) }, modifier = Modifier.fillMaxWidth()) {
|
||||
Text(stringResource(R.string.activate_jump))
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
SelectionContainer {
|
||||
Text(text = stringResource(R.string.activate_device_admin_command))
|
||||
}
|
||||
CopyTextButton(R.string.copy_command, stringResource(R.string.activate_device_admin_command))
|
||||
}
|
||||
}
|
||||
}
|
||||
if(deactivateDialog) {
|
||||
AlertDialog(
|
||||
title = { Text(stringResource(R.string.deactivate)) },
|
||||
onDismissRequest = { deactivateDialog = false },
|
||||
dismissButton = {
|
||||
TextButton(
|
||||
onClick = { deactivateDialog = false }
|
||||
) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
dpm.removeActiveAdmin(receiver)
|
||||
deactivateDialog = false
|
||||
}
|
||||
) {
|
||||
Text(stringResource(R.string.confirm))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable object ProfileOwner
|
||||
|
||||
@Composable
|
||||
@@ -378,7 +310,8 @@ fun ProfileOwnerScreen(onNavigateUp: () -> Unit) {
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
var deactivateDialog by remember { mutableStateOf(false) }
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val profileOwner = privilege.profile
|
||||
MyScaffold(R.string.profile_owner, onNavigateUp) {
|
||||
Text(stringResource(if(profileOwner) R.string.activated else R.string.deactivated), style = typography.titleLarge)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
@@ -432,7 +365,8 @@ fun DeviceOwnerScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
var deactivateDialog by remember { mutableStateOf(false) }
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val deviceOwner = privilege.device
|
||||
MyScaffold(R.string.device_owner, onNavigateUp) {
|
||||
Text(text = stringResource(if(deviceOwner) R.string.activated else R.string.deactivated), style = typography.titleLarge)
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
@@ -644,15 +578,15 @@ fun AddDelegatedAdminScreen(data: AddDelegatedAdmin, onNavigateUp: () -> Unit) {
|
||||
fun DeviceInfoScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.device_info, onNavigateUp, 0.dp) {
|
||||
if(VERSION.SDK_INT>=34 && (context.isDeviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT>=34 && (privilege.device || privilege.org)) {
|
||||
InfoItem(R.string.financed_device, dpm.isDeviceFinanced.yesOrNo)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 33) {
|
||||
val dpmRole = dpm.devicePolicyManagementRoleHolderPackage
|
||||
InfoItem(R.string.dpmrh, if(dpmRole == null) stringResource(R.string.none) else dpmRole)
|
||||
InfoItem(R.string.dpmrh, dpmRole ?: stringResource(R.string.none))
|
||||
}
|
||||
val encryptionStatus = mutableMapOf(
|
||||
DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE to R.string.es_inactive,
|
||||
@@ -670,7 +604,7 @@ fun DeviceInfoScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
val adminList = dpm.activeAdmins
|
||||
if(adminList != null) {
|
||||
InfoItem(R.string.activated_device_admin, adminList.map { it.flattenToShortString() }.joinToString("\n"))
|
||||
InfoItem(R.string.activated_device_admin, adminList.joinToString("\n") { it.flattenToShortString() })
|
||||
}
|
||||
}
|
||||
if(dialog != 0) AlertDialog(
|
||||
@@ -766,6 +700,7 @@ fun SupportMessageScreen(onNavigateUp: () -> Unit) {
|
||||
@Composable
|
||||
fun TransferOwnershipScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val focusMgr = LocalFocusManager.current
|
||||
var input by remember { mutableStateOf("") }
|
||||
val componentName = ComponentName.unflattenFromString(input)
|
||||
@@ -793,7 +728,7 @@ fun TransferOwnershipScreen(onNavigateUp: () -> Unit) {
|
||||
text = {
|
||||
Text(stringResource(
|
||||
R.string.transfer_ownership_warning,
|
||||
stringResource(if(context.isDeviceOwner) R.string.device_owner else R.string.profile_owner),
|
||||
stringResource(if(privilege.device) R.string.device_owner else R.string.profile_owner),
|
||||
ComponentName.unflattenFromString(input)!!.packageName
|
||||
))
|
||||
},
|
||||
@@ -805,11 +740,12 @@ fun TransferOwnershipScreen(onNavigateUp: () -> Unit) {
|
||||
try {
|
||||
dpm.transferOwnership(receiver, componentName!!, null)
|
||||
context.showOperationResultToast(true)
|
||||
updatePrivilege(context)
|
||||
dialog = false
|
||||
backToHomeStateFlow.value = true
|
||||
onNavigateUp()
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
Toast.makeText(context, R.string.failed, Toast.LENGTH_SHORT).show()
|
||||
context.showOperationResultToast(false)
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.textButtonColors(contentColor = colorScheme.error)
|
||||
@@ -825,14 +761,3 @@ fun TransferOwnershipScreen(onNavigateUp: () -> Unit) {
|
||||
onDismissRequest = { dialog = false }
|
||||
)
|
||||
}
|
||||
|
||||
private fun activateDeviceAdmin(inputContext:Context,inputComponent:ComponentName) {
|
||||
try {
|
||||
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
|
||||
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, inputComponent)
|
||||
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, inputContext.getString(R.string.activate_device_admin_here))
|
||||
addDeviceAdmin.launch(intent)
|
||||
} catch(_:ActivityNotFoundException) {
|
||||
Toast.makeText(inputContext, R.string.unsupported, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -36,9 +35,12 @@ import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.IUserService
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.ui.MySmallTitleScaffold
|
||||
import com.bintianqi.owndroid.updatePrivilege
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -46,17 +48,13 @@ import rikka.shizuku.Shizuku
|
||||
|
||||
@Serializable object ShizukuScreen
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun ShizukuScreen(navArgs: Bundle, onNavigateUp: () -> Unit, onNavigateToAccountsViewer: (Accounts) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val coScope = rememberCoroutineScope()
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val coroutine = rememberCoroutineScope()
|
||||
val outputTextScrollState = rememberScrollState()
|
||||
var outputText by rememberSaveable { mutableStateOf("") }
|
||||
var showDeviceOwnerButton by remember { mutableStateOf(!context.isDeviceOwner) }
|
||||
var showOrgProfileOwnerButton by remember { mutableStateOf(true) }
|
||||
val binder = navArgs.getBinder("binder")!!
|
||||
var service by remember { mutableStateOf<IUserService?>(null) }
|
||||
LaunchedEffect(Unit) {
|
||||
@@ -70,7 +68,7 @@ fun ShizukuScreen(navArgs: Bundle, onNavigateUp: () -> Unit, onNavigateToAccount
|
||||
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
coroutine.launch{
|
||||
outputText = service!!.execute("dpm list-owners")
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
}
|
||||
@@ -81,7 +79,7 @@ fun ShizukuScreen(navArgs: Bundle, onNavigateUp: () -> Unit, onNavigateToAccount
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
coroutine.launch{
|
||||
outputText = service!!.execute("pm list users")
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
}
|
||||
@@ -100,7 +98,7 @@ fun ShizukuScreen(navArgs: Bundle, onNavigateUp: () -> Unit, onNavigateToAccount
|
||||
onNavigateToAccountsViewer(Accounts(accounts))
|
||||
} catch(_: Exception) {
|
||||
outputText = service!!.execute("dumpsys account")
|
||||
coScope.launch{
|
||||
coroutine.launch{
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
}
|
||||
}
|
||||
@@ -111,39 +109,37 @@ fun ShizukuScreen(navArgs: Bundle, onNavigateUp: () -> Unit, onNavigateToAccount
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
|
||||
AnimatedVisibility(showDeviceOwnerButton, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
AnimatedVisibility(!privilege.device, modifier = Modifier.align(Alignment.CenterHorizontally)) {
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
coroutine.launch{
|
||||
outputText = service!!.execute(context.getString(R.string.dpm_activate_do_command))
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
delay(500)
|
||||
showDeviceOwnerButton = !context.isDeviceOwner
|
||||
updatePrivilege(context)
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text(text = stringResource(R.string.activate_device_owner))
|
||||
}
|
||||
}
|
||||
|
||||
if(VERSION.SDK_INT >= 30 && context.isProfileOwner && dpm.isManagedProfile(receiver) && !dpm.isOrganizationOwnedDeviceWithManagedProfile) {
|
||||
AnimatedVisibility(showOrgProfileOwnerButton) {
|
||||
Button(
|
||||
onClick = {
|
||||
coScope.launch{
|
||||
val userID = Binder.getCallingUid() / 100000
|
||||
outputText = service!!.execute(
|
||||
"dpm mark-profile-owner-on-organization-owned-device --user $userID com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver"
|
||||
)
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
delay(500)
|
||||
showOrgProfileOwnerButton = !dpm.isOrganizationOwnedDeviceWithManagedProfile
|
||||
}
|
||||
},
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = stringResource(R.string.activate_org_profile))
|
||||
}
|
||||
|
||||
AnimatedVisibility(VERSION.SDK_INT >= 30 && privilege.work && !privilege.org) {
|
||||
Button(
|
||||
onClick = {
|
||||
coroutine.launch{
|
||||
val userID = Binder.getCallingUid() / 100000
|
||||
outputText = service!!.execute(
|
||||
"dpm mark-profile-owner-on-organization-owned-device --user $userID com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver"
|
||||
)
|
||||
outputTextScrollState.animateScrollTo(0)
|
||||
delay(500)
|
||||
updatePrivilege(context)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = stringResource(R.string.activate_org_profile))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ 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.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.ChoosePackageContract
|
||||
import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.NotificationUtils
|
||||
@@ -123,6 +124,7 @@ import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.SharedPrefs
|
||||
import com.bintianqi.owndroid.formatFileSize
|
||||
import com.bintianqi.owndroid.humanReadableDate
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.parseDate
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||
@@ -160,62 +162,54 @@ fun SystemManagerScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val sp = SharedPrefs(context)
|
||||
val dhizuku = sp.dhizuku
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.system, onNavigateUp, 0.dp) {
|
||||
if(deviceOwner || profileOwner) {
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SystemOptions) }
|
||||
}
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(SystemOptions) }
|
||||
FunctionItem(R.string.keyguard, icon = R.drawable.screen_lock_portrait_fill0) { onNavigate(Keyguard) }
|
||||
if(VERSION.SDK_INT >= 24 && deviceOwner && !dhizuku)
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device && !privilege.dhizuku)
|
||||
FunctionItem(R.string.hardware_monitor, icon = R.drawable.memory_fill0) { onNavigate(HardwareMonitor) }
|
||||
if(VERSION.SDK_INT >= 24 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device) {
|
||||
FunctionItem(R.string.reboot, icon = R.drawable.restart_alt_fill0) { dialog = 1 }
|
||||
}
|
||||
if(deviceOwner && VERSION.SDK_INT >= 24 && (VERSION.SDK_INT < 28 || dpm.isAffiliatedUser)) {
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device && (VERSION.SDK_INT < 28 || dpm.isAffiliatedUser)) {
|
||||
FunctionItem(R.string.bug_report, icon = R.drawable.bug_report_fill0) { dialog = 2 }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT >= 28 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.change_time, icon = R.drawable.schedule_fill0) { onNavigate(ChangeTime) }
|
||||
FunctionItem(R.string.change_timezone, icon = R.drawable.schedule_fill0) { onNavigate(ChangeTimeZone) }
|
||||
}
|
||||
/*if(VERSION.SDK_INT >= 28 && (deviceOwner || profileOwner))
|
||||
FunctionItem(R.string.key_pairs, icon = R.drawable.key_vertical_fill0) { navCtrl.navigate("KeyPairs") }*/
|
||||
if(VERSION.SDK_INT >= 35 && (deviceOwner || (profileOwner && dpm.isAffiliatedUser)))
|
||||
if(VERSION.SDK_INT >= 35 && (privilege.device || (privilege.profile && privilege.affiliated)))
|
||||
FunctionItem(R.string.content_protection_policy, icon = R.drawable.search_fill0) { onNavigate(ContentProtectionPolicy) }
|
||||
if(VERSION.SDK_INT >= 23 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
FunctionItem(R.string.permission_policy, icon = R.drawable.key_fill0) { onNavigate(PermissionPolicy) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 34 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 34 && privilege.device) {
|
||||
FunctionItem(R.string.mte_policy, icon = R.drawable.memory_fill0) { onNavigate(MtePolicy) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 31) {
|
||||
FunctionItem(R.string.nearby_streaming_policy, icon = R.drawable.share_fill0) { onNavigate(NearbyStreamingPolicy) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.lock_task_mode, icon = R.drawable.lock_fill0) { onNavigate(LockTaskMode) }
|
||||
}
|
||||
if(deviceOwner || profileOwner) {
|
||||
FunctionItem(R.string.ca_cert, icon = R.drawable.license_fill0) { onNavigate(CaCert) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && !dhizuku && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
FunctionItem(R.string.ca_cert, icon = R.drawable.license_fill0) { onNavigate(CaCert) }
|
||||
if(VERSION.SDK_INT >= 26 && !privilege.dhizuku && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.security_logging, icon = R.drawable.description_fill0) { onNavigate(SecurityLogging) }
|
||||
}
|
||||
if(deviceOwner || profileOwner) {
|
||||
FunctionItem(R.string.disable_account_management, icon = R.drawable.account_circle_fill0) { onNavigate(DisableAccountManagement) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 23 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
FunctionItem(R.string.disable_account_management, icon = R.drawable.account_circle_fill0) { onNavigate(DisableAccountManagement) }
|
||||
if(VERSION.SDK_INT >= 23 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.system_update_policy, icon = R.drawable.system_update_fill0) { onNavigate(SetSystemUpdatePolicy) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 29 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT >= 29 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.install_system_update, icon = R.drawable.system_update_fill0) { onNavigate(InstallSystemUpdate) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 30 && (deviceOwner || dpm.isOrgProfile(receiver))) {
|
||||
if(VERSION.SDK_INT >= 30 && (privilege.device || privilege.org)) {
|
||||
FunctionItem(R.string.frp_policy, icon = R.drawable.device_reset_fill0) { onNavigate(FrpPolicy) }
|
||||
}
|
||||
if(sp.displayDangerousFeatures && context.isDeviceAdmin && !(VERSION.SDK_INT >= 24 && profileOwner && dpm.isManagedProfile(receiver))) {
|
||||
if(sp.displayDangerousFeatures && !privilege.work) {
|
||||
FunctionItem(R.string.wipe_data, icon = R.drawable.device_reset_fill0) { onNavigate(WipeData) }
|
||||
}
|
||||
}
|
||||
@@ -253,27 +247,21 @@ fun SystemOptionsScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val um = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.options, onNavigateUp, 0.dp) {
|
||||
if(deviceOwner || profileOwner) {
|
||||
SwitchItem(R.string.disable_cam, icon = R.drawable.photo_camera_fill0,
|
||||
getState = { dpm.getCameraDisabled(null) }, onCheckedChange = { dpm.setCameraDisabled(receiver,it) }
|
||||
)
|
||||
}
|
||||
if(deviceOwner || profileOwner) {
|
||||
SwitchItem(R.string.disable_screen_capture, icon = R.drawable.screenshot_fill0,
|
||||
getState = { dpm.getScreenCaptureDisabled(null) }, onCheckedChange = { dpm.setScreenCaptureDisabled(receiver,it) }
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 34 && (deviceOwner || (profileOwner && dpm.isAffiliatedUser))) {
|
||||
SwitchItem(R.string.disable_cam, icon = R.drawable.photo_camera_fill0,
|
||||
getState = { dpm.getCameraDisabled(null) }, onCheckedChange = { dpm.setCameraDisabled(receiver,it) }
|
||||
)
|
||||
SwitchItem(R.string.disable_screen_capture, icon = R.drawable.screenshot_fill0,
|
||||
getState = { dpm.getScreenCaptureDisabled(null) }, onCheckedChange = { dpm.setScreenCaptureDisabled(receiver,it) }
|
||||
)
|
||||
if(VERSION.SDK_INT >= 34 && (privilege.device || (privilege.profile && privilege.affiliated))) {
|
||||
SwitchItem(R.string.disable_status_bar, icon = R.drawable.notifications_fill0,
|
||||
getState = { dpm.isStatusBarDisabled}, onCheckedChange = { dpm.setStatusBarDisabled(receiver,it) }
|
||||
)
|
||||
}
|
||||
if(deviceOwner || (VERSION.SDK_INT >= 23 && profileOwner && um.isSystemUser) || dpm.isOrgProfile(receiver)) {
|
||||
if(privilege.device || privilege.org) {
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
SwitchItem(R.string.auto_time, icon = R.drawable.schedule_fill0,
|
||||
getState = { dpm.getAutoTimeEnabled(receiver) }, onCheckedChange = { dpm.setAutoTimeEnabled(receiver,it) }
|
||||
@@ -286,30 +274,28 @@ fun SystemOptionsScreen(onNavigateUp: () -> Unit) {
|
||||
getState = { dpm.autoTimeRequired }, onCheckedChange = { dpm.setAutoTimeRequired(receiver,it) }, padding = false)
|
||||
}
|
||||
}
|
||||
if(deviceOwner || profileOwner) {
|
||||
SwitchItem(R.string.master_mute, icon = R.drawable.volume_off_fill0,
|
||||
getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = { dpm.setMasterVolumeMuted(receiver,it) }
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && (deviceOwner || profileOwner)) {
|
||||
SwitchItem(R.string.master_mute, icon = R.drawable.volume_off_fill0,
|
||||
getState = { dpm.isMasterVolumeMuted(receiver) }, onCheckedChange = { dpm.setMasterVolumeMuted(receiver,it) }
|
||||
)
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
SwitchItem(R.string.backup_service, icon = R.drawable.backup_fill0,
|
||||
getState = { dpm.isBackupServiceEnabled(receiver) }, onCheckedChange = { dpm.setBackupServiceEnabled(receiver,it) },
|
||||
onClickBlank = { dialog = 1 }
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && profileOwner && dpm.isManagedProfile(receiver)) {
|
||||
if(VERSION.SDK_INT >= 24 && privilege.work) {
|
||||
SwitchItem(R.string.disable_bt_contact_share, icon = R.drawable.account_circle_fill0,
|
||||
getState = { dpm.getBluetoothContactSharingDisabled(receiver) },
|
||||
onCheckedChange = { dpm.setBluetoothContactSharingDisabled(receiver,it) }
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 30 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 30 && privilege.device) {
|
||||
SwitchItem(R.string.common_criteria_mode , icon =R.drawable.security_fill0,
|
||||
getState = { dpm.isCommonCriteriaModeEnabled(receiver) }, onCheckedChange = { dpm.setCommonCriteriaModeEnabled(receiver,it) },
|
||||
onClickBlank = { dialog = 2 }
|
||||
)
|
||||
}
|
||||
if(VERSION.SDK_INT >= 31 && (deviceOwner || dpm.isOrgProfile(receiver)) && dpm.canUsbDataSignalingBeDisabled()) {
|
||||
if(VERSION.SDK_INT >= 31 && (privilege.device || privilege.org) && dpm.canUsbDataSignalingBeDisabled()) {
|
||||
SwitchItem(
|
||||
R.string.disable_usb_signal, icon = R.drawable.usb_fill0, getState = { !dpm.isUsbDataSignalingEnabled },
|
||||
onCheckedChange = { dpm.isUsbDataSignalingEnabled = !it },
|
||||
@@ -340,24 +326,21 @@ fun KeyguardScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.keyguard, onNavigateUp) {
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
if(VERSION.SDK_INT >= 23 && (privilege.device || (VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated))) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Button(
|
||||
onClick = { context.showOperationResultToast(dpm.setKeyguardDisabled(receiver, true)) },
|
||||
enabled = deviceOwner || (VERSION.SDK_INT >= 28 && profileOwner && dpm.isAffiliatedUser),
|
||||
modifier = Modifier.fillMaxWidth(0.49F)
|
||||
) {
|
||||
Text(stringResource(R.string.disable))
|
||||
}
|
||||
Button(
|
||||
onClick = { context.showOperationResultToast(dpm.setKeyguardDisabled(receiver, false)) },
|
||||
enabled = deviceOwner || (VERSION.SDK_INT >= 28 && profileOwner && dpm.isAffiliatedUser),
|
||||
modifier = Modifier.fillMaxWidth(0.96F)
|
||||
) {
|
||||
Text(stringResource(R.string.enable))
|
||||
@@ -369,7 +352,7 @@ fun KeyguardScreen(onNavigateUp: () -> Unit) {
|
||||
if(VERSION.SDK_INT >= 23) Text(text = stringResource(R.string.lock_now), style = typography.headlineLarge)
|
||||
Spacer(Modifier.padding(vertical = 2.dp))
|
||||
var flag by remember { mutableIntStateOf(0) }
|
||||
if(VERSION.SDK_INT >= 26 && profileOwner && dpm.isManagedProfile(receiver)) {
|
||||
if(VERSION.SDK_INT >= 26 && privilege.work) {
|
||||
CheckBoxItem(
|
||||
R.string.evict_credential_encryption_key,
|
||||
flag and FLAG_EVICT_CREDENTIAL_ENCRYPTION_KEY != 0
|
||||
@@ -380,12 +363,11 @@ fun KeyguardScreen(onNavigateUp: () -> Unit) {
|
||||
onClick = {
|
||||
if(VERSION.SDK_INT >= 26) dpm.lockNow(flag) else dpm.lockNow()
|
||||
},
|
||||
enabled = context.isDeviceAdmin,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(stringResource(R.string.lock_now))
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && profileOwner && dpm.isManagedProfile(receiver)) {
|
||||
if(VERSION.SDK_INT >= 26 && privilege.work) {
|
||||
Notes(R.string.info_evict_credential_encryption_key)
|
||||
}
|
||||
}
|
||||
@@ -393,7 +375,6 @@ fun KeyguardScreen(onNavigateUp: () -> Unit) {
|
||||
|
||||
@Serializable object HardwareMonitor
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun HardwareMonitorScreen(onNavigateUp: () -> Unit) {
|
||||
@@ -1332,7 +1313,7 @@ fun CaCertScreen(onNavigateUp: () -> Unit) {
|
||||
text = {
|
||||
if(dialog == 3) Text(stringResource(R.string.uninstall_all_user_ca_cert))
|
||||
else {
|
||||
var text = ""
|
||||
var text: String
|
||||
val sha256 = MessageDigest.getInstance("SHA-256").digest(caCertByteArray).toHexString()
|
||||
try {
|
||||
val cf = CertificateFactory.getInstance("X.509")
|
||||
@@ -1634,6 +1615,7 @@ fun WipeDataScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
val dpm = context.getDPM()
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val focusMgr = LocalFocusManager.current
|
||||
var flag by remember { mutableIntStateOf(0) }
|
||||
var warning by remember { mutableStateOf(false) }
|
||||
@@ -1642,7 +1624,7 @@ fun WipeDataScreen(onNavigateUp: () -> Unit) {
|
||||
var reason by remember { mutableStateOf("") }
|
||||
MyScaffold(R.string.wipe_data, onNavigateUp) {
|
||||
CheckBoxItem(R.string.wipe_external_storage, flag and WIPE_EXTERNAL_STORAGE != 0) { flag = flag xor WIPE_EXTERNAL_STORAGE }
|
||||
if(VERSION.SDK_INT >= 22 && context.isDeviceOwner) CheckBoxItem(
|
||||
if(VERSION.SDK_INT >= 22 && privilege.device) CheckBoxItem(
|
||||
R.string.wipe_reset_protection_data, flag and WIPE_RESET_PROTECTION_DATA != 0) { flag = flag xor WIPE_RESET_PROTECTION_DATA }
|
||||
if(VERSION.SDK_INT >= 28) CheckBoxItem(R.string.wipe_euicc, flag and WIPE_EUICC != 0) { flag = flag xor WIPE_EUICC }
|
||||
if(VERSION.SDK_INT >= 29) CheckBoxItem(R.string.wipe_silently, silent) { silent = it }
|
||||
@@ -1667,7 +1649,7 @@ fun WipeDataScreen(onNavigateUp: () -> Unit) {
|
||||
Text("WipeData")
|
||||
}
|
||||
}
|
||||
if (VERSION.SDK_INT >= 34 && context.isDeviceOwner) {
|
||||
if (VERSION.SDK_INT >= 34 && privilege.device) {
|
||||
Button(
|
||||
onClick = {
|
||||
focusMgr.clearFocus()
|
||||
|
||||
@@ -10,11 +10,13 @@ import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.ui.FunctionItem
|
||||
import com.bintianqi.owndroid.ui.MyScaffold
|
||||
import com.bintianqi.owndroid.ui.SwitchItem
|
||||
@@ -33,14 +35,12 @@ data class Restriction(
|
||||
@RequiresApi(24)
|
||||
@Composable
|
||||
fun UserRestrictionScreen(onNavigateUp: () -> Unit, onNavigate: (Int, List<Restriction>) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.user_restriction, onNavigateUp, 0.dp) {
|
||||
Spacer(Modifier.padding(vertical = 2.dp))
|
||||
Text(text = stringResource(R.string.switch_to_disable_feature), modifier = Modifier.padding(start = 16.dp))
|
||||
if(context.isProfileOwner) { Text(text = stringResource(R.string.profile_owner_is_restricted), modifier = Modifier.padding(start = 16.dp)) }
|
||||
if(context.isProfileOwner && dpm.isManagedProfile(receiver)) {
|
||||
if(privilege.profile) { Text(text = stringResource(R.string.profile_owner_is_restricted), modifier = Modifier.padding(start = 16.dp)) }
|
||||
if(privilege.work) {
|
||||
Text(text = stringResource(R.string.some_features_invalid_in_work_profile), modifier = Modifier.padding(start = 16.dp))
|
||||
}
|
||||
Spacer(Modifier.padding(vertical = 2.dp))
|
||||
|
||||
@@ -64,8 +64,10 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.HorizontalPadding
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.parseTimestamp
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.FullWidthCheckBoxItem
|
||||
@@ -89,28 +91,25 @@ fun UsersScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val deviceOwner = context.isDeviceOwner
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
var dialog by remember { mutableIntStateOf(0) }
|
||||
MyScaffold(R.string.users, onNavigateUp, 0.dp) {
|
||||
if(VERSION.SDK_INT >= 28 && profileOwner && dpm.isAffiliatedUser) {
|
||||
if(VERSION.SDK_INT >= 28 && privilege.profile && privilege.affiliated) {
|
||||
FunctionItem(R.string.logout, icon = R.drawable.logout_fill0) { dialog = 2 }
|
||||
}
|
||||
FunctionItem(R.string.user_info, icon = R.drawable.person_fill0) { onNavigate(UserInfo) }
|
||||
if(deviceOwner && VERSION.SDK_INT >= 28) {
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.secondary_users, icon = R.drawable.list_fill0) { dialog = 1 }
|
||||
FunctionItem(R.string.options, icon = R.drawable.tune_fill0) { onNavigate(UsersOptions) }
|
||||
}
|
||||
if(deviceOwner) {
|
||||
if(privilege.device) {
|
||||
FunctionItem(R.string.user_operation, icon = R.drawable.sync_alt_fill0) { onNavigate(UserOperation) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 24 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 24 && privilege.device) {
|
||||
FunctionItem(R.string.create_user, icon = R.drawable.person_add_fill0) { onNavigate(CreateUser) }
|
||||
}
|
||||
if(deviceOwner || profileOwner) {
|
||||
FunctionItem(R.string.change_username, icon = R.drawable.edit_fill0) { onNavigate(ChangeUsername) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 23 && (deviceOwner || profileOwner)) {
|
||||
FunctionItem(R.string.change_username, icon = R.drawable.edit_fill0) { onNavigate(ChangeUsername) }
|
||||
if(VERSION.SDK_INT >= 23) {
|
||||
var changeUserIconDialog by remember { mutableStateOf(false) }
|
||||
var bitmap: Bitmap? by remember { mutableStateOf(null) }
|
||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||
@@ -123,12 +122,12 @@ fun UsersScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
Toast.makeText(context, R.string.select_an_image, Toast.LENGTH_SHORT).show()
|
||||
launcher.launch("image/*")
|
||||
}
|
||||
if(changeUserIconDialog == true) ChangeUserIconDialog(bitmap!!) { changeUserIconDialog = false }
|
||||
if(changeUserIconDialog) ChangeUserIconDialog(bitmap!!) { changeUserIconDialog = false }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 28 && deviceOwner) {
|
||||
if(VERSION.SDK_INT >= 28 && privilege.device) {
|
||||
FunctionItem(R.string.user_session_msg, icon = R.drawable.notifications_fill0) { onNavigate(UserSessionMessage) }
|
||||
}
|
||||
if(VERSION.SDK_INT >= 26 && (deviceOwner || profileOwner)) {
|
||||
if(VERSION.SDK_INT >= 26) {
|
||||
FunctionItem(R.string.affiliation_id, icon = R.drawable.id_card_fill0) { onNavigate(AffiliationId) }
|
||||
}
|
||||
}
|
||||
@@ -190,6 +189,7 @@ fun UserInfoScreen(onNavigateUp: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
val userManager = context.getSystemService(Context.USER_SERVICE) as UserManager
|
||||
val user = Process.myUserHandle()
|
||||
var infoDialog by remember { mutableIntStateOf(0) }
|
||||
@@ -205,10 +205,8 @@ fun UserInfoScreen(onNavigateUp: () -> Unit) {
|
||||
}
|
||||
if (VERSION.SDK_INT >= 28) {
|
||||
InfoItem(R.string.logout_enabled, dpm.isLogoutEnabled.yesOrNo)
|
||||
if(context.isDeviceOwner || context.isProfileOwner) {
|
||||
InfoItem(R.string.ephemeral_user, dpm.isEphemeralUser(receiver).yesOrNo)
|
||||
}
|
||||
InfoItem(R.string.affiliated_user, dpm.isAffiliatedUser.yesOrNo)
|
||||
InfoItem(R.string.ephemeral_user, dpm.isEphemeralUser(receiver).yesOrNo)
|
||||
InfoItem(R.string.affiliated_user, privilege.affiliated.yesOrNo)
|
||||
}
|
||||
InfoItem(R.string.user_id, (Binder.getCallingUid() / 100000).toString())
|
||||
InfoItem(R.string.user_serial_number, userManager.getSerialNumberForUser(Process.myUserHandle()).toString())
|
||||
@@ -447,7 +445,7 @@ fun AffiliationIdScreen(onNavigateUp: () -> Unit) {
|
||||
Spacer(Modifier.padding(vertical = 5.dp))
|
||||
Button(
|
||||
onClick = {
|
||||
list.removeAll(listOf(""))
|
||||
list.removeAll(setOf(""))
|
||||
dpm.setAffiliationIds(receiver, list.toSet())
|
||||
context.showOperationResultToast(true)
|
||||
refreshIds()
|
||||
|
||||
@@ -53,7 +53,9 @@ 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.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.bintianqi.owndroid.R
|
||||
import com.bintianqi.owndroid.myPrivilege
|
||||
import com.bintianqi.owndroid.showOperationResultToast
|
||||
import com.bintianqi.owndroid.ui.CheckBoxItem
|
||||
import com.bintianqi.owndroid.ui.CopyTextButton
|
||||
@@ -69,26 +71,16 @@ import kotlinx.serialization.Serializable
|
||||
|
||||
@Composable
|
||||
fun WorkProfileScreen(onNavigateUp: () -> Unit, onNavigate: (Any) -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val dpm = context.getDPM()
|
||||
val receiver = context.getReceiver()
|
||||
val profileOwner = context.isProfileOwner
|
||||
val privilege by myPrivilege.collectAsStateWithLifecycle()
|
||||
MyScaffold(R.string.work_profile, onNavigateUp, 0.dp) {
|
||||
if(VERSION.SDK_INT >= 30 && profileOwner && dpm.isManagedProfile(receiver)) {
|
||||
if(VERSION.SDK_INT >= 30) {
|
||||
FunctionItem(R.string.org_owned_work_profile, icon = R.drawable.corporate_fare_fill0) { onNavigate(OrganizationOwnedProfile) }
|
||||
}
|
||||
if(VERSION.SDK_INT < 24 || dpm.isProvisioningAllowed(ACTION_PROVISION_MANAGED_PROFILE)) {
|
||||
FunctionItem(R.string.create_work_profile, icon = R.drawable.work_fill0) { onNavigate(CreateWorkProfile) }
|
||||
}
|
||||
if(dpm.isOrgProfile(receiver)) {
|
||||
if(privilege.org) {
|
||||
FunctionItem(R.string.suspend_personal_app, icon = R.drawable.block_fill0) { onNavigate(SuspendPersonalApp) }
|
||||
}
|
||||
if(profileOwner && (VERSION.SDK_INT < 24 || dpm.isManagedProfile(receiver))) {
|
||||
FunctionItem(R.string.intent_filter, icon = R.drawable.filter_alt_fill0) { onNavigate(CrossProfileIntentFilter) }
|
||||
}
|
||||
if(profileOwner && (VERSION.SDK_INT < 24 || dpm.isManagedProfile(receiver))) {
|
||||
FunctionItem(R.string.delete_work_profile, icon = R.drawable.delete_forever_fill0) { onNavigate(DeleteWorkProfile) }
|
||||
}
|
||||
FunctionItem(R.string.intent_filter, icon = R.drawable.filter_alt_fill0) { onNavigate(CrossProfileIntentFilter) }
|
||||
FunctionItem(R.string.delete_work_profile, icon = R.drawable.delete_forever_fill0) { onNavigate(DeleteWorkProfile) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user