package im.angry.openeuicc.util import android.os.Bundle import android.util.Log import androidx.fragment.app.Fragment import im.angry.openeuicc.core.EuiccChannel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import net.typeblog.lpac_jni.LocalProfileAssistant private const val TAG = "EuiccChannelFragmentUtils" interface EuiccChannelFragmentMarker: OpenEuiccContextMarker // We must use extension functions because there is no way to add bounds to the type of "self" // in the definition of an interface, so the only way is to limit where the extension functions // can be applied. fun newInstanceEuicc(clazz: Class, slotId: Int, portId: Int, addArguments: Bundle.() -> Unit = {}): T where T: Fragment, T: EuiccChannelFragmentMarker { val instance = clazz.newInstance() instance.arguments = Bundle().apply { putInt("slotId", slotId) putInt("portId", portId) addArguments() } return instance } val T.slotId: Int where T: Fragment, T: EuiccChannelFragmentMarker get() = requireArguments().getInt("slotId") val T.portId: Int where T: Fragment, T: EuiccChannelFragmentMarker get() = requireArguments().getInt("portId") val T.channel: EuiccChannel where T: Fragment, T: EuiccChannelFragmentMarker get() = euiccChannelManager.findEuiccChannelByPortBlocking(slotId, portId)!! /* * Begin a "tracked" operation where notifications may be generated by the eSIM * Automatically handle any newly generated notification during the operation * if the function "op" returns true. */ suspend fun T.beginTrackedOperation(op: suspend () -> Boolean) where T : Fragment, T : EuiccChannelFragmentMarker = withContext(Dispatchers.IO) { val latestSeq = channel.lpa.notifications.firstOrNull()?.seqNumber ?: 0 Log.d(TAG, "Latest notification is $latestSeq before operation") if (op()) { Log.d(TAG, "Operation has requested notification handling") // Note that the exact instance of "channel" might have changed here if reconnected; // so we MUST use the automatic getter for "channel" channel.lpa.notifications.filter { it.seqNumber > latestSeq }.forEach { Log.d(TAG, "Handling notification $it") channel.lpa.handleNotification(it.seqNumber) } } Log.d(TAG, "Operation complete") } interface EuiccProfilesChangedListener { fun onEuiccProfilesChanged() }