摘要:以为例不同卡主要区别就是文件结构不同,因此各自实现方法接记录卡的文件信息,具体的读取卡文件信息的过程是由来实现的,以为例。构造方法在初始化时,卡状态是状态并且会广播出去然后在中设置模式。
1.UiccController 是处理SIM卡的核心类,其他关键类都是通过他产生
* Following is class diagram for uicc classes: * * UiccController * # * | * UiccCard * # # * | ------------------ * UiccCardApplication CatService * # # * | | * IccRecords IccFileHandler * ^ ^ ^ ^ ^ ^ ^ ^ * SIMRecords---- | | | | | | ---SIMFileHandler * RuimRecords----- | | | | ----RuimFileHandler * IsimUiccRecords--- | | -----UsimFileHandler * | ------CsimFileHandler * ----IsimFileHandler * * Legend: # stands for Composition * ^ stands for Generalization * * See also {@link com.android.internal.telephony.IccCard} * and {@link com.android.internal.telephony.uicc.IccCardProxy}
2 分析UiccController是如何初始化的
2.1 Phone进程初始化PhoneApp.java
public void onCreate() { if (UserHandle.myUserId() == 0) { // We are running as the primary user, so should bring up the // global phone state. mPhoneGlobals = new PhoneGlobals(this); mPhoneGlobals.onCreate(); mTelephonyGlobals = new TelephonyGlobals(this); mTelephonyGlobals.onCreate(); } }
2.2 在PhoneGlobals.java的onCreate()中创建Phone
if (mCM == null) { // Initialize the telephony framework PhoneFactory.makeDefaultPhones(this);
2.3 PhoneFactory类makeDefaultPhone方法中初始化UiccController,UiccController是UICC的控制接口,与RIL建立监听关系,当SIM卡状态变化时,RIL通知UiccController.
sCommandsInterfaces = new RIL[numPhones]; sCommandsInterfaces[i] = new RIL(context, networkModes[i],cdmaSubscription, i); sUiccController = UiccController.make(context, sCommandsInterfaces); if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { phone = new GsmCdmaPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i, PhoneConstants.PHONE_TYPE_GSM, TelephonyComponentFactory.getInstance()); } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) { phone = new GsmCdmaPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i, PhoneConstants.PHONE_TYPE_CDMA_LTE, TelephonyComponentFactory.getInstance()); }
2.4 看看UiccController的make方法中都对RIL注册了哪些监听
public static UiccController make(Context c, CommandsInterface[] ci) { synchronized (mLock) { if (mInstance != null) { throw new RuntimeException("MSimUiccController.make() should only be called once"); } mInstance = new UiccController(c, ci); return (UiccController)mInstance; } }
private UiccController(Context c, CommandsInterface []ci) {
if (DBG) log("Creating UiccController"); mContext = c; mCis = ci; for (int i = 0; i < mCis.length; i++) { Integer index = new Integer(i); mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index); // TODO remove this once modem correctly notifies the unsols // If the device has been decrypted or FBE is supported, read SIM when radio state is // available. // Else wait for radio to be on. This is needed for the scenario when SIM is locked -- // to avoid overlap of CryptKeeper and SIM unlock screen. if (DECRYPT_STATE.equals(SystemProperties.get("vold.decrypt")) || StorageManager.isFileEncryptedNativeOrEmulated()) { mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index); } else { mCis[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index); } mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index); mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index); } }
监听了三个事件:EVENT_ICC_STATUS_CHANGED/EVENT_RADIO_UNAVAILABLE/EVENT_SIM_REFRESH
index对应phoneId
registerForIccStatusChanged方法是CommandsInterface接口中定义 抽象类BaseCommands中实现 @Override public void registerForIccStatusChanged(Handler h, int what, Object obj) { Registrant r = new Registrant (h, what, obj); mIccStatusChangedRegistrants.add(r); } mIccStatusChangedRegistrants是在RIL中发出通知 private void processUnsolicited (Parcel p, int type) { .... case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: if (RILJ_LOGD) unsljLog(response); if (mIccStatusChangedRegistrants != null) { mIccStatusChangedRegistrants.notifyRegistrants(); } break;
2.5 UiccController handleMessage方法中处理事件EVENT_ICC_STATUS_CHANGED,请求RIL getIccCardStatus()方法发送RIL_REQUEST_GET_SIM_STATUS消息给modem查询SIM卡状态,通过onGetIccCardStatusDone处理
@Override public void handleMessage (Message msg) { synchronized (mLock) { Integer index = getCiIndex(msg); if (index < 0 || index >= mCis.length) { Rlog.e(LOG_TAG, "Invalid index : " + index + " received with event " + msg.what); return; } AsyncResult ar = (AsyncResult)msg.obj; switch (msg.what) { case EVENT_ICC_STATUS_CHANGED: if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); break; case EVENT_GET_ICC_STATUS_DONE: if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); onGetIccCardStatusDone(ar, index); break; case EVENT_RADIO_UNAVAILABLE: if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card"); if (mUiccCards[index] != null) { mUiccCards[index].dispose(); } mUiccCards[index] = null; mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); break; case EVENT_SIM_REFRESH: if (DBG) log("Received EVENT_SIM_REFRESH"); onSimRefresh(ar, index); break; default: Rlog.e(LOG_TAG, " Unknown Event " + msg.what); } } } RIL.java @Override public void getIccCardStatus(Message result) { //Note: This RIL request has not been renamed to ICC, // but this request is also valid for SIM and RUIM RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); }
2.6 在onGetIccCardStatusDone方法中,依据IccCardStatus创建UiccCard,每个UiccCard对应一张SIM卡,方法的最后通知注册UiccController监听,UiccCard的构造方法也是调用update方法
private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) {
if (ar.exception != null) { Rlog.e(LOG_TAG,"Error getting ICC status. " + "RIL_REQUEST_GET_ICC_STATUS should " + "never return an error", ar.exception); return; } if (!isValidCardIndex(index)) { Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index); return; } IccCardStatus status = (IccCardStatus)ar.result; if (mUiccCards[index] == null) { //Create new card mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index); } else { //Update already existing card mUiccCards[index].update(mContext, mCis[index] , status); } if (DBG) log("Notifying IccChangedRegistrants"); mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); }
UiccController总结:
3.UiccCard
3.1 UiccCard构造方法
public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) { mCardState = ics.mCardState; mPhoneId = phoneId; update(c, ci, ics); } public void update(Context c, CommandsInterface ci, IccCardStatus ics) { synchronized (mLock) { CardState oldState = mCardState; mCardState = ics.mCardState; mUniversalPinState = ics.mUniversalPinState; mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex; mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex; mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex; mContext = c; mCi = ci; //update applications if (DBG) log(ics.mApplications.length + " applications"); for ( int i = 0; i < mUiccApplications.length; i++) { if (mUiccApplications[i] == null) { //Create newly added Applications if (i < ics.mApplications.length) { mUiccApplications[i] = new UiccCardApplication(this, ics.mApplications[i], mContext, mCi); } } else if (i >= ics.mApplications.length) { //Delete removed applications mUiccApplications[i].dispose(); mUiccApplications[i] = null; } else { //Update the rest mUiccApplications[i].update(ics.mApplications[i], mContext, mCi); } } createAndUpdateCatService(); // Reload the carrier privilege rules if necessary. log("Before privilege rules: " + mCarrierPrivilegeRules + " : " + mCardState); if (mCarrierPrivilegeRules == null && mCardState == CardState.CARDSTATE_PRESENT) { mCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(this, mHandler.obtainMessage(EVENT_CARRIER_PRIVILIGES_LOADED)); } else if (mCarrierPrivilegeRules != null && mCardState != CardState.CARDSTATE_PRESENT) { mCarrierPrivilegeRules = null; } sanitizeApplicationIndexes(); RadioState radioState = mCi.getRadioState(); if (DBG) log("update: radioState=" + radioState + " mLastRadioState=" + mLastRadioState); // No notifications while radio is off or we just powering up if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) { //根据mCardState 和oldState 判断是ADD还是REMOVE card if (oldState != CardState.CARDSTATE_ABSENT && mCardState == CardState.CARDSTATE_ABSENT) { if (DBG) log("update: notify card removed"); mAbsentRegistrants.notifyRegistrants(); mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null)); } else if (oldState == CardState.CARDSTATE_ABSENT && mCardState != CardState.CARDSTATE_ABSENT) { if (DBG) log("update: notify card added"); mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null)); } } mLastRadioState = radioState; } }
在构造方法中调用update方法,在update中创建或者更新UiccCardApplication,
根据mCardState 和oldState 判断是ADD还是REMOVE card,当SIM卡拔出时,通知IccCardProxy, 以及promptForRestart。
createAndUpdateCatService();建CatService,用于读取STK的信息
protected void createAndUpdateCatService() { if (mUiccApplications.length > 0 && mUiccApplications[0] != null) { // Initialize or Reinitialize CatService if (mCatService == null) { mCatService = CatService.getInstance(mCi, mContext, this, mPhoneId); } else { ((CatService)mCatService).update(mCi, mContext, this); } } else { if (mCatService != null) { mCatService.dispose(); } mCatService = null; } }
UiccCard主要就是创建UiccCardApplication和CatService,以及通知SIM Card ADD和REMOVE事件
4.UiccCardApplication
主要方法:
public void registerForReady(Handler h, int what, Object obj) {} public void registerForLocked(Handler h, int what, Object obj) {} public void registerForNetworkLocked(Handler h, int what, Object obj) {} public AppState getState() {} public AppType getType() {} public PersoSubState getPersoSubState() {} public String getAid() {} public PinState getPin1State() {} public IccFileHandler getIccFileHandler() {} public IccRecords getIccRecords() {} public void supplyPin (String pin, Message onComplete) {} public void supplyPuk (String puk, String newPin, Message onComplete) {} public void supplyPin2 (String pin2, Message onComplete) {} public void supplyPuk2 (String puk2, String newPin2, Message onComplete) {} public void supplyNetworkDepersonalization (String pin, Message onComplete) {} public boolean getIccLockEnabled() {} public boolean getIccFdnEnabled() {} public void setIccLockEnabled (boolean enabled, String password, Message onComplete) {} public void setIccFdnEnabled (boolean enabled, String password, Message onComplete) {} public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {} public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {}
UiccCardApplication的主要功能:创建对象IccFileHandler、IccRecords,并提供获取对象的接口;FDN/PIN/PUK设置和查询接口(通过RIL实现);查询UiccCardApplication状态信息(mAppState、mAppType)
public UiccCardApplication(UiccCard uiccCard, IccCardApplicationStatus as, Context c, CommandsInterface ci) { if (DBG) log("Creating UiccApp: " + as); mUiccCard = uiccCard; mAppState = as.app_state; mAppType = as.app_type; mAuthContext = getAuthContext(mAppType); mPersoSubState = as.perso_substate; mAid = as.aid; mAppLabel = as.app_label; mPin1Replaced = (as.pin1_replaced != 0); mPin1State = as.pin1; mPin2State = as.pin2; mContext = c; mCi = ci; mIccFh = createIccFileHandler(as.app_type); mIccRecords = createIccRecords(as.app_type, mContext, mCi); if (mAppState == AppState.APPSTATE_READY) { queryFdn(); queryPin1State(); } mCi.registerForNotAvailable(mHandler, EVENT_RADIO_UNAVAILABLE, null); }
创建IccFileHandler:SIMFileHandler/RuimFileHandler/UsimFileHandler/CsimFileHandler/IsimFileHandler
创建IccRecords:SIMRecords/RuimRecords/IsimUiccRecords
查询Fdn号码/查询Pin码状态
4.1 UiccCardApplication的更新
SIM卡或者Radio状态改变时,ril通过UiccController更新UiccCard,由UiccCard更新UiccCardApplication调用update()
public void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) { synchronized (mLock) { if (mDestroyed) { loge("Application updated after destroyed! Fix me!"); return; } if (DBG) log(mAppType + " update. New " + as); //变量更新 mContext = c; mCi = ci; AppType oldAppType = mAppType; AppState oldAppState = mAppState; PersoSubState oldPersoSubState = mPersoSubState; mAppType = as.app_type; mAuthContext = getAuthContext(mAppType); mAppState = as.app_state; mPersoSubState = as.perso_substate; mAid = as.aid; mAppLabel = as.app_label; mPin1Replaced = (as.pin1_replaced != 0); mPin1State = as.pin1; mPin2State = as.pin2; //更新IccRecords和IccFileHandler if (mAppType != oldAppType) { if (mIccFh != null) { mIccFh.dispose();} if (mIccRecords != null) { mIccRecords.dispose();} mIccFh = createIccFileHandler(as.app_type); mIccRecords = createIccRecords(as.app_type, c, ci); } if (mPersoSubState != oldPersoSubState && mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { notifyNetworkLockedRegistrantsIfNeeded(null); } if (mAppState != oldAppState) { if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState); // If the app state turns to APPSTATE_READY, then query FDN status, //as it might have failed in earlier attempt. if (mAppState == AppState.APPSTATE_READY) { queryFdn(); queryPin1State(); } notifyPinLockedRegistrantsIfNeeded(null); notifyReadyRegistrantsIfNeeded(null); } } }
4.2
// 根据modem返回的不同卡类型,创建不同 IccRecords 对象 private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) { if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) { return new SIMRecords(this, c, ci); } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){ return new RuimRecords(this, c, ci); } else if (type == AppType.APPTYPE_ISIM) { return new IsimUiccRecords(this, c, ci); } else { // Unknown app type (maybe detection is still in progress) return null; } } // 根据modem返回的不同卡类型,创建不同 IccFileHandler 对象 private IccFileHandler createIccFileHandler(AppType type) { switch (type) { case APPTYPE_SIM: return new SIMFileHandler(this, mAid, mCi); case APPTYPE_RUIM: return new RuimFileHandler(this, mAid, mCi); case APPTYPE_USIM: return new UsimFileHandler(this, mAid, mCi); case APPTYPE_CSIM: return new CsimFileHandler(this, mAid, mCi); case APPTYPE_ISIM: return new IsimFileHandler(this, mAid, mCi); default: return null; } }
5.CatService(接3)
6.IccFileHandler(接4)
从这些方法可以看出,IccFileHandler的主要作用就是提供SIM卡文件系统的读写操作,当调用这些方法时,需要传递要读写的文件系统地址,以及读写完毕后的回调函数,IccFileHandler会在读取完数据之后通知到调用者,并把返回值传递过去。
6.1 以UsimFileHandler为例
protected String getEFPath(int efid) { // TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility. // Implement this after discussion with OEMs. switch(efid) { case EF_SMS: return MF_SIM + DF_TELECOM; case EF_EXT6: case EF_MWIS: case EF_MBI: case EF_SPN: case EF_AD: case EF_MBDN: case EF_PNN: case EF_SPDI: case EF_SST: case EF_CFIS: case EF_GID1: case EF_GID2: case EF_MAILBOX_CPHS: case EF_VOICE_MAIL_INDICATOR_CPHS: case EF_CFF_CPHS: case EF_SPN_CPHS: case EF_SPN_SHORT_CPHS: case EF_INFO_CPHS: case EF_CSP_CPHS: return MF_SIM + DF_GSM; } String path = getCommonIccEFPath(efid); if (path == null) { Rlog.e(LOG_TAG, "Error: EF Path being returned in null"); } return path; }
不同SIM卡主要区别就是文件结构不同,因此各自实现getEFPath方法
6.2
6.3
7.IccRecords(接4)
IccRecords 记录SIM卡的EF文件信息,具体的读取SIM卡EF文件信息的过程是由 IccFileHandler 来实现的,以 SIMRecords 为例。
7.1
主要方法:
父类的方法
// * Constructor
public IccRecords(UiccCardApplication app, Context c, CommandsInterface ci) { mContext = c; mCi = ci; mFh = app.getIccFileHandler(); mParentApp = app; mTelephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); } // ***** Constructor public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) { super(app, c, ci); mAdnCache = new AdnRecordCache(mFh); mVmConfig = new VoiceMailConstants(); mSpnOverride = new SpnOverride(); mRecordsRequested = false; // No load request is made till SIM ready // recordsToLoad is set to 0 because no requests are made yet mRecordsToLoad = 0; mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null); mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null); // Start off by setting empty state resetRecords(); mParentApp.registerForReady(this, EVENT_APP_READY, null); mParentApp.registerForLocked(this, EVENT_APP_LOCKED, null); if (DBG) log("SIMRecords X ctor this=" + this); IntentFilter intentfilter = new IntentFilter(); intentfilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); c.registerReceiver(mReceiver, intentfilter); }
以上的创建过程完成了两个重要任务:
创建Adn和VoiceMail缓存,这里的Adn缓存用于SIM卡联系人的增、删、改、查等功能;
监听UiccCardApplication的Ready状态;
@Override public void onReady() { fetchSimRecords(); }
7.2 SIMRecords更新
protected void fetchSimRecords() { mRecordsRequested = true; if (DBG) log("fetchSimRecords " + mRecordsToLoad); mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); mRecordsToLoad++; // FIXME should examine EF[MSISDN]"s capability configuration // to determine which is the voice/data/fax line new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, getExtFromEf(EF_MSISDN), 1, obtainMessage(EVENT_GET_MSISDN_DONE)); mRecordsToLoad++; // Record number is subscriber profile mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); mRecordsToLoad++; // Record number is subscriber profile mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE)); mRecordsToLoad++; // Also load CPHS-style voice mail indicator, which stores // the same info as EF[MWIS]. If both exist, both are updated // but the EF[MWIS] data is preferred // Please note this must be loaded after EF[MWIS] mFh.loadEFTransparent( EF_VOICE_MAIL_INDICATOR_CPHS, obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE)); mRecordsToLoad++; // Same goes for Call Forward Status indicator: fetch both // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred. loadCallForwardingRecords(); getSpnFsm(true, null); mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE)); mRecordsToLoad++; mFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_GID2, obtainMessage(EVENT_GET_GID2_DONE)); mRecordsToLoad++; mFh.loadEFTransparent(EF_PLMN_W_ACT, obtainMessage(EVENT_GET_PLMN_W_ACT_DONE)); mFh.loadEFTransparent(EF_OPLMN_W_ACT, obtainMessage(EVENT_GET_OPLMN_W_ACT_DONE)); mFh.loadEFTransparent(EF_HPLMN_W_ACT, obtainMessage(EVENT_GET_HPLMN_W_ACT_DONE)); mFh.loadEFTransparent(EF_EHPLMN, obtainMessage(EVENT_GET_EHPLMN_DONE)); mFh.loadEFTransparent(EF_FPLMN, obtainMessage(EVENT_GET_FPLMN_DONE)); mRecordsToLoad++; loadEfLiAndEfPl(); // XXX should seek instead of examining them all if (false) { // XXX mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE)); mRecordsToLoad++; } if (CRASH_RIL) { String sms = "0107912160130310f20404d0110041007030208054832b0120" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "ffffffffffffffffffffffffffffff"; byte[] ba = IccUtils.hexStringToBytes(sms); mFh.updateEFLinearFixed(EF_SMS, 1, ba, null, obtainMessage(EVENT_MARK_SMS_READ_DONE, 1)); } if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested); }
从log中可以看到更新流程:
1572:09-12 15:33:37.899 2237 2237 D UiccCardApplication: Notifying 1 registrant: READY 1588:09-12 15:33:37.956 2237 2237 D SIMRecords: [SIMRecords] fetchSimRecords 0 查询IMSI: 1589:09-12 15:33:37.957 2237 2237 D RILJ : [3749]> getIMSI: GET_IMSI aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询ICCID: 1590:09-12 15:33:37.962 2237 2237 D RILJ : [3750]> iccIO: SIM_IO 0xc0 0x2fe2 path: 3F00,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询电话号码: 1593:09-12 15:33:37.969 2237 2237 D RILJ : [3751]> iccIO: SIM_IO 0xc0 0x6f40 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_MBI 语音信箱号码: 1594:09-12 15:33:37.971 2237 2237 D RILJ : [3752]> iccIO: SIM_IO 0xc0 0x6fc9 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 返回IMSI: 1597:09-12 15:33:37.971 2237 2299 D RILJ : [3749]< GET_IMSI [SUB0] 查询EF_AD: 1598:09-12 15:33:37.975 2237 2237 D RILJ : [3753]> iccIO: SIM_IO 0xc0 0x6fad path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_MWIS: 1602:09-12 15:33:37.978 2237 2237 D RILJ : [3754]> iccIO: SIM_IO 0xc0 0x6fca path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_VOICE_MAIL_INDICATOR_CPHS: 1603:09-12 15:33:37.979 2237 2237 D RILJ : [3755]> iccIO: SIM_IO 0xc0 0x6f11 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询call forwarding EF_CFIS: 1604:09-12 15:33:37.984 2237 2237 D RILJ : [3756]> iccIO: SIM_IO 0xc0 0x6fcb path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_CFF_CPHS: 1605:09-12 15:33:37.989 2237 2237 D RILJ : [3757]> iccIO: SIM_IO 0xc0 0x6f13 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_SPN: 1606:09-12 15:33:37.991 2237 2237 D RILJ : [3758]> iccIO: SIM_IO 0xc0 0x6f46 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_SPDI: 1608:09-12 15:33:37.995 2237 2237 D RILJ : [3759]> iccIO: SIM_IO 0xc0 0x6fcd path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 查询EF_PNN: 1609:09-12 15:33:37.997 2237 2237 D RILJ : [3760]> iccIO: SIM_IO 0xc0 0x6fc5 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 其他查询: 1610:09-12 15:33:37.999 2237 2237 D RILJ : [3761]> iccIO: SIM_IO 0xc0 0x6f38 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1611:09-12 15:33:38.001 2237 2237 D RILJ : [3762]> iccIO: SIM_IO 0xc0 0x6f16 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1612:09-12 15:33:38.002 2237 2299 D RILJ : [3751]< SIM_IO IccIoResult sw1:0x90 sw2:0x0 [SUB0] 1613:09-12 15:33:38.003 2237 2237 D RILJ : [3763]> iccIO: SIM_IO 0xc0 0x6f15 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1614:09-12 15:33:38.005 2237 2237 D RILJ : [3764]> iccIO: SIM_IO 0xc0 0x6f3e path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1615:09-12 15:33:38.010 2237 2237 D RILJ : [3765]> iccIO: SIM_IO 0xc0 0x6f3f path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1616:09-12 15:33:38.024 2237 2299 D RILJ : [3753]< SIM_IO IccIoResult sw1:0x90 sw2:0x0 [SUB0] 1633:09-12 15:33:38.206 2237 2237 D RILJ : [3766]> iccIO: SIM_IO 0xc0 0x6f60 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1634:09-12 15:33:38.213 2237 2237 D RILJ : [3767]> iccIO: SIM_IO 0xc0 0x6f61 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1636:09-12 15:33:38.231 2237 2237 D RILJ : [3768]> iccIO: SIM_IO 0xc0 0x6f62 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1638:09-12 15:33:38.235 2237 2237 D RILJ : [3769]> iccIO: SIM_IO 0xc0 0x6fd9 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1639:09-12 15:33:38.237 2237 2237 D RILJ : [3770]> iccIO: SIM_IO 0xc0 0x6f7b path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1641:09-12 15:33:38.241 2237 2299 D RILJ : [3764]< SIM_IO IccIoResult sw1:0x90 sw2:0x0 [SUB0] 1642:09-12 15:33:38.241 2237 2237 D RILJ : [3771]> iccIO: SIM_IO 0xc0 0x6f05 path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1644:09-12 15:33:38.247 2237 2237 D RILJ : [3772]> iccIO: SIM_IO 0xc0 0x2f05 path: 3F00,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1646:09-12 15:33:38.248 2237 2237 D RILJ : [3773]> iccIO: SIM_IO 0xc0 0x6f3c path: 3F007FFF,0,0,15 aid: a0000000871002ff86ffff89ffffffff [SUB0] 1648:09-12 15:33:38.250 2237 2237 D SIMRecords: [SIMRecords] fetchSimRecords 20 requested: true
在ICCCardProxy中注册IccRecords事件监听
private void registerUiccCardEvents() { if (mUiccCard != null) { mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); } if (mUiccApplication != null) { mUiccApplication.registerForReady(this, EVENT_APP_READY, null); mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null); mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null); } if (mIccRecords != null) { mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null); mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); } }
加载完IMSI/record load complete会通知IccCardProxy更新SIM卡状态
7.3
8.IccCardProxy
在PhoneFactory makeDefaultPhone是会创建Phone,在Phone的初始化时会创建IccCardProxy,UiccController初始化之后.IccCardProxy实现IccCard接口,通过Phone getIccCard返回IccCardProxy实例,接口的注释:
/** * {@hide} * @Deprecated use UiccController.getUiccCard instead. * * Integrated Circuit Card (ICC) interface * An object of a class implementing this interface is used by external * apps (specifically PhoneApp) to perform icc card related functionality. * * Apps (those that have access to Phone object) can retrieve this object * by calling phone.getIccCard() * * This interface is implemented by IccCardProxy and the object PhoneApp * gets when it calls getIccCard is IccCardProxy. */
接口定义的方法都是通过持有UiccController/UiccCard/UiccCardApplication/IccRecords来实现
8.1 IccCardProxy初始化
makeDefaultPhone方法: phone = new GsmCdmaPhone(context, sCommandsInterfaces[i], sPhoneNotifier, i, PhoneConstants.PHONE_TYPE_CDMA_LTE, TelephonyComponentFactory.getInstance()); 构造方法: public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory) { super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA", notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory); // phone type needs to be set before other initialization as other objects rely on it mPrecisePhoneType = precisePhoneType; initOnce(ci); initRatSpecific(precisePhoneType); mSST = mTelephonyComponentFactory.makeServiceStateTracker(this, this.mCi); // DcTracker uses SST so needs to be created after it is instantiated mDcTracker = mTelephonyComponentFactory.makeDcTracker(this); mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); logd("GsmCdmaPhone: constructor: sub = " + mPhoneId); } initOnce方法: mIccCardProxy = mTelephonyComponentFactory.makeIccCardProxy(mContext, mCi, mPhoneId); IccCardProxy实例的个数是与Phone的个数相对应的,有2个phone就会有两个IccCardProxy对象。 IccCardProxy构造方法: public IccCardProxy(Context context, CommandsInterface ci, int phoneId) { if (DBG) log("ctor: ci=" + ci + " phoneId=" + phoneId); mContext = context; mCi = ci; mPhoneId = phoneId; mTelephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, ci, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); mUiccController = UiccController.getInstance(); mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); ci.registerForOn(this,EVENT_RADIO_ON, null); ci.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_UNAVAILABLE, null); resetProperties(); setExternalState(State.NOT_READY, false); }
在IccCardProxy初始化时,SIM卡状态是NOT_READY状态并且会broadcastIccStateChangedIntent广播出去;然后在Phone中设置radio模式setVoiceRadioTech。
8.2 IccCardProxy事件处理
IccCardProxy构造方法中向UiccController中注册ICC_CARD_STATUS_CHANGED消息,UiccController在更新完自己内部的UiccCard之后会notify IccCardProxy更新内部各个实例,处理EVENT_ICC_CHANGED的方法updateIccAvailability():
private void updateIccAvailability() { synchronized (mLock) { //获取UiccCard UiccCard newCard = mUiccController.getUiccCard(mPhoneId); CardState state = CardState.CARDSTATE_ABSENT; UiccCardApplication newApp = null; IccRecords newRecords = null; if (newCard != null) { state = newCard.getCardState(); //获取UiccCardApplication newApp = newCard.getApplication(mCurrentAppType); if (newApp != null) { //获取IccRecords newRecords = newApp.getIccRecords(); } } if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) { if (DBG) log("Icc changed. Reregestering."); unregisterUiccCardEvents(); mUiccCard = newCard; mUiccApplication = newApp; mIccRecords = newRecords; //注册UiccCard/UiccCardApplication/IccRecords 监听 registerUiccCardEvents(); } //更新SIM卡状态判断是否发送广播 updateExternalState(); } }
监听事件:
private void registerUiccCardEvents() { if (mUiccCard != null) { //SIM卡拔出事件对外发送广播 mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); } if (mUiccApplication != null) { //SIM卡Ready对外发送广播 mUiccApplication.registerForReady(this, EVENT_APP_READY, null); mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null); mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null); } if (mIccRecords != null) { mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null); mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); mIccRecords.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null); } }
UiccController负责对卡槽的卡实时实例化或销毁对象,IccCardProxy监听UiccController里的变化并及时更新自己内部的状态,Phone实例通过getIccCard得到IccCardProxy实例来获取各种卡状态。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70419.html
摘要:一介绍了解全称意思应用程序,理解就是手机软件,主要是指安装在智能手机上面的软件,完善原始安卓系统的不足和多样性,或者说个性化,以此满足各个人群的需求,例如微信抖音这些,都是。测试测试就是要找出中的。可以更好的模拟用户操作,确保的稳定性 ...
摘要:在今年杭州云栖大会上,阿里云正式对外发布产品,向客户提供低成本软硬结合多安全等级的物联网安全解决方案。具体而言,采用阿里云安全技术,实现复用卡安全载体和卡商安全产线,每个卡实现预置一机一密物联网安全解决方案。 2016年在美国发生的摄像头安全漏洞导致大半个美国断网、摄像头偷窥、智能门锁被破解,这些事件都给物联网安全敲响警钟。 在今年杭州云栖大会上,阿里云Link正式对外发布LinkSec...
阅读 1842·2021-09-28 09:36
阅读 2333·2021-09-08 09:35
阅读 3031·2019-08-30 15:53
阅读 1524·2019-08-30 14:08
阅读 635·2019-08-29 18:40
阅读 2811·2019-08-29 13:57
阅读 2672·2019-08-29 13:55
阅读 651·2019-08-26 13:45