(M) Ril analysis of SIM card start-up flow analysis

Source: Internet
Author: User
Tags constructor socket throwable

Today, let's take a look at another important class in the SIM card startup process, Ril.java

First, enter the Ril.java file

/**
 * RIL implementation of the Commandsinterface.
 *
 * {@hide} */
/Leo, you need to be aware of this place, inherit from Basecommands, implement Commandsinterface interface public
final class RIL Extends Basecommands implements Commandsinterface {
    ...
}
Note that this class is inherited from Basecommands and implements the Commandsinterface interface

Take a look at the creation of the Ril class in the Makedefaultphone method in the Phonefactory.java file.

for (int i = 0; i < numphones; i++) {
     //reads the system properties and makes Commandsinterface
     /Get Preferr Ed network type.
     Networkmodes[i] = Rilconstants.preferred_network_mode;

     RLOG.I (Log_tag, "Network Mode set to" + integer.tostring (Networkmodes[i]));
     Leo, creating a new Ril object
     //Ril for each slot is an interface that implements Commandsinterface, so the name of this place is scommandsinterfaces
     scommandsinterfaces[ I] = new RIL (context, networkmodes[i], cdmasubscription, i);
}
Leo, get the value of Settings.Global.CDMA_SUBSCRIPTION_MODE
int cdmasubscription = Cdmasubscriptionsourcemanager.getdefault (context);
Cdmasubscriptionsourcemanager.java

/**
     * Gets The default CDMA subscription source
     *
     * @return Default CDMA subscription source from Settings DB if present.
     *
    /public static int Getdefault (context context) {
        //Get The default value from the Settings
        int Subscription Source = Settings.Global.getInt (Context.getcontentresolver (),
                Settings.Global.CDMA_SUBSCRIPTION_MODE, preferred_cdma_subscription);
        RLOG.D (Log_tag, "Subscriptionsource from Settings:" + subscriptionsource);
        return subscriptionsource;
    }
Networkmodes[i] parameter, from the above can be seen, is the direct assignment, the cdmasubscription parameter, from the above value for the specified value, the provisional hold, I parameter is the number of slots, next, look at the Ril constructor

Leo, Ril construction method//The fourth parameter is the Instanceid slot//The second parameter is the Preferrednetworkmode value of the Instanceid slot//The third parameter cdmasubscription, is the value of Settings.Global.CDMA_SUBSCRIPTION_MODE public RIL (context context, int preferrednetworktype, int cdmasubscription,
    Integer instanceId) {super (context);
    ... mcontext = context;
    Mcdmasubscription = cdmasubscription;
    Mpreferrednetworktype = Preferrednetworktype;
    Mphonetype = Rilconstants.no_phone;

    Minstanceid = instanceId;
    PowerManager pm = (powermanager) context.getsystemservice (Context.power_service);
    Leo, what's this wakelock for?
    Mwakelock = Pm.newwakelock (Powermanager.partial_wake_lock, Rilj_log_tag);
    Mwakelock.setreferencecounted (FALSE); Mwakelocktimeout = Systemproperties.getint (Telephonyproperties.property_wake_lock_timeout, DEFAULT_WAKE_LOCK_
    TIMEOUT);

    Mwakelockcount = 0;
    Leo handlerthread msenderthread = new Handlerthread ("Rilsender" + Minstanceid);

    Msenderthread.start (); Looper Looper = mSeNderthread.getlooper ();

     //Leo, this rilsender inherits handler, and implements runnable interface Msender = new Rilsender (looper);
    Connectivitymanager cm = (Connectivitymanager) context.getsystemservice (Context.connectivity_service); if (cm.isnetworksupported (connectivitymanager.type_mobile) = = False) {Riljlog ("not starting rilreceiver:wifi-onl
    Y ");
        } else {Riljlog ("starting Rilreceiver" + Minstanceid);
        Leo, implement socket communication, runnable object mreceiver = new Rilreceiver ();
        Mreceiverthread = new Thread (mreceiver, "rilreceiver" + Minstanceid);

        Mreceiverthread.start ();
        Displaymanager DM = (displaymanager) context.getsystemservice (Context.display_service);
        Mdefaultdisplay = Dm.getdisplay (Display.default_display);
        Dm.registerdisplaylistener (Mdisplaylistener, NULL);

        Mdefaultdisplaystate = Mdefaultdisplay.getstate ();
        Leo, monitor the power change, why.
       Intentfilter filter = new Intentfilter (intent.action_battery_changed); Intent batterystatus = Context.registerreceiver (Mbatterystatelistener, filter); if (batterystatus! = null) {//0 means it ' s on battery misdeviceplugged = Batterystatus.getintext
        RA (batterymanager.extra_plugged, 0)! = 0; }}//Leo, just called a Telephonydevcontroller create method at Phonefactory//Call getinstance method here, can get its object Telephonydevc
    Ontroller TDC = Telephonydevcontroller.getinstance ();
Tdc.registerril (this); }
As you can see from the code, the Ril constructor is mostly done

1) Assignment operation

2) New Wakelock, I do not know the role of the present, after the analysis it

3) A handlerthread is started and a new Rilsender object is created, which inherits the handler and implements the Runnable interface, but does nothing in the Run method

4) on the basis of judging the mobile phone support mobile data traffic, create a new Rilreceiver object and start directly, this object implements the interface of Runnable, in its Run method, establishes the communication connection, realizes the RIL message transmission and RIL message processing, this later looks

5) monitor display settings and power changes

6) Create a new Telephonydevcontroller object and register the RIL


Next, we'll focus on 4th), enter the Rilreceiver class

Class Rilreceiver implements Runnable {byte[] buffer;
    Rilreceiver () {buffer = new byte[ril_max_command_bytes];
	} @Override public void Run () {int retrycount = 0;
	String rilsocket = "Rild"; Leo,socket communication try {for (;;)
			{Localsocket s = null;

			Localsocketaddress l;
			if (Minstanceid = = NULL | | minstanceid = = 0) {rilsocket = socket_name_ril[0];
			} else {rilsocket = Socket_name_ril[minstanceid];
				} try {s = new localsocket ();
				L = new Localsocketaddress (Rilsocket, LocalSocketAddress.Namespace.RESERVED);
			S.connect (l);
					} catch (IOException ex) {try {if (s! = null) {s.close (); }} catch (IOException ex2) {//Ignore failure to close after failure to connect}//don ' t print a ER ROR message after the first time//or after the 8th time if (RetryCount = = 8) {RLOG.E (Rilj_log_tag, "C Ouldn ' t find ' "+ rilsocket +" ' socket after "+ RetryCount +"Times, continuing to retry silently ");
							} else if (retrycount >= 0 && RetryCount < 8) {RLOG.I (Rilj_log_tag, "couldn ' t find '" + rilsocket + "' socket;
				Retrying after timeout ");
				} try {Thread.Sleep (socket_open_retry_millis);
				} catch (Interruptedexception er) {} retrycount++;
			Continue
 			} retrycount = 0;
			Msocket = s;
			... int length = 0;
				try {InputStream is = Msocket.getinputstream (); for (;;)
					{Parcel p;
					Length = Readrilmessage (is, buffer);
					if (length < 0) {//End-of-stream reached break;
					} p = Parcel.obtain ();
					P.unmarshall (buffer, 0, length);
					P.setdataposition (0);
					RLOG.V (Rilj_log_tag, "Read packet:" + length +//"bytes");
					ProcessResponse (P);
				P.recycle ();
			}} catch (Java.io.IOException ex) {rlog.i (Rilj_log_tag, "'" + rilsocket + "' socket closed", ex); } catch (Throwable tr) {RLOG.E (rilj_log_tAG, "uncaught exception read Length=" + length + "Exception:" + tr.tostring ());
			} rlog.i (Rilj_log_tag, "(" + Minstanceid + ") disconnected from ' + rilsocket + ' socket ');

			Setradiostate (radiostate.radio_unavailable);
			try {msocket.close ();
			} catch (IOException ex) {} msocket = null;

					Rilrequest.resetserial ();
				Clear request list on close Clearrequestlist (radio_not_available, false);
			}} catch (Throwable tr) {RLOG.E (Rilj_log_tag, "uncaught exception", TR);
		}/* we ' re disconnected so we don ' t know the RIL version */notifyregistrantsrilconnectionchanged (-1); }
	}
The Rilreceiver class is an interface that implements the Runnable, and its run method is primarily a new dead loop

1) Create a new Localsocket and Localsocketaddress object in the dead loop and establish the link, then assign the Localsocket object to the global object Msocket

2) Create a new Dead loop, the dead loop continuously reads the message from the underlying RIL, and then calls the ProcessResponse method to process the RIL message until it completely finishes, releases the socket, and notifies rilconnection of the status change

So, in Ril, how to deal with the RIL message of the underlying RIL delivery.

private void ProcessResponse (Parcel p) {
    int type;

    Type = P.readint ();

    if (type = = response_unsolicited) {
        processunsolicited (p);
    } else if (type = = response_solicited) {
        Rilreque St RR = processsolicited (p);
        if (RR! = null) {
            rr.release ();
            Decrementwakelock ();}}}
If the request is answered, the Processsolicited method is called, and conversely, the Processunsoliciterd method is called

private void processunsolicited (Parcel p) {
    ...
}
Private Rilrequest processsolicited (Parcel p) {
    ...
}
For different requests, the processing

When we see this Ril.java file, we find that there is a Rilrequest class in its file, what is the function of this class? First look at the methods in this class

/** * Retrieves a new Rilrequest instance from the pool.  * * @param request ril_request_* * @param result sent when operation completes * @return a rilrequest instance from the
 Pool.

    */static Rilrequest obtain (int request, Message result) {Rilrequest rr = null;
            Synchronized (Spoolsync) {if (SPool! = null) {rr = SPool;
            SPool = Rr.mnext;
            Rr.mnext = null;
        spoolsize--;
    }} if (rr = = null) {rr = new rilrequest ();

    } rr.mserial = Snextserial.getandincrement ();
    Rr.mrequest = Request;
    Rr.mresult = result;

    Rr.mparcel = Parcel.obtain (); if (result = null && result.gettarget () = = null) {throw new NullPointerException ("Message Target must no
    t be null ");
    }//First elements in any RIL Parcel rr.mParcel.writeInt (Request);

    Rr.mParcel.writeInt (rr.mserial);
return RR; }
In this way, from the code, you first create a Rilrequest object that holds the incoming request object and the result object, and then writes the request and its own mserial to the Mparcel object

For the release method, etc., do not do other analysis here, you can see

In other places, we often see the need to invoke a large number of methods to fetch data from the Ril object, so we will only confirm what the process is, as follows:

@Override public
void getvoiceradiotechnology (Message result) {
    rilrequest rr = Rilrequest.obtain (ril_request _voice_radio_tech, result);

    if (RILJ_LOGD) Riljlog (rr.serialstring () + ">" + requesttostring (rr.mrequest));

    Send (RR);
}
We see that this place called the Rilrequest obtain method, creating a Rilrequest object, from the above analysis we know that this will set the Mrequest parameter of the object to Ril_request_voice_radio_tech, Instead, the Mresult object is set to the result message object, and then a new Mparcel object is created

Next enter the Send method for the Ril class

private void Send (Rilrequest rr) {
    Message msg;

    if (Msocket = = null) {
        rr.onerror (radio_not_available, null);
        Rr.release ();
        return;
    }

    msg = Msender.obtainmessage (event_send, RR);

    Acquirewakelock ();

    Msg.sendtotarget ();
}
Msender from the previous article, we know this is Rilsender object, this object inherits handler, and implements Runnable, so its essence is handler, then call Msg Sendtotarget method, That is, the Handlemessage method of the Msender object is called, and the What for MSG is the Event_send,obj parameter for the newly created Rilrequest object

The Handlemessage method of Rilsender is for the processing of event_send

@Override public void Handlemessage (Message msg) {Rilrequest rr = (rilrequest) (msg.obj);

    Rilrequest req = null;
                Switch (msg.what) {case Event_send:try {localsocket s;
                s = msocket; ... synchronized (mrequestlist) {//Leo, write  mrequestlist.
                Append (rr.mserial, RR);

                } byte[] data;
                data = Rr.mParcel.marshall ();
                Rr.mParcel.recycle ();

                Rr.mparcel = null;
                ...//parcel length in big endian datalength[0] = datalength[1] = 0;
                DATALENGTH[2] = (byte) ((Data.length >> 8) & 0xff);

                DATALENGTH[3] = (byte) ((data.length) & 0xff);
                .... S.getoutputstream (). write (datalength);
            S.getoutputstream (). write (data); } catch (IoexCeption ex) {...} catch (RuntimeException exc) {...}
            Break
......
    } }
Create a new Localsocket object, and point to Msocket,msocket we analyzed earlier, in the rilrequest inner class to bind and send, then who receives it. Nature is in the Rilreceiver run method, remember it is a dead cycle, constantly go to Ril command. It calls the ProcessResponse method, and the final call is the Processsolicited method

Private Rilrequest processsolicited (Parcel p) {
	int serial, error;
	Boolean found = false;

	serial = P.readint ();
	Error = P.readint ();

	Rilrequest RR;

	rr = Findandremoverequestfromlist (serial);

	if (rr = = null) {
		...
		return null;
	}

	Object ret = null;

	if (Error = = 0 | | p.dataavail () > 0) {
		//either command succeeds or command fails but with data payload
		try {
			switch (rr.mrequest) {
			...
			Case Ril_request_voice_radio_tech:
				ret = responseints (p);
				break;
			......
		} catch (Throwable tr) {
			...
		}
	}
	......
	return RR;
}
The Findandremoverequestfromlist method takes the rr.mserial corresponding rilrequest from Mrequestlist, which is added at the rilsender message of the Event_send object.

Then gets its Mrequest object, which we know is Ril_request_voice_radio_tech, so call responseints to process

Private Object responseints (Parcel p) {
    int numints;
    int response[];

    Numints = P.readint ();

    Response = new Int[numints];

    for (int i = 0; i < numints; i++) {
        Response[i] = P.readint ();
    }

    return response;
}
At this point, the Ril class in the SIM card start-up process, the general purpose, has been analyzed to complete, to follow the start-up process encountered in the specific problems, and then in the specific method of analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.