Short MMS receiving process and the call process is a bit similar, the beginning is also the RIL layer to report SMS events, and then the upper layer to handle the process of receiving text messages. Android Ril is located between the application framework and the kernel, divided into two parts, one part is the rild, it is responsible for the socket and the application framework to communicate. Another part is the vendor RIL, which is responsible for the downward is in two ways to communicate with the radio, they are direct communication with the radio at instruction Channel and the transmission packet data channel, the data channel for the mobile phone's internet function, Where Ril.java is primarily used for hardware layer and framework communication. Through socket communication in Ril.java, receive events escalated from hardware layer, localsocket communication in Ril.java's inner class rilreceiver, get escalation events, processresponse process receive or send SMS
Class Rilreceiver implements Runnable {byte[] buffer; Rilreceiver () {buffer = new byte[ril_max_command_bytes]; } @Override public void Run () {int retrycount = 0; String rilsocket = "Rild"; try {for (;;) {Localsocket s = null; Localsocketaddress l; ... try {s = new localsocket (); L = new Localsocketaddress (Rilsocket, LocalSocketAddress.Namespace.RESERVED); S.connect (l); } catch (IOException ex) {...} 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 CL Osed ", ex); } ... } }
In ProcessResponse, depending on the type of types to determine whether to accept short MMS or send short MMS,processunsolicited processing acceptance process, processsolicited processing the sending process
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 ();}}}
Processunsolicited will process the escalated ril_unsol_response_new_sms event, and in Gsminboundsmshandler.java, register the Ril_unsol_ Response_new_sms event Monitoring, when Mgsmsmsregistrant.notifyregistrant is called, the system notifies Gsminboundsmshandler to process event_new_sms events
processunsolicited (Parcel p) {int response; Object ret; Response = P.readint (); try {switch (response) {... case ril_unsol_response_new_sms:ret = responsestring (p); ... }} catch (Throwable tr) {RLOG.E (Rilj_log_tag, "Exception processing Unsol Response:" + response + "Exception:" + tr.tostring ()); Return } switch (response) {... case ril_unsol_response_new_sms: {if (RILJ_LOGD) uns Ljlog (response); Fixme This should move up a layer String a[] = new STRING[2]; A[1] = (String) ret; Smsmessage SMS; SMS = SMSMESSAGE.NEWFROMCMT (a); if (mgsmsmsregistrant! = null) {mgsmsmsregistrant. notifyregistrant (New Asyncre Sult (NULL, SMS, NULL)); } break; }... } }
Gsminboundsmshandler registered listening for events, handling event_new_sms events in their parent class Inboundsmshandler.java
@Override public boolean ProcessMessage (Message msg) {log ("Deliveringstate.processmessage:" + M Sg.what); Switch (msg.what) {case event_new_sms//handle NEW SMS from RIL Han Dlenewsms ((AsyncResult) msg.obj); SendMessage (Event_return_to_idle); return HANDLED; Case EVENT_INJECT_SMS://Handle New injected SMS handleinjectsms ((AsyncResult) Msg. OBJ); SendMessage (Event_return_to_idle); return HANDLED; Case EVENT_BROADCAST_SMS://If any broadcasts were sent, transition to waiting state if (Processmessagepart ((inboundsmstracker) msg.obj)) {Transitionto (mwaitingstate); } return HANDLED; Case Event_return_to_idle://RETURN to IDLE After processing all other messages Transitionto (midlestate); return HANDLED; Case EVENT_RELEASE_WAKELOCK:mWakeLock.release (); Decrement Wakelock from previous entry to Idle if (!mwakelock.isheld ()) {// Wakelock should still is held until 3 seconds after we enter the Idle Loge ("Mwakelock released while de Livering/broadcasting! ");} return HANDLED; We shouldn ' t get this message of type in this state, log error and halt. Case Event_broadcast_complete:case Event_start_accepting_sms:default:/ /Let Defaultstate handle these unexpected message types return not_handled; } } }
When a event_new_sms event is received from the RIL layer, the
handlenewsms, which is called in Handlenewsms.
DispatchMessage
void Handlenewsms (AsyncResult ar) { if (ar.exception! = null) { Loge ("Exception processing incoming SMS:" + ar.ex ception); return; } int result; try { Smsmessage SMS = (smsmessage) ar.result; result = DispatchMessage (sms.mwrappedsmsmessage); } catch (RuntimeException ex) { Loge ("Exception dispatching Message", ex); result = Intents.result_sms_generic_error; } Result_ok means that the SMS would be acknowledged by special handling, //e.g. for sms-pp data download. Any and result, we should ack here. if (result = = Activity.result_ok) { Boolean handled = (result = = intents.result_sms_handled); Notifyandacknowledgelastincomingsms (handled, result, null); } }
in the DispatchMessage Calling subclasses of dispatchmessageradiospecific
Frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/gsminboundsmshandler.java @Override protected int dispatchmessageradiospecific (Smsmessagebase smsb) {smsmessage SMS = (smsmessage) SMSB; if (Sms.istypezero ()) {//as per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be//DISPLA Yed/stored/notified. They should only be acknowledged. Log ("Received short message type 0, Don ' t display or store it. Send Ack "); return intents.result_sms_handled; }//Send sms-pp data download messages to UICC. See 3GPP TS 31.111 section 7.1.1. if (Sms.isusimdatadownload ()) {usimservicetable ust = mphone.getusimservicetable (); Return Mdatadownloadhandler.handleusimdatadownload (UST, SMS); } Boolean handled = FALSE; if (Sms.ismwisetmessage ()) {Updatemessagewaitingindicator (Sms.getnumofvoicemails ()); handled = Sms.ismwidontstore (); if (DBG) log ("Received voice mail indicator set SMS shouldstore=" +!handled); } else if (Sms.ismwiclearmessage ()) {updatemessagewaitingindicator (0); handled = Sms.ismwidontstore (); if (DBG) log ("Received voice mail indicator clear SMS shouldstore=" +!handled); } if (handled) {return intents.result_sms_handled; } if (!mstoragemonitor.isstorageavailable () && sms.getmessageclass ()! = Smsconstants.message CLASS.CLASS_0) {//It ' s a storable message and there ' s no storage available. Bail. (See TS 23.038 for a description of Class 0 messages.) return intents.result_sms_out_of_memory; } return Dispatchnormalmessage (SMSB); }
The
Then calls the dispatchnormalmessage
protected int dispatchnormalmessage (smsmessagebase sms) {smsheader Smsheader = Sms.getuserdataheader (); Inboundsmstracker Tracker; if ((Smsheader = = null) | | (Smsheader.concatref = = null)) {//Message is not concatenated. int destport =-1; if (Smsheader! = NULL && Smsheader.portaddrs! = null) {//The message is sent to a port. Destport = SmsHeader.portAddrs.destPort; if (DBG) log ("Destination port:" + destport); } tracker = new Inboundsmstracker (SMS.GETPDU (), Sms.gettimestampmillis (), Destport, IS3GPP2 ( ), false); } else {//Create a tracker for this message segment. Smsheader.concatref concatref = smsheader.concatref; Smsheader.portaddrs Portaddrs = Smsheader.portaddrs; int destport = (Portaddrs! = null? Portaddrs.destport:-1); Tracker = new Inboundsmstracker (sms.geTPdu (), Sms.gettimestampmillis (), Destport, Is3gpp2 (), sms.getoriginatingaddress (), Concatref.refnumber , Concatref.seqnumber, Concatref.msgcount, false); } if (vdbg) log ("Created tracker:" + tracker); Return Addtrackertorawtableandsendmessage (tracker); }
send addtrackertorawtableandsendmessage Style= "Background-color:rgb (255,255,51)" >event_broadcast_sms , Processmessag response to this event call Processmessagepart handling SMS or MMS messages separately
Boolean Processmessagepart (Inboundsmstracker tracker) {int messagecount = Tracker.getmessagecount (); Byte[][] PDUs; int destport = Tracker.getdestport (); ... Smsbroadcastreceiver resultreceiver = new Smsbroadcastreceiver (tracker); if (Destport = = Smsheader.port_wap_push) {//Build up the data stream Bytearrayoutputstream output = new Bytearrayoutputstream (); For (byte[] pdu:pdus) {//3GPP needs to extract the User Data from the PDU; 3GPP2 have already done this if (!TRACKER.IS3GPP2 ()) {smsmessage msg = SMSMESSAGE.CREATEFROMPDU (PDU, Smsconstants.fo RMAT_3GPP); PDU = Msg.getuserdata (); } output.write (PDU, 0, pdu.length); } int result = MWAPPUSH.DISPATCHWAPPDU (Output.tobytearray (), resultreceiver, this); if (DBG) log ("DISPATCHWAPPDU () returned" + result); Result is ACtivity. RESULT_OK If an ordered broadcast is sent return (result = = ACTIVITY.RESULT_OK); } list<string> carrierpackages = null; Uicccard card = Uicccontroller.getinstance (). Getuicccard (Mphone.getphoneid ()); if (card! = null) {carrierpackages = Card.getcarrierpackagenamesforintent (mcontext.getpack Agemanager (), New Intent (Carriermessagingservice.service_interface)); } else {Loge ("Uicccard not initialized."); } list<string> systempackages = getsystemappforintent (New Intent (Carriermessagingservice.servi Ce_interface)); if (carrierpackages! = null && carrierpackages.size () = = 1) {log ("Found carrier package."); Carriersmsfilter smsfilter = new Carriersmsfilter (PDUs, Destport, Tracker.getformat (), Resultreceiver ); Carriersmsfiltercallback smsfiltercallback = new CarriersmsfilterCallback (Smsfilter); Smsfilter.filtersms (carrierpackages.get (0), smsfiltercallback); } else if (systempackages! = null && systempackages.size () = = 1) {log ("Found System Package."); Carriersmsfilter smsfilter = new Carriersmsfilter (PDUs, Destport, Tracker.getformat (), resultrece Iver); Carriersmsfiltercallback smsfiltercallback = new Carriersmsfiltercallback (smsfilter); Smsfilter.filtersms (systempackages.get (0), smsfiltercallback); } else {LOGV ("Unable to find carrier package:" + carrierpackages + ", nor systempackages: "+ systempackages); Dispatchsmsdeliveryintent (PDUs, Tracker.getformat (), Destport, resultreceiver); } return true; }
In the method above, call Wappushoversms.java's DISPATCHWAPPDU to process MMS messages and continue to invoke Dispatchsmsdeliveryintent Handling SMS
Frameworks/opt/telephony/src/java/com/android/internal/telephony/wappushoversms.java public int DispatchWapPdu ( Byte[] PDU, broadcastreceiver receiver, Inboundsmshandler handler) {if (DBG) rlog.d (TAG, "Rx:" + iccutils.bytesto HexString (PDU)); ...//Direct the intent to only the default MMS app. If we can ' t find a default MMS app//then sent it to all broadcast receivers. ComponentName componentname = Smsapplication.getdefaultmmsapplication (Mcontext, true); if (componentname! = null) {//deliver MMS message only to this receiver Intent.setcomponen T (componentname); if (DBG) rlog.v (TAG, "Delivering MMS to:" + componentname.getpackagename () + "" + componentname.g Etclassname ()); } handler.dispatchintent (Intent, permission, Appop, receiver, Userhandle.owner); return ACTIVITY.RESULT_OK; } catch (ArrayindexoutofboundseXception AIE) {//0-byte WAP PDU or other unexpected WAP PDUs contents can easily throw this; Log exception string without stack trace and return false. RLOG.E (TAG, "ignoring DISPATCHWAPPDU () array index exception:" + AIE); return intents.result_sms_generic_error; } }
In
wappushoversmsDISPATCHWAPPDU will get the default MMS app, giving MMS to the application layer's Pushreceiver.java processing logic to resolve PDUs and download MMS messages. If it is a text message, will be processed in the dispatchsmsdeliveryintent, the same is the first to get the default MMS app, and then passed through intent to the upper text messaging application
Privilegedsmsreceiver. Java handles the display of text messages and the insertion of databases, among other things
Frameworks/opt/telephony/src/java/com/android/internal/telephony/inboundsmshandler.java void Dispatchsmsdeliveryintent (byte[][] PDUs, String format, int destport, Broadcastreceiver resultreceiver) { Intent Intent = new Intent (); Intent.putextra ("PDUs", PDUs); Intent.putextra ("format", format); if (Destport = =-1) {intent.setaction (intents.sms_deliver_action); Direct the intent to the default SMS app. If we can ' t find a default SMS app//then sent it to all broadcast receivers. We are deliberately delivering to the primary user ' s default SMS App. ComponentName componentname = Smsapplication.getdefaultsmsapplication (Mcontext, true); if (componentname! = null) {//deliver SMS message only to this receiver. Intent.setcomponent (componentname); Log ("Delivering SMS to:" + componentname.getpackagename () + "" + Componentname.getclassname ()); } else {intent.setcomponent (null); }//Todo:validate that's the right place to store the SMS. if (Smsmanager.getdefault (). getautopersisting ()) {final URI uri = writeinboxmessage (Intent); if (uri! = null) {//Pass this to SMS apps so, they know where it is stored Intent.putextra ("uri", Uri.tostring ()); }}}} else {intent.setaction (intents.data_sms_received_action); Uri uri = Uri.parse ("sms://localhost:" + destport); Intent.setdata (URI); Intent.setcomponent (NULL); } dispatchintent (Intent, Android. Manifest.permission.RECEIVE_SMS, Appopsmanager.op_receive_sms, Resultreceiver, Userhandle.owner); }
Simple recording of the next short MMS to accept the processing of the framework layer, the following is the timing diagram of their own analysis:
Android 5.0 Lollipop Short MMS receive process