0%

Android O SMS 接收过程源码分析

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

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

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

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

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

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

源码分析

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

RIL 借由 IRadioIndication 和 IRadioResponse 定义了 HIDL 接口,建立起 HAL 层和 framework 层的 RIL 通信交互。在 Framework 层,由 RadioIndication 和 RadioResponse 分别实现了该 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 {
// ...省略
}

无线通信制式有 CDMA 和 GSM ,在 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 注册者。

RIL 的 mGsmSmsRegistrant 是 Registrant 对象:

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 到底是哪个,就需要看 Ril 的 mGsmSmsRegistrant 在哪里被初始化。

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);
}
}

 
而 setOnNewGsmSms 在 GsmInboundSmsHandler 的构造函数中被调用:

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 制式下的流程基本一致,就不再详述了。

参考