Browse Source

refactor: open sim toolkit logical (#58)

Reviewed-on: https://gitea.angry.im/PeterCxy/OpenEUICC/pulls/58
Co-authored-by: septs <github@septs.pw>
Co-committed-by: septs <github@septs.pw>
septs 1 year ago
parent
commit
9d8e58a95d

+ 2 - 0
app-unpriv/src/main/AndroidManifest.xml

@@ -29,5 +29,7 @@
 
 
     <queries>
     <queries>
         <package android:name="com.android.stk" />
         <package android:name="com.android.stk" />
+        <package android:name="com.android.stk1" />
+        <package android:name="com.android.stk2" />
     </queries>
     </queries>
 </manifest>
 </manifest>

+ 8 - 17
app-unpriv/src/main/java/im/angry/openeuicc/ui/UnprivilegedEuiccManagementFragment.kt

@@ -1,12 +1,9 @@
 package im.angry.openeuicc.ui
 package im.angry.openeuicc.ui
 
 
-import android.util.Log
 import android.view.Menu
 import android.view.Menu
 import android.view.MenuInflater
 import android.view.MenuInflater
-import android.view.MenuItem
 import im.angry.easyeuicc.R
 import im.angry.easyeuicc.R
 import im.angry.openeuicc.util.SIMToolkit
 import im.angry.openeuicc.util.SIMToolkit
-import im.angry.openeuicc.util.isUsb
 import im.angry.openeuicc.util.newInstanceEuicc
 import im.angry.openeuicc.util.newInstanceEuicc
 import im.angry.openeuicc.util.slotId
 import im.angry.openeuicc.util.slotId
 
 
@@ -19,22 +16,16 @@ class UnprivilegedEuiccManagementFragment : EuiccManagementFragment() {
             newInstanceEuicc(UnprivilegedEuiccManagementFragment::class.java, slotId, portId)
             newInstanceEuicc(UnprivilegedEuiccManagementFragment::class.java, slotId, portId)
     }
     }
 
 
+    private val stk by lazy {
+        SIMToolkit(requireContext())
+    }
+
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
     override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
         super.onCreateOptionsMenu(menu, inflater)
         super.onCreateOptionsMenu(menu, inflater)
         inflater.inflate(R.menu.fragment_sim_toolkit, menu)
         inflater.inflate(R.menu.fragment_sim_toolkit, menu)
-        menu.findItem(R.id.open_sim_toolkit).isVisible =
-            SIMToolkit.getComponentName(requireContext(), slotId) != null
-    }
-
-    override fun onOptionsItemSelected(item: MenuItem): Boolean =
-        when (item.itemId) {
-            R.id.open_sim_toolkit -> {
-                val intent = SIMToolkit.intent(requireContext(), slotId)
-                Log.d(TAG, "Opening SIM Toolkit for $slotId slot, intent: $intent")
-                startActivity(intent)
-                true
-            }
-
-            else -> super.onOptionsItemSelected(item)
+        menu.findItem(R.id.open_sim_toolkit).apply {
+            isVisible = stk.isAvailable(slotId)
+            intent = stk.intent(slotId)
         }
         }
+    }
 }
 }

+ 55 - 29
app-unpriv/src/main/java/im/angry/openeuicc/util/SIMToolkit.kt

@@ -3,36 +3,62 @@ package im.angry.openeuicc.util
 import android.content.ComponentName
 import android.content.ComponentName
 import android.content.Context
 import android.content.Context
 import android.content.Intent
 import android.content.Intent
-import android.content.pm.PackageManager.NameNotFoundException
-
-object SIMToolkit {
-    private val slot1activities = arrayOf(
-        ComponentName("com.android.stk", "com.android.stk.StkMain1"),
-    )
-
-    private val slot2activities = arrayOf(
-        ComponentName("com.android.stk", "com.android.stk.StkMain2"),
-    )
-
-    fun getComponentName(context: Context, slotId: Int): ComponentName? {
-        val components = when (slotId) {
-            0 -> slot1activities
-            1 -> slot2activities
-            else -> return null
-        }
-        return components.find {
-            try {
-                context.packageManager.getActivityIcon(it)
-                true
-            } catch (_: NameNotFoundException) {
-                false
-            }
-        }
+import android.content.pm.PackageManager
+import androidx.annotation.ArrayRes
+import im.angry.easyeuicc.R
+import im.angry.openeuicc.core.EuiccChannelManager
+
+class SIMToolkit(private val context: Context) {
+    private val slotSelection = getComponentNames(R.array.sim_toolkit_slot_selection)
+
+    private val slots = buildMap {
+        put(0, getComponentNames(R.array.sim_toolkit_slot_1))
+        put(1, getComponentNames(R.array.sim_toolkit_slot_2))
+    }
+
+    private val packageNames = buildSet {
+        addAll(slotSelection.map { it.packageName })
+        addAll(slots.values.flatten().map { it.packageName })
+    }
+
+    private val activities = packageNames.flatMap(::getActivities).toSet()
+
+    private val launchIntent by lazy {
+        packageNames.firstNotNullOfOrNull(::getLaunchIntent)
     }
     }
 
 
-    fun intent(context: Context, slotId: Int) = Intent(Intent.ACTION_MAIN, null).apply {
-        flags = Intent.FLAG_ACTIVITY_NEW_TASK
-        component = getComponentName(context, slotId)
-        addCategory(Intent.CATEGORY_LAUNCHER)
+    private fun getLaunchIntent(packageName: String) = try {
+        val pm = context.packageManager
+        pm.getLaunchIntentForPackage(packageName)
+    } catch (_: PackageManager.NameNotFoundException) {
+        null
+    }
+
+    private fun getActivities(packageName: String) = try {
+        val pm = context.packageManager
+        val packageInfo = pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES)
+        packageInfo.activities!!.filter { it.exported }
+            .map { ComponentName(it.packageName, it.name) }
+    } catch (_: PackageManager.NameNotFoundException) {
+        emptyList()
+    }
+
+    private fun getComponentNames(@ArrayRes id: Int) =
+        context.resources.getStringArray(id).mapNotNull(ComponentName::unflattenFromString)
+
+    fun isAvailable(slotId: Int) = when (slotId) {
+        -1 -> false
+        EuiccChannelManager.USB_CHANNEL_ID -> false
+        else -> intent(slotId) != null
+    }
+
+    fun intent(slotId: Int): Intent? {
+        val components = slots.getOrDefault(slotId, emptySet()) + slotSelection
+        val intent = Intent(Intent.ACTION_MAIN, null).apply {
+            flags = Intent.FLAG_ACTIVITY_NEW_TASK
+            component = components.find(activities::contains)
+            addCategory(Intent.CATEGORY_LAUNCHER)
+        }
+        return if (intent.component != null) intent else launchIntent
     }
     }
 }
 }

+ 32 - 0
app-unpriv/src/main/res/values/sim_toolkit.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="Typos">
+    <string-array name="sim_toolkit_slot_selection">
+        <item>com.android.stk/.StkMain</item>
+        <item>com.android.stk/.StkMainHide</item>
+        <item>com.android.stk/.StkListActivity</item>
+        <item>com.android.stk/.StkLauncherListActivity</item>
+    </string-array>
+    <string-array name="sim_toolkit_slot_1">
+        <item>com.android.stk/.StkMain1</item>
+        <item>com.android.stk/.PrimaryStkMain</item>
+        <item>com.android.stk/.StkLauncherActivity</item>
+        <item>com.android.stk/.StkLauncherActivity_Chn</item>
+        <item>com.android.stk/.StkLauncherActivityI</item>
+        <item>com.android.stk/.OppoStkLauncherActivity1</item>
+        <item>com.android.stk/.OplusStkLauncherActivity1</item>
+        <item>com.android.stk/.mtk.StkLauncherActivityI</item>
+    </string-array>
+    <string-array name="sim_toolkit_slot_2">
+        <item>com.android.stk/.StkMain2</item>
+        <item>com.android.stk/.SecondaryStkMain</item>
+        <item>com.android.stk/.StkLauncherActivity2</item>
+        <item>com.android.stk/.StkLauncherActivityII</item>
+        <item>com.android.stk/.OppoStkLauncherActivity2</item>
+        <item>com.android.stk/.OplusStkLauncherActivity2</item>
+        <item>com.android.stk/.mtk.StkLauncherActivityII</item>
+        <item>com.android.stk1/.StkLauncherActivity</item>
+        <item>com.android.stk2/.StkLauncherActivity</item>
+        <item>com.android.stk2/.StkLauncherActivity_Chn</item>
+        <item>com.android.stk2/.StkLauncherActivity2</item>
+    </string-array>
+</resources>