mirror of
https://github.com/awfixers-stuff/OwnDroid.git
synced 2026-03-23 19:15:58 +00:00
@@ -62,8 +62,6 @@ import com.bintianqi.owndroid.dpm.AddApnSetting
|
||||
import com.bintianqi.owndroid.dpm.AddApnSettingScreen
|
||||
import com.bintianqi.owndroid.dpm.AddDelegatedAdmin
|
||||
import com.bintianqi.owndroid.dpm.AddDelegatedAdminScreen
|
||||
import com.bintianqi.owndroid.dpm.AddNetwork
|
||||
import com.bintianqi.owndroid.dpm.AddNetworkScreen
|
||||
import com.bintianqi.owndroid.dpm.AddPreferentialNetworkServiceConfig
|
||||
import com.bintianqi.owndroid.dpm.AddPreferentialNetworkServiceConfigScreen
|
||||
import com.bintianqi.owndroid.dpm.AffiliationId
|
||||
@@ -164,6 +162,7 @@ import com.bintianqi.owndroid.dpm.PermittedAccessibilityServices
|
||||
import com.bintianqi.owndroid.dpm.PermittedAsAndImPackages
|
||||
import com.bintianqi.owndroid.dpm.PermittedInputMethods
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkService
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceInfo
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceScreen
|
||||
import com.bintianqi.owndroid.dpm.PrivateDns
|
||||
import com.bintianqi.owndroid.dpm.PrivateDnsScreen
|
||||
@@ -198,6 +197,8 @@ import com.bintianqi.owndroid.dpm.TransferOwnership
|
||||
import com.bintianqi.owndroid.dpm.TransferOwnershipScreen
|
||||
import com.bintianqi.owndroid.dpm.UninstallApp
|
||||
import com.bintianqi.owndroid.dpm.UninstallAppScreen
|
||||
import com.bintianqi.owndroid.dpm.UpdateNetwork
|
||||
import com.bintianqi.owndroid.dpm.UpdateNetworkScreen
|
||||
import com.bintianqi.owndroid.dpm.UserInfo
|
||||
import com.bintianqi.owndroid.dpm.UserInfoScreen
|
||||
import com.bintianqi.owndroid.dpm.UserOperation
|
||||
@@ -393,28 +394,62 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
||||
composable<WipeData> { WipeDataScreen(vm::wipeData, ::navigateUp) }
|
||||
|
||||
composable<Network> { NetworkScreen(::navigateUp, ::navigate) }
|
||||
composable<WiFi> { WifiScreen(::navigateUp, ::navigate) { navController.navigate(AddNetwork, it)} }
|
||||
composable<NetworkOptions> { NetworkOptionsScreen(::navigateUp) }
|
||||
composable<AddNetwork> { AddNetworkScreen(it.arguments!!, ::navigateUp) }
|
||||
composable<WifiSecurityLevel> { WifiSecurityLevelScreen(::navigateUp) }
|
||||
composable<WifiSsidPolicyScreen> { WifiSsidPolicyScreen(::navigateUp) }
|
||||
composable<WiFi> {
|
||||
WifiScreen(vm, ::navigateUp, ::navigate) { navController.navigate(UpdateNetwork(it)) }
|
||||
}
|
||||
composable<NetworkOptions> {
|
||||
NetworkOptionsScreen(vm::getLanEnabled, vm::setLanEnabled, ::navigateUp)
|
||||
}
|
||||
composable<UpdateNetwork> {
|
||||
val info = vm.configuredNetworks.collectAsStateWithLifecycle().value[
|
||||
(it.toRoute() as UpdateNetwork).index
|
||||
]
|
||||
UpdateNetworkScreen(info, vm::setWifi, ::navigateUp)
|
||||
}
|
||||
composable<WifiSecurityLevel> {
|
||||
WifiSecurityLevelScreen(vm::getMinimumWifiSecurityLevel,
|
||||
vm::setMinimumWifiSecurityLevel, ::navigateUp)
|
||||
}
|
||||
composable<WifiSsidPolicyScreen> {
|
||||
WifiSsidPolicyScreen(vm::getSsidPolicy, vm::setSsidPolicy, ::navigateUp)
|
||||
}
|
||||
composable<QueryNetworkStats> {
|
||||
NetworkStatsScreen(vm.chosenPackage, ::choosePackage, ::navigateUp, ::navigate)
|
||||
NetworkStatsScreen(vm.chosenPackage, ::choosePackage, vm::getPackageUid,
|
||||
vm::queryNetworkStats, ::navigateUp) { navController.navigate(NetworkStatsViewer) }
|
||||
}
|
||||
composable<NetworkStatsViewer>(mapOf(serializableNavTypePair<List<NetworkStatsViewer.Data>>())) {
|
||||
NetworkStatsViewerScreen(it.toRoute(), ::navigateUp)
|
||||
composable<NetworkStatsViewer> {
|
||||
NetworkStatsViewerScreen(vm.networkStatsData, vm::clearNetworkStats, ::navigateUp)
|
||||
}
|
||||
composable<PrivateDns> {
|
||||
PrivateDnsScreen(vm::getPrivateDns, vm::setPrivateDns, ::navigateUp)
|
||||
}
|
||||
composable<PrivateDns> { PrivateDnsScreen(::navigateUp) }
|
||||
composable<AlwaysOnVpnPackage> {
|
||||
AlwaysOnVpnPackageScreen(vm.chosenPackage, ::choosePackage, ::navigateUp)
|
||||
AlwaysOnVpnPackageScreen(vm::getAlwaysOnVpnPackage, vm::getAlwaysOnVpnLockdown,
|
||||
vm::setAlwaysOnVpn, vm.chosenPackage, ::choosePackage, ::navigateUp)
|
||||
}
|
||||
composable<RecommendedGlobalProxy> {
|
||||
RecommendedGlobalProxyScreen(vm::setRecommendedGlobalProxy, ::navigateUp)
|
||||
}
|
||||
composable<RecommendedGlobalProxy> { RecommendedGlobalProxyScreen(::navigateUp) }
|
||||
composable<NetworkLogging> { NetworkLoggingScreen(::navigateUp) }
|
||||
composable<WifiAuthKeypair> { WifiAuthKeypairScreen(::navigateUp) }
|
||||
composable<PreferentialNetworkService> { PreferentialNetworkServiceScreen(::navigateUp, ::navigate) }
|
||||
composable<AddPreferentialNetworkServiceConfig> { AddPreferentialNetworkServiceConfigScreen(it.toRoute(), ::navigateUp) }
|
||||
composable<OverrideApn> { OverrideApnScreen(::navigateUp) { navController.navigate(AddApnSetting, it) } }
|
||||
composable<AddApnSetting> { AddApnSettingScreen(it.arguments?.getParcelable("setting"), ::navigateUp) }
|
||||
//composable<WifiAuthKeypair> { WifiAuthKeypairScreen(::navigateUp) }
|
||||
composable<PreferentialNetworkService> {
|
||||
PreferentialNetworkServiceScreen(vm::getPnsEnabled, vm::setPnsEnabled, vm.pnsConfigs,
|
||||
vm::getPnsConfigs, ::navigateUp, ::navigate)
|
||||
}
|
||||
composable<AddPreferentialNetworkServiceConfig> {
|
||||
val info = vm.pnsConfigs.collectAsStateWithLifecycle().value.getOrNull(
|
||||
it.toRoute<AddPreferentialNetworkServiceConfig>().index
|
||||
) ?: PreferentialNetworkServiceInfo()
|
||||
AddPreferentialNetworkServiceConfigScreen(info, vm::setPnsConfig, ::navigateUp)
|
||||
}
|
||||
composable<OverrideApn> {
|
||||
OverrideApnScreen(vm.apnConfigs, vm::getApnConfigs, vm::getApnEnabled,
|
||||
vm::setApnEnabled, ::navigateUp) { navController.navigate(AddApnSetting(it)) }
|
||||
}
|
||||
composable<AddApnSetting> {
|
||||
val origin = vm.apnConfigs.collectAsStateWithLifecycle().value.getOrNull((it.toRoute() as AddApnSetting).index)
|
||||
AddApnSettingScreen(vm::setApnConfig, vm::removeApnConfig, origin, ::navigateUp)
|
||||
}
|
||||
|
||||
composable<WorkProfile> { WorkProfileScreen(::navigateUp, ::navigate) }
|
||||
composable<OrganizationOwnedProfile> {
|
||||
@@ -542,7 +577,7 @@ fun Home(vm: MyViewModel, onLock: () -> Unit) {
|
||||
composable<UserRestrictionEditor> {
|
||||
UserRestrictionEditorScreen(vm.userRestrictions, vm::setUserRestriction, ::navigateUp)
|
||||
}
|
||||
composable<UserRestrictionOptions>(mapOf(serializableNavTypePair<List<Restriction>>())) {
|
||||
composable<UserRestrictionOptions> {
|
||||
UserRestrictionOptionsScreen(it.toRoute(), vm.userRestrictions,
|
||||
vm::setUserRestriction, ::navigateUp)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.bintianqi.owndroid
|
||||
|
||||
import android.accounts.Account
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.ActivityOptions
|
||||
import android.app.Application
|
||||
import android.app.PendingIntent
|
||||
@@ -9,9 +10,14 @@ import android.app.admin.DeviceAdminReceiver
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback
|
||||
import android.app.admin.FactoryResetProtectionPolicy
|
||||
import android.app.admin.IDevicePolicyManager
|
||||
import android.app.admin.PackagePolicy
|
||||
import android.app.admin.PreferentialNetworkServiceConfig
|
||||
import android.app.admin.SystemUpdateInfo
|
||||
import android.app.admin.SystemUpdatePolicy
|
||||
import android.app.admin.WifiSsidPolicy
|
||||
import android.app.usage.NetworkStats
|
||||
import android.app.usage.NetworkStatsManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
@@ -21,23 +27,36 @@ import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Bitmap
|
||||
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
|
||||
import android.os.Binder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.HardwarePropertiesManager
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import android.telephony.data.ApnSetting
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.drawable.toDrawable
|
||||
import androidx.core.net.toUri
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.application
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bintianqi.owndroid.Privilege.DAR
|
||||
import com.bintianqi.owndroid.Privilege.DPM
|
||||
import com.bintianqi.owndroid.dpm.ACTIVATE_DEVICE_OWNER_COMMAND
|
||||
import com.bintianqi.owndroid.dpm.ApnAuthType
|
||||
import com.bintianqi.owndroid.dpm.ApnConfig
|
||||
import com.bintianqi.owndroid.dpm.ApnMvnoType
|
||||
import com.bintianqi.owndroid.dpm.ApnProtocol
|
||||
import com.bintianqi.owndroid.dpm.AppStatus
|
||||
import com.bintianqi.owndroid.dpm.CaCertInfo
|
||||
import com.bintianqi.owndroid.dpm.CreateUserResult
|
||||
@@ -48,10 +67,24 @@ import com.bintianqi.owndroid.dpm.FrpPolicyInfo
|
||||
import com.bintianqi.owndroid.dpm.HardwareProperties
|
||||
import com.bintianqi.owndroid.dpm.IntentFilterDirection
|
||||
import com.bintianqi.owndroid.dpm.IntentFilterOptions
|
||||
import com.bintianqi.owndroid.dpm.IpMode
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsData
|
||||
import com.bintianqi.owndroid.dpm.NetworkStatsTarget
|
||||
import com.bintianqi.owndroid.dpm.PendingSystemUpdateInfo
|
||||
import com.bintianqi.owndroid.dpm.PreferentialNetworkServiceInfo
|
||||
import com.bintianqi.owndroid.dpm.PrivateDnsConfiguration
|
||||
import com.bintianqi.owndroid.dpm.ProxyMode
|
||||
import com.bintianqi.owndroid.dpm.ProxyType
|
||||
import com.bintianqi.owndroid.dpm.QueryNetworkStatsParams
|
||||
import com.bintianqi.owndroid.dpm.RecommendedProxyConf
|
||||
import com.bintianqi.owndroid.dpm.SsidPolicy
|
||||
import com.bintianqi.owndroid.dpm.SsidPolicyType
|
||||
import com.bintianqi.owndroid.dpm.SystemOptionsStatus
|
||||
import com.bintianqi.owndroid.dpm.SystemUpdatePolicyInfo
|
||||
import com.bintianqi.owndroid.dpm.UserInformation
|
||||
import com.bintianqi.owndroid.dpm.WifiInfo
|
||||
import com.bintianqi.owndroid.dpm.WifiSecurity
|
||||
import com.bintianqi.owndroid.dpm.WifiStatus
|
||||
import com.bintianqi.owndroid.dpm.activateOrgProfileCommand
|
||||
import com.bintianqi.owndroid.dpm.delegatedScopesList
|
||||
import com.bintianqi.owndroid.dpm.getPackageInstaller
|
||||
@@ -70,6 +103,8 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.net.InetAddress
|
||||
import java.security.MessageDigest
|
||||
import java.security.cert.CertificateException
|
||||
import java.security.cert.CertificateFactory
|
||||
@@ -77,6 +112,8 @@ import java.security.cert.X509Certificate
|
||||
import java.time.ZoneId
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.reflect.jvm.jvmErasure
|
||||
import kotlin.system.measureTimeMillis
|
||||
|
||||
class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
val myRepo = getApplication<MyApplication>().myRepo
|
||||
@@ -1246,6 +1283,368 @@ class MyViewModel(application: Application): AndroidViewModel(application) {
|
||||
fun logoutUser(): Int {
|
||||
return getUserOperationResultText(DPM.logoutUser(DAR))
|
||||
}
|
||||
|
||||
val WM = application.getSystemService(Context.WIFI_SERVICE) as WifiManager
|
||||
// Lockdown admin configured networks
|
||||
@RequiresApi(30)
|
||||
fun getLanEnabled(): Boolean {
|
||||
return DPM.hasLockdownAdminConfiguredNetworks(DAR)
|
||||
}
|
||||
@RequiresApi(30)
|
||||
fun setLanEnabled(state: Boolean) {
|
||||
DPM.setConfiguredNetworksLockdownState(DAR, state)
|
||||
}
|
||||
fun setWifiEnabled(enabled: Boolean): Boolean {
|
||||
return WM.setWifiEnabled(enabled)
|
||||
}
|
||||
fun disconnectWifi(): Boolean {
|
||||
return WM.disconnect()
|
||||
}
|
||||
fun reconnectWifi(): Boolean {
|
||||
return WM.reconnect()
|
||||
}
|
||||
@RequiresApi(24)
|
||||
fun getWifiMac(): String? {
|
||||
return DPM.getWifiMacAddress(DAR)
|
||||
}
|
||||
val configuredNetworks = MutableStateFlow(emptyList<WifiInfo>())
|
||||
fun getConfiguredNetworks() {
|
||||
configuredNetworks.value = WM.configuredNetworks.distinctBy { it.networkId }.map { conf ->
|
||||
WifiInfo(
|
||||
conf.networkId, conf.SSID.removeSurrounding("\""), null, conf.BSSID ?: "", null,
|
||||
WifiStatus.entries.find { it.id == conf.status }!!, null, "", null, null, null, null
|
||||
)
|
||||
}
|
||||
}
|
||||
fun enableNetwork(id: Int): Boolean {
|
||||
return WM.enableNetwork(id, false)
|
||||
}
|
||||
fun disableNetwork(id: Int): Boolean {
|
||||
return WM.disableNetwork(id)
|
||||
}
|
||||
fun removeNetwork(id: Int): Boolean{
|
||||
return WM.removeNetwork(id)
|
||||
}
|
||||
fun setWifi(info: WifiInfo): Boolean {
|
||||
val conf = WifiConfiguration()
|
||||
conf.SSID = "\"" + info.ssid + "\""
|
||||
info.hiddenSsid?.let { conf.hiddenSSID = it }
|
||||
if (VERSION.SDK_INT >= 30) info.security?.let { conf.setSecurityParams(it.id) }
|
||||
if (info.security == WifiSecurity.Psk) conf.preSharedKey = info.password
|
||||
if (VERSION.SDK_INT >= 33) info.macRandomization?.let { conf.macRandomizationSetting = it.id }
|
||||
if (VERSION.SDK_INT >= 33 && info.ipMode != null) {
|
||||
val ipConf = if (info.ipMode == IpMode.Static && info.ipConf != null) {
|
||||
val constructor = LinkAddress::class.constructors.find {
|
||||
it.parameters.size == 1 && it.parameters[0].type.jvmErasure == String::class
|
||||
}
|
||||
val address = constructor!!.call(info.ipConf.address)
|
||||
val staticIpConf = StaticIpConfiguration.Builder()
|
||||
.setIpAddress(address)
|
||||
.setGateway(InetAddress.getByName(info.ipConf.gateway))
|
||||
.setDnsServers(info.ipConf.dns.map { InetAddress.getByName(it) })
|
||||
.build()
|
||||
IpConfiguration.Builder().setStaticIpConfiguration(staticIpConf).build()
|
||||
} else null
|
||||
conf.setIpConfiguration(ipConf)
|
||||
}
|
||||
if (VERSION.SDK_INT >= 26 && info.proxyMode != null) {
|
||||
val proxy = if (info.proxyMode == ProxyMode.Http) {
|
||||
info.proxyConf?.let {
|
||||
ProxyInfo.buildDirectProxy(it.host, it.port, it.exclude)
|
||||
}
|
||||
} else null
|
||||
conf.httpProxy = proxy
|
||||
}
|
||||
val result = if (info.id != -1) {
|
||||
conf.networkId = info.id
|
||||
WM.updateNetwork(conf)
|
||||
} else {
|
||||
WM.addNetwork(conf)
|
||||
}
|
||||
if (result != -1) {
|
||||
when (info.status) {
|
||||
WifiStatus.Current -> WM.enableNetwork(result, true)
|
||||
WifiStatus.Enabled -> WM.enableNetwork(result, false)
|
||||
WifiStatus.Disabled -> WM.disableNetwork(result)
|
||||
}
|
||||
}
|
||||
return result != -1
|
||||
}
|
||||
@RequiresApi(33)
|
||||
fun getMinimumWifiSecurityLevel(): Int {
|
||||
return DPM.minimumRequiredWifiSecurityLevel
|
||||
}
|
||||
@RequiresApi(33)
|
||||
fun setMinimumWifiSecurityLevel(level: Int) {
|
||||
DPM.minimumRequiredWifiSecurityLevel = level
|
||||
}
|
||||
@RequiresApi(33)
|
||||
fun getSsidPolicy(): SsidPolicy {
|
||||
val policy = DPM.wifiSsidPolicy
|
||||
return SsidPolicy(
|
||||
SsidPolicyType.entries.find { it.id == policy?.policyType } ?: SsidPolicyType.None,
|
||||
policy?.ssids?.map { it.bytes.decodeToString() } ?: emptyList()
|
||||
)
|
||||
}
|
||||
@RequiresApi(33)
|
||||
fun setSsidPolicy(policy: SsidPolicy) {
|
||||
val newPolicy = if (policy.type != SsidPolicyType.None) {
|
||||
WifiSsidPolicy(
|
||||
policy.type.id, policy.list.map { WifiSsid.fromBytes(it.encodeToByteArray()) }.toSet()
|
||||
)
|
||||
} else null
|
||||
DPM.wifiSsidPolicy = newPolicy
|
||||
}
|
||||
@RequiresApi(24)
|
||||
fun getPackageUid(name: String): Int {
|
||||
return PM.getPackageUid(name, 0)
|
||||
}
|
||||
var networkStatsData = emptyList<NetworkStatsData>()
|
||||
@RequiresApi(23)
|
||||
fun readNetworkStats(stats: NetworkStats): List<NetworkStatsData> {
|
||||
val list = mutableListOf<NetworkStatsData>()
|
||||
while (stats.hasNextBucket()) {
|
||||
val bucket = NetworkStats.Bucket()
|
||||
stats.getNextBucket(bucket)
|
||||
list += readNetworkStatsBucket(bucket)
|
||||
}
|
||||
stats.close()
|
||||
return list
|
||||
}
|
||||
@RequiresApi(23)
|
||||
fun readNetworkStatsBucket(bucket: NetworkStats.Bucket): NetworkStatsData {
|
||||
return NetworkStatsData(
|
||||
bucket.rxBytes, bucket.rxPackets, bucket.txBytes, bucket.txPackets,
|
||||
bucket.uid, bucket.state, bucket.startTimeStamp, bucket.endTimeStamp,
|
||||
if (VERSION.SDK_INT >= 24) bucket.tag else null,
|
||||
if (VERSION.SDK_INT >= 24) bucket.roaming else null,
|
||||
if (VERSION.SDK_INT >= 26) bucket.metered else null
|
||||
)
|
||||
}
|
||||
@Suppress("NewApi")
|
||||
fun queryNetworkStats(params: QueryNetworkStatsParams, callback: (String?) -> Unit) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val nsm = application.getSystemService(NetworkStatsManager::class.java)
|
||||
try {
|
||||
val data = when (params.target) {
|
||||
NetworkStatsTarget.Device -> listOf(readNetworkStatsBucket(
|
||||
nsm.querySummaryForDevice(
|
||||
params.networkType.type, null, params.startTime, params.endTime
|
||||
)
|
||||
))
|
||||
NetworkStatsTarget.User -> listOf(readNetworkStatsBucket(
|
||||
nsm.querySummaryForUser(
|
||||
params.networkType.type, null, params.startTime, params.endTime
|
||||
)
|
||||
))
|
||||
NetworkStatsTarget.Uid -> readNetworkStats(nsm.queryDetailsForUid(
|
||||
params.networkType.type, null, params.startTime, params.endTime, params.uid
|
||||
))
|
||||
NetworkStatsTarget.UidTag -> readNetworkStats(nsm.queryDetailsForUidTag(
|
||||
params.networkType.type, null, params.startTime, params.endTime,
|
||||
params.uid, params.tag
|
||||
))
|
||||
NetworkStatsTarget.UidTagState -> readNetworkStats(
|
||||
nsm.queryDetailsForUidTagState(
|
||||
params.networkType.type, null, params.startTime, params.endTime,
|
||||
params.uid, params.tag, params.state.id
|
||||
)
|
||||
)
|
||||
}
|
||||
networkStatsData = data
|
||||
withContext(Dispatchers.Main) {
|
||||
if (data.isEmpty()) {
|
||||
callback(application.getString(R.string.no_data))
|
||||
} else {
|
||||
callback(null)
|
||||
}
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
e.printStackTrace()
|
||||
withContext(Dispatchers.Main) {
|
||||
callback(e.message ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fun clearNetworkStats() {
|
||||
networkStatsData = emptyList()
|
||||
}
|
||||
@RequiresApi(29)
|
||||
fun getPrivateDns(): PrivateDnsConfiguration {
|
||||
return PrivateDnsConfiguration(
|
||||
DPM.getGlobalPrivateDnsMode(DAR), DPM.getGlobalPrivateDnsHost(DAR) ?: ""
|
||||
)
|
||||
}
|
||||
@Suppress("PrivateApi")
|
||||
@RequiresApi(29)
|
||||
fun setPrivateDns(conf: PrivateDnsConfiguration): Boolean {
|
||||
return try {
|
||||
val field = DevicePolicyManager::class.java.getDeclaredField("mService")
|
||||
field.isAccessible = true
|
||||
val dpm = field.get(DPM) as IDevicePolicyManager
|
||||
val result = dpm.setGlobalPrivateDns(DAR, conf.mode, conf.host)
|
||||
result == DevicePolicyManager.PRIVATE_DNS_SET_NO_ERROR
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
false
|
||||
}
|
||||
}
|
||||
@RequiresApi(24)
|
||||
fun getAlwaysOnVpnPackage(): String {
|
||||
return DPM.getAlwaysOnVpnPackage(DAR) ?: ""
|
||||
}
|
||||
@RequiresApi(29)
|
||||
fun getAlwaysOnVpnLockdown(): Boolean {
|
||||
return DPM.isAlwaysOnVpnLockdownEnabled(DAR)
|
||||
}
|
||||
@RequiresApi(24)
|
||||
fun setAlwaysOnVpn(name: String?, lockdown: Boolean): Int {
|
||||
return try {
|
||||
DPM.setAlwaysOnVpnPackage(DAR, name, lockdown)
|
||||
R.string.succeeded
|
||||
} catch (_: UnsupportedOperationException) {
|
||||
R.string.unsupported
|
||||
} catch (_: PackageManager.NameNotFoundException) {
|
||||
R.string.not_installed
|
||||
}
|
||||
}
|
||||
fun setRecommendedGlobalProxy(conf: RecommendedProxyConf) {
|
||||
val info = when (conf.type) {
|
||||
ProxyType.Off -> null
|
||||
ProxyType.Pac -> {
|
||||
if (VERSION.SDK_INT >= 30 && conf.specifyPort) {
|
||||
ProxyInfo.buildPacProxy(conf.url.toUri(), conf.port)
|
||||
} else {
|
||||
ProxyInfo.buildPacProxy(conf.url.toUri())
|
||||
}
|
||||
}
|
||||
ProxyType.Direct -> {
|
||||
ProxyInfo.buildDirectProxy(conf.host, conf.port, conf.exclude)
|
||||
}
|
||||
}
|
||||
DPM.setRecommendedGlobalProxy(DAR, info)
|
||||
}
|
||||
// PNS: preferential network service
|
||||
@RequiresApi(31)
|
||||
fun getPnsEnabled(): Boolean {
|
||||
return DPM.isPreferentialNetworkServiceEnabled
|
||||
}
|
||||
@RequiresApi(31)
|
||||
fun setPnsEnabled(enabled: Boolean) {
|
||||
DPM.isPreferentialNetworkServiceEnabled = enabled
|
||||
}
|
||||
val pnsConfigs = MutableStateFlow(emptyList<PreferentialNetworkServiceInfo>())
|
||||
@RequiresApi(33)
|
||||
fun getPnsConfigs() {
|
||||
pnsConfigs.value = DPM.preferentialNetworkServiceConfigs.map {
|
||||
PreferentialNetworkServiceInfo(
|
||||
it.isEnabled, it.networkId, it.isFallbackToDefaultConnectionAllowed,
|
||||
if (VERSION.SDK_INT >= 34) it.shouldBlockNonMatchingNetworks() else false,
|
||||
it.excludedUids.toList(), it.includedUids.toList()
|
||||
)
|
||||
}
|
||||
}
|
||||
@RequiresApi(33)
|
||||
fun buildPnsConfig(
|
||||
info: PreferentialNetworkServiceInfo
|
||||
): PreferentialNetworkServiceConfig {
|
||||
return PreferentialNetworkServiceConfig.Builder().apply {
|
||||
setEnabled(info.enabled)
|
||||
@Suppress("WrongConstant")
|
||||
setNetworkId(info.id)
|
||||
setFallbackToDefaultConnectionAllowed(info.allowFallback)
|
||||
if (VERSION.SDK_INT >= 34) setShouldBlockNonMatchingNetworks(info.blockNonMatching)
|
||||
setIncludedUids(info.includedUids.toIntArray())
|
||||
setExcludedUids(info.excludedUids.toIntArray())
|
||||
}.build()
|
||||
}
|
||||
@RequiresApi(33)
|
||||
fun setPnsConfig(info: PreferentialNetworkServiceInfo, state: Boolean) {
|
||||
val configs = pnsConfigs.value.run {
|
||||
if (state) plus(info) else minus(info)
|
||||
}.map { buildPnsConfig(it) }
|
||||
DPM.preferentialNetworkServiceConfigs = configs
|
||||
}
|
||||
val apnConfigs = MutableStateFlow(listOf<ApnConfig>())
|
||||
@RequiresApi(28)
|
||||
fun getApnEnabled(): Boolean {
|
||||
return DPM.isOverrideApnEnabled(DAR)
|
||||
}
|
||||
@RequiresApi(28)
|
||||
fun setApnEnabled(enabled: Boolean) {
|
||||
DPM.setOverrideApnsEnabled(DAR, enabled)
|
||||
}
|
||||
@RequiresApi(28)
|
||||
fun getApnConfigs() {
|
||||
apnConfigs.value = DPM.getOverrideApns(DAR).map {
|
||||
val proxy = if (VERSION.SDK_INT >= 29) it.proxyAddressAsString else it.proxyAddress.hostName
|
||||
val mmsProxy = if (VERSION.SDK_INT >= 29) it.mmsProxyAddressAsString else it.mmsProxyAddress.hostName
|
||||
ApnConfig(
|
||||
it.isEnabled, it.entryName, it.apnName, proxy, it.proxyPort,
|
||||
it.user, it.password, it.apnTypeBitmask, it.mmsc.toString(),
|
||||
mmsProxy, it.mmsProxyPort,
|
||||
ApnAuthType.entries.find { type -> type.id == it.authType }!!,
|
||||
ApnProtocol.entries.find { protocol -> protocol.id == it.protocol }!!,
|
||||
ApnProtocol.entries.find { protocol -> protocol.id == it.roamingProtocol }!!,
|
||||
it.networkTypeBitmask,
|
||||
if (VERSION.SDK_INT >= 33) it.profileId else 0,
|
||||
if (VERSION.SDK_INT >= 29) it.carrierId else 0,
|
||||
if (VERSION.SDK_INT >= 33) it.mtuV4 else 0,
|
||||
if (VERSION.SDK_INT >= 33) it.mtuV6 else 0,
|
||||
ApnMvnoType.entries.find { type -> type.id == it.mvnoType }!!,
|
||||
it.operatorNumeric,
|
||||
if (VERSION.SDK_INT >= 33) it.isPersistent else true,
|
||||
if (VERSION.SDK_INT >= 35) it.isAlwaysOn else true,
|
||||
it.id
|
||||
)
|
||||
}
|
||||
}
|
||||
@RequiresApi(28)
|
||||
fun buildApnSetting(config: ApnConfig): ApnSetting? {
|
||||
val builder = ApnSetting.Builder()
|
||||
builder.setCarrierEnabled(config.enabled)
|
||||
builder.setEntryName(config.name)
|
||||
builder.setApnName(config.apn)
|
||||
if (VERSION.SDK_INT >= 29) builder.setProxyAddress(config.proxy)
|
||||
else builder.setProxyAddress(InetAddress.getByName(config.proxy))
|
||||
config.port?.let { builder.setProxyPort(it) }
|
||||
builder.setUser(config.username)
|
||||
builder.setPassword(config.password)
|
||||
builder.setApnTypeBitmask(config.apnType)
|
||||
builder.setMmsc(config.mmsc.toUri())
|
||||
if (VERSION.SDK_INT >= 29) builder.setMmsProxyAddress(config.mmsProxy)
|
||||
else builder.setMmsProxyAddress(InetAddress.getByName(config.mmsProxy))
|
||||
builder.setAuthType(config.authType.id)
|
||||
builder.setProtocol(config.protocol.id)
|
||||
builder.setRoamingProtocol(config.roamingProtocol.id)
|
||||
builder.setNetworkTypeBitmask(config.networkType)
|
||||
if (VERSION.SDK_INT >= 33) config.profileId?.let { builder.setProfileId(it) }
|
||||
if (VERSION.SDK_INT >= 29) config.carrierId?.let { builder.setCarrierId(it) }
|
||||
if (VERSION.SDK_INT >= 33) {
|
||||
config.mtuV4?.let { builder.setMtuV4(it) }
|
||||
config.mtuV6?.let { builder.setMtuV6(it) }
|
||||
}
|
||||
builder.setMvnoType(config.mvno.id)
|
||||
builder.setOperatorNumeric(config.operatorNumeric)
|
||||
if (VERSION.SDK_INT >= 33) builder.setPersistent(config.persistent)
|
||||
if (VERSION.SDK_INT >= 35) builder.setAlwaysOn(config.alwaysOn)
|
||||
return builder.build()
|
||||
}
|
||||
@RequiresApi(28)
|
||||
fun setApnConfig(config: ApnConfig): Boolean {
|
||||
val settings = buildApnSetting(config)
|
||||
if (settings == null) return false
|
||||
return if (config.id == -1) {
|
||||
DPM.addOverrideApn(DAR, settings) != -1
|
||||
} else {
|
||||
DPM.updateOverrideApn(DAR, config.id, settings)
|
||||
}
|
||||
}
|
||||
@RequiresApi(28)
|
||||
fun removeApnConfig(id: Int): Boolean {
|
||||
return DPM.removeOverrideApn(DAR, id)
|
||||
}
|
||||
}
|
||||
|
||||
data class ThemeSettings(
|
||||
|
||||
@@ -6,11 +6,13 @@ import android.app.admin.DeviceAdminReceiver
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Binder
|
||||
import android.os.Build.VERSION
|
||||
import android.os.UserHandle
|
||||
import android.os.UserManager
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.bintianqi.owndroid.dpm.handleNetworkLogs
|
||||
import com.bintianqi.owndroid.dpm.handlePrivilegeChange
|
||||
import com.bintianqi.owndroid.dpm.processSecurityLogs
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -34,6 +36,7 @@ class Receiver : DeviceAdminReceiver() {
|
||||
override fun onEnabled(context: Context, intent: Intent) {
|
||||
super.onEnabled(context, intent)
|
||||
Privilege.updateStatus()
|
||||
if (Binder.getCallingUid() / 100000 != 0) handlePrivilegeChange(context)
|
||||
}
|
||||
|
||||
override fun onDisabled(context: Context, intent: Intent) {
|
||||
|
||||
@@ -7,14 +7,11 @@ import android.content.Context
|
||||
import android.content.pm.PackageInfo
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.saveable.Saver
|
||||
import androidx.compose.runtime.saveable.SaverScope
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.io.FileNotFoundException
|
||||
@@ -25,7 +22,6 @@ import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
var zhCN = true
|
||||
|
||||
@@ -81,18 +77,6 @@ fun Context.showOperationResultToast(success: Boolean) {
|
||||
|
||||
const val APK_MIME = "application/vnd.android.package-archive"
|
||||
|
||||
inline fun <reified T> serializableNavTypePair() =
|
||||
typeOf<T>() to object : NavType<T>(false) {
|
||||
override fun get(bundle: Bundle, key: String): T? =
|
||||
bundle.getString(key)?.let { parseValue(it) }
|
||||
override fun put(bundle: Bundle, key: String, value: T) =
|
||||
bundle.putString(key, serializeAsValue(value))
|
||||
override fun parseValue(value: String): T =
|
||||
Json.decodeFromString(value)
|
||||
override fun serializeAsValue(value: T): String =
|
||||
Json.encodeToString(value)
|
||||
}
|
||||
|
||||
fun exportLogs(context: Context, uri: Uri) {
|
||||
context.contentResolver.openOutputStream(uri)?.use { output ->
|
||||
val proc = Runtime.getRuntime().exec("logcat -d")
|
||||
@@ -103,10 +87,6 @@ fun exportLogs(context: Context, uri: Uri) {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> NavHostController.navigate(route: T, args: Bundle) {
|
||||
navigate(graph.findNode(route)!!.id, args)
|
||||
}
|
||||
|
||||
val HorizontalPadding = 16.dp
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
@@ -391,19 +391,13 @@ fun parseSecurityEventData(event: SecurityLog.SecurityEvent): JsonElement? {
|
||||
}
|
||||
|
||||
fun setDefaultAffiliationID() {
|
||||
if(VERSION.SDK_INT < 26) return
|
||||
val privilege = Privilege.status.value
|
||||
if (VERSION.SDK_INT < 26) return
|
||||
if(!SP.isDefaultAffiliationIdSet) {
|
||||
try {
|
||||
if(privilege.device || (!privilege.primary && privilege.profile)) {
|
||||
val affiliationIDs = Privilege.DPM.getAffiliationIds(Privilege.DAR)
|
||||
if(affiliationIDs.isEmpty()) {
|
||||
Privilege.DPM.setAffiliationIds(Privilege.DAR, setOf("OwnDroid_default_affiliation_id"))
|
||||
SP.isDefaultAffiliationIdSet = true
|
||||
Log.d("DPM", "Default affiliation id set")
|
||||
}
|
||||
}
|
||||
} catch(e: Exception) {
|
||||
Privilege.DPM.setAffiliationIds(Privilege.DAR, setOf("OwnDroid_default_affiliation_id"))
|
||||
SP.isDefaultAffiliationIdSet = true
|
||||
Log.d("DPM", "Default affiliation id set")
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user