From a67b564a816db59d74c78a96de1b1e1588a79858 Mon Sep 17 00:00:00 2001 From: septs Date: Sun, 15 Sep 2024 19:49:45 +0800 Subject: [PATCH] refactor --- app/build.gradle.kts | 2 +- app/src/main/AndroidManifest.xml | 21 +++++++++++++--- .../java/app/septs/euiccprobe/MainActivity.kt | 4 ++- .../app/septs/euiccprobe/OpenMobileAPI.kt | 25 +++++++++++-------- .../euiccprobe/PrivAppPermissionParser.kt | 25 +++++++++++++++++++ .../java/app/septs/euiccprobe/SystemApps.kt | 19 +++----------- .../app/septs/euiccprobe/SystemProperties.kt | 9 +++++++ .../app/septs/euiccprobe/SystemService.kt | 9 ++----- 8 files changed, 74 insertions(+), 40 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 167d987..7e38913 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,7 +13,7 @@ android { applicationId = "app.septs.euiccprobe" minSdk = 21 targetSdk = 34 - versionCode = 6 + versionCode = 7 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 62b8947..e6c0362 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,12 +3,11 @@ xmlns:tools="http://schemas.android.com/tools"> - + android:name="org.simalliance.openmobileapi.SMARTCARD" + android:maxSdkVersion="28" /> + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/app/septs/euiccprobe/MainActivity.kt b/app/src/main/java/app/septs/euiccprobe/MainActivity.kt index b387928..cba719b 100644 --- a/app/src/main/java/app/septs/euiccprobe/MainActivity.kt +++ b/app/src/main/java/app/septs/euiccprobe/MainActivity.kt @@ -78,7 +78,7 @@ class MainActivity : AppCompatActivity() { if (label != null) { appendLine("- $label (${pkg.packageName})") } else { - appendLine("- ${pkg.packageName} [uninstalled]") + appendLine("- ${pkg.packageName}") } } } @@ -86,6 +86,8 @@ class MainActivity : AppCompatActivity() { "esim.enable_esim_system_ui_by_default", "ro.telephony.sim_slots.count", "ro.setupwizard.esim_cid_ignore", + // Xiaomi Vendor + "ro.vendor.miui.support_esim" ) SystemProperties.pick(*properties).let { if (it.isEmpty()) return@let diff --git a/app/src/main/java/app/septs/euiccprobe/OpenMobileAPI.kt b/app/src/main/java/app/septs/euiccprobe/OpenMobileAPI.kt index 6da0ab4..227c226 100644 --- a/app/src/main/java/app/septs/euiccprobe/OpenMobileAPI.kt +++ b/app/src/main/java/app/septs/euiccprobe/OpenMobileAPI.kt @@ -1,7 +1,6 @@ package app.septs.euiccprobe import android.content.Context -import android.content.pm.PackageManager import android.os.Build import android.telephony.TelephonyManager import android.util.Log @@ -33,27 +32,31 @@ object OpenMobileAPI { Available, } - enum class SEBypass { Unavailable, CannotBeBypassed, CanBeBypassed, - FullAccess, + TemporaryFullAccess, + PersistentFullAccess } + @Suppress("SpellCheckingInspection") @RequiresApi(Build.VERSION_CODES.P) fun getBypassState(context: Context): SEBypass { - val pkgName = "com.android.se" - if (!SystemService.hasService(context, pkgName)) { + if (!SystemService.hasService(context, "com.android.se")) { return SEBypass.Unavailable } - if (SystemProperties["ro.debuggable"].toInt() != 1) { - return SEBypass.CannotBeBypassed + val isDebuggable = SystemProperties.isEnabled("ro.debuggable") + val isFullAccess = SystemProperties.boolean("service.seek") { + it.contains("fullaccess") + } + val isPersistFullAccess = SystemProperties.boolean("persist.service.seek") { + it.contains("fullaccess") } - val isFullAccess = SystemProperties["service.seek"] - .ifEmpty { SystemProperties["persist.service.seek"] } - .contains("fullaccess") - return if (isFullAccess) SEBypass.FullAccess else SEBypass.CanBeBypassed + if (!isDebuggable) return SEBypass.CannotBeBypassed + if (isFullAccess) return SEBypass.TemporaryFullAccess + if (isPersistFullAccess) return SEBypass.PersistentFullAccess + return SEBypass.CanBeBypassed } suspend fun getSlots(context: Context): Result { diff --git a/app/src/main/java/app/septs/euiccprobe/PrivAppPermissionParser.kt b/app/src/main/java/app/septs/euiccprobe/PrivAppPermissionParser.kt index f04b015..67e2da2 100644 --- a/app/src/main/java/app/septs/euiccprobe/PrivAppPermissionParser.kt +++ b/app/src/main/java/app/septs/euiccprobe/PrivAppPermissionParser.kt @@ -4,6 +4,7 @@ import android.util.Xml import app.septs.euiccprobe.PrivAppPermissionParser.Companion.PrivAppPermission import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParserException +import java.io.File import java.io.IOException import java.io.InputStream import java.nio.charset.Charset @@ -15,6 +16,30 @@ class PrivAppPermissionParser : Iterable { val allowedPermissions: MutableSet, val deniedPermissions: MutableSet ) + + fun loadPermissions(): List { + val permissions = listOf( + File("/etc/permissions/"), + File("/system/etc/permissions/"), + File("/vendor/etc/permissions/"), + File("/product/etc/permissions/"), + ) + val parser = PrivAppPermissionParser() + for (permission in permissions) { + if (!permission.exists()) continue + val files = permission.listFiles() ?: continue + for (file in files) { + if (!file.canRead()) continue + if (file.extension != "xml") continue + try { + file.inputStream().use(parser::parse) + } catch (e: Exception) { + // ignore + } + } + } + return parser.permissions.values.toList() + } } private val namespace: String? = null diff --git a/app/src/main/java/app/septs/euiccprobe/SystemApps.kt b/app/src/main/java/app/septs/euiccprobe/SystemApps.kt index 9654582..a5fb051 100644 --- a/app/src/main/java/app/septs/euiccprobe/SystemApps.kt +++ b/app/src/main/java/app/septs/euiccprobe/SystemApps.kt @@ -1,8 +1,6 @@ package app.septs.euiccprobe -import android.content.Context import android.content.pm.PackageManager -import java.io.File object SystemApps { private val requiredPermissions = setOf( @@ -12,25 +10,14 @@ object SystemApps { ) private val optionalPermissions = setOf( + "android.permission.BIND_EUICC_SERVICE", "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION", "com.android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS", ) fun getSystemLPAs(): List { - val directories = listOf("/", "/system", "/vendor", "/product") - val parser = PrivAppPermissionParser() - for (directory in directories) { - val permissions = File(directory, "etc/permissions/") - if (!permissions.exists()) continue - val files = permissions.listFiles() ?: continue - for (file in files) { - if (!file.canRead()) continue - if (!file.name.startsWith("privapp-permissions")) continue - if (file.extension != "xml") continue - file.inputStream().use(parser::parse) - } - } - return parser.filter { perm -> + val permissions = PrivAppPermissionParser.loadPermissions() + return permissions.filter { perm -> perm.allowedPermissions.containsAll(requiredPermissions) && perm.allowedPermissions.any(optionalPermissions::contains) } diff --git a/app/src/main/java/app/septs/euiccprobe/SystemProperties.kt b/app/src/main/java/app/septs/euiccprobe/SystemProperties.kt index 86d4ed5..2d0b356 100644 --- a/app/src/main/java/app/septs/euiccprobe/SystemProperties.kt +++ b/app/src/main/java/app/septs/euiccprobe/SystemProperties.kt @@ -25,4 +25,13 @@ object SystemProperties { put(name, properties[name]) } } + + fun boolean(name: String, matcher: (value: String) -> Boolean): Boolean { + return matcher(properties[name] ?: return false) + } + + fun isEnabled(name: String) = boolean(name) { + val value = it.lowercase() + value == "1" || value == "y" || value == "true" || value == "yes" || value == "on" + } } \ No newline at end of file diff --git a/app/src/main/java/app/septs/euiccprobe/SystemService.kt b/app/src/main/java/app/septs/euiccprobe/SystemService.kt index 815bb6f..2dd29b6 100644 --- a/app/src/main/java/app/septs/euiccprobe/SystemService.kt +++ b/app/src/main/java/app/septs/euiccprobe/SystemService.kt @@ -22,6 +22,7 @@ object SystemService { "android.hardware.telephony.euicc", "android.hardware.telephony.euicc.mep", "android.hardware.se.omapi.uicc", + "android.hardware.usb.host", ) return buildMap { for (feature in features) { @@ -41,14 +42,8 @@ object SystemService { } fun hasService(context: Context, name: String): Boolean { - val pm = context.packageManager - val flags = 0 return try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - pm.getApplicationInfo(name, PackageManager.ApplicationInfoFlags.of(flags.toLong())) - } else { - pm.getApplicationInfo(name, flags) - } + context.packageManager.getApplicationInfo(name, 0) true } catch (_: PackageManager.NameNotFoundException) { false