CatService主要负责STK菜单的相关事宜,本节我们就来分析该对象。
一、CatService的创建过程
@UiccCard.java
public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
synchronized (mLock) {
if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
//创建CatService
mCatService = CatService.getInstance(mCi, mContext, this);
} else {
if (mCatService != null) {
mCatService.dispose();
}
mCatService = null;
}
}
}
然后看具体的初始化流程:
@CatService.java
public static CatService getInstance(CommandsInterface ci, Context context, UiccCard ic) {
UiccCardApplication ca = null;
IccFileHandler fh = null;
IccRecords ir = null;
if (ic != null) {
//获取UiccCardApplication、IccFileHandler、IccRecords等对象
ca = ic.getApplicationIndex(0);
if (ca != null) {
fh = ca.getIccFileHandler();
ir = ca.getIccRecords();
}
}
synchronized (sInstanceLock) {
if (sInstance == null) {
if (ci == null || ca == null || ir == null || context == null || fh == null || ic == null) {
return null;
}
//创建CatService的消息处理线程
HandlerThread thread = new HandlerThread("Cat Telephony service");
thread.start();
//创建CatService实例对象
sInstance = new CatService(ci, ca, ir, context, fh, ic);
} else if ((ir != null) && (mIccRecords != ir)) {
//CatService已经被创建过,只需要更新其监听器
if (mIccRecords != null) {
mIccRecords.unregisterForRecordsLoaded(sInstance);
}
if (mUiccApplication != null) {
mUiccApplication.unregisterForReady(sInstance);
}
mIccRecords = ir;
mUiccApplication = ca;
mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
mUiccApplication.registerForReady(sInstance, MSG_ID_SIM_READY, null);
} else {
CatLog.d(sInstance, "Return current sInstance");
}
return sInstance;
}
}
看他的构造函数:
private CatService(CommandsInterface ci, UiccCardApplication ca, IccRecords ir, Context context, IccFileHandler fh, UiccCard ic) {
if (ci == null || ca == null || ir == null || context == null || fh == null || ic == null) {
throw new NullPointerException( "Service: Input parameters must not be null");
}
mCmdIf = ci;
mContext = context;
//获取RilMessageDecoder对象
mMsgDecoder = RilMessageDecoder.getInstance(this, fh);
//向RIL注册监听器
mCmdIf.setOnCatSessionEnd(this, MSG_ID_SESSION_END, null);
mCmdIf.setOnCatProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null);
mCmdIf.setOnCatEvent(this, MSG_ID_EVENT_NOTIFY, null);
mCmdIf.setOnCatCallSetUp(this, MSG_ID_CALL_SETUP, null);
mIccRecords = ir;
mUiccApplication = ca;
//向UiccCardApplication对象注册SIM Ready的监听器
//向IccRecords对象注册Icc Record Loaded的监听器
mUiccApplication.registerForReady(this, MSG_ID_SIM_READY, null);
mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
mStkAppInstalled = isStkAppInstalled();
}
我们看到在CatService的初始化过程中主要完成了一下三个任务:
1、获取RilMessageDecoder对象mMsgDecoder;
2、向RIL注册相关的通知监听;
3、向UiccCardApplication、IccRecords注册SIM卡和Record的监听;
二、CatService的消息机制
1、MSG_ID_SESSION_END
2、MSG_ID_PROACTIVE_COMMAND
3、MSG_ID_RIL_MSG_DECODED
4、MSG_ID_EVENT_NOTIFY
5、MSG_ID_CALL_SETUP
6、MSG_ID_SIM_READY
7、MSG_ID_ICC_RECORDS_LOADED
而这六个消息事件中,有四个是比较重要的,按照接收的先后顺序分别是:
MSG_ID_SIM_READY ----通知CatService,SIM卡已经就绪,需要CatService反馈是否就绪
MSG_ID_PROACTIVE_COMMAND ----CatService拿到SIM卡中的STK信息
MSG_ID_RIL_MSG_DECODED ----RilMessageDecoder解析完STK数据后给CatService发送通知
MSG_ID_SESSION_END ----RIL上传当前消息已经传输完毕
下面我们主要介绍以上四个消息的处理流程。
2.1、MSG_ID_SIM_READY
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ID_SIM_READY:
//向RIL发送消息
mCmdIf.reportStkServiceIsRunning(null);
break;
default:
throw new AssertionError("Unrecognized CAT command: " + msg.what);
}
}
此时的RIL将会向Modem发送RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING的消息,从而告诉Modem,CatService已经准备好接受STK的数据了。
2.2、MSG_ID_PROACTIVE_COMMAND
请注意, 如果SIM卡不支持STK业务,将接收不到该消息。
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ID_SESSION_END:
case MSG_ID_PROACTIVE_COMMAND:
case MSG_ID_EVENT_NOTIFY:
case MSG_ID_REFRESH:
String data = null;
if (msg.obj != null) {
AsyncResult ar = (AsyncResult) msg.obj;
if (ar != null && ar.result != null) {
try {
data = (String) ar.result;
} catch (ClassCastException e) {
break;
}
}
}
//通过RilMessageDecoder去解析数据
mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, data));
break;
default:
throw new AssertionError("Unrecognized CAT command: " + msg.what);
}
}
我们看到,对于拿到的数据时通过mMsgDecoder去解析的,也就是RilMessageDecoder的对象,这个对象是在CatService的构造函数中被创建的。我们来看具体的解析数据的过程:
@RilMessageDecoder.java
public void sendStartDecodingMessageParams(RilMessage rilMsg) {
Message msg = obtainMessage(CMD_START);
msg.obj = rilMsg;
sendMessage(msg);
}
在RilMessageDecoder中又将消息封装后发送给自己,并在StateStart中被处理:
private class StateStart extends State {
@Override
public boolean processMessage(Message msg) {
if (msg.what == CMD_START) {
if (decodeMessageParams((RilMessage)msg.obj)) {
transitionTo(mStateCmdParamsReady);
}
} else {
CatLog.d(this, "StateStart unexpecte