Compare commits

...

5 commits

Author SHA1 Message Date
Peter Cai 2270e4aa53 Merge remote-tracking branch 'openeuicc/master' into jmp
All checks were successful
/ build-debug (push) Successful in 3m28s
2024-03-18 18:49:00 -04:00
Peter Cai 999462c294 ui: Hide spinner when no eSIM is found 2024-03-17 14:19:07 -04:00
Peter Cai 2061e6fea3 ui: Better placeholder for the no-eSIM case 2024-03-17 14:02:38 -04:00
Peter Cai 6977a32e80 refactor: EuiccChannel is not abstract 2024-03-17 11:19:37 -04:00
Peter Cai 3a0d805eb2 treewide: Nullability fixes for AOSP 14 r29
Mainly a treewide `findViewById` -> `requireViewById`, with
miscellaneous fixes.
2024-03-11 18:55:32 -04:00
32 changed files with 200 additions and 106 deletions

View file

@ -24,7 +24,7 @@ open class DefaultEuiccChannelFactory(protected val context: Context) : EuiccCha
Log.i(DefaultEuiccChannelManager.TAG, "Trying OMAPI for physical slot ${port.card.physicalSlotIndex}")
try {
return OmapiChannel(seService!!, port)
return EuiccChannel(port, OmapiApduInterface(seService!!, port))
} catch (e: IllegalArgumentException) {
// Failed
Log.w(

View file

@ -1,16 +1,21 @@
package im.angry.openeuicc.core
import im.angry.openeuicc.util.*
import net.typeblog.lpac_jni.ApduInterface
import net.typeblog.lpac_jni.LocalProfileAssistant
import net.typeblog.lpac_jni.impl.HttpInterfaceImpl
import net.typeblog.lpac_jni.impl.LocalProfileAssistantImpl
abstract class EuiccChannel(
val port: UiccPortInfoCompat
class EuiccChannel(
val port: UiccPortInfoCompat,
apduInterface: ApduInterface,
) {
val slotId = port.card.physicalSlotIndex // PHYSICAL slot
val logicalSlotId = port.logicalSlotIndex
val portId = port.portIndex
abstract val lpa: LocalProfileAssistant
val lpa: LocalProfileAssistant = LocalProfileAssistantImpl(apduInterface, HttpInterfaceImpl())
val valid: Boolean
get() = lpa.valid

View file

@ -5,9 +5,6 @@ import android.se.omapi.SEService
import android.se.omapi.Session
import im.angry.openeuicc.util.*
import net.typeblog.lpac_jni.ApduInterface
import net.typeblog.lpac_jni.LocalProfileAssistant
import net.typeblog.lpac_jni.impl.HttpInterfaceImpl
import net.typeblog.lpac_jni.impl.LocalProfileAssistantImpl
class OmapiApduInterface(
private val service: SEService,
@ -47,13 +44,4 @@ class OmapiApduInterface(
return lastChannel.transmit(tx)
}
}
class OmapiChannel(
service: SEService,
port: UiccPortInfoCompat,
) : EuiccChannel(port) {
override val lpa: LocalProfileAssistant = LocalProfileAssistantImpl(
OmapiApduInterface(service, port),
HttpInterfaceImpl())
}
}

View file

@ -1,9 +1,13 @@
package im.angry.openeuicc.di
import androidx.fragment.app.Fragment
import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.ui.EuiccManagementFragment
import im.angry.openeuicc.ui.NoEuiccPlaceholderFragment
open class DefaultUiComponentFactory : UiComponentFactory {
override fun createEuiccManagementFragment(channel: EuiccChannel): EuiccManagementFragment =
EuiccManagementFragment.newInstance(channel.slotId, channel.portId)
override fun createNoEuiccPlaceholderFragment(): Fragment = NoEuiccPlaceholderFragment()
}

View file

@ -1,8 +1,10 @@
package im.angry.openeuicc.di
import androidx.fragment.app.Fragment
import im.angry.openeuicc.core.EuiccChannel
import im.angry.openeuicc.ui.EuiccManagementFragment
interface UiComponentFactory {
fun createEuiccManagementFragment(channel: EuiccChannel): EuiccManagementFragment
fun createNoEuiccPlaceholderFragment(): Fragment
}

View file

@ -58,9 +58,9 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
): View {
val view = inflater.inflate(R.layout.fragment_euicc, container, false)
swipeRefresh = view.findViewById(R.id.swipe_refresh)
fab = view.findViewById(R.id.fab)
profileList = view.findViewById(R.id.profile_list)
swipeRefresh = view.requireViewById(R.id.swipe_refresh)
fab = view.requireViewById(R.id.fab)
profileList = view.requireViewById(R.id.profile_list)
return view
}
@ -191,11 +191,11 @@ open class EuiccManagementFragment : Fragment(), EuiccProfilesChangedListener,
}
inner class ProfileViewHolder(private val root: View) : ViewHolder(root) {
private val iccid: TextView = root.findViewById(R.id.iccid)
private val name: TextView = root.findViewById(R.id.name)
private val state: TextView = root.findViewById(R.id.state)
private val provider: TextView = root.findViewById(R.id.provider)
private val profileMenu: ImageButton = root.findViewById(R.id.profile_menu)
private val iccid: TextView = root.requireViewById(R.id.iccid)
private val name: TextView = root.requireViewById(R.id.name)
private val state: TextView = root.requireViewById(R.id.state)
private val provider: TextView = root.requireViewById(R.id.provider)
private val profileMenu: ImageButton = root.requireViewById(R.id.profile_menu)
init {
iccid.setOnClickListener {

View file

@ -39,12 +39,12 @@ class LogsActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_logs)
setSupportActionBar(findViewById(R.id.toolbar))
setSupportActionBar(requireViewById(R.id.toolbar))
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
swipeRefresh = findViewById(R.id.swipe_refresh)
scrollView = findViewById(R.id.scroll_view)
logText = findViewById(R.id.log_text)
swipeRefresh = requireViewById(R.id.swipe_refresh)
scrollView = requireViewById(R.id.scroll_view)
logText = requireViewById(R.id.log_text)
swipeRefresh.setOnRefreshListener {
lifecycleScope.launch {

View file

@ -25,20 +25,22 @@ open class MainActivity : AppCompatActivity(), OpenEuiccContextMarker {
}
private lateinit var spinnerAdapter: ArrayAdapter<String>
private lateinit var spinnerItem: MenuItem
private lateinit var spinner: Spinner
private val fragments = arrayListOf<EuiccManagementFragment>()
private lateinit var noEuiccPlaceholder: View
protected lateinit var tm: TelephonyManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(findViewById(R.id.toolbar))
setSupportActionBar(requireViewById(R.id.toolbar))
noEuiccPlaceholder = findViewById(R.id.no_euicc_placeholder)
supportFragmentManager.beginTransaction().replace(
R.id.fragment_root,
appContainer.uiComponentFactory.createNoEuiccPlaceholderFragment()
).commit()
tm = telephonyManager
@ -53,7 +55,11 @@ open class MainActivity : AppCompatActivity(), OpenEuiccContextMarker {
menuInflater.inflate(R.menu.activity_main, menu)
if (!this::spinner.isInitialized) {
spinner = menu.findItem(R.id.spinner).actionView as Spinner
spinnerItem = menu.findItem(R.id.spinner)
spinner = spinnerItem.actionView as Spinner
if (spinnerAdapter.isEmpty) {
spinnerItem.isVisible = false
}
spinner.adapter = spinnerAdapter
spinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
@ -108,7 +114,9 @@ open class MainActivity : AppCompatActivity(), OpenEuiccContextMarker {
}
if (fragments.isNotEmpty()) {
noEuiccPlaceholder.visibility = View.GONE
if (this@MainActivity::spinner.isInitialized) {
spinnerItem.isVisible = true
}
supportFragmentManager.beginTransaction().replace(R.id.fragment_root, fragments.first()).commit()
}
}

View file

@ -0,0 +1,18 @@
package im.angry.openeuicc.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import im.angry.openeuicc.common.R
class NoEuiccPlaceholderFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_no_euicc_placeholder, container, false)
}
}

View file

@ -37,14 +37,14 @@ class NotificationsActivity: AppCompatActivity(), OpenEuiccContextMarker {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_notifications)
setSupportActionBar(findViewById(R.id.toolbar))
setSupportActionBar(requireViewById(R.id.toolbar))
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
euiccChannel = euiccChannelManager
.findEuiccChannelBySlotBlocking(intent.getIntExtra("logicalSlotId", 0))!!
swipeRefresh = findViewById(R.id.swipe_refresh)
notificationList = findViewById(R.id.recycler_view)
swipeRefresh = requireViewById(R.id.swipe_refresh)
notificationList = requireViewById(R.id.recycler_view)
notificationList.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
@ -118,8 +118,8 @@ class NotificationsActivity: AppCompatActivity(), OpenEuiccContextMarker {
@SuppressLint("ClickableViewAccessibility")
inner class NotificationViewHolder(private val root: View):
RecyclerView.ViewHolder(root), View.OnCreateContextMenuListener, OnMenuItemClickListener {
private val address: TextView = root.findViewById(R.id.notification_address)
private val profileName: TextView = root.findViewById(R.id.notification_profile_name)
private val address: TextView = root.requireViewById(R.id.notification_address)
private val profileName: TextView = root.requireViewById(R.id.notification_profile_name)
private lateinit var notification: LocalProfileNotificationWrapper

View file

@ -69,13 +69,13 @@ class ProfileDownloadFragment : BaseMaterialDialogFragment(),
): View {
val view = inflater.inflate(R.layout.fragment_profile_download, container, false)
toolbar = view.findViewById(R.id.toolbar)
profileDownloadServer = view.findViewById(R.id.profile_download_server)
profileDownloadCode = view.findViewById(R.id.profile_download_code)
profileDownloadConfirmationCode = view.findViewById(R.id.profile_download_confirmation_code)
profileDownloadIMEI = view.findViewById(R.id.profile_download_imei)
profileDownloadFreeSpace = view.findViewById(R.id.profile_download_free_space)
progress = view.findViewById(R.id.progress)
toolbar = view.requireViewById(R.id.toolbar)
profileDownloadServer = view.requireViewById(R.id.profile_download_server)
profileDownloadCode = view.requireViewById(R.id.profile_download_code)
profileDownloadConfirmationCode = view.requireViewById(R.id.profile_download_confirmation_code)
profileDownloadIMEI = view.requireViewById(R.id.profile_download_imei)
profileDownloadFreeSpace = view.requireViewById(R.id.profile_download_free_space)
progress = view.requireViewById(R.id.progress)
toolbar.inflateMenu(R.menu.fragment_profile_download)

View file

@ -46,9 +46,9 @@ class ProfileRenameFragment : BaseMaterialDialogFragment(), EuiccChannelFragment
): View {
val view = inflater.inflate(R.layout.fragment_profile_rename, container, false)
toolbar = view.findViewById(R.id.toolbar)
profileRenameNewName = view.findViewById(R.id.profile_rename_new_name)
progress = view.findViewById(R.id.progress)
toolbar = view.requireViewById(R.id.toolbar)
profileRenameNewName = view.requireViewById(R.id.profile_rename_new_name)
progress = view.requireViewById(R.id.progress)
toolbar.inflateMenu(R.menu.fragment_profile_rename)

View file

@ -9,7 +9,7 @@ class SettingsActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings)
setSupportActionBar(findViewById(R.id.toolbar))
setSupportActionBar(requireViewById(R.id.toolbar))
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
supportFragmentManager.beginTransaction()
.replace(R.id.settings_container, SettingsFragment())

View file

@ -39,13 +39,13 @@ class SlotSelectFragment : BaseMaterialDialogFragment(), OpenEuiccContextMarker
): View? {
val view = inflater.inflate(R.layout.fragment_slot_select, container, false)
toolbar = view.findViewById(R.id.toolbar)
toolbar = view.requireViewById(R.id.toolbar)
toolbar.setTitle(R.string.slot_select)
toolbar.inflateMenu(R.menu.fragment_slot_select)
val adapter = ArrayAdapter<String>(inflater.context, R.layout.spinner_item)
spinner = view.findViewById(R.id.spinner)
spinner = view.requireViewById(R.id.spinner)
spinner.adapter = adapter
channels.forEach { channel ->

View file

@ -18,4 +18,4 @@ class LongSummaryPreferenceCategory: PreferenceCategory {
summaryText.isSingleLine = false
summaryText.maxLines = 10
}
}
}

View file

@ -24,7 +24,7 @@ val Context.selfAppVersion: String
get() =
try {
val pInfo = packageManager.getPackageInfo(packageName, 0)
pInfo.versionName
pInfo.versionName!!
} catch (e: PackageManager.NameNotFoundException) {
throw RuntimeException(e)
}
@ -91,4 +91,4 @@ suspend fun connectSEService(context: Context): SEService = suspendCoroutine { c
}
}
}
}
}

View file

@ -21,15 +21,6 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar">
<TextView
android:id="@+id/no_euicc_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:gravity="center"
android:text="@string/no_euicc" />
</FrameLayout>
app:layout_constraintTop_toBottomOf="@id/toolbar"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/no_euicc_placeholder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:gravity="center"
android:text="@string/no_euicc" />
</FrameLayout>

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="no_euicc">No eUICC card on this device is accessible by this app.\nInsert a supported eUICC card, or try out the privileged OpenEUICC app instead.</string>
<string name="no_euicc">No removable eUICC card accessible by this app is detected on this device.</string>
<string name="unknown">Unknown</string>
<string name="help">Help</string>

View file

@ -1,12 +1,17 @@
package im.angry.openeuicc
import android.content.Intent
import im.angry.openeuicc.di.UnprivilegedAppContainer
import im.angry.openeuicc.ui.LogsActivity
import im.angry.openeuicc.util.*
import kotlinx.coroutines.runBlocking
import kotlin.system.exitProcess
class UnprivilegedOpenEuiccApplication : OpenEuiccApplication() {
override val appContainer by lazy {
UnprivilegedAppContainer(this)
}
override fun onCreate() {
super.onCreate()

View file

@ -0,0 +1,9 @@
package im.angry.openeuicc.di
import android.content.Context
class UnprivilegedAppContainer(context: Context) : DefaultAppContainer(context) {
override val uiComponentFactory by lazy {
UnprivilegedUiComponentFactory()
}
}

View file

@ -0,0 +1,9 @@
package im.angry.openeuicc.di
import androidx.fragment.app.Fragment
import im.angry.openeuicc.ui.UnprivilegedNoEuiccPlaceholderFragment
class UnprivilegedUiComponentFactory : DefaultUiComponentFactory() {
override fun createNoEuiccPlaceholderFragment(): Fragment =
UnprivilegedNoEuiccPlaceholderFragment()
}

View file

@ -24,10 +24,10 @@ class CompatibilityCheckActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_compatibility_check)
setSupportActionBar(findViewById(R.id.toolbar))
setSupportActionBar(requireViewById(R.id.toolbar))
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
compatibilityCheckList = findViewById(R.id.recycler_view)
compatibilityCheckList = requireViewById(R.id.recycler_view)
compatibilityCheckList.layoutManager =
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
compatibilityCheckList.addItemDecoration(DividerItemDecoration(this, LinearLayoutManager.VERTICAL))
@ -51,9 +51,9 @@ class CompatibilityCheckActivity: AppCompatActivity() {
}
inner class ViewHolder(private val root: View): RecyclerView.ViewHolder(root) {
private val titleView: TextView = root.findViewById(R.id.compatibility_check_title)
private val descView: TextView = root.findViewById(R.id.compatibility_check_desc)
private val statusContainer: ViewGroup = root.findViewById(R.id.compatibility_check_status_container)
private val titleView: TextView = root.requireViewById(R.id.compatibility_check_title)
private val descView: TextView = root.requireViewById(R.id.compatibility_check_desc)
private val statusContainer: ViewGroup = root.requireViewById(R.id.compatibility_check_status_container)
fun bindItem(item: CompatibilityCheck) {
titleView.text = item.title
@ -65,16 +65,16 @@ class CompatibilityCheckActivity: AppCompatActivity() {
when (item.state) {
CompatibilityCheck.State.SUCCESS -> {
root.findViewById<View>(R.id.compatibility_check_checkmark).visibility = View.VISIBLE
root.requireViewById<View>(R.id.compatibility_check_checkmark).visibility = View.VISIBLE
}
CompatibilityCheck.State.FAILURE -> {
root.findViewById<View>(R.id.compatibility_check_error).visibility = View.VISIBLE
root.requireViewById<View>(R.id.compatibility_check_error).visibility = View.VISIBLE
}
CompatibilityCheck.State.FAILURE_UNKNOWN -> {
root.findViewById<View>(R.id.compatibility_check_unknown).visibility = View.VISIBLE
root.requireViewById<View>(R.id.compatibility_check_unknown).visibility = View.VISIBLE
}
else -> {
root.findViewById<View>(R.id.compatibility_check_progress_bar).visibility = View.VISIBLE
root.requireViewById<View>(R.id.compatibility_check_progress_bar).visibility = View.VISIBLE
}
}
}

View file

@ -0,0 +1,29 @@
package im.angry.openeuicc.ui
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import im.angry.easyeuicc.R
class UnprivilegedNoEuiccPlaceholderFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(
R.layout.fragment_no_euicc_placeholder_unprivileged,
container,
false
)
view.findViewById<View>(R.id.compatibility_check).setOnClickListener {
startActivity(Intent(requireContext(), CompatibilityCheckActivity::class.java))
}
return view
}
}

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="@+id/no_euicc_placeholder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
android:gravity="center"
android:text="@string/no_euicc"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/compatibility_check"
android:text="@string/compatibility_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/no_euicc_placeholder"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -26,9 +26,7 @@ class PrivilegedEuiccChannelFactory(context: Context) : DefaultEuiccChannelFacto
"Trying TelephonyManager for slot ${port.card.physicalSlotIndex} port ${port.portIndex}"
)
try {
return TelephonyManagerChannel(
port, tm
)
return EuiccChannel(port, TelephonyManagerApduInterface(port, tm))
} catch (e: IllegalArgumentException) {
// Failed
Log.w(

View file

@ -3,10 +3,7 @@ package im.angry.openeuicc.core
import android.telephony.IccOpenLogicalChannelResponse
import android.telephony.TelephonyManager
import im.angry.openeuicc.util.*
import net.typeblog.lpac_jni.LocalProfileAssistant
import net.typeblog.lpac_jni.ApduInterface
import net.typeblog.lpac_jni.impl.HttpInterfaceImpl
import net.typeblog.lpac_jni.impl.LocalProfileAssistantImpl
class TelephonyManagerApduInterface(
private val port: UiccPortInfoCompat,
@ -54,14 +51,4 @@ class TelephonyManagerApduInterface(
cla, instruction, p1, p2, p3, p4)?.decodeHex() ?: byteArrayOf()
}
}
class TelephonyManagerChannel(
port: UiccPortInfoCompat,
private val tm: TelephonyManager
) : EuiccChannel(port) {
override val lpa: LocalProfileAssistant = LocalProfileAssistantImpl(
TelephonyManagerApduInterface(port, tm),
HttpInterfaceImpl()
)
}

View file

@ -104,9 +104,9 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
return GetDefaultDownloadableSubscriptionListResult(RESULT_OK, arrayOf())
}
override fun onGetEuiccProfileInfoList(slotId: Int): GetEuiccProfileInfoListResult? {
override fun onGetEuiccProfileInfoList(slotId: Int): GetEuiccProfileInfoListResult {
Log.i(TAG, "onGetEuiccProfileInfoList slotId=$slotId")
val channel = findChannel(slotId) ?: return null
val channel = findChannel(slotId)!!
val profiles = channel.lpa.profiles.operational.map {
EuiccProfileInfo.Builder(it.iccid).apply {
setProfileName(it.name)
@ -256,4 +256,4 @@ class OpenEuiccService : EuiccService(), OpenEuiccContextMarker {
// No-op -- we do not care
return RESULT_FIRST_USER
}
}
}

View file

@ -10,10 +10,10 @@ class LuiActivity : AppCompatActivity() {
super.onStart()
setContentView(R.layout.activity_lui)
findViewById<View>(R.id.lui_skip).setOnClickListener { finish() }
requireViewById<View>(R.id.lui_skip).setOnClickListener { finish() }
// TODO: Deactivate LuiActivity if there is no eSIM found.
// TODO: Support pre-filled download info (from carrier apps); UX
findViewById<View>(R.id.lui_download).setOnClickListener {
requireViewById<View>(R.id.lui_download).setOnClickListener {
startActivity(Intent(this, DirectProfileDownloadActivity::class.java))
}
}

View file

@ -17,7 +17,7 @@ class PrivilegedEuiccManagementFragment: EuiccManagementFragment() {
override suspend fun onCreateFooterViews(parent: ViewGroup): List<View> =
if (channel.isMEP) {
val view = layoutInflater.inflate(R.layout.footer_mep, parent, false)
view.findViewById<Button>(R.id.footer_mep_slot_mapping).setOnClickListener {
view.requireViewById<Button>(R.id.footer_mep_slot_mapping).setOnClickListener {
(requireActivity() as PrivilegedMainActivity).showSlotMappingFragment()
}
listOf(view)

View file

@ -51,12 +51,12 @@ class SlotMappingFragment: BaseMaterialDialogFragment(),
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_slot_mapping, container, false)
toolbar = view.findViewById(R.id.toolbar)
toolbar = view.requireViewById(R.id.toolbar)
toolbar.inflateMenu(R.menu.fragment_slot_mapping)
recyclerView = view.findViewById(R.id.mapping_list)
recyclerView = view.requireViewById(R.id.mapping_list)
recyclerView.layoutManager =
LinearLayoutManager(view.context, LinearLayoutManager.VERTICAL, false)
helpTextView = view.findViewById(R.id.mapping_help)
helpTextView = view.requireViewById(R.id.mapping_help)
return view
}
@ -148,8 +148,8 @@ class SlotMappingFragment: BaseMaterialDialogFragment(),
}
inner class ViewHolder(root: View): RecyclerView.ViewHolder(root), OnItemSelectedListener {
private val textViewLogicalSlot: TextView = root.findViewById(R.id.slot_mapping_logical_slot)
private val spinnerPorts: Spinner = root.findViewById(R.id.slot_mapping_ports)
private val textViewLogicalSlot: TextView = root.requireViewById(R.id.slot_mapping_logical_slot)
private val spinnerPorts: Spinner = root.requireViewById(R.id.slot_mapping_ports)
init {
spinnerPorts.adapter = ArrayAdapter(requireContext(), im.angry.openeuicc.common.R.layout.spinner_item, portsDesc)

View file

@ -95,9 +95,9 @@ fun TelephonyManager.iccOpenLogicalChannelByPortCompat(
slotIndex: Int, portIndex: Int, aid: String?, p2: Int
): IccOpenLogicalChannelResponse =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
iccOpenLogicalChannelByPort(slotIndex, portIndex, aid, p2)
iccOpenLogicalChannelByPort(slotIndex, portIndex, aid, p2)!!
} else {
iccOpenLogicalChannelBySlot(slotIndex, aid, p2)
iccOpenLogicalChannelBySlot(slotIndex, aid, p2)!!
}
fun TelephonyManager.iccCloseLogicalChannelByPortCompat(
@ -121,4 +121,4 @@ fun TelephonyManager.iccTransmitApduLogicalChannelByPortCompat(
iccTransmitApduLogicalChannelBySlot(
slotIndex, channel, cla, inst, p1, p2, p3, data
)
}
}