refactor: open sim toolkit logical #58
4 changed files with 95 additions and 44 deletions
|
@ -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>
|
|
@ -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 =
|
menu.findItem(R.id.open_sim_toolkit).apply {
|
||||||
SIMToolkit.getComponentName(requireContext(), slotId) != null
|
isVisible = stk.isAvailable(slotId)
|
||||||
|
intent = stk.intent(slotId)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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
|
import android.content.pm.PackageManager
|
||||||
|
import androidx.annotation.ArrayRes
|
||||||
|
import im.angry.easyeuicc.R
|
||||||
|
import im.angry.openeuicc.core.EuiccChannelManager
|
||||||
|
|
||||||
object SIMToolkit {
|
class SIMToolkit(private val context: Context) {
|
||||||
private val slot1activities = arrayOf(
|
private val slotSelection = getComponentNames(R.array.sim_toolkit_slot_selection)
|
||||||
ComponentName("com.android.stk", "com.android.stk.StkMain1"),
|
|
||||||
)
|
|
||||||
|
|
||||||
private val slot2activities = arrayOf(
|
private val slots = buildMap {
|
||||||
ComponentName("com.android.stk", "com.android.stk.StkMain2"),
|
put(0, getComponentNames(R.array.sim_toolkit_slot_1))
|
||||||
)
|
put(1, getComponentNames(R.array.sim_toolkit_slot_2))
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun intent(context: Context, slotId: Int) = Intent(Intent.ACTION_MAIN, null).apply {
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
component = getComponentName(context, slotId)
|
component = components.find(activities::contains)
|
||||||
addCategory(Intent.CATEGORY_LAUNCHER)
|
addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
}
|
}
|
||||||
|
return if (intent.component != null) intent else launchIntent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
32
app-unpriv/src/main/res/values/sim_toolkit.xml
Normal file
32
app-unpriv/src/main/res/values/sim_toolkit.xml
Normal file
|
@ -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>
|
Loading…
Add table
Reference in a new issue