Uicccontroller is the entire UICC transaction processing portal, responsible for providing external iccrecords, Iccfilehandler, Uicccardapplication and other objects, and complete the initialization of the entire UICC system.
first, the main functions provided by Uicccontroller
We look at his main functions through the public method it provides: [Java] view plain copy public Uicccard Getuicccard () {} public uicccardapplication ge tuicccardapplication (int family) {} public iccrecords Geticcrecords (int. family) {} public Iccfilehandler Geticcfilehan Dler (int family) {} public void registerforiccchanged (Handler H, int. what, Object obj) {}
From the method provided above, we can know that the main function of Uicccontroller is embodied in two aspects: 1, create and provide Uicccard, Uicccardapplication, Iccrecords, Iccfilehandler and other objects
2. Provide monitoring of the SIM status
second, the creation of Uicccontroller process
Let's start by looking at where the Uicccontroller was created. We know that the phone object was created through Phonefactory in the initialization of the phone module:[Java]View plain copy @PhoneGlobals. Java public void OnCreate () {if (phone = = null) {//Create phone object P Honefactory.makedefaultphones (this); Get Phone Object phone = Phonefactory.getdefaultphone (); }} and then look at the process of Makedefaultphones ():[Java] View plain copy @PhoneFactory .java public static void makedefaultphones (context Context) { makedefaultphone (context); } public static void makedefaultphone (context context) { //get rilj scommandsinterface = new ril (context, networkmode, cdmasubscription); //Create uicccontroller uicccontroller.make (context, scommandsinterface); // Get the phone's type int phonetype = telephonymanager.getphonetype ( Networkmode); //Create PhoneProxy object if ( PHONETYPE == PHONECONSTANTS.PHONE_TYPE_GSM) { & nbsp; sproxyphone = new phoneproxy (New gsmphone (context, scommandsinterface, sphonenotifier)); } else if (phonetype == PHONECONSTANTS.PHONE_TYPE_CDMA) { switch (Telephonymanager.getlteoncdmamodestatic ()) { case PhoneConstants.LTE_ON_CDMA_TRUE: sproxyphone = new phoneproxy ( New cdmaltephone (context, scommandsinterface, sphonenotifier)); break; case PhoneConstants.LTE_ON_CDMA_FALSE:   &Nbsp; default: sproxyphone = new phoneproxy ( New cdmaphone (context, scommandsinterface, sphonenotifier)); break; } } } Here we see that after new Ril objects, the Uicccontroller is created by the Uicccontroller make () method, and two parameters are passed in, one of which is the context type Object , and the other is a Ril object of type Commandsinterface.
Next we look at the specific creation process through the make () method of Uicccontroller:[Java]View plain copy @UiccController. Java public static Uicccontroller make (Context C, Commandsinterface ci) {Synchron Ized (MLock) {if (minstance! = null) {throw new RuntimeException ("Uicccontroller.make () should O Nly be called once "); } minstance = new Uicccontroller (c, CI); return minstance; It is important to note that the make () method of Uicccontroller can only be called once, that is, in the whole global,only one Uicccontroller object exists。[Java]View Plain Copy private Uicccontroller (Context C, Commandsinterface ci) {mcontext = C; MCi = CI; Mci.registerforiccstatuschanged (this, event_icc_status_changed, null); Mci.registerforon (this, event_icc_status_changed, null); }
As we can see, in Uicccontroller's constructor, only one thing is done, registering two listeners: Registerforiccstatuschanged and Registerforon. The two listeners are listening to the status of the SIM card and the radio, and they are the triggers of the Uicccontroller update.
Third, the Uicccontroller update mechanism
Just now, Uicccontroller's initialization process mainly registered two listeners to Rilj, and these two listeners are the trigger point of the Uicccontroller update mechanism, when the listening event occurs, Uicccontroller will initiate the update mechanism for the entire UICC framework.
Here's a look at the specific update process. 3.1. Events monitored by the listener
3.1.1, registerforiccstatuschanged listener
For registerforiccstatuschanged This registration action is not directly called into the Ril class, but is called to the Ril parent class Basecommands:[Java]View plain copy @BaseCommands. Java public void registerforiccstatuschanged (Handler H, int. what, Object obj) {Regi Strant r = new Registrant (h, what, obj); Miccstatuschangedregistrants.add (R); We see that the registration process here is actually adding the current registration object to the Miccstatuschangedregistrants object list and then iterating through the listeners in the list when the following two events occur:
1. When you enter the wrong PIN or PUK: [Java]View plain Copy private rilrequest processsolicited (Parcel p) {switch (rr.mrequest) {case Ril_request_e Nter_sim_puk:case ril_request_enter_sim_puk2:if (miccstatuschangedregistrants! = null) { Miccstatuschangedregistrants.notifyregistrants (); } break; } }2. When the SIM card status changes: [Java]View plain copy private void processunsolicited (Parcel p) {switch (response) {case Ril_unsol_response_si M_status_changed:if (miccstatuschangedregistrants! = null) {miccstatuschangedregistrants . notifyregistrants (); } break; } }
3.1.2, Registerforon listenerSimilar to registerforiccstatuschanged, Registerforon () is also implemented in Basecommands:[Java] View plain copy @BaseCommands .java Public void registerforon (handler h, int What, object obj) { Registrant r = new registrant (h, what, obj); synchronized (Mstatemonitor) { //Save the registration information in the Monregistrants list monregistrants.add (r); if (Mstate.ison ()) { r.notifyregistrant (New asyncresult (null, null, null)); } } } The process of registration is to store listener information in the list of monregistrants variables and then traverse the list and notify listeners when the following two events occur:
1, when the radio state changes: [Java] View Plain copy private void processunsolicited (parcel p) { switch (response) { case ril_ unsol_response_radio_state_changed: radiostate newstate = getradiostatefromint (P.readint ()); switchtoradiostate (newState); break; } } private void switchtoradiostate (radiostate newstate) { setradiostate (newstate); } protected void Setradiostate (radiostate newstate) { synchronized ( Mstatemonitor)  { &NBsp //Notify listeners mradiostatechangedregistrants.notifyregistrants (); } } 2. When the Rilj and RILC channels are disconnected [Java]View plain Copy class Rilreceiver implements Runnable {@Override public void run () {//socket channel disconnected, set The RADIO status is unavailable state setradiostate (radiostate.radio_unavailable); } }
Through the above analysis, we can see that when the following event occurs, RIL will initiate a notification to the current Uicccontroller:
1, enter the wrong pin, PUK code
2, the SIM card status changes
3, Radio state changes
4. Socket Channel Disconnected
Next we look at the Uicccontroller action when this happens:
3.2, Uicccontroller the process of monitoring eventsSince Uicccontroller registers the above two listeners with the What parameter is "event_icc_status_changed", so the above listener event occurs, will enter the same event_icc_status_ Changed's case branch:[Java] View plain copy @UiccController .java public void handlemessage (message msg) { synchronized (mLock) { switch (msg.what) { case EVENT_ICC_STATUS_CHANGED: //the status of the SIM card or radio changes, it will enter the case Mci.geticccardstatus (Obtainmessage (event_get_icc_status_done)); break; case EVENT_GET_ICC_STATUS_DONE: asyncresult ar = (AsyncResult) msg.obj ; Ongeticccardstatusdone (AR); break; default:    RLOG.E (log_tag, " Unknown Event " + msg.what); } } } then calls Ril.java's Geticccardstatus () method to query the latest SIM and radio status.
When Rilj obtains a request for geticccardstatus (), it initiates a request to the modem to query the current SIM status:[Java]View plain copy @RIL. Java public void Geticccardstatus (Message result) {//sends a request to the modem to obtain the current SIM status Rilrequest rr = Rilrequest.obtain (ril_request_get_sim_status, result); Send (RR); After you get to the latest state, feed the results back to the object that originated the request, which is currently Uicccontroller:[Java] View Plain copy private rilrequest processsolicited (parcel p) { switch (rr.mrequest) { case RIL_REQUEST_GET_SIM_STATUS: //build Icccardstatus objects based on the return value of the modem ret = responseicccardstatus (p); break; } &n