Uicc之UiccController

本文深入解析UiccController作为UICC框架核心组件的作用,包括其创建过程、提供的主要功能及更新机制,阐述SIM卡状态和Radio状态变化时UiccController如何响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  UiccController是整个UICC事务处理的入口,负责对外提供IccRecords、IccFileHandler、UiccCardApplication等对象,并完成整个UICC系统的初始化工作。


一、UiccController提供的主要功能


        我们通过其提供的public方法来看他的主要功能:
  1. public UiccCard getUiccCard() {}  
  2. public UiccCardApplication getUiccCardApplication(int family) {}  
  3. public IccRecords getIccRecords(int family) {}  
  4. public IccFileHandler getIccFileHandler(int family) {}  
  5. public void registerForIccChanged(Handler h, int what, Object obj) {}  

        从上面提供的方法可以知道,UiccController的主要作用体现在两个方面:

        1、创建并向外提供UiccCard、UiccCardApplication、IccRecords、IccFileHandler等对象

        2、提供对SIM状态的监听


二、UiccController的创建过程


        我们先来看一下UiccController是在哪里被创建的。

        我们知道,Phone对象是在Phone模块的初始化中通过PhoneFactory创建的:
  1. @PhoneGlobals.java  
  2. public void onCreate() {  
  3.     if (phone == null) {  
  4.         //创建Phone对象  
  5.         PhoneFactory.makeDefaultPhones(this);  
  6.         //得到Phone对象  
  7.         phone = PhoneFactory.getDefaultPhone();  
  8.     }  
  9. }  
        然后看makeDefaultPhones()的过程:
  1. @PhoneFactory.java  
  2. public static void makeDefaultPhones(Context context) {  
  3.     makeDefaultPhone(context);  
  4. }  
  5. public static void makeDefaultPhone(Context context) {   
  6.     //获取RILJ  
  7.     sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);  
  8.     //创建UiccController  
  9.     UiccController.make(context, sCommandsInterface);  
  10.     //得到phone的Type  
  11.     int phoneType = TelephonyManager.getPhoneType(networkMode);  
  12.     //创建PhoneProxy对象  
  13.     if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {  
  14.         sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier));  
  15.     } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {  
  16.         switch (TelephonyManager.getLteOnCdmaModeStatic()) {  
  17.             case PhoneConstants.LTE_ON_CDMA_TRUE:  
  18.                 sProxyPhone = new PhoneProxy(new CDMALTEPhone(context, sCommandsInterface, sPhoneNotifier));  
  19.                 break;  
  20.             case PhoneConstants.LTE_ON_CDMA_FALSE:  
  21.             default:  
  22.                 sProxyPhone = new PhoneProxy(new CDMAPhone(context, sCommandsInterface, sPhoneNotifier));  
  23.                 break;  
  24.         }  
  25.     }  
  26. }  
        这里看到,在new完RIL对象之后,就通过UiccController的make()方法对UiccController进行创建,而且传递进去的两个参数,其中一个是Context类型对象,另一个是CommandsInterface类型的RIL对象。
        接下来我们通过UiccController的make()方法来看具体的创建过程:
  1. @UiccController.java  
  2. public static UiccController make(Context c, CommandsInterface ci) {  
  3.     synchronized (mLock) {  
  4.         if (mInstance != null) {  
  5.             throw new RuntimeException("UiccController.make() should only be called once");  
  6.         }  
  7.         mInstance = new UiccController(c, ci);  
  8.         return mInstance;  
  9.     }  
  10. }  
        这里需要注意,UiccController的make()方法只能调用一次,也就是说,在整个全局中, 只存在一个UiccController对象
  1. private UiccController(Context c, CommandsInterface ci) {  
  2.     mContext = c;  
  3.     mCi = ci;  
  4.     mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);  
  5.     mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);  
  6. }  

        我们看到,在UiccController的构造函数中,只完成了一件事情,就是注册了两个监听器:registerForIccStatusChanged和registerForOn。这两个监听器监听的是SIM卡和Radio的状态,他们是UiccController更新的触发器。


三、UiccController更新机制

        

        刚才讲到,UiccController的初始化过程主要向RILJ注册了两个监听器,而这两个监听器就是UiccController更新机制的触发点,当监听的事件发生时,UiccController就会启动整个UICC框架的更新机制。

        下面来看具体的更新过程。

3.1、监听器所监听的事件


3.1.1、registerForIccStatusChanged监听器

        对于registerForIccStatusChanged这个注册的动作,并没有直接调用到RIL类里面,而是调用到了RIL的父类BaseCommands中:

  1. @BaseCommands.java  
  2. public void registerForIccStatusChanged(Handler h, int what, Object obj) {  
  3.     Registrant r = new Registrant (h, what, obj);  
  4.     mIccStatusChangedRegistrants.add(r);  
  5. }  
        我们看到,这里的注册过程其实就是在mIccStatusChangedRegistrants对象List中添加当前的注册对象,然后当以下两种事件发生时就会遍历该List中的监听者进行通知:
        1、输入错误的PIN或PUK时:
  1. private RILRequest processSolicited (Parcel p) {  
  2.     switch (rr.mRequest) {  
  3.         case RIL_REQUEST_ENTER_SIM_PUK:  
  4.         case RIL_REQUEST_ENTER_SIM_PUK2:  
  5.             if (mIccStatusChangedRegistrants != null) {  
  6.                 mIccStatusChangedRegistrants.notifyRegistrants();  
  7.             }  
  8.             break;  
  9.     }  
  10. }  
         2、当SIM卡状态发生改变时:
  1. private void processUnsolicited (Parcel p) {  
  2.     switch(response) {  
  3.         case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:  
  4.             if (mIccStatusChangedRegistrants != null) {  
  5.                 mIccStatusChangedRegistrants.notifyRegistrants();  
  6.             }  
  7.             break;  
  8.     }  
  9. }  

3.1.2、registerForOn监听器

        与registerForIccStatusChanged类似,registerForOn()也是在BaseCommands中被实现的:
  1. @BaseCommands.java  
  2. public void registerForOn(Handler h, int what, Object obj) {  
  3.     Registrant r = new Registrant (h, what, obj);  
  4.     synchronized (mStateMonitor) {  
  5.         //将注册信息保存在mOnRegistrants列表中  
  6.         mOnRegistrants.add(r);  
  7.         if (mState.isOn()) {  
  8.             r.notifyRegistrant(new AsyncResult(nullnullnull));  
  9.         }  
  10.     }  
  11. }  
        注册的过程就是把监听者信息保存在mOnRegistrants变量的List列表中,然后当以下两种事件发生时就会遍历该List并通知监听者:
        1、Radio状态发生改变时:
  1. private void processUnsolicited (Parcel p) {  
  2.     switch(response) {  
  3.         case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:  
  4.             RadioState newState = getRadioStateFromInt(p.readInt());  
  5.             switchToRadioState(newState);  
  6.             break;  
  7.     }  
  8. }  
  9. private void switchToRadioState(RadioState newState) {  
  10.     setRadioState(newState);  
  11. }  
  12. protected void setRadioState(RadioState newState) {  
  13.     synchronized (mStateMonitor) {  
  14.         //通知监听者  
  15.         mRadioStateChangedRegistrants.notifyRegistrants();  
  16.     }  
  17. }  
         2、RILJ与RILC通道断开时
  1. class RILReceiver implements Runnable {  
  2.     @Override  
  3.     public void run() {  
  4.         //Socket通道断开,设置Radio状态为unavailable状态  
  5.         setRadioState (RadioState.RADIO_UNAVAILABLE);  
  6.     }  
  7. }  

        经过上面的分析,我们可以看到,当发生以下事件时,RIL就会对当前的UiccController发起通知:
        1、输入错误的PIN、PUK码
        2、SIM卡状态发生改变
        3、Radio状态发生改变
        4、Socket通道断开

        接下来我们查看当上述情况发生时,UiccController的动作:


3.2、UiccController对监听事件的处理流程

        由于UiccController注册以上两种监听器时所使用的what参数均为“EVENT_ICC_STATUS_CHANGED”,因此上述监听的事件发生时,都会进入同一个EVENT_ICC_STATUS_CHANGED的case分支:
  1. @UiccController.java  
  2. public void handleMessage (Message msg) {  
  3.     synchronized (mLock) {  
  4.         switch (msg.what) {  
  5.             case EVENT_ICC_STATUS_CHANGED:  
  6.                 //无论是SIM卡的状态或者Radio的状态发生改变,都会进入该case中  
  7.                 mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));  
  8.                 break;  
  9.             case EVENT_GET_ICC_STATUS_DONE:  
  10.                 AsyncResult ar = (AsyncResult)msg.obj;  
  11.                 onGetIccCardStatusDone(ar);  
  12.                 break;  
  13.             default:  
  14.                 Rlog.e(LOG_TAG, " Unknown Event " + msg.what);  
  15.         }  
  16.     }  
  17. }  
        然后就会调用RIL.java的getIccCardStatus()方法,去查询最新的SIM和Radio状态。
        当RILJ获取到getIccCardStatus()的请求后,就会向Modem发起请求查询当前的SIM卡状态:
  1. @RIL.java  
  2. public void getIccCardStatus(Message result) {  
  3.     //向Modem发送请求,获取当前的SIM卡状态  
  4.     RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result);  
  5.     send(rr);  
  6. }  
        然后获取到最新状态后,将结果反馈给发起请求的对象,当前就是UiccController:
  1. private RILRequest processSolicited (Parcel p) {  
  2.     switch (rr.mRequest) {  
  3.         case RIL_REQUEST_GET_SIM_STATUS:   
  4.             //根据Modem得到的返回值构建IccCardStatus对象  
  5.             ret =  responseIccCardStatus(p); break;  
  6.     }  
  7.     if (rr.mResult != null) {  
  8.         AsyncResult.forMessage(rr.mResult, ret, null);  
  9.         //将结果返回给UiccController  
  10.         rr.mResult.sendToTarget();  
  11.     }  
  12. }  
        接下来,UiccController就再次通过handleMessage()方法来处理接下来的流程,只不过这次进入的是EVENT_GET_ICC_STATUS_DONE的case流程:
  1. @UiccController.java  
  2. public void handleMessage (Message msg) {  
  3.     synchronized (mLock) {  
  4.         switch (msg.what) {  
  5.             case EVENT_ICC_STATUS_CHANGED:  
  6.                 //得到状态改变通知,发起请求  
  7.                 mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));  
  8.                 break;  
  9.             case EVENT_GET_ICC_STATUS_DONE:  
  10.                 //获取最新的SIM卡状态  
  11.                 AsyncResult ar = (AsyncResult)msg.obj;  
  12.                 onGetIccCardStatusDone(ar);  
  13.                 break;  
  14.             default:  
  15.                 Rlog.e(LOG_TAG, " Unknown Event " + msg.what);  
  16.         }  
  17.     }  
  18. }  
        继续看UiccController对最新状态的处理:
  1. private synchronized void onGetIccCardStatusDone(AsyncResult ar) {  
  2.     if (ar.exception != null) {  
  3.         return;  
  4.     }  
  5.     //拿到RIL中创建的IccCardStatus对象  
  6.     IccCardStatus status = (IccCardStatus)ar.result;  
  7.   
  8.     //创建或更新UiccCard  
  9.     if (mUiccCard == null) {  
  10.         mUiccCard = new UiccCard(mContext, mCi, status);  
  11.     } else {  
  12.         mUiccCard.update(mContext, mCi , status);  
  13.     }  
  14.     //继续向其他对象派发消息  
  15.     mIccChangedRegistrants.notifyRegistrants();  
  16. }  
        到这里我们看到,UiccController获取到最新的SIM卡状态之后,做了两件事情: 1、创建或更新UiccCard;2、通知其他子监听对象
        而且我们获取到两个信息:1、UiccCard对象是在UiccController更新SIM卡状态时创建的;2、其他对象可以通过registerForIccChanged()方法向UiccController申请监听SIM卡状态监听。
        至此,UiccController的分析结束,下一章将会介绍 UiccCard对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值