赞
踩
这几天调试适配NFC部分热插NFC SIM激活SWP时。
发现,
总是无法成功,经过调试原来根本原因是SIM_STATE_CHANGED广播的Extra数据已经不再具有slotId, 拿不到。
接下来的流程跑步下去了。
发现QCOM 和MediaTek 基线都是如此。
异常log如下:
- 08-02 00:04:08.168 2463 2463 D NfcSimStateObserver: onReceive: android.intent.action.SIM_STATE_CHANGED
- 08-02 00:04:08.168 2463 2463 D NfcSimStateObserver: ACTION_SIM_STATE_CHANGED receiver with iccState = LOADED, simId = -1
- 08-02 00:04:08.168 2463 2463 D Nfc_SecureElementSelector: onSimStateChanged() - simId = -1 newPresenceState = 2 mUICC1State: Active mUICC2State: ? airplane: false
- 08-02 00:04:08.168 2463 2463 D Nfc_SecureElementSelector: onSimStateChanged() - simId not supported -1
- 08-02 00:04:08.507 2463 2463 D NfcSimStateObserver: onReceive: android.intent.action.SIM_STATE_CHANGED
- 08-02 00:04:08.507 2463 2463 D NfcSimStateObserver: ACTION_SIM_STATE_CHANGED receiver with iccState = LOADED, simId = -1
- 08-02 00:04:08.507 2463 2463 D Nfc_SecureElementSelector: onSimStateChanged() - simId = -1 newPresenceState = 2 mUICC1State: Active mUICC2State: ? airplane: false
- 08-02 00:04:08.507 2463 2463 D Nfc_SecureElementSelector: onSimStateChanged() - simId not supported -1
原来正常log如下:
- 08-09 06:49:57.206 4048 4048 D NfcSimStateObserver: onReceive: android.intent.action.SIM_STATE_CHANGED
- 08-09 06:49:57.206 4048 4048 D NfcSimStateObserver: ACTION_SIM_STATE_CHANGED receiver with iccState = LOADED, simId = 0
- 08-09 06:49:57.206 4048 4048 D Nfc_SecureElementSelector: onSimStateChanged() - simId = 0 newPresenceState = 2 mUICC1State: Available mUICC2State: ? airplane: false
- 08-09 06:49:57.206 4048 4048 D Nfc_SecureElementSelector: getIdofString() - str = SIM1 id = 81
- 08-09 06:49:57.206 4048 4048 D Nfc_SecureElementSelector: getUserDesiredSeId() - 0x81
- 08-09 06:49:57.207 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus(start, false) - nfceeid[0]: 0x81 conInfo[0]: 0x01, nfceeid[1]: 0x82 conInfo[1]: 0x01
- 08-09 06:49:57.207 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus() - not in Airplane mode, so using presence information SIM1=0x02, SIM2=0x00
- 08-09 06:49:57.207 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus() - mStActiveeSe = 0x00 mStActiveUicc = 0x00
- 08-09 06:49:57.207 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus(end) - mUICC1State: Available, mUICC2State: ?, meSEState: Available, mDHSEState: ?
- 08-09 06:49:57.207 4048 4048 D Nfc_SecureElementSelector: getActiveUiccValue() - mStActiveUicc= 0
- 08-09 06:49:58.235 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus(start, false) - nfceeid[0]: 0x81 conInfo[0]: 0x00, nfceeid[1]: 0x82 conInfo[1]: 0x01
- 08-09 06:49:58.236 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus() - not in Airplane mode, so using presence information SIM1=0x02, SIM2=0x00
- 08-09 06:49:58.236 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus() - mStActiveeSe = 0x00 mStActiveUicc = 0x81
- 08-09 06:49:58.236 4048 4048 D Nfc_SecureElementSelector: RefreshSeStatus(end) - mUICC1State: Active, mUICC2State: ?, meSEState: Available, mDHSEState: ?
- 08-09 06:49:58.237 4048 4048 D NfcService: setRoutingTableDirty()
接下来跟踪发送SIM_STATE_CHANGED广播的出处。
/frameworks/opt/telephony/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
- ///frameworks/opt/telephony/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
-
- @UnsupportedAppUsage
- private void broadcastSimStateChanged(int slotId, String state, String reason) {
- Intent i = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
- // TODO - we'd like this intent to have a single snapshot of all sim state,
- // but until then this should not use REPLACE_PENDING or we may lose
- // information
- // i.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
- // | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- i.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
- i.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state);
- i.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
-
- SubscriptionManager.putPhoneIdAndSubIdExtra(i, slotId); //赋值SLOT ID的地方
- logd("Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason " + reason +
- " for phone: " + slotId);
- IntentBroadcaster.getInstance().broadcastStickyIntent(i, slotId);
- }

接着看SubsciptionManager的putPhoneIdAndSubIdExtra()方法。
- ///frameworks/base/telephony/java/android/telephony/SubscriptionManager.java
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
- public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) {
- int[] subIds = SubscriptionManager.getSubId(phoneId);
- if (subIds != null && subIds.length > 0) {
- putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]);
- } else {
- logd("putPhoneIdAndSubIdExtra: no valid subs");
- intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- }
- }
-
- /** @hide */
- @UnsupportedAppUsage
- public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) {
- if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
- intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
- intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId);
- intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
- }

经过对比,可以发现方法上多了个注释。
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
这个注释的意思是,Android P(API 28)之前(含P)才支持。
【解决方案】
直接从phoneid中拿,拿不到直接默认slotid=0.
- ///packages/apps/NfcSt/src/com/android/nfc/st/NfcSimStateObserver.java
- if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
- String iccState;
- int simId;
- iccState = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
- //[NFC] Begin modify by xxxie for T7753592 on 2019/08/02
- // because of SubscriptionManager send sticky broadcast SIM_STATE_CHANGED
- // UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) definition, so that
- // there are no more 'slot' value in ExtraData
- //simId = intent.getIntExtra(PhoneConstants.SLOT_KEY, -1);
- simId = intent.getIntExtra(PhoneConstants.PHONE_KEY, -1);
- //[NFC] End modify by xxxie for T7753592 on 2019/08/02
- if (iccState == null) {
- iccState = "NULL";
- }
- Log.d(TAG, "ACTION_SIM_STATE_CHANGED receiver with iccState = " + iccState +
- ", simId = " + simId);
- //[NFC] Begin modify by xxxie for T7753592 on 2019/08/02
- if (-1 == simId) {
- simId = 0;//拿不到默认给卡1
- }
- //[NFC] End modify by xxxie for T7753592 on 2019/08/02
- if (iccState.equals(IccCardConstants.INTENT_VALUE_ICC_LOADED)) {

这样就能暂时解决这个问题,但是倘若支持双NFC SIM的情况,单单热插slot2(SIM2),这将会是一个问题。
【Google解决方案】
经过当前最新的MTK baseline alps-trunk-q0.bsp-pre11.1查看,发现SubscriptionInfoUpdater已经更新,更新日期是2019/04/18。
这个提交的人是Jordan Liu(jminjie@google.com)。
发现自己又好像白干活了。。。
不知道为什么不干脆将SubscriptionManager.java中的接口开放,而是临时自己打个patch。
现在Android Q还尚不稳定,不知后边将如何变化。
静观其变吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。