短彩信接收流程和来电流程有点类似,最开始也是RIL层上报短信事件,然后上层来处理接收短信的流程。android的ril位于应用程序框架与内核之间,分成了两个部分,一个部分是rild,它负责socket与应用程序框架进行通信。另外一个部分是Vendor RIL,这个部分负责向下是通过两种方式与radio进行通信,它们是直接与radio通信的AT指令通道和用于传输包数据的通道,数据通道用于手机的上网功能,其中RIL.java主要用于hardware层和framework通信。在RIL.java中通过socket通信,接收来自hardware层上报的事件,在RIL.java的内部类RILReceiver中通过LocalSocket通信,获取上报事件,在processResponse处理接收或发送短信
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 closed", ex); } ... } }
在processResponse中会根据type的类型来判断是接受短彩信还是发送短彩信,processUnsolicited处理接受流程,processSolicited处理发送流程
processResponse (Parcel p) { int type; type = p.readInt(); if (type == RESPONSE_UNSOLICITED) { processUnsolicited (p); } else if (type == RESPONSE_SOLICITED) { RILRequest rr = processSolicited (p); if (rr != null) { rr.release(); decrementWakeLock(); } } }
processUnsolicited会处理上报的RIL_UNSOL_RESPONSE_NEW_SMS事件,在GsmInboundSmsHandler.java中,注册了RIL_UNSOL_RESPONSE_NEW_SMS事件的监听,当调用mGsmSmsRegistrant.notifyRegistrant时,系统会通知GsmInboundSmsHandler处理EVENT_NEW_SMS事件
processUnsolicited (Parcel p) { int response; Object ret; response = p.readInt(); try {switch(response) { ... case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break; ... }} 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) 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; } ... } }
GsmInboundSmsHandler在构造方法中注册了EVENT_NEW_SMS事件的监听,在其父类InboundSmsHandler.java中处理EVENT_NEW_SMS事件
@Override public boolean processMessage(Message msg) { log("DeliveringState.processMessage:" + msg.what); switch (msg.what) { case EVENT_NEW_SMS // handle new SMS from RIL handleNewSms((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 be held until 3 seconds after we enter Idle loge("mWakeLock released while delivering/broadcasting!"); } return HANDLED; // we shouldn't get this message 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; } } }当接收到RIL层的EVENT_NEW_SMS事件,会调用 handleNewSms,在handleNewSms中会调用 dispatchMessage
void handleNewSms(AsyncResult ar) { if (ar.exception != null) { loge("Exception processing incoming SMS: " + ar.exception); 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 will be acknowledged by special handling, // e.g. for SMS-PP data download. Any other result, we should ack here. if (result != Activity.RESULT_OK) { boolean handled = (result == Intents.RESULT_SMS_HANDLED); notifyAndAcknowledgeLastIncomingSms(handled, result, null); } }在dispatchMessage调用子类的 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 // Displayed/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.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); }
然后在GsmInboundSmsHandler.java调用父类的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 was 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); }
在addTrackerToRawTableAndSendMessage中发送EVENT_BROADCAST_SMS,processMessag会响应到这个事件调用processMessagePart分开处理短信或彩信
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 has already done this if (!tracker.is3gpp2()) { SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_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 was sent return (result == Activity.RESULT_OK); } List<String> carrierPackages = null; UiccCard card = UiccController.getInstance().getUiccCard(mPhone.getPhoneId()); if (card != null) { carrierPackages = card.getCarrierPackageNamesForIntent( mContext.getPackageManager(), new Intent(CarrierMessagingService.SERVICE_INTERFACE)); } else { loge("UiccCard not initialized."); } List<String> systemPackages = getSystemAppForIntent(new Intent(CarrierMessagingService.SERVICE_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(), resultReceiver); 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; }
在上面这个方法中调用WapPushOverSms.java的dispatchWapPdu处理彩信,继续调用InboundSmsHandler.java中的dispatchSmsDeliveryIntent处理短信
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.bytesToHexString(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.setComponent(componentName); if (DBG) Rlog.v(TAG, "Delivering MMS to: " + componentName.getPackageName() + " " + componentName.getClassName()); } handler.dispatchIntent(intent, permission, appOp, receiver, UserHandle.OWNER); return Activity.RESULT_OK; } catch (ArrayIndexOutOfBoundsException aie) { // 0-byte WAP PDU or other unexpected WAP PDU 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; } }在 WapPushOverSms的dispatchWapPdu会获取默认的MMS app,把彩信交给应用层里的PushReceiver.java处理解析pdu和下载彩信的逻辑。如果是短信,会在dispatchSmsDeliveryIntent中处理,同样也是先获取默认的MMs app,然后通过intent传递到上层短信应用里的 PrivilegedSmsReceiver.java处理短信的显示和插入数据库等操作
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 only 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 this is 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 that 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); }
简单的记录了下短彩信接受framework层的处理,下面是自己分析时画的时序图: