0%

Android O SMS 接收过程源码分析

Android O (8.0 和 8.1) 起,Google 开启了 Project Treble 计划,引入了新的系统架构模式 Treble

关于 Treble 架构,详情请参考:

简单来说,宏观上,Treble 之前的 Android 设备更新系统时,在更新上层系统之前必须先更新底层供应商(Vendor)的硬件支持代码,这很麻烦,新系统往往不能得到及时更新,TrebleVendor(芯片供应制造商编写的设备专属底层代码) 和 Android 系统代码分离,这样就规避之前版本的问题。

HAL (Hardware Abstract Layer - 硬件抽象层) 将硬件设备和 Android 操作系统分割开来,负责硬件设备和操作系统的通信。Android O 起,HAL 的硬件组件得到划分,比如音频,无线电频。这些底层的硬件划分通过 HIDL (HAL interface defination language - HAL接口定义语言) 和上层的操作系统中的系统服务进行通信。目前有数十个不同的 HIDL接口包,其中 HIDL 也是通过 Binder 实现通信的。 HIDLAIDL 很相似,具体语法有区别,但核心都是通过 Binder 实现通讯

RIL (Radio interface layer - 无线接口层) 用于提供电话通信(Telephony)服务,其中也包括了 SMS,而 RIL 是位于 HAL 层的。所以 Android O 起,RIL 的通信方式由之前的 Socket 通信变成了 Binder 通信。

关于 RIL 的底层逻辑,详情参考

源码分析

这里用 Android 8.1 (api 27) 的源码来进行分析。

RIL 借由 IRadioIndicationIRadioResponse 定义了 HIDL 接口,建立起 HAL 层和 framework 层的 RIL 通信交互。在 Framework 层,由 RadioIndicationRadioResponse 分别实现了该 HIDL 接口:

1
2
3
4
5
6
7
8
9
// RadioIndication 用于处理 RIL 底层发起的消息
public class RadioIndication extends IRadioIndication.Stub {
// ...省略
}

// RadioResponse 用于对 RIL 底层进行响应,回馈消息,
public class RadioResponse extends IRadioResponse.Stub {
// ...省略
}

无线通信制式有 CDMAGSM ,在 Android 系统中也有对应的编码实现。

GSM 制式下的 SMS 接收过程

GSM 制式下,新短信到来,会调用 RadionIndication#newSms()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class RadionIndication extends IRadioIndication.Stub {
RIL mRil;

RadioIndication(RIL ril) {
mRil = ril;
}
public void newSms(int indicationType, ArrayList<Byte> pdu) {
// 根据 indication 类型,用于必要时获取唤醒锁和发送ACK消息
mRil.processIndication(indicationType);

byte[] pduArray = RIL.arrayListToPrimitiveArray(pdu);
if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_NEW_SMS);

mRil.writeMetricsNewSms(SmsSession.Event.Tech.SMS_GSM,
SmsSession.Event.Format.SMS_FORMAT_3GPP);

// 解析出 SmsMessage 实体
SmsMessage sms = SmsMessage.newFromCMT(pduArray);
if (mRil.mGsmSmsRegistrant != null) {
// 通知给 RIL 中的 GSM 注册者
mRil.mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));
}
}
}

解析出 SmsMessage 对象后,将短信数据封装在 AsyncResult 对象并通知给相应的 GSM 注册者。

RILmGsmSmsRegistrantRegistrant 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class Registrant {
WeakReference refH;
int what;
Object userObj;

public Registrant(Handler h, int what, Object obj) {
refH = new WeakReference(h);
this.what = what;
userObj = obj;
}
// ...省略

// 通知注册者
public void notifyRegistrant(AsyncResult ar) {
internalNotifyRegistrant (ar.result, ar.exception);
}

// 本质上使用 Handler 进行消息通知
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);
}
}

public Handler getHandler() {
if (refH == null)
return null;
return (Handler) refH.get();
}
}

可以看出,Registrant 其实就是借由 Handler 发送消息,携带 SMS 信息的 AsyncResult 的消息则是在 Handler#handleMessage() 中被处理。而 Handler 是在 Registrant 的构造函数中被引用的,我们需要看 Handler 到底是哪个,就需要看 RilmGsmSmsRegistrant 在哪里被初始化。

RIL 继承自 BaseCommands,通过调用 setOnNewGsmSms 实现 mGsmSmsRegistrant 的初始化。

1
2
3
4
5
6
7
8
9
10
public abstract class BaseCommands implements CommandsInterface {
protected Registrant mGsmSmsRegistrant;
// ...省略

// 初始化 Gsm SMS 的 Registrant
@Override
public void setOnNewGsmSms(Handler h, int what, Object obj) {
mGsmSmsRegistrant = new Registrant (h, what, obj);
}
}

 
setOnNewGsmSmsGsmInboundSmsHandler 的构造函数中被调用:

1
2
3
4
5
6
7
8
9
10
11
public class GsmInboundSmsHandler extends InboundSmsHandler {
private GsmInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
Phone phone) {
super("GsmInboundSmsHandler", context, storageMonitor, phone,
GsmCellBroadcastHandler.makeGsmCellBroadcastHandler(context, phone));

// 初始化 Gsm SMS 的 Registrant,该注册者只关注类型为 EVENT_NEW_SMS 的事件
phone.mCi.setOnNewGsmSms(getHandler(), EVENT_NEW_SMS, null);
mDataDownloadHandler = new UsimDataDownloadHandler(phone.mCi);
}
}

从以上分析可以看出, GsmInboundSmsHandler 注册的 Registrant 对象只关注 EVENT_NEW_SMS 事件,并且在 RadioIndication#newSms() 中也会发送 EVENT_NEW_SMS 事件消息。

我们现在来看一下 GsmInboundSmsHandler 的继承关系,GsmInboundSmsHandler 继承自 InboundSmsHanlder,而 InboundSmsHandler 继承自 StateMachine, 这里的 StateMachine 就是 有限状态机,状态机里面的不同状态(State)可以在特定条件下进行相互转换。那么,这里的 StateMachine 类是如何实现状态机的呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class StateMachine {
// ... 省略
private static class SmsHandler extends Handler {
/**
* 通过调用 State 的 processMessage 方法去处理发送至此状态机的消息。
*/
@Override
public final void handleMessage(Message msg) {
if (!mHasQuit) {
// ...省略
if (mIsConstructionCompleted) {
// 处理消息
msgProcessedState = processMsg(msg);
}
// ...省略

// 根据当前状态,执行相应的状态变化操作,即状态迁移
performTransitions(msgProcessState, msg);
}
}

/**
* 处理消息,执行 State 的 processMessage 方法,如果当前状态无法处理,则调用父状态进行处理,以类推
* @return 返回处理了当前消息的状态
*/
private final State processMsg(Message msg) {
// ... 省略
// 用当前状态处理消息,无法处理则循环下去
while (!curStateInfo.state.processMessage(msg)) {
curStateInfo = curStateInfo.parentStateInfo;
if (curStateInfo == null) {
mSm.unhandledMessage(msg);
break;
}
//... 省略
}
return (curStateInfo != null) ? curStateInfo.state : null;
}

// 根据处理了该消息的状态信息,执行相关状态迁移。
private void performTransitions(State msgProcessedState, Message msg) {
// ... 省略
}

// 执行状态转移
private final void transitionTo(IState destState) {
// ... 忽略
}

// 在当前状态机中添加状态,需要指明其父状态
private void addState(State state, State parent) {
// ... 忽略
}
}

private SmsHandler mSmsHandler;

public final Handler getHandler() {
return mSmsHandler;
}

protected StateMachine(String name, Looper looper) {
initStateMachine(name, looper);
}

private void initStateMachine(String name, Looper looper) {
mName = name;
mSmHandler = new SmHandler(looper, this);
}
}

public interface IState {
// 进入状态
void enter();
// 退出状态
void exit();
// 处理状态
boolean processMessage(Message msg);
// ...省略
}

public class State implements IState {
// ...省略
}

通过上面的源码可以看出来,StateMachine 其实就是通过 Handler 去实现的,通过 handleMessage() 来处理当前状态,通过 transitionTo() 来进行状态迁移,通过 addState() 来进行状态机中状态的添加。而 GsmInboundSmsHandler 初始化方法中的 getHandler() 返回的就是 StateMachine 中的 SmsHandler 对象 mSmsHandler

接下来看一下状态机中初始时,添加了哪些状态,在 InboundSmsHandler 构造函数中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public abstract class InboundSmsHanlder extends StateMachine {
protected InboundSmsHandler(String name, Context context, SmsStorageMonitor storageMonitor,
Phone phone, CellBroadcastHandler cellBroadcastHandler) {
super(name);

// 添加默认状态
addState(mDefaultState);
// 添加 启动状态 - StartupState
addState(mStartupState, mDefaultState);
// 添加 空闲状态 - IdleState
addState(mIdleState, mDefaultState);
// 添加 分发状态 - DeliveringState
addState(mDeliveringState, mDefaultState);
// 添加 等待状态 - WaitingState
addState(mWaitingState, mDeliveringState);

// 设置初始状态为 StartupState
setInitialState(mStartupState);
}
}

 
初始状态是 StartupState

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private class StartupState extends State {
// ...省略

@Override
public boolean processMessage(Message msg) {
log("StartupState.processMessage:" + msg.what);
switch (msg.what) {
// ...省略
case EVENT_START_ACCEPTING_SMS:
// 类型为 EVENT_START_ACCEPTING_SMS 的信息发送后,进入 IdleState
transitionTo(mIdleState);
return HANDLED;
// ...省略
}
}
}

 
而在 GsmInboundSmsHandler 初始化之后,就会发送 EVENT_START_ACCEPTING_SMS 消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public class ImsSMSDispatcher extends SMSDispatcher {
public ImsSMSDispatcher(Phone phone, SmsStorageMonitor storageMonitor, SmsUsageMonitor usageMonitor) {
super(phone, usageMonitor, null);

// Create dispatchers, inbound SMS handlers and
// broadcast undelivered messages in raw table.
mCdmaDispatcher = new CdmaSMSDispatcher(phone, usageMonitor, this);
// 初始化 GsmInboundSmsHandler
mGsmInboundSmsHandler = GsmInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
storageMonitor, phone);
// 初始化 GsmInboundSmsHandler
mCdmaInboundSmsHandler = CdmaInboundSmsHandler.makeInboundSmsHandler(phone.getContext(),
storageMonitor, phone, (CdmaSMSDispatcher) mCdmaDispatcher);
mGsmDispatcher = new GsmSMSDispatcher(phone, usageMonitor, this, mGsmInboundSmsHandler);
// 发送初始化信息
SmsBroadcastUndelivered.initialize(phone.getContext(),
mGsmInboundSmsHandler, mCdmaInboundSmsHandler);
InboundSmsHandler.registerNewMessageNotificationActionHandler(phone.getContext());
}
}

public class SmsBroadcastUndelivered {
// ...省略

public static void initialize(Context context, GsmInboundSmsHandler gsmInboundSmsHandler,
CdmaInboundSmsHandler cdmaInboundSmsHandler) {
if (instance == null) {
instance = new SmsBroadcastUndelivered(
context, gsmInboundSmsHandler, cdmaInboundSmsHandler);
}

if (gsmInboundSmsHandler != null) {
// GsmInboundSmsHandler 发送 EVENT_START_ACCEPTING_SMS 消息
gsmInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_START_ACCEPTING_SMS);
}
if (cdmaInboundSmsHandler != null) {
// CdmaInboundSmsHandler 发送 EVENT_START_ACCEPTING_SMS 消息
cdmaInboundSmsHandler.sendMessage(InboundSmsHandler.EVENT_START_ACCEPTING_SMS);
}
}
}

 
所以在 GsmInboundSmsHandler 发送 EVENT_START_ACCEPTING_SMS 之后,状态机进入 IdleState 状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private class IdleState extends State {
// ...省略
@Override
public boolean processMessage(Message msg) {
log("IdleState.processMessage:" + msg.what);
if (DBG) log("Idle state processing message type " + msg.what);
switch (msg.what) {
case EVENT_NEW_SMS:
case EVENT_INJECT_SMS:
case EVENT_BROADCAST_SMS:
deferMessage(msg);
transitionTo(mDeliveringState);
return HANDLED;
// ...省略
}
}
}

 
在之前的分析中说到,RadioIndication#newSms() 发送 EVENT_NEW_SMS 事件消息,所以在接收到该消息之后,IdleState 状态会进入到 DeliveringState 状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private class DeliveringState extends State {
// ...省略
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case EVENT_NEW_SMS:
// 处理新短信
handleNewSms((AsyncResult) msg.obj);
sendMessage(EVENT_RETURN_TO_IDLE);
return HANDLED;
// ...省略
}
}
}

 
DeliveringState 状态下,接收到 EVENT_NEW_SMS 消息事件,会执行 handleNewSms() 方法,接下来看下该方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public abstract class InboundSmsHandler {
// 处理新信息
private void handleNewSms(AsyncResult ar) {
// ...省略
try {
SmsMessage sms = (SmsMessage) ar.result;
result = dispatchMessage(sms.mWrappedSmsMessage);
} catch (RuntimeException ex) {
// ...
}
// ...省略
}

private int dispatchMessage(SmsMessageBase smsb) {
// ...省略
return dispatchMessageRadioSpecific(smsb);
}

protected abstract int dispatchMessageRadioSpecific(SmsMessageBase smsb);

protected int dispatchNormalMessage(SmsMessageBase sms) {
SmsHeader smsHeader = sms.getUserDataHeader();
InboundSmsTracker tracker;

// 初始化并获取 InboundSmsTracker 对象
if ((smsHeader == null) || (smsHeader.concatRef == null)) {
tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
sms.getTimestampMillis(), destPort, is3gpp2(), false,
sms.getOriginatingAddress(), sms.getDisplayOriginatingAddress(),
sms.getMessageBody());
} else {
// ...
tracker = TelephonyComponentFactory.getInstance().makeInboundSmsTracker(sms.getPdu(),
sms.getTimestampMillis(), destPort, is3gpp2(), sms.getOriginatingAddress(),
sms.getDisplayOriginatingAddress(), concatRef.refNumber, concatRef.seqNumber,
concatRef.msgCount, false, sms.getMessageBody());
}

return addTrackerToRawTableAndSendMessage(tracker,
tracker.getDestPort() == -1);
}
}

public class GsmInboundSmsHandler extends InboundSmsHandler {
protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) {
// ...省略
return dispatchNormalMessage(smsb);
}
}

从上面的源码中可以看出,handleNewSms() 调用链为 handleNewSms() -> dispatchMessage() -> dispatchMessageRadioSpecific() -> dispatchNormalMessage() -> addTrackerToRawTableAndSendMessage()

接着看 addTrackerToRawTableAndSendMessage() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker, boolean deDup) {
switch(addTrackerToRawTable(tracker, deDup)) { // 插入短信数据库
case Intents.RESULT_SMS_HANDLED:
sendMessage(EVENT_BROADCAST_SMS, tracker);
return Intents.RESULT_SMS_HANDLED;

case Intents.RESULT_SMS_DUPLICATED:
return Intents.RESULT_SMS_HANDLED;

case Intents.RESULT_SMS_GENERIC_ERROR:
default:
return Intents.RESULT_SMS_GENERIC_ERROR;
}
}

private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) {
if (deDup) { // 处理短信冗余重复的逻辑
try {
if (duplicateExists(tracker)) {
return Intents.RESULT_SMS_DUPLICATED; // reject message
}
} catch (SQLException e) {
return Intents.RESULT_SMS_GENERIC_ERROR; // reject message
}
}

String address = tracker.getAddress();
String refNumber = Integer.toString(tracker.getReferenceNumber());
String count = Integer.toString(tracker.getMessageCount());
ContentValues values = tracker.getContentValues();

// 插入短信数据库
Uri newUri = mResolver.insert(sRawUri, values);

try {
long rowId = ContentUris.parseId(newUri);
if (tracker.getMessageCount() == 1) {
// set the delete selection args for single-part message
tracker.setDeleteWhere(SELECT_BY_ID, new String[]{Long.toString(rowId)});
} else {
// set the delete selection args for multi-part message
String[] deleteWhereArgs = {address, refNumber, count};
tracker.setDeleteWhere(tracker.getQueryForSegments(), deleteWhereArgs);
}
// 成功插入新短信数据到短信数据库,则返回 RESULT_SMS_HANDLED
return Intents.RESULT_SMS_HANDLED;
} catch (Exception e) {
loge("error parsing URI for new row: " + newUri, e);
return Intents.RESULT_SMS_GENERIC_ERROR;
}
}

上述源码中,先执行 addTrackerToRawTable() 来试图将新短信数据插入到短信数据库,根据该方法返回的结果进而返回不同的值。插入成功后,返回 Intents.RESULT_SMS_HANDLED,并通过 sendMessage(EVENT_BROADCAST_SMS, tracker) 发送 EVENT_BROADCAST_SMS 事件。

相同的思路,EVENT_BROADCAST_SMS 事件最终还是会在 DeliveringState 状态时被处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private class DeliveringState extends State {
// ...省略
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
// ...省略
case EVENT_BROADCAST_SMS:
InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj;
if (processMessagePart(inboundSmsTracker)) {
sendMessage(EVENT_UPDATE_TRACKER, inboundSmsTracker);
transitionTo(mWaitingState);
} else {
sendMessage(EVENT_RETURN_TO_IDLE);
}
return HANDLED;
}
}
}

 
EVENT_BROADCAST_SMS 事件到来,会执行 processMessagePart() 方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
private boolean processMessagePart(InboundSmsTracker tracker) {
// ...省略
// Sms 的 BroadcastReceiver,接收系统广播,经过一定处理后,将短信广播继续向下分发广播
SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);

boolean filterInvoked = filterSms(pdus, destPort, tracker, resultReceiver, true );
if (!filterInvoked) {
// 分发 Sms 投递意图
dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver);
}
// ...省略
}

private void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,
SmsBroadcastReceiver resultReceiver) {
Intent intent = new Intent();
intent.putExtra("pdus", pdus);
intent.putExtra("format", format);

if (destPort == -1) {
intent.setAction(Intents.SMS_DELIVER_ACTION);

// 先看系统没有默认的短信App
ComponentName componentName = SmsApplication.getDefaultSmsApplication(mContext, true);
if (componentName != null) {
// 系统默认的短信App存在,则仅给该App发送 SMS_DELIVER_ACTION 广播
intent.setComponent(componentName);
} else {
// 否则向所有的相关 Receiver 发送 SMS_DELIVER_ACTION 广播
intent.setComponent(null);
}

// ...省略
} else {
intent.setAction(Intents.DATA_SMS_RECEIVED_ACTION);
Uri uri = Uri.parse("sms://localhost:" + destPort);
intent.setData(uri);
intent.setComponent(null);
// Allow registered broadcast receivers to get this intent even
// when they are in the background.
intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
}

Bundle options = handleSmsWhitelisting(intent.getComponent());
// 分发广播意图
dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM);
}

public void dispatchIntent(Intent intent, String permission, int appOp,
Bundle opts, BroadcastReceiver resultReceiver, UserHandle user) {
// ...省略

// 发送广播
mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,
resultReceiver, getHandler(), Activity.RESULT_OK, null, null);
}

通过调用链:processMessagePart() -> dispatchSmsDeliveryIntent() -> dispatchIntent() 最终向系统发送相关短信广播。至此,Gsm 制式下的 Android 系统短信接收和广播发送过程基本分析完毕。

CDMA 制式下的 SMS 接收过程

CDMA 制式下,新短信到来,会调用 RadionIndication#cdmaNewSms()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class RadionIndication extends IRadioIndication.Stub {
RIL mRil;

RadioIndication(RIL ril) {
mRil = ril;
}

public void cdmaNewSms(int indicationType, CdmaSmsMessage msg) {
mRil.processIndication(indicationType);
mRil.writeMetricsNewSms(SmsSession.Event.Tech.SMS_CDMA,
SmsSession.Event.Format.SMS_FORMAT_3GPP2);

SmsMessage sms = SmsMessageConverter.newSmsMessageFromCdmaSmsMessage(msg);
if (mRil.mCdmaSmsRegistrant != null) {
mRil.mCdmaSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));
}
}
}

同样也会通过 mRil.mCdmaSmsRegistrant.notifyRegistrant 来通知给 CDMA 相关的 Registrant 对象。接下来流程和 GSM 制式下的流程基本一致,就不再详述了。

参考