Android短信接收过程源码分析(原)
2013-10-14 10:53
483 查看
本文主要讨论RILJ接收到一条普通短消息时是如何把它转换成Broadcast发送到系统中的。
而GSMPhone又是Framework中与RIL层沟通的对象,因此我们从GSMPhone开始入手分析。
上面看到,在GSMPhone的构造函数中,创建了GsmSMSDispatcher对象,这个对象是干什么用的呢?
其实在对SMS的处理上,不同的制式也有不同的处理方法,与Phone对象类似,SMS同样抽象出来了一个SMSDispatcher类,他把各个制式对于SMS的处理中相同的部分抽象出来,而对于制式中不同的部分派生出了GsmSMSDispatcher子类和CdmaSMSDispatcher子类。
而我们主要关注GsmSMSDispatcher子类:
从上面可以看到,GsmSMSDispatcher的作用主要检测三种短消息事件。而上面的mCm是在其父类SMSDispatcher中进行初始化的:
因此,在GsmSMSDispatcher构造函数中通过mCM.setOnNewGsmSms注册的监听器其实调用的是RILJ中的方法,而这个方法其实存在RILJ的父类BaseCommands中:
上面的过程,简单来说就是,在GSMPhone的构造函数中,创建了GsmSMSDispatcher的对象用于接收短消息,而GsmSMSDispatcher的初始化过程就是通过GSMPhone对象找到了RILJ(的父类),并把自己所关注的三种RIL层消息注册给RILJ,等待RILJ接收到短信时通知GsmSMSDispatcher。
我们在《Framework层中的RIL》一文中分析过,在RILJ中有两个独立的线程,一个用于向RILC发送数据(RILSender),一个用于接收RILC层上报的数据(RILReceiver)。当有新消息来时,一定会通过RILReceiver发送数据,而他又是通过processResponse处理数据的:
我们继续看notifyRegistrant的过程:
看来,RILJ对注册客户端的通知是通过sendMessage的方式实现的。
上面分析到了sendMessage,还记得当初是GsmSMSDispatcher通过GSMPhone找到了RILJ,并为自己注册了三种关于SMS的监听。
当前既然有了新的消息,RILJ通过sendMessage的方式发送的Message就会发送给GsmSMSDispatcher,而这个通知是在GsmSMSDispatcher的父类SMSDispatcher中被处理的:
继续看dispatchMessage的过程,这个过程又进入到了子类GsmSMSDispatcher中处理:
上面对一些特殊条件进行处理,比如设备不支持短消息,或者接收到的消息是语音信箱提示、设备存储空间不足等,然后就进入普通消息的处理流程,而这个处理过程又进入了父类中:
这里看到,对于普通短消息,是通过dispatchPdus()接口分发出去的:
继续往下看:
由此,Framework就通过SMSDispatcher将短消息用Broadcast的形式发送到了系统中。
一、GsmSMSDispatcher注册监听过程
在《Framework层中的RIL》一文中我们介绍过,Framework与应用层中的Phone对象其实就是用GSMPhone对象生成的PhoneProxy对象(CDMA制式不谈)。可以简单的理解为Phone就是GSMPhone对象。而GSMPhone又是Framework中与RIL层沟通的对象,因此我们从GSMPhone开始入手分析。
@GSMPhone.java public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) { //调用父类PhoneBase的构造函数,在内部实现一下赋值:phone.mCM=ci=RILJ super(notifier, context, ci, unitTestMode); //初始化GsmSMSDispatcher,用于派发短消息 mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor); }
上面看到,在GSMPhone的构造函数中,创建了GsmSMSDispatcher对象,这个对象是干什么用的呢?
其实在对SMS的处理上,不同的制式也有不同的处理方法,与Phone对象类似,SMS同样抽象出来了一个SMSDispatcher类,他把各个制式对于SMS的处理中相同的部分抽象出来,而对于制式中不同的部分派生出了GsmSMSDispatcher子类和CdmaSMSDispatcher子类。
而我们主要关注GsmSMSDispatcher子类:
@GsmSMSDispatcher.java public GsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, SmsUsageMonitor usageMonitor) { super(phone, storageMonitor, usageMonitor); mDataDownloadHandler = new UsimDataDownloadHandler(mCm); //监测3个与SMS有关的状态 mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null); mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); mCm.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null); }
从上面可以看到,GsmSMSDispatcher的作用主要检测三种短消息事件。而上面的mCm是在其父类SMSDispatcher中进行初始化的:
@SMSDispatcher.java protected SMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, SmsUsageMonitor usageMonitor) { mPhone = phone; //phone是GSMPhone,而phone的mCm就是RILJ mCm = phone.mCM; }
因此,在GsmSMSDispatcher构造函数中通过mCM.setOnNewGsmSms注册的监听器其实调用的是RILJ中的方法,而这个方法其实存在RILJ的父类BaseCommands中:
@BaseCommands.java public void setOnNewGsmSms(Handler h, int what, Object obj) { mGsmSmsRegistrant = new Registrant (h, what, obj); }
上面的过程,简单来说就是,在GSMPhone的构造函数中,创建了GsmSMSDispatcher的对象用于接收短消息,而GsmSMSDispatcher的初始化过程就是通过GSMPhone对象找到了RILJ(的父类),并把自己所关注的三种RIL层消息注册给RILJ,等待RILJ接收到短信时通知GsmSMSDispatcher。
二、RILJ通知GsmSMSDispatcher过程
下面我们来看,当有短消息上来时,RILJ如何把消息派发下去。我们在《Framework层中的RIL》一文中分析过,在RILJ中有两个独立的线程,一个用于向RILC发送数据(RILSender),一个用于接收RILC层上报的数据(RILReceiver)。当有新消息来时,一定会通过RILReceiver发送数据,而他又是通过processResponse处理数据的:
@RIL.java private void processResponse (Parcel p) { int type; type = p.readInt(); //新消息是属于URC消息 if (type == RESPONSE_UNSOLICITED) { processUnsolicited (p); } else if (type == RESPONSE_SOLICITED) { } }
private void processUnsolicited (Parcel p) { switch(response) { case RIL_UNSOL_RESPONSE_NEW_SMS: { String a[] = new String[2]; a[1] = (String)ret; SmsMessage sms; sms = SmsMessage.newFromCMT(a); if (mGsmSmsRegistrant != null) { //通过RILJ中的mGsmSmsRegistrant通知他的注册者,也就是GsmSMSDispatcher对象 mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null)); } break; } } }
我们继续看notifyRegistrant的过程:
@Registrant.java public void notifyRegistrant(AsyncResult ar) { internalNotifyRegistrant (ar.result, ar.exception); } void internalNotifyRegistrant (Object result, Throwable exception) { Handler h = getHandler(); if (h == null) { clear(); } else { Message msg = Message.obtain(); msg.what = what; msg.obj = new AsyncResult(userObj, result, exception); h.sendMessage(msg); } }
看来,RILJ对注册客户端的通知是通过sendMessage的方式实现的。
三、SMSDispatcher把短信通知发送到系统广播的过程
在这一步中,SMSDispatcher将把短信转换为Intent,并通过sendOrderedBroadcast发送到系统中。上面分析到了sendMessage,还记得当初是GsmSMSDispatcher通过GSMPhone找到了RILJ,并为自己注册了三种关于SMS的监听。
mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null); mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null); mCm.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null);
当前既然有了新的消息,RILJ通过sendMessage的方式发送的Message就会发送给GsmSMSDispatcher,而这个通知是在GsmSMSDispatcher的父类SMSDispatcher中被处理的:
@SMSDispatcher.java public void handleMessage(Message msg) { switch (msg.what) { case EVENT_NEW_SMS: //新消息的处理 SmsMessage sms; ar = (AsyncResult) msg.obj; sms = (SmsMessage) ar.result; int result = dispatchMessage(sms.mWrappedSmsMessage); break; case EVENT_SEND_SMS_COMPLETE: //发送完成 case EVENT_STOP_SENDING://停止发送 } }
继续看dispatchMessage的过程,这个过程又进入到了子类GsmSMSDispatcher中处理:
@GsmSMSDispatcher.java public int dispatchMessage(SmsMessageBase smsb) { SmsMessage sms = (SmsMessage) smsb; if (mSmsReceiveDisabled) { //设备不支持短消息 return Intents.RESULT_SMS_HANDLED; } boolean handled = false; if (sms.isMWISetMessage()) { //新来语音信箱的短信通知 mPhone.setVoiceMessageWaiting(1, -1); // line 1: unknown number of msgs waiting handled = sms.isMwiDontStore(); } else if (sms.isMWIClearMessage()) { //清除语音信箱的短信通知 mPhone.setVoiceMessageWaiting(1, 0); // line 1: no msgs waiting handled = sms.isMwiDontStore(); } if (!mStorageMonitor.isStorageAvailable() && sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) { //存储不够,发送提示 return Intents.RESULT_SMS_OUT_OF_MEMORY; } //普通短信处理 return dispatchNormalMessage(smsb); }
上面对一些特殊条件进行处理,比如设备不支持短消息,或者接收到的消息是语音信箱提示、设备存储空间不足等,然后就进入普通消息的处理流程,而这个处理过程又进入了父类中:
@SMSDispatcher.java protected int dispatchNormalMessage(SmsMessageBase sms) { SmsHeader smsHeader = sms.getUserDataHeader(); if ((smsHeader == null) || (smsHeader.concatRef == null)) { 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 //Wap push 信息的分发 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 { //普通短消息处理 dispatchPdus(pdus); } return Activity.RESULT_OK; } else { 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); } }
这里看到,对于普通短消息,是通过dispatchPdus()接口分发出去的:
protected void dispatchPdus(byte[][] pdus) { //发送SMS_RECEIVED_ACTION的Intent Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION); intent.putExtra("pdus", pdus); intent.putExtra("format", getFormat()); //接收这个消息需要RECEIVE_SMS_PERMISSION的权限 dispatch(intent, RECEIVE_SMS_PERMISSION); }
继续往下看:
public void dispatch(Intent intent, String permission) { mWakeLock.acquire(WAKE_LOCK_TIMEOUT); //向系统中发送有序的广播,并且添加接收权限 mContext.sendOrderedBroadcast(intent, permission, mResultReceiver, this, Activity.RESULT_OK, null, null); }
由此,Framework就通过SMSDispatcher将短消息用Broadcast的形式发送到了系统中。
四、总体流程图
现在贴出以上过程的流程图。相关文章推荐
- Android短信接收过程源码分析
- Android短信源码分析 --PDU解析过程
- Android短信发送和接收流程源码分析
- Android短信源码分析 --PDU解析过程
- Android 4.0 Launcher2源码分析——启动过程分析
- [Android源码分析]L2CAP的创建过程分析
- android源码分析 Service的启动过程
- Android中将xml布局文件转化为View树的过程分析(下)-- LayoutInflater源码分析
- Android 4.0 Launcher2源码分析——启动过程分析
- Android Assets打开调用过程源码分析
- Android 5.0源码分析---startService的过程
- Android 4.0 Launcher2源码分析——Launcher内容加载详细过程
- Android系统默认Home应用程序(Launcher)的启动过程源码分析
- [Android源码分析]蓝牙搜索过程分析
- Android 4.0 Launcher2源码分析——启动过程分析
- Android 从源码分析 Android 触摸事件分发过程
- Android系统默认Home应用程序(Launcher)的启动过程源码分析
- 深度分析:Android4.3下MMS发送到附件为音频文件(音频为系统内置音频)的彩信给自己,添加音频-发送彩信-接收彩信-下载音频附件-预览-播放(三,接收彩信<1,接收短信>)
- Android 短信模块分析(六) 接收Wappush信息及彩信附件增加删除
- Android抢先截获短信(源码分析)