kaifyou Android 7.0 UICC 分析

来源:互联网 发布:淘宝 笑涵阁 猫腻 编辑:程序博客网 时间:2024/05/22 17:38

Android 7.0 UICC 分析(一)

Android 7.0 UICC 分析(一)

UICC(Universal Intergrated Circuit Card) 框架

复制代码
 * Following is class diagram for uicc classes: * *                       UiccController *                            # *                            | *                        UiccCard *                          #   # *                          |   ------------------ *                    UiccCardApplication    CatService *                      #            # *                      |            | *                 IccRecords    IccFileHandler *                 ^ ^ ^           ^ ^ ^ ^ ^ *    SIMRecords---- | |           | | | | ---SIMFileHandler *    RuimRecords----- |           | | | ----RuimFileHandler *    IsimUiccRecords---           | | -----UsimFileHandler *                                 | ------CsimFileHandler *                                 ----IsimFileHandler
复制代码

UiccController 类与RILJ 交互,实质是一个Handler,当SIM卡状态发生变化UICCController就会更新。

其构造函数注册监听事件:

复制代码
    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 (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);            }            mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index);            mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index);        }    }
复制代码

CommandsInterface[] 数组对象的 i 对应的就是PhoneID;

EVENT_ICC_STATUS_CHANGED 监听SIM卡的状态变化;

 

当SIM卡状态变化,就有EVENT_ICC_STATUS_CHANGED 消息发出,此消息的处理如下:

复制代码
    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;                .............                default:                    Rlog.e(LOG_TAG, " Unknown Event " + msg.what);            }        }    }    
复制代码

调用RILJ 的getIccCardStatus() 方法,参数是自定义的EVENT_GET_ICC_STATUS_DONE 消息Message对象,用于返回SIM卡状态信息;

生成RIL_REQUEST_GET_SIM_STATUS RILRequest 请求下发RILC 层,获取SIM 卡状态信息:

复制代码
    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);    }
复制代码

SIM 卡状态的信息通过 RILReceiver 类接收 RILC 层的返回,由ProcessSolicited() 方法处理;

case RIL_REQUEST_GET_SIM_STATUS: ret =  responseIccCardStatus(p); break;

responseIccCardStatus() 方法返回IccCardStatus 对象,保存着SIM卡的状态信息,上报UiccController EVENT_GET_ICC_STATUS_DONE 消息:

                case EVENT_GET_ICC_STATUS_DONE:                    if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");                    onGetIccCardStatusDone(ar, index);                    break;

onGetIccCardStatusDone() 方法解析出IccCardStatue,如果没有SIM卡,则创建一个UiccCard,否则更新UiccCard 信息,一个UiccCard对象代表着一张SIM:

复制代码
    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);        }        if (DBG) log("Notifying IccChangedRegistrants");        mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));    }
复制代码

mIccChangedRigistrants 向监听者发出消息通知,监听者通过如下方法注册mIccChangedRigistrants :

复制代码
    //Notifies when card status changes    public void registerForIccChanged(Handler h, int what, Object obj) {        synchronized (mLock) {            Registrant r = new Registrant (h, what, obj);            mIccChangedRegistrants.add(r);            //Notify registrant right after registering, so that it will get the latest ICC status,            //otherwise which may not happen until there is an actual change in ICC status.            r.notifyRegistrant();        }    }
复制代码

监听者有如下:

IccCardProxy、GsmSMSDispactcher、CatService、Phone、ServiceStateTracker、DcTracker

Android 7.0 UICC 分析(二)

本文讲解UiccCard类

/frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/UiccCard.java

UICCController 类的onGetIccCardStatusDone() 方法,根据获取的SIM状态信息IccCardStatus 创建或更新UiccCard 对象;

复制代码
    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);        }        .......    }
复制代码

 

UiccCard 类的构造方法,同样会调用update() 方法更新SIM 卡状态信息;

    public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId) {        mCardState = ics.mCardState;        mPhoneId = phoneId;        update(c, ci, ics);    }

UiccCard 类的 update() 方法:

1、根据IccCardStatus 参数在mUiccApplication 列表中匹配UiccCardApplication 对象,通过UiccCardApplication 类的update() 方法更新,否则创建一个UiccCardApplication 对象;

2、调用createAndUpdateCatService() 方法创建或更新CatService 对象;

3、获取RadioState状态,更新CardState,发出SIM卡插拔消息;

复制代码
    public void update(Context c, CommandsInterface ci, IccCardStatus ics) {             ........            //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); //调用UiccCardApplication.java                }            }            createAndUpdateCatService(); //CatService            ..........            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) {                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;        }    }
复制代码

 

createAndUpdateCatService() 方法,创建或更新CatService:

复制代码
    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;        }    }
复制代码


消息EVENT_CARD_REMOVED、 EVENT_CARD_ADDED 在UiccCard 类的handleMessage()方法中处理:

复制代码
    protected Handler mHandler = new Handler() {        @Override        public void handleMessage(Message msg){            switch (msg.what) {                case EVENT_CARD_REMOVED:                    onIccSwap(false);                    break;                case EVENT_CARD_ADDED:                    onIccSwap(true);                    break;                .........            }        }    };
复制代码

onIccSwap() 方法,判断是否共卡座,如果是直接返回,否则调用promptForRestart():

复制代码
    private void onIccSwap(boolean isAdded) {        boolean isHotSwapSupported = mContext.getResources().getBoolean(                R.bool.config_hotswapCapable);        if (isHotSwapSupported) { //给国内双卡共卡座设计留下接口            log("onIccSwap: isHotSwapSupported is true, don't prompt for rebooting");            return;        }        log("onIccSwap: isHotSwapSupported is false, prompt for rebooting");        promptForRestart(isAdded);    }
复制代码

promptForRestart() 方法,切换sim卡,弹出提示框:

复制代码
    private void promptForRestart(boolean isAdded) {        synchronized (mLock) {            final Resources res = mContext.getResources();            final String dialogComponent = res.getString(                    R.string.config_iccHotswapPromptForRestartDialogComponent);            if (dialogComponent != null) {                Intent intent = new Intent().setComponent(ComponentName.unflattenFromString(                        dialogComponent)).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)                        .putExtra(EXTRA_ICC_CARD_ADDED, isAdded);                try {                    mContext.startActivity(intent);                    return;                } catch (ActivityNotFoundException e) {                    loge("Unable to find ICC hotswap prompt for restart activity: " + e);                }            }            // TODO: Here we assume the device can't handle SIM hot-swap            //      and has to reboot. We may want to add a property,            //      e.g. REBOOT_ON_SIM_SWAP, to indicate if modem support            //      hot-swap.            DialogInterface.OnClickListener listener = null;            // TODO: SimRecords is not reset while SIM ABSENT (only reset while            //       Radio_off_or_not_available). Have to reset in both both            //       added or removed situation.            listener = new DialogInterface.OnClickListener() {                @Override                public void onClick(DialogInterface dialog, int which) {                    synchronized (mLock) {                        if (which == DialogInterface.BUTTON_POSITIVE) {                            if (DBG) log("Reboot due to SIM swap");                            PowerManager pm = (PowerManager) mContext                                    .getSystemService(Context.POWER_SERVICE);                            pm.reboot("SIM is added.");  //SIM卡上电重启                        }                    }                }            };            Resources r = Resources.getSystem();            String title = (isAdded) ? r.getString(R.string.sim_added_title) :                r.getString(R.string.sim_removed_title);            String message = (isAdded) ? r.getString(R.string.sim_added_message) :                r.getString(R.string.sim_removed_message);            String buttonTxt = r.getString(R.string.sim_restart_button);            AlertDialog dialog = new AlertDialog.Builder(mContext)            .setTitle(title)            .setMessage(message)            .setPositiveButton(buttonTxt, listener)            .create();            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);            dialog.show();  //SIM卡弹出提示框        }    }
复制代码