(M)SIM卡开机流程分析之UiccController类分析

看看这个方法,定义一个UiccController对象
UiccController.make(context, sCommandsInterfaces);
// 单例模式
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;
        // 这个是RIL,CommandsInterface
        mCis = ci;
        for (int i = 0; i < mCis.length; i++) {
            Integer index = new Integer(i);
            // 注册EVENT_ICC_STATUS_CHANGED
            mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
            // TODO remove this once modem correctly notifies the unsols
            if (DECRYPT_STATE.equals(SystemProperties.get("vold.decrypt"))) {
                mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index);
            } else {
                mCis[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index);
            }
            // 注册EVENT_RADIO_UNAVAILABLE
            mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index);
            // 注册EVENT_SIM_REFRESH
            mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index);
        }
}
此处的mCis为CommandsInterface对象,从前文知道,这个是RIL对象。
进入RIL.java文件中看看:
public final class RIL extends BaseCommands implements CommandsInterface {
……
}
BaseCommands.java文件:
@Override
public void registerForIccStatusChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
   mIccStatusChangedRegistrants.add(r);
}
而mIccStatusChangedRegistrants在RIL.java文件中使用的。
RIL.java
switch (rr.mRequest) {
    case RIL_REQUEST_ENTER_SIM_PUK:
    case RIL_REQUEST_ENTER_SIM_PUK2:
    	if (mIccStatusChangedRegistrants != null) {
      	    if (RILJ_LOGD) {
               riljLog("ON enter sim puk fakeSimStatusChanged: reg count=" + mIccStatusChangedRegistrants.size());
            }
            mIccStatusChangedRegistrants.notifyRegistrants();
     }
     break;
}
    case RIL_REQUEST_ENTER_SIM_PIN:
    case RIL_REQUEST_ENTER_SIM_PIN2:
    case RIL_REQUEST_CHANGE_SIM_PIN:
    case RIL_REQUEST_CHANGE_SIM_PIN2:
    case RIL_REQUEST_SET_FACILITY_LOCK:
        if (mIccStatusChangedRegistrants != null) {
            if (RILJ_LOGD) {
                riljLog("ON some errors fakeSimStatusChanged: reg count=" + mIccStatusChangedRegistrants.size());
            }       
            mIccStatusChangedRegistrants.notifyRegistrants();
        }
        break;
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
    if (RILJ_LOGD) unsljLog(response); 
    if (mIccStatusChangedRegistrants != null) {            
mIccStatusChangedRegistrants.notifyRegistrants();
    }
    break;
也就是说,在UiccController.java的函数中,注册了一个EVENT_ICC_STATUS_CHANGED的消息,而它是在接收到RIL_REQUEST_ENTER_SIM_PUK、RIL_REQUEST_ENTER_SIM_PUK2、或者RIL_REQUEST_ENTER_SIM_PIN、RIL_REQUEST_ENTER_SIM_PIN2、RIL_REQUEST_CHANGE_SIM_PIN、RIL_REQUEST_CHANGE_SIM_PIN2、RIL_REQUEST_SET_FACILITY_LOCK和RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED消息后就会直接调用,那么这几个消息会从什么地方发出来呢?其实这些都就是底层Rild中会发出了,这个不做研究。
在EVENT_ICC_STATUS_CHANGED消息被接收到后,在UiccController中处理:
@Override
public void handleMessage (Message msg) { 
    AsyncResult ar = (AsyncResult)msg.obj;
    switch (msg.what) {
        case EVENT_ICC_STATUS_CHANGED:
            ……
			  // mCis为CommandsInterface,为RIL对象
mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index));
           break;
        case EVENT_GET_ICC_STATUS_DONE:
            ……
            onGetIccCardStatusDone(ar, index);
            break;
        ……
    }
}
进入RIL.java中,getIccCardStatus方法:
@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);
    ……
    send(rr);
}
case RIL_REQUEST_GET_SIM_STATUS: ret =  responseIccCardStatus(p); break;
private Object responseIccCardStatus(Parcel p) {
    IccCardApplicationStatus appStatus;
    IccCardStatus cardStatus = new IccCardStatus();
    cardStatus.setCardState(p.readInt());
    cardStatus.setUniversalPinState(p.readInt());
    cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt();
    cardStatus.mCdmaSubscriptionAppIndex = p.readInt();
    cardStatus.mImsSubscriptionAppIndex = p.readInt();
    int numApplications = p.readInt();
    // limit to maximum allowed applications
    if (numApplications > IccCardStatus.CARD_MAX_APPS) {
    	numApplications = IccCardStatus.CARD_MAX_APPS;
    }
    cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
    for (int i = 0 ; i < numApplications ; i++) {
    	appStatus = new IccCardApplicationStatus();
       appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt());
       appStatus.app_state = appStatus.AppStateFromRILInt(p.readInt());
       appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt());
       appStatus.aid = p.readString();
       appStatus.app_label = p.readString();
       appStatus.pin1_replaced = p.readInt();
       appStatus.pin1 = appStatus.PinStateFromRILInt(p.readInt());
       appStatus.pin2 = appStatus.PinStateFromRILInt(p.readInt());
       cardStatus.mApplications[i] = appStatus;
    }
    return cardStatus;
}
这个是读取SIM卡中的信息了,这个不做研究,若有需要,可以在这个位置打一些LOG,来确认SIM卡中读取到的数据值。
读取数据完成后,发送EVENT_GET_ICC_STATUS_DONE消息,在UiccController.java中接收,如上述UiccController代码,然后直接调用onGetIccCardStatusDone(ar, index);方法:
private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) {
        ……
        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);
        }
        ……	
        mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
}
新建一个UiccCards对象,注意这个地方UiccCards对象,先判断存在与否,若存在,则直接update数据,若不存在,在新建一个UiccCards对象。新建对象时,传入的参数为,第一个是上下文对象,第二个是mCis[index],CommandsInterface,即RIL对象,第三个为status,即在RIL.java文件中读取到的IccCardStatus对象,第四个为index,为第几张SIM卡。
进入UiccCards.java文件:
public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) {
    mCardState = ics.mCardState;
    mPhoneId = phoneId;
    // 第一个参数是上下文对象,第二个为RIL对象,第三个为IccCardStatus对象,从RIL.java文件中读取到的
    update(c, ci, ics);
}
public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
        synchronized (mLock) {
            ……
            mContext = c;
            mCi = ci;

            //update 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(); 
            ……
        }
}
新建UiccCardApplications对象,若已经存在,则直接update,若不存在,新建,和之前UiccCards一样。mUiccApplications新建函数中的第二个参数ics.mApplications[i],是从RIL.java文件中读取到的,见前面的RIL.java文件讲解。
先新建UiccCardApplications对象:
UiccCardApplication(UiccCard uiccCard,
                        IccCardApplicationStatus as,
                        Context c,
                        CommandsInterface ci) {
	   // 这些值全部是在RIL.java文件中,从SIM卡中读出来的
        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);
}
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;
        }
}
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;
        }
}
根据从SIM卡中读取出来的字段,新建IccFileHandler和IccRecords对象。
再看UiccCard.java的update方法中的createAndUpdateCatService();这个方法,从名字看,是创建/更新CatService,进入其中查看:
protected void createAndUpdateCatService() {
        if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
            // Initialize or Reinitialize CatService
            if (mCatService == null) {
				// mCi为ConmandsInterface,RIL对象
                mCatService = CatService.getInstance(mCi, mContext, this, mPhoneId);
            } else {
                ((CatService)mCatService).update(mCi, mContext, this);
            }
        }
		……
    }
单例模式,和之前一样,若无,则新建,若已有,则update。
public static CatService getInstance(CommandsInterface ci,
            Context context, UiccCard ic, int slotId) {
        UiccCardApplication ca = null;
        IccFileHandler fh = null;
        IccRecords ir = null;
        if (ic != null) {
            /* Since Cat is not tied to any application, but rather is Uicc application
             * in itself - just get first FileHandler and IccRecords object
             */
            ca = ic.getApplicationIndex(0);
            if (ca != null) {
				//IccFileHandler对象,在上面新建的,ca是UiccCardApplication
                fh = ca.getIccFileHandler();
				//新建IccRecords对象,在上面新建的
                ir = ca.getIccRecords();
            }
        }

        synchronized (sInstanceLock) {
            ……
            if (sInstance[slotId] == null) {
                ……
                sInstance[slotId] = new CatService(ci, ca, ir, context, fh, ic, slotId);
            } else if ((ir != null) && (mIccRecords != ir)) {
                if (mIccRecords != null) {
                    mIccRecords.unregisterForRecordsLoaded(sInstance[slotId]);
                }
                mIccRecords = ir;
                mUiccApplication = ca; 
                mIccRecords.registerForRecordsLoaded(sInstance[slotId],
                        MSG_ID_ICC_RECORDS_LOADED, null);
                CatLog.d(sInstance[slotId], "registerForRecordsLoaded slotid=" + slotId + " instance:" + sInstance[slotId]);
            }
            return sInstance[slotId];
        }
}
后续,还有很多流程,等以后有时间研究





















 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值