Android Mms專題之:Android短彩信收發流程(Framework)

短信部分:
短信的發送,Framework部分從SmsManager的sendTextMessage(普通短信,無分段)與sendMultipartTextMessage(長短信,已分段)開始,一直到RIL。主要涉及到的類有。SmsManager、Isms、IccSmsInterfaceManager、SMSDispatcher、ImsSMSDispatcher、GsmSMSDispatcher、CdmaSMSDispatcher、SmsMessage、SmsTracker、CommandsInterface、BaseCommands、RIL、LocalSocket、RilRequest、Parcel等。

\

SmsManager->RIL:
sendTextMessage和sendMultipartTextMessage的過程其實差很少,無非是sendMultipartTextMessage對長短信進行了一下處理,爲每個part設置了SmsHeader。ImsSMSDispatcher中包含了兩種不一樣的SmsDispatcher,IccSmsInterfaceManager調用SmsDispatcher中各個方法時,會根據手機類型的不一樣,調用不一樣SmsDispatcher的相應方法。大體過程爲:一、計算編碼方式;二、對每個分段構造SmsHeader、SubmitPdu、SmsTracker,並設置RadioTechnologyFamily;三、利用SmsTracker構造當消息正常發送後調用的Message對象;四、調用與手機卡類型有關的RIL中的相應方法發送。

\

RIL中發送:
sendImsGsmSms、sendSms、sendCdmaSms、sendImsCdmaSms這四個方法基本流程是大體相同的,都是先構造RILRequest,再調用send方法發送。區別就在於不一樣的方法在得到RILRequest時傳入的請求類型不一樣,構造出來的pdu結構不一樣,以及兩個Ims方法須要先往RILRequest中寫入一個數字。

\

發送後的處理:
已發送狀態修改(sentIntent的調用過程)RILReceiver->SMSDispatcher:
在RIL的構造方法中,建立了一個RILReceiver對象,該對象實現了Runnable接口。它的做用是不停地從下層獲取數據,分析類型,轉到相應SMSDispatcher處理。
當短信經過LocalSocket發送出去後,因爲是主動請求,下層會傳上來一個響應,其基本類型爲RESPONSE_SOLICITED,轉入processSolicited處理。在該方法中,對於短信發送的處理,均調用responseSMS方法獲取SmsResponse對象。(前面四種方式對應的事件類型爲sendSMS-RIL_REQUEST_SEND_SMS、 sendCdmaSms-RIL_REQUEST_CDMA_SEND_SMS、sendImsGsmSms&sendImsCdmaSms-RIL_REQUEST_IMS_SEND_SMS)
而後建立AsyncResult對象,將SmsResponse對象與SmsTracker對象(SMSRequest中的)傳入,更新以前在各個SMSDispatcher中建立的消息正常發送後調用的Message中的obj,設爲建立的AsyncResult對象。將消息發送至相應SmsDispatcher處理。

\

已發送狀態修改(sentIntent的調用過程)SMSDispatcher.handleMessage:
因爲以前在構造Message對象時設置了what爲SEND_SMS_COMPLETE,所以,此處調用handleSendComplete方法進行短信發送的後續處理。若須要發送報告,將SmsTracker加入deliveryPendingList中,這樣後面收到發送報告時,可以從該列表中取出進行處理(具體參見應用層部分發送報告的處理)。

\

deliveryIntent(發送報告)RIL->SMSDispatcher:
對於GSM,在構造方法中,將GsmSMSDispatcher註冊爲RIL接收到發送報告時該事件的接收者,並設置消息類型爲EVENT_NEW_SMS_STATUS_REPORT,相應的Registrant類爲mSmsStatusRegistrant。
而對於CDMA,則設置消息類型爲EVENT_NEW_SMS,相應的Registrant類爲mCdmaSMSRegistrant。
當RIL收到底層傳來的發送報告後(過程與已發送狀態修改相同),會產生一個基本類型爲RESPONSE_UNSOLICITED,轉入processUnsolicited處理。
對於GSM,其事件類型爲RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT。先調用responseString從Parcel中獲取數據,再調用mSmsStatusRegistrant的notifyRegistrant方法設置消息類型(what屬性爲EVENT_NEW_SMS_STATUS_REPORT)並轉到SMSDispatcher進行處理。
而CDMA,事件類型爲RIL_UNSOL_RESPONSE_CDMA_NEW_SMS。處理過程與GSM大體相同,只是從Parcel中獲取數據是調用responseCdmaSms方法獲取SmsMessage對象。而後調用mCdmaSMSRegistrant的notifyRegistrant方法設置消息類型(what屬性爲EVENT_NEW_SMS)並轉到SMSDispatcher進行處理。
deliveryIntent(發送報告)SMSDispatcher:
對於GSM,直接調用handleStatusReport方法處理。從傳入的AsyncResult對象中獲取SmsMessage進而獲取SmsTracker的索引,從deliveryPendingList中取出SmsTracker,發送deliveryIntent併發送消息確認。
對於CDMA,在handleMessage中轉到EVENT_NEW_SMS。調用dispatchMessage進行消息的分發。

\

短信接收RIL->SMSDispatcher:
GSM,在構造方法中,將GsmSMSDispatcher註冊爲RIL接收短信時該事件的接收者,並設置消息類型爲EVENT_NEW_SMS,相應的Registrant類爲mSMSRegistrant。
CDMA,與發送報告相同,消息類型爲EVENT_NEW_SMS,相應的Registrant類爲mCdmaSMSRegistrant。
RILReceiver接收到短信後,會轉到processUnsolicited進行處理。
對於GSM,其事件類型爲RIL_UNSOL_RESPONSE_NEW_SMS。先調用responseString從Parcel中獲取數據,再使用newFromCMT方法獲取SmsMessage對象,最後調用mSMSRegistrant的notifyRegistrant方法設置消息類型(what屬性爲EVENT_NEW_SMS)並轉到SMSDispatcher進行處理。
而CDMA,事件類型爲RIL_UNSOL_RESPONSE_CDMA_NEW_SMS。過程與接收報告相同。
短信接收SMSDispatcher:
GSM,首先獲取SmsHeader。
若是SmsHeader或SmsHeader.concatRef均不爲空,說明是長短信,則調用processMessagePart將短信分段存入raw表,待全部分段都收到後,將其組裝。而後根據端口的不一樣,按照彩信通知(WapPushOverSms的dispatchWapPdu方法)、指定端口的彩信(dispatchPortAddressedPdus)、長短信(dispatchPdus)進行分發處理。
若SmsHeader或SmsHeader.concatRef有一個爲空,說明不是長短信。而後根據端口的不一樣,按照彩信通知(WapPushOverSms的dispatchWapPdu方法)、指定端口的彩信(dispatchPortAddressedPdus)、普通短信(dispatchPdus)進行分發處理。
GSM和CDMA的短信接收有很大一部分是相同的,只是CDMA因爲標準定義的不一樣,須要進行一些其餘的處理。
CDMA沒有相似GSM中的User Data Header(UDA)來存儲一些額外信息,而是使用一個16位整數CDMA TELESERVICE來肯定消息的類型。
若是其爲TELESERVICE_WAP,說明是CDMA彩信通知,則調用processCdmaWapPdu來處理。該方法的做用是將接收到的分段數據先存入raw表。只有當全部分段都接收到後,若是端口是WAP_PUSH的彩信,才調用WapPushOverSms的dispatchWapPdu方法將彩信通知內容解碼後經過廣播發送到應用層。不然,調用dispatchPortAddressedPdus方法將其發送到指定端口(sms://localhost:port)。
另外,CDMA中提供了一種cmas消息。若是是這種消息,當收到時,當即調用dispatchBroadcastPdus方法發送緊急廣播。

\

彩信接收:
在Android中,彩信的接收分爲兩部分。彩信通知經過短信的方式接收,如上文所述。彩信數據的下載在應用層中處理。 併發


做者 haliluya4 編碼

相關文章
相關標籤/搜索