Make the hidden APIs of TelephonyManager extensions

So that it looks nicer and we can potentially build against AOSP by
simply excluding all of the reflection-based hacks (by putting them in a
library first)
This commit is contained in:
Peter Cai 2022-05-03 16:18:05 -04:00
parent 0de44f7d03
commit 103be89d17
2 changed files with 50 additions and 23 deletions

View File

@ -1,14 +1,13 @@
package im.angry.openeuicc.core
import android.telephony.IccOpenLogicalChannelResponse
import android.telephony.IccOpenLogicalChannelResponse.INVALID_CHANNEL
import android.telephony.IccOpenLogicalChannelResponse.STATUS_NO_ERROR
import android.telephony.TelephonyManager
import android.util.Log
import com.truphone.lpa.ApduChannel
import com.truphone.lpa.ApduTransmittedListener
import im.angry.openeuicc.util.*
import java.lang.Exception
import java.lang.reflect.Method
class TelephonyManagerApduChannel(
private val tm: TelephonyManager,
@ -19,23 +18,12 @@ class TelephonyManagerApduChannel(
private const val TAG = "TelephonyManagerApduChannel"
private const val EUICC_APP_ID = "A0000005591010FFFFFFFF8900000100"
private val iccOpenLogicalChannelBySlot: Method =
TelephonyManager::class.java.getMethod("iccOpenLogicalChannelBySlot",
Int::class.java, String::class.java, Int::class.java)
private val iccCloseLogicalChannelBySlot: Method =
TelephonyManager::class.java.getMethod("iccCloseLogicalChannelBySlot",
Int::class.java, Int::class.java)
private val iccTransmitApduLogicalChannelBySlot: Method =
TelephonyManager::class.java.getMethod("iccTransmitApduLogicalChannelBySlot",
Int::class.java, Int::class.java, Int::class.java, Int::class.java,
Int::class.java, Int::class.java, Int::class.java, String::class.java)
// TODO: On Tiramisu, we need to specify the portId also if we want MEP support
fun tryConnectUiccSlot(tm: TelephonyManager, slotId: Int): Pair<ApduChannel, EuiccChannelStateManager>? {
try {
// FIXME: Clean up previously opened channels across restarts
iccCloseLogicalChannelBySlot.invoke(tm, slotId, 1)
val channel = iccOpenLogicalChannelBySlot.invoke(tm, slotId, EUICC_APP_ID, 0) as IccOpenLogicalChannelResponse
tm.iccCloseLogicalChannelBySlot(slotId, 1)
val channel = tm.iccOpenLogicalChannelBySlot(slotId, EUICC_APP_ID, 0)
if (channel.status != STATUS_NO_ERROR || channel.channel == INVALID_CHANNEL) {
Log.e(TAG, "Unable to open eUICC channel for slot ${slotId} via TelephonyManager: ${channel.status}")
return null
@ -48,7 +36,7 @@ class TelephonyManagerApduChannel(
get() = true // TODO: Fix this properly
override fun destroy() {
iccCloseLogicalChannelBySlot.invoke(tm, slotId, channel.channel)
tm.iccCloseLogicalChannelBySlot(slotId, channel.channel)
}
}
@ -62,7 +50,7 @@ class TelephonyManagerApduChannel(
}
}
override fun transmitAPDU(apdu: String): String {
override fun transmitAPDU(apdu: String): String? {
val cla = Integer.parseInt(apdu.substring(0, 2), 16)
val instruction = Integer.parseInt(apdu.substring(2, 4), 16)
val p1 = Integer.parseInt(apdu.substring(4, 6), 16)
@ -70,13 +58,13 @@ class TelephonyManagerApduChannel(
val p3 = Integer.parseInt(apdu.substring(8, 10), 16)
val p4 = apdu.substring(10)
return iccTransmitApduLogicalChannelBySlot.invoke(
tm, slotId, channelId,
cla, instruction, p1, p2, p3, p4) as String
return tm.iccTransmitApduLogicalChannelBySlot(
slotId, channelId,
cla, instruction, p1, p2, p3, p4)
}
override fun transmitAPDUS(apdus: MutableList<String>): String {
var res = ""
override fun transmitAPDUS(apdus: MutableList<String>): String? {
var res: String? = ""
for (pdu in apdus) {
res = transmitAPDU(pdu)
}

View File

@ -1,6 +1,8 @@
package im.angry.openeuicc.util
import android.telephony.IccOpenLogicalChannelResponse
import android.telephony.TelephonyManager
import java.lang.reflect.Method
val TelephonyManager.supportsDSDS: Boolean
get() = supportedModemCount == 2
@ -9,4 +11,41 @@ var TelephonyManager.dsdsEnabled: Boolean
get() = activeModemCount >= 2
set(value) {
switchMultiSimConfig(if (value) { 2 } else {1})
}
}
// Hidden APIs via reflection to enable building without AOSP source tree
private val iccOpenLogicalChannelBySlot: Method by lazy {
TelephonyManager::class.java.getMethod(
"iccOpenLogicalChannelBySlot",
Int::class.java, String::class.java, Int::class.java
)
}
private val iccCloseLogicalChannelBySlot: Method by lazy {
TelephonyManager::class.java.getMethod(
"iccCloseLogicalChannelBySlot",
Int::class.java, Int::class.java
)
}
private val iccTransmitApduLogicalChannelBySlot: Method by lazy {
TelephonyManager::class.java.getMethod(
"iccTransmitApduLogicalChannelBySlot",
Int::class.java, Int::class.java, Int::class.java, Int::class.java,
Int::class.java, Int::class.java, Int::class.java, String::class.java
)
}
fun TelephonyManager.iccOpenLogicalChannelBySlot(
slotId: Int, appletId: String, p2: Int
): IccOpenLogicalChannelResponse =
iccOpenLogicalChannelBySlot.invoke(this, slotId, appletId, p2) as IccOpenLogicalChannelResponse
fun TelephonyManager.iccCloseLogicalChannelBySlot(slotId: Int, channel: Int): Boolean =
iccCloseLogicalChannelBySlot.invoke(this, slotId, channel) as Boolean
fun TelephonyManager.iccTransmitApduLogicalChannelBySlot(
slotId: Int, channel: Int, cla: Int, instruction: Int,
p1: Int, p2: Int, p3: Int, data: String?
): String? =
iccTransmitApduLogicalChannelBySlot.invoke(
this, slotId, channel, cla, instruction, p1, p2, p3, data
) as String?