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