Make OpenEuiccUIContextMarker usable for services as well

This commit is contained in:
Peter Cai 2024-02-04 20:29:57 -05:00
parent 632b6b4931
commit 1c8918e7f0
9 changed files with 36 additions and 44 deletions

View file

@ -8,7 +8,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class DirectProfileDownloadActivity : AppCompatActivity(), SlotSelectFragment.SlotSelectedListener, OpenEuiccUIContextMarker { class DirectProfileDownloadActivity : AppCompatActivity(), SlotSelectFragment.SlotSelectedListener, OpenEuiccContextMarker {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
lifecycleScope.launch { lifecycleScope.launch {

View file

@ -5,7 +5,7 @@ import androidx.fragment.app.Fragment
import im.angry.openeuicc.core.EuiccChannel import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.util.* import im.angry.openeuicc.util.*
interface EuiccFragmentMarker: OpenEuiccUIContextMarker interface EuiccFragmentMarker: OpenEuiccContextMarker
fun <T> newInstanceEuicc(clazz: Class<T>, slotId: Int, portId: Int, addArguments: Bundle.() -> Unit = {}): T where T: Fragment, T: EuiccFragmentMarker { fun <T> newInstanceEuicc(clazz: Class<T>, slotId: Int, portId: Int, addArguments: Bundle.() -> Unit = {}): T where T: Fragment, T: EuiccFragmentMarker {
val instance = clazz.newInstance() val instance = clazz.newInstance()

View file

@ -20,7 +20,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
open class MainActivity : AppCompatActivity(), OpenEuiccUIContextMarker { open class MainActivity : AppCompatActivity(), OpenEuiccContextMarker {
companion object { companion object {
const val TAG = "MainActivity" const val TAG = "MainActivity"
} }

View file

@ -27,7 +27,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.typeblog.lpac_jni.LocalProfileNotification import net.typeblog.lpac_jni.LocalProfileNotification
class NotificationsActivity: AppCompatActivity(), OpenEuiccUIContextMarker { class NotificationsActivity: AppCompatActivity(), OpenEuiccContextMarker {
private lateinit var swipeRefresh: SwipeRefreshLayout private lateinit var swipeRefresh: SwipeRefreshLayout
private lateinit var notificationList: RecyclerView private lateinit var notificationList: RecyclerView
private val notificationAdapter = NotificationAdapter() private val notificationAdapter = NotificationAdapter()

View file

@ -12,7 +12,7 @@ import im.angry.openeuicc.common.R
import im.angry.openeuicc.core.EuiccChannel import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.util.* import im.angry.openeuicc.util.*
class SlotSelectFragment : BaseMaterialDialogFragment(), OpenEuiccUIContextMarker { class SlotSelectFragment : BaseMaterialDialogFragment(), OpenEuiccContextMarker {
companion object { companion object {
const val TAG = "SlotSelectFragment" const val TAG = "SlotSelectFragment"

View file

@ -1,32 +1,9 @@
package im.angry.openeuicc.util package im.angry.openeuicc.util
import android.content.Context
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Rect import android.graphics.Rect
import android.telephony.TelephonyManager
import android.view.ViewGroup import android.view.ViewGroup
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import im.angry.openeuicc.OpenEuiccApplication
import im.angry.openeuicc.core.EuiccChannelManager
interface OpenEuiccUIContextMarker
val OpenEuiccUIContextMarker.context: Context
get() = when (this) {
is Context -> this
is Fragment -> requireContext()
else -> throw RuntimeException("OpenEuiccUIContextMarker shall only be used on Fragments or UI types that derive from Context")
}
val OpenEuiccUIContextMarker.openEuiccApplication: OpenEuiccApplication
get() = context.applicationContext as OpenEuiccApplication
val OpenEuiccUIContextMarker.euiccChannelManager: EuiccChannelManager
get() = openEuiccApplication.euiccChannelManager
val OpenEuiccUIContextMarker.telephonyManager: TelephonyManager
get() = openEuiccApplication.telephonyManager
// Source: <https://stackoverflow.com/questions/12478520/how-to-set-dialogfragments-width-and-height> // Source: <https://stackoverflow.com/questions/12478520/how-to-set-dialogfragments-width-and-height>
/** /**

View file

@ -3,7 +3,11 @@ package im.angry.openeuicc.util
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.se.omapi.SEService import android.se.omapi.SEService
import android.telephony.TelephonyManager
import androidx.fragment.app.Fragment
import im.angry.openeuicc.OpenEuiccApplication
import im.angry.openeuicc.core.EuiccChannel import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.core.EuiccChannelManager
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
@ -22,6 +26,24 @@ val Context.selfAppVersion: String
throw RuntimeException(e) throw RuntimeException(e)
} }
interface OpenEuiccContextMarker
val OpenEuiccContextMarker.context: Context
get() = when (this) {
is Context -> this
is Fragment -> requireContext()
else -> throw RuntimeException("OpenEuiccUIContextMarker shall only be used on Fragments or UI types that derive from Context")
}
val OpenEuiccContextMarker.openEuiccApplication: OpenEuiccApplication
get() = context.applicationContext as OpenEuiccApplication
val OpenEuiccContextMarker.euiccChannelManager: EuiccChannelManager
get() = openEuiccApplication.euiccChannelManager
val OpenEuiccContextMarker.telephonyManager: TelephonyManager
get() = openEuiccApplication.telephonyManager
val LocalProfileInfo.isEnabled: Boolean val LocalProfileInfo.isEnabled: Boolean
get() = state == LocalProfileInfo.State.Enabled get() = state == LocalProfileInfo.State.Enabled

View file

@ -6,30 +6,23 @@ import android.telephony.euicc.DownloadableSubscription
import android.telephony.euicc.EuiccInfo import android.telephony.euicc.EuiccInfo
import android.util.Log import android.util.Log
import net.typeblog.lpac_jni.LocalProfileInfo import net.typeblog.lpac_jni.LocalProfileInfo
import im.angry.openeuicc.OpenEuiccApplication
import im.angry.openeuicc.core.EuiccChannel import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.util.* import im.angry.openeuicc.util.*
import java.lang.IllegalStateException import java.lang.IllegalStateException
class OpenEuiccService : EuiccService() { class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
companion object { companion object {
const val TAG = "OpenEuiccService" const val TAG = "OpenEuiccService"
} }
private val openEuiccApplication
get() = application as OpenEuiccApplication
private fun findChannel(physicalSlotId: Int): EuiccChannel? = private fun findChannel(physicalSlotId: Int): EuiccChannel? =
openEuiccApplication.euiccChannelManager euiccChannelManager.findEuiccChannelByPhysicalSlotBlocking(physicalSlotId)
.findEuiccChannelByPhysicalSlotBlocking(physicalSlotId)
private fun findChannel(slotId: Int, portId: Int): EuiccChannel? = private fun findChannel(slotId: Int, portId: Int): EuiccChannel? =
openEuiccApplication.euiccChannelManager euiccChannelManager.findEuiccChannelByPortBlocking(slotId, portId)
.findEuiccChannelByPortBlocking(slotId, portId)
private fun findAllChannels(physicalSlotId: Int): List<EuiccChannel>? = private fun findAllChannels(physicalSlotId: Int): List<EuiccChannel>? =
openEuiccApplication.euiccChannelManager euiccChannelManager.findAllEuiccChannelsByPhysicalSlotBlocking(physicalSlotId)
.findAllEuiccChannelsByPhysicalSlotBlocking(physicalSlotId)
override fun onGetEid(slotId: Int): String? = override fun onGetEid(slotId: Int): String? =
findChannel(slotId)?.lpa?.eID findChannel(slotId)?.lpa?.eID
@ -41,7 +34,7 @@ class OpenEuiccService : EuiccService() {
lpa.profiles.any { it.iccid == iccid } lpa.profiles.any { it.iccid == iccid }
private fun ensurePortIsMapped(slotId: Int, portId: Int) { private fun ensurePortIsMapped(slotId: Int, portId: Int) {
val mappings = openEuiccApplication.telephonyManager.simSlotMapping.toMutableList() val mappings = telephonyManager.simSlotMapping.toMutableList()
mappings.firstOrNull { it.physicalSlotIndex == slotId && it.portIndex == portId }?.let { mappings.firstOrNull { it.physicalSlotIndex == slotId && it.portIndex == portId }?.let {
throw IllegalStateException("Slot $slotId port $portId has already been mapped") throw IllegalStateException("Slot $slotId port $portId has already been mapped")
@ -57,14 +50,14 @@ class OpenEuiccService : EuiccService() {
} }
try { try {
openEuiccApplication.telephonyManager.simSlotMapping = mappings telephonyManager.simSlotMapping = mappings
return return
} catch (_: Exception) { } catch (_: Exception) {
} }
// Sometimes hardware supports one ordering but not the reverse // Sometimes hardware supports one ordering but not the reverse
openEuiccApplication.telephonyManager.simSlotMapping = mappings.reversed() telephonyManager.simSlotMapping = mappings.reversed()
} }
private fun <T> retryWithTimeout(timeoutMillis: Int, backoff: Int = 1000, f: () -> T?): T? { private fun <T> retryWithTimeout(timeoutMillis: Int, backoff: Int = 1000, f: () -> T?): T? {
@ -233,7 +226,7 @@ class OpenEuiccService : EuiccService() {
} catch (e: Exception) { } catch (e: Exception) {
return RESULT_FIRST_USER return RESULT_FIRST_USER
} finally { } finally {
openEuiccApplication.euiccChannelManager.invalidate() euiccChannelManager.invalidate()
} }
} }

View file

@ -27,7 +27,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
class SlotMappingFragment: BaseMaterialDialogFragment(), class SlotMappingFragment: BaseMaterialDialogFragment(),
OnMenuItemClickListener, OpenEuiccUIContextMarker { OnMenuItemClickListener, OpenEuiccContextMarker {
companion object { companion object {
const val TAG = "SlotMappingFragment" const val TAG = "SlotMappingFragment"
} }