Ps.基于4.1的源码进行分析。。。。
com.android.internal.telephony/Ril.java com.android.internal.telephony/SMSDispatcher com.android.internal.telephony/CommandsInterface com.android.internal.telephony/GsmSMSDispatcher hardware/ril/libril/ril.cpp
Ril.java中有内部类:RILReceiver,RILReceiver的run方法中不断的监听: InputStream is = mSocket.getInputStream();然后 readRilMessage(is, buffer);把消息存入buffer中,然后p.unmarshall(buffer, 0, length);打包成一个Parcel p;然后run方法到最后调用了processResponse(p);进行下一步处理。
class RILReceiver implements Runnable { byte[] buffer; RILReceiver() { buffer = new byte[RIL_MAX_COMMAND_BYTES]; } public void run() { int retryCount = 0; try {for (;;) { LocalSocket s = null; LocalSocketAddress l; try { s = new LocalSocket(); l = new LocalSocketAddress(SOCKET_NAME_RIL, 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 an error message after the the first time // or after the 8th time if (retryCount == 8) { Log.e (LOG_TAG, "Couldn't find '" + SOCKET_NAME_RIL + "' socket after " + retryCount + " times, continuing to retry silently"); } else if (retryCount > 0 && retryCount < 8) { Log.i (LOG_TAG, "Couldn't find '" + SOCKET_NAME_RIL + "' socket; retrying after timeout"); } try { Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); } catch (InterruptedException er) { } retryCount++; continue; } retryCount = 0; mSocket = s; Log.i(LOG_TAG, "Connected to '" + SOCKET_NAME_RIL + "' socket"); 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); //Log.v(LOG_TAG, "Read packet: " + length + " bytes"); processResponse(p); p.recycle(); } } catch (java.io.IOException ex) { Log.i(LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed", ex); } catch (Throwable tr) { Log.e(LOG_TAG, "Uncaught exception read length=" + length + "Exception:" + tr.toString()); } Log.i(LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL + "' socket"); setRadioState (RadioState.RADIO_UNAVAILABLE); try { mSocket.close(); } catch (IOException ex) { } mSocket = null; RILRequest.resetSerial(); // Clear request list on close clearRequestsList(RADIO_NOT_AVAILABLE, false); }} catch (Throwable tr) { Log.e(LOG_TAG,"Uncaught exception", tr); } /* We're disconnected so we don't know the ril version */ notifyRegistrantsRilConnectionChanged(-1); } }
processResponse(p)会根据类型选择调用 processUnsolicited (p)(无需请求直接上报);或是processSolicited (p)(需要先请求才可以);在短信接收过程中调用的是processUnsolicited (p);
processUnsolicited (p)方法会在switch语句中根据p中的类型进行不同的操作,接收短信 会在这个分支中操作case RIL_UNSOL_RESPONSE_NEW_SMS:
case RIL_UNSOL_RESPONSE_NEW_SMS: { if (RILJ_LOGD) unsljLog(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 AsyncResult(null, sms, null)); } break;把短消息进一步封装处理成一个SmsMessage类型的消息,然后mGsmSmsRegistrant这个是什么呢O O这是一个Registrant类型(消息注册机制:一个对象中开辟一个空间用于存放Message,当调用regist方法时将Message存放进去,当其调用notify方法时将所有Message取出并发送到MessageQueue中等待处理)暂时不太明白,我简单的理解就是把message发送给handler让handler去处理。
1:那么这个handler在哪里实现的呢??
答:在GsmSMSDispatcher.java(父类:SMSDispather.java)的handleMessage方法中实现。
2:这个handler是在哪里设置到呢。。。
答:在GsmSMSDispatcher.java的构造函数中调用了mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null);而mCm是在手机开机时调用的PhoneFactory调用makeDefaultPhone()方法创建的RIL实例的一个引用,RIL的父类BaseCommands.java(BaseCommands类实现CommandsInterface的部分接口,通知手机内部状态变化)中实现了
public void setOnNewGsmSms(Handler h, int what, Object obj) {
mGsmSmsRegistrant = new Registrant (h, what, obj);
//由此可知在GsmSMSDispatcher.java把handler设置成了自己
}
然后短消息就从RIL.java中通过SmsMessage的形式提交到了GsmSMSDispatcher.java与他的父类SMSDispather.java这两个进行短信进一步分发的类中的handleMessage方法中进行处理。
最开始的handleMessage处理是在SMSDispatcher.java中,直接上SMSDispatcher.java中handleMessage方法的代码:
/** * Handles events coming from the phone stack. Overridden from handler. * * @param msg the message to handle * */ @Override public void handleMessage(Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_NEW_SMS: // A new SMS has been received by the device if (false) { Log.d(TAG, "New SMS Message Received"); } SmsMessage sms; ar = (AsyncResult) msg.obj; if (ar.exception != null) { Log.e(TAG, "Exception processing incoming SMS. Exception:" + ar.exception); return; } sms = (SmsMessage) ar.result; try { int result = dispatchMessage(sms.mWrappedSmsMessage); if (result != Activity.RESULT_OK) { // RESULT_OK means that message was broadcast for app(s) to handle. // Any other result, we should ack here. boolean handled = (result == Intents.RESULT_SMS_HANDLED); notifyAndAcknowledgeLastIncomingSms(handled, result, null); } } catch (RuntimeException ex) { Log.e(TAG, "Exception dispatching message", ex); notifyAndAcknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null); } break; case EVENT_SEND_SMS_COMPLETE: // An outbound SMS has been successfully transferred, or failed. handleSendComplete((AsyncResult) msg.obj); break; case EVENT_SEND_RETRY: sendSms((SmsTracker) msg.obj); break; case EVENT_SEND_LIMIT_REACHED_CONFIRMATION: handleReachSentLimit((SmsTracker)(msg.obj)); break; case EVENT_SEND_CONFIRMED_SMS: { SmsTracker tracker = (SmsTracker) msg.obj; if (tracker.isMultipart()) { sendMultipartSms(tracker); } else { sendSms(tracker); } mPendingTrackerCount--; break; } case EVENT_STOP_SENDING: { SmsTracker tracker = (SmsTracker) msg.obj; if (tracker.mSentIntent != null) { try { tracker.mSentIntent.send(RESULT_ERROR_LIMIT_EXCEEDED); } catch (CanceledException ex) { Log.e(TAG, "failed to send RESULT_ERROR_LIMIT_EXCEEDED"); } } mPendingTrackerCount--; break; } } }
在case EVENT_NEW_SMS:分支语句中:调用下一步函数dispatchMessage(……)这个方法我们在SMSDispatcher.java中是一个抽象方法,我们很快就能发现真正的实现是在子类GsmSMSDispatcher.java中,接着上代码:
/** {@inheritDoc} */ @Override public int dispatchMessage(SmsMessageBase smsb) { // If sms is null, means there was a parsing error. if (smsb == null) { Log.e(TAG, "dispatchMessage: message is null"); return Intents.RESULT_SMS_GENERIC_ERROR; } SmsMessage sms = (SmsMessage) smsb; if (sms.isTypeZero()) { // As per 3GPP TS 23.040 9.2.3.9, Type Zero messages should not be // Displayed/Stored/Notified. They should only be acknowledged. Log.d(TAG, "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(); // If we receive an SMS-PP message before the UsimServiceTable has been loaded, // assume that the data download service is not present. This is very unlikely to // happen because the IMS connection will not be established until after the ISIM // records have been loaded, after the USIM service table has been loaded. if (ust != null && ust.isAvailable( UsimServiceTable.UsimService.DATA_DL_VIA_SMS_PP)) { Log.d(TAG, "Received SMS-PP data download, sending to UICC."); return mDataDownloadHandler.startDataDownload(sms); } else { Log.d(TAG, "DATA_DL_VIA_SMS_PP service not available, storing message to UICC."); String smsc = IccUtils.bytesToHexString( PhoneNumberUtils.networkPortionToCalledPartyBCDWithLength( sms.getServiceCenterAddress())); mCm.writeSmsToSim(SmsManager.STATUS_ON_ICC_UNREAD, smsc, IccUtils.bytesToHexString(sms.getPdu()), obtainMessage(EVENT_WRITE_SMS_COMPLETE)); return Activity.RESULT_OK; // acknowledge after response from write to USIM } } if (mSmsReceiveDisabled) { // Device doesn't support SMS service, Log.d(TAG, "Received short message on device which doesn't support " + "SMS service. Ignored."); return Intents.RESULT_SMS_HANDLED; } // Special case the message waiting indicator messages boolean handled = false; if (sms.isMWISetMessage()) { mPhone.setVoiceMessageWaiting(1, -1); // line 1: unknown number of msgs waiting handled = sms.isMwiDontStore(); if (false) { Log.d(TAG, "Received voice mail indicator set SMS shouldStore=" + !handled); } } else if (sms.isMWIClearMessage()) { mPhone.setVoiceMessageWaiting(1, 0); // line 1: no msgs waiting handled = sms.isMwiDontStore(); if (false) { Log.d(TAG, "Received voice mail indicator clear SMS shouldStore=" + !handled); } } if (handled) { return Intents.RESULT_SMS_HANDLED; } if (!mStorageMonitor.isStorageAvailable() && sms.getMessageClass() != MessageClass.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); }没有管他到底干了什么事情。大概就是判断是不是一条普普通通的短信而不是什么特别的短信。
总之最后又重新回到父类SMSDispatcher.java中调用了父类方法dispatchNormalMessage(smsb);上代码:
/** * Dispatch a normal incoming SMS. This is called from the format-specific * {@link #dispatchMessage(SmsMessageBase)} if no format-specific handling is required. * * @param sms * @return */ protected int dispatchNormalMessage(SmsMessageBase sms) { SmsHeader smsHeader = sms.getUserDataHeader(); // See if message is partial or port addressed. if ((smsHeader == null) || (smsHeader.concatRef == null)) { // Message is not partial (not part of concatenated sequence). byte[][] pdus = new byte[1][]; pdus[0] = sms.getPdu(); if (smsHeader != null && smsHeader.portAddrs != null) { if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) { // GSM-style WAP indication return mWapPush.dispatchWapPdu(sms.getUserData()); } else { // The message was sent to a port, so concoct a URI for it. dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort); } } else { // Normal short and non-port-addressed message, dispatch it. dispatchPdus(pdus); } return Activity.RESULT_OK; } else { // Process the message part. SmsHeader.ConcatRef concatRef = smsHeader.concatRef; SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs; return processMessagePart(sms.getPdu(), sms.getOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber, concatRef.msgCount, sms.getTimestampMillis(), (portAddrs != null ? portAddrs.destPort : -1), false); } }
然后提取了sms中的pdu部分,协议数据单元么??大概就是短信都是根据一定的协议规定而成的一个byte[],比如前几个byte代表什么什么的。。。maybe是这样子。。
总之接着调用dispatchPdus(pdus); // Normal short and non-port-addressed message, dispatch it。
分发这个pdu(就是短信)接着上dispatchPdus方法的代码(也在父类SMSDispatcher.java中)
protected void dispatchPdus(byte[][] pdus) { Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION); intent.putExtra("pdus", pdus); intent.putExtra("format", getFormat()); dispatch(intent, RECEIVE_SMS_PERMISSION); }
接着上dispatch(intent, RECEIVE_SMS_PERMISSION)方法的代码(也在父类SMSDispatcher.java中)
public void dispatch(Intent intent, String permission) { // Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any // receivers time to take their own wake locks. mWakeLock.acquire(WAKE_LOCK_TIMEOUT); mContext.sendOrderedBroadcast(intent, permission, mResultReceiver, this, Activity.RESULT_OK, null, null); }
Ps. 4.4之后的版本这里的广播有所区别,好像变成无序广播了。。总之,4.4以前短信广播可以被高优先级的应用截断,然而4.4以后短信广播是不能截断的了。。。而且4.4以后除了默认短信应用都无法享受短信数据库的更新,删除,插入操作。