modem层不懂,所以直接从RIL.java开始。以电信卡接收短信为例

modem通知RIL.java中的 RILReceiver处理接收信息

class RILReceiver implements Runnable {
byte[] buffer; RILReceiver() {
buffer = new byte[RIL_MAX_COMMAND_BYTES];
} @Override
public void
run() {
......
//建立socked连接,读取数据 processResponse(p);
......
}
}
private void
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(Parcel p)方法中,罗列了各种类型的信息,
processUnsolicited (Parcel p) {
int response;
Object ret; response = p.readInt(); try {switch(response) {
/*
cat libs/telephony/ril_unsol_commands.h \
| egrep "^ *{RIL_" \
| sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/'
*/ case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break;
case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: ret = responseString(p); break;
case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: ret = responseInts(p); break;
case RIL_UNSOL_ON_USSD: ret = responseStrings(p); break;
case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break;
case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break;
case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break;
case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break;
case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break;
case RIL_UNSOL_STK_EVENT_NOTIFY: ret = responseString(p); break;
case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break;
case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret = responseVoid(p); break;
case RIL_UNSOL_SIM_REFRESH: ret = responseSimRefresh(p); break;
case RIL_UNSOL_CALL_RING: ret = responseCallRing(p); break;
case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: ret = responseCdmaSms(p); break;
case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: ret = responseRaw(p); break;
case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: ret = responseVoid(p); break;
case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break;
case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break;
case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;
case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;
case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break;
case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break;
case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break;
case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_CELL_INFO_LIST: ret = responseCellInfoList(p); break;
case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: ret = responseInts(p); break;
case RIL_UNSOL_SRVCC_STATE_NOTIFY: ret = responseInts(p); break;
case RIL_UNSOL_HARDWARE_CONFIG_CHANGED: ret = responseHardwareConfig(p); break;
case RIL_UNSOL_RADIO_CAPABILITY:
ret = responseRadioCapability(p); break;
case RIL_UNSOL_ON_SS: ret = responseSsData(p); break;
case RIL_UNSOL_STK_CC_ALPHA_NOTIFY: ret = responseString(p); break;
case RIL_UNSOL_LCEDATA_RECV: ret = responseLceData(p); break;

电信卡接收信息,是 RIL_UNSOL_RESPONSE_CDMA_NEW_SMS

case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:
if (RILJ_LOGD) unsljLog(response); SmsMessage sms = (SmsMessage) ret; if (mCdmaSmsRegistrant != null) {
mCdmaSmsRegistrant
.notifyRegistrant(new AsyncResult(null, sms, null)); //mCdmaSmsRegistrant 在 CdmaInboundSmsHandler 初始化时创建
}
break;
public void
notifyRegistrant(AsyncResult ar)
{
internalNotifyRegistrant (ar.result, ar.exception);
} /*package*/ 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); //handler来处理接收信息事件
}
}
mCdmaSmsRegistrant.notifyRegistrant(..)就进入状态机(StateMachine)处理了。处理的信息接收的状态机是 InboundSmsHandler extends StateMachine
InboundSmsHandler是抽象类,对于CDMA信息是 CdmaInboundSmsHandler extends InboundSmsHandler, 对于GSM信息是 GsmInboundSmsHandler extends InboundSmsHandler

关于CdmaInboundSmsHandler 状态机是何时启动并初始化的,细节没研究。应该是在手机启动后,一系列系统服务启动时完成的。
看看CdmaInboundSmsHandler 的构造函数  
/**
* Create a new inbound SMS handler for CDMA.
*/
private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
super("CdmaInboundSmsHandler", context, storageMonitor, phone,
CellBroadcastHandler.makeCellBroadcastHandler(context, phone));
mSmsDispatcher = smsDispatcher;
mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
phone.mCi);
phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null); //这里构造了RIL中需要的 mCdmaSmsRegistrant
}
 public void setOnNewCdmaSms(Handler h, int what, Object obj) {
mCdmaSmsRegistrant = new Registrant (h, what, obj);
}
/**
* Wait for state machine to enter startup state. We can't send any messages until then.
*/
public static CdmaInboundSmsHandler makeInboundSmsHandler(Context context,
SmsStorageMonitor storageMonitor, PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
CdmaInboundSmsHandler handler = new CdmaInboundSmsHandler(context, storageMonitor,
phone, smsDispatcher); //构造CdmaInboudSmsHandler状态机
handler.start(); //启动 state machine
return handler;
}

在CdmaInboudSmsHandler初始化会调用父类InboundSmsHandler的构造函数,会增加各种状态。

protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
PhoneBase phone, CellBroadcastHandler cellBroadcastHandler) {
super(name);
...... addState(mDefaultState);
addState(mStartupState, mDefaultState);
addState(mIdleState, mDefaultState);
addState(mDeliveringState, mDefaultState);
addState(mWaitingState, mDeliveringState); setInitialState(mStartupState);
if (DBG) log("created InboundSmsHandler");
}

综上,RILReceiver接收信息,进入状态机CdmaInboundSmsHandler处理,具体是父类StateMachine中的Hanler传递消息,并切换各状态(state)处理。

状态: mDefaultState,mStartupState,mIdleState,mDeliveringState,mWaitingState以及默认的QuitSatte, HaltState。
各状态是如何切换处理的? 没搞明白。有待研究。 接收信息最终传递处理在 mDeliveringState中 (代码实现在InboundsSmsHandler.java中)
 class DeliveringState extends State {
@Override
public void enter() {
if (DBG) log("entering Delivering state");
} @Override
public void exit() {
if (DBG) log("leaving Delivering state");
} @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;
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) { //注意这里的返回结果,一般是 Intents.RESULT_SMS_HANDLED,才可以继续反馈 ack 到 smsc
boolean handled = (result == Intents.RESULT_SMS_HANDLED);
notifyAndAcknowledgeLastIncomingSms(handled, result, null); //这里返回ACK给短信中心(smsc),表示信息已接收。
}
}
 void notifyAndAcknowledgeLastIncomingSms(boolean success,
int result, Message response) {
if (!success) {
// broadcast SMS_REJECTED_ACTION intent
Intent intent = new Intent(Intents.SMS_REJECTED_ACTION);
intent.putExtra("result", result);
mContext.sendBroadcast(intent, android.Manifest.permission.RECEIVE_SMS);
}
acknowledgeLastIncomingSms(success, result, response);
}
protected abstract void acknowledgeLastIncomingSms(boolean success,
int result, Message response); //具体实现在 CdmaInboundsSmsHandler 或 GsmInboundSmsHandler中
CdmaInboundsSmsHandler中处理acknowledgeLastIncomingSms
@Override
protected void acknowledgeLastIncomingSms(boolean success, int result, Message response) {
if (isInEmergencyCallMode()) {
return;
} int causeCode = resultToCause(result);
mPhone.mCi.acknowledgeLastIncomingCdmaSms(success, causeCode, response); //这里又回到RIL中处理 if (causeCode == 0) {
mLastAcknowledgedSmsFingerprint = mLastDispatchedSmsFingerprint;
}
mLastDispatchedSmsFingerprint = null;
}

RIL中用 RILSender 处理返回ACK,

 public void
acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result); rr.mParcel.writeInt(success ? 0 : 1); //RIL_CDMA_SMS_ErrorClass
// cause code according to X.S004-550E
rr.mParcel.writeInt(cause); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " " + success + " " + cause); send(rr);
}

再看看信息传递处理dispatchMessage()

public int dispatchMessage(SmsMessageBase smsb) {
// If sms is null, there was a parsing error.
if (smsb == null) {
loge("dispatchSmsMessage: message is null");
return Intents.RESULT_SMS_GENERIC_ERROR;
} if (mSmsReceiveDisabled) {
// Device doesn't support receiving SMS,
log("Received short message on device which doesn't support "
+ "receiving SMS. Ignored.");
return Intents.RESULT_SMS_HANDLED;
} return dispatchMessageRadioSpecific(smsb);
}
protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb);
 

InboundsSmsHandler中的dispatchMessageRadioSpecific(..)是抽象的,具体处理在CdmaInboundSmsHandler 或 GsmInboundSmsHandler中

然后会将新信息,用广播传递给MMS应用处理。


												

android接收短信——framework处理流程(android 5.1)的更多相关文章

  1. Android接收短信

    Android收到短信时会广播android.provider.Telephony.SMS_RECEIVED消息,因此只要定义一个Receiver,收听该消息,就能接收短信. <receiver ...

  2. Android 接收短信

    启动程序时启动一个service,在service里注册接收短信的广播,当手机收到短信里,打印出短信内容跟电话号码. package com.lmy.SmsListener; import andro ...

  3. android拦截短信并屏蔽系统的Notification

    拦截短信有几个关键点: 1.android接收短信时是以广播的方式 2.程序只要在自己的Manifest.xml里加有"接收"SMS的权限 <uses-permission  ...

  4. Android短信彩信收发流程(应用层)

    下图为ComposeMessageActivity中confirmSendMessageIfNeeded部分的信息发送流程.主要以接收者有效性的确认为主,然后转向sendMessage方法进行发送. ...

  5. android 发送短信的两种方式,以及接收报告和发送报告

               android发送短信,以及接收报告和发送报告          android中发送短信其实有两种方式,这个和打电话类似,大家可以了解一下:    一.调起系统发短信功能    ...

  6. android基础---->发送和接收短信

    收发短信应该是每个手机最基本的功能之一了,即使是许多年前的老手机也都会具备这项功能,而Android 作为出色的智能手机操作系统,自然也少不了在这方面的支持.今天我们开始自己创建一个简单的发送和接收短 ...

  7. android学习十四(android的接收短信)

    收发短信是每一个手机主要的操作,android手机当然也能够接收短信了. android系统提供了一系列的API,使得我们能够在自己的应用程序里接收和发送短信. 事实上接收短信主要是利用我们前面学过的 ...

  8. Android使用BroadCastRecevier广播实现接收短信,并利用Toast弹出显示内容

    在上一篇文章 Android简单实现BroadCastReceiver广播机制 中简单的实现了一个广播机制,这里利用BroadCarstRecevier实现一个接收短信并显示内容的案例,当然至于接收到 ...

  9. android发送短信验证码并自动获取验证码填充文本框

    android注册发送短信验证码并自动获取短信,截取数字验证码填充文本框. 一.接入短信平台 首先需要选择短信平台接入,这里使用的是榛子云短信平台(http://smsow.zhenzikj.com) ...

随机推荐

  1. Python自动化 【第十一篇】:Python进阶-RabbitMQ队列/Memcached/Redis

     本节内容: RabbitMQ队列 Memcached Redis 1.  RabbitMQ 安装 http://www.rabbitmq.com/install-standalone-mac.htm ...

  2. HTTP权威指南笔记-2.URL与资源

    2.1 URI与URL.URN URL是浏览器寻找信息时所需的具体位置.URl是人们对HTTP和其他协议的常用访问点:浏览器指向一个URL,浏览器就会发送适当的协议报文向服务器获取内容. URI是一类 ...

  3. 《跑跑跑》(五)——添加障碍物,Tiled障碍层的使用

    [转]http://blog.csdn.net/u010778159/article/details/44036365 首先利用TiledMap在原来的地图上添加上障碍物,先新建两个图层,分别叫bar ...

  4. HBase学习

    记录HBase的学习过程.之后会陆续添加内容. 阅读hbase的博客,理解hbase是什么.推荐博文: 1,HBase原理,基础架构,基础概念 2,HBase超详细介绍 --------------- ...

  5. VS2013无法加载JSON格式

    js中通过$.getJSON加载.json 文件时,报如下错误: 解决方案:dos命令中打开 IIS Express  ,执行如下命令: appcmd set config /section:stat ...

  6. the server quit without updating pid file (/var/lib/mysql/localhost.localdomain.pid)

    前几天装的mysql,用的还挺爽的,第二天再用就不行了,报的错误如标题.网上也是众说纷纭,可能有很多原因会导致这种错误吧.我用的是将Mysqld这个进程杀掉,就可以启动mysql了

  7. ICMP Protocol

    [ICMP Protocol] 参考: 1.ICMP Types and Codes:http://www.nthelp.com/icmp.html 2.RFC 792 - Internet Cont ...

  8. [Docker] docker 基础学习笔记4(共6篇)

    离线安装nginx   apache 如何启动war包   linux 离线升级内核   nginx和Apache的使用   nginx 的负载均衡配置 是如此的简单,比weblogic的要简单100 ...

  9. Java基础之OOP

    1. 类(类型)于对象 (1)面向过程的开发于面向对象开发的区别: 面向过程更重视流程化以及功能的开发,简单点来讲,就是按照固定的模式一步步按部就班的进行,最终达成一个功能的实现.这种模式叫做面向过程 ...

  10. 【Python全栈笔记】01 [模块二] 14-15 Oct 运算符和字符串 4-1

    编码的问题 中文版 Windows 终端是默认GBK编码格式,python2默认为ASCII编码,虽然我们注释了需要用UTF-8,但是通过命令行运行的文件如果print中文内容还是会出现乱码. Uni ...