短彩信接收流程和来电流程有点类似,最开始也是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
在dispatchMessage调用子类的 dispatchMessageRadioSpecificvoid 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); } }
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层的处理,下面是自己分析时画的时序图: