在最近的工作中,遇到一个需求,需要让第三方应用向MODEM层请求AT命令,且有两种响应方式,分别为同步方式和异步方式,同步的情况下,调用后要等MODEM返回结果后,将结果送给第三方应用, 异步的方式,采用等MODEM响应后,通过广播发送出去,让应用接收。鉴于目前大部分市面的MODEM都是通过AT来交互的,特有此需求。
1. 需求分析:
A. 由于需求要求的是第三方应用可以使用,那就是注定了,不是在PHONE的进程中,需要扩展TelephonyManager相关的接口,以及AIDL供其它调用。复杂。
B. 两种发送模式,归结到一起都是一样的,所以,在RIL层添加一条请求消息即可,扩展RIL层的请求消息。较复杂,
C. 主动上报的消息扩展。 比较简单,very easy.
D. 修改RIL C的请求函数,将请求发送给MODEM,并将结果送回RIL.JAVA
2. 可行性分析:
A. 第三方应用要使用,肯定扩展Telephony.aidl这个文件,这个应该问题不大,可以实现,估计4天。
B. 两种发送模式对于全是异步的RIL层来说,都是一样的,只是处理结果时不一样而已, 估计2天。
C. 该块是需求的重点,可行性问题不大,就是比较烦而已, 主要是调试环境复杂, 估计10天
D. 该处理是直接命令透传即可,不用太费时间,估计1天。
通过以上的个个分析,该需求应该是可以实现的,主要时间消耗在RIL层的扩展,其它都相对来说比较简单。
3. 需求实现
3.1. Framework/base的扩展
3.1.1. ITelephony.aidl扩展。
文件位置:telephony/java/com/android/internal/telephony/ITelephony.aidl。为了方便第三方调用该接口,需要扩展ITelephony.aidl文件中的接口,AIDL说白了,就是一个接口,便于不同进程之间的调用。而AIDL在编译时,会被编译成对应的java文件,最重要的是里面有一个stub, 这个才是进程通讯的核心,具体的内容不在这多说。但大家可以注意下PhoneInterfaceManager.java的声明类型。
public class PhoneInterfaceManager extends ITelephony.Stub
它真是实现第三方应用可以调用该接口的问题所在。
/**
* Execute AT command via unsync tunnel
* @param cmd AT command to execute
* execute successfully return true,
* AT command result will send by broadcast with action android.intent.action.AtCommand.result
*/
boolean AtCommandSendUnSync(String cmd);<pre name="code" class="java">
int RIL_UNSOL_RESPONSE_TUNNEL_AT = 1052;
/** * Execute AT command via sync tunnel * @param cmd AT command, time is timeout of process unit is ms */String AtCommandSendSync(String cmd, int time);
3.1.2. telephony/java/com/android/internal/telephony/RILConstants.java
扩展主动请求和主动上报的消息,注意要与ril.h中的定义的变量是一致,否则无法收到了对应的请求。
int RIL_REQUEST_SEND_AT = 336;
int RIL_UNSOL_RESPONSE_TUNNEL_AT = 1052;
3.1.3. telephony/java/android/telephony/TelephonyManager.java扩展方法
Teel(TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
/**
* Send AT command via sync tunnel, it should return result until the command execute completely.
* @param cmd AT command
* @param time max time for executing at command, unit is ms.
* return is result of AT.
*/
public String AtCommandSendSync(String cmd, int time){
try {
return getITelephony().AtCommandSendSync(cmd, time);
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
return null;
}
}
/**
* Send AT command via unsync tunnel, it should return true