Android4.4 RIL的AT命令增加流程
2015-01-17 23:03
295 查看
首先,感谢http://blog.csdn.net/guoleimail/article/details/41649537这篇博文的出现,文中不仅列出了大部分要修改的代码,还给出了原理阐述。本文作为该博文的补充,将所有修改的地方全部给出,由上层应用逐级往下调用,但类之间的关系不作说明,想弄清楚的朋友可以看看下面的链接
http://blog.csdn.net/youbang321/article/details/7803023
http://www.elexcon.com/news/54715.html
http://blog.csdn.net/arnoldlu/article/details/9189939
http://blog.sina.com.cn/s/blog_682793a50100jeo5.html
http://www.cnblogs.com/jesse123/p/3167519.html
http://www.redwolf-blog.com/?p=966
http://yelinsen.iteye.com/blog/848137
http://yelinsen.iteye.com/blog/848129
http://blog.163.com/fengxuedong_fxd/blog/static/71926306201181933443646/
http://blog.csdn.net/forlong401/article/details/5403379
frameworks\base\telephony\java\android\telephony\TelephonyManager.java
在尾部增加
/**
* 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 or false when AT command has been send.
* @param cmd AT command
* return boolean
*/
public boolean AtCommandSendUnSync(String cmd){
try {
return getITelephony().AtCommandSendUnSync(cmd);
} catch (RemoteException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
}
frameworks\base\telephony\java\com\android\internal\telephony\ITelephony.aidl
在尾部增加
/**
* 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);
/**
* Execute AT command via sync tunnel
* @param cmd AT command, time is timeout of process unit is ms
*/
String AtCommandSendSync(String cmd, int time);
frameworks\base\telephony\java\com\android\internal\telephony\RILConstants.java
在尾部增加
int RIL_REQUEST_SEND_AT = 114;
...
int RIL_UNSOL_RESPONSE_TUNNEL_AT = 1038;
注意,两个id必须在已有的基础上按顺序递增添加。
frameworks\opt\telephony\src\java\com\android\internal\telephony\Phone.java
在尾部增加
//Add AT tunnel
void sendAtToModem(String at_string, Message result);
frameworks\opt\telephony\src\java\com\android\internal\telephony\PhoneBase.java
增加一个成员变量,表示主动上发的消息
在尾部增加
@Override
public void sendAtToModem(String at_string, Message result){
Log.e(LOG_TAG, "sendAtToModem Error! This function is only for GSMPhone.");
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\PhoneProxy.java
在尾部增加
如果是2G网络,修改frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm\GSMPhone.java
如果是3G网络,比如CDMA2000,修改frameworks\opt\telephony\src\java\com\android\internal\telephony\cdma\CDMAPhone.java
在构造函数增加
mCi.registerForAtTunnel(this, EVENT_UNSOL_AT_TUNNEL, null);
在dispose函数中添加
在handleMessage中添加
在尾部添加
frameworks\opt\telephony\src\java\com\android\internal\telephony\CommandsInterface.java
在尾部添加
//Add for AT tunnel to modem
void sendAtToModem(String at_string, Message result);
void registerForAtTunnel(Handler h, int what, Object obj);
void unregisterForAtTunnel(Handler h);
frameworks\opt\telephony\src\java\com\android\internal\telephony\sip\SipCommandInterface.java
在尾部添加
@Override
public void sendAtToModem(String at_string, Message result){
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\test\SimulatedCommands.java
在尾部添加
@Override
public void sendAtToModem(String at_string, Message result){
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\BaseCommands.java
添加一个成员变量,用于注册处理主动上发的消息
protected Registrant mAtTunnelRegistrant;
在尾部添加
/**
* Sets the handler for AT sync tunnel
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
@Override
public void registerForAtTunnel(Handler h, int what, Object obj) {
mAtTunnelRegistrant = new Registrant(h, what, obj);
}
@Override
public void unregisterForAtTunnel(Handler h) {
mAtTunnelRegistrant.clear();
}
@Override
public void sendAtToModem(String at_string, Message result) {
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java
在processSolicited中添加
在processUnsolicited中添加
在requestToString中添加
在responseToString中添加
在尾部添加
@Override
public void sendAtToModem(String at_string, Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SEND_AT, result);
rr.mParcel.writeString(at_string);
if (RILJ_LOGD) riljLog(rr.serialString() +
"> sendAtToModem: " + requestToString(rr.mRequest)
+ " at_string: " + at_string);
send(rr);
}
packages\services\Telephony\src\com\android\phone\PhoneInterfaceManager.java
在尾部添加
hardware\ril\include\telephony\ril.h和hardware\ril\reference-ril\ril.h
添加两条命令码
注意要与上面的RILConstants.java添加的相同
hardware\ril\libril\ril_commands.h
在尾部添加
{RIL_REQUEST_SEND_AT, dispatchString, responseString},
hardware\ril\libril\ril_unsol_commands.h
在尾部添加
{RIL_UNSOL_RESPONSE_TUNNEL_AT, responseString, WAKE_PARTIAL},
hardware\ril\reference-ril\reference-ril.c
在onRequest中添加处理RILJ发送过来的AT命令
case RIL_REQUEST_SEND_AT:
requestSendAt(data, datalen, t);
break;
注意,你需要知道下发的命令要不要求返回数据,如果不要求一般用at_send_command即可,要求就用at_send_command_singleline。这个不能出错,否则RILJ和RILC之间的socket会断开。
在onUnsolicited中添加主动上发消息的处理
注意,这个要放在已有的if-else语句的最后,目的是把过滤剩下的消息全部当成RIL_UNSOL_RESPONSE_TUNNEL_AT上发,其中atReadStorage为静态内存块。
static char atReadStorage[1024];
调试的时候可以用logcat -b radio命令查看信息。
一些常见的LOG TAG是:
RIL: /hardware/ril/reference-ril/refereince-ril.c
AT: /hardware/ril/reference-ril/atchannel.c
RILD: /hardware/ril/rild/rild.c
RILC: /hardware/ril/libril/ril.cpp
RILB frameworks/base/telephony/java/com/android/internal/telephony/BaseCommands.java
RILJ: /frameworks/base/telephony/java/com/android/internal/telephony/gsm/RIL.java
GSM: /frameworks/base/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
http://blog.csdn.net/youbang321/article/details/7803023
http://www.elexcon.com/news/54715.html
http://blog.csdn.net/arnoldlu/article/details/9189939
http://blog.sina.com.cn/s/blog_682793a50100jeo5.html
http://www.cnblogs.com/jesse123/p/3167519.html
http://www.redwolf-blog.com/?p=966
http://yelinsen.iteye.com/blog/848137
http://yelinsen.iteye.com/blog/848129
http://blog.163.com/fengxuedong_fxd/blog/static/71926306201181933443646/
http://blog.csdn.net/forlong401/article/details/5403379
frameworks\base\telephony\java\android\telephony\TelephonyManager.java
在尾部增加
/**
* 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 or false when AT command has been send.
* @param cmd AT command
* return boolean
*/
public boolean AtCommandSendUnSync(String cmd){
try {
return getITelephony().AtCommandSendUnSync(cmd);
} catch (RemoteException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
}
frameworks\base\telephony\java\com\android\internal\telephony\ITelephony.aidl
在尾部增加
/**
* 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);
/**
* Execute AT command via sync tunnel
* @param cmd AT command, time is timeout of process unit is ms
*/
String AtCommandSendSync(String cmd, int time);
frameworks\base\telephony\java\com\android\internal\telephony\RILConstants.java
在尾部增加
int RIL_REQUEST_SEND_AT = 114;
...
int RIL_UNSOL_RESPONSE_TUNNEL_AT = 1038;
注意,两个id必须在已有的基础上按顺序递增添加。
frameworks\opt\telephony\src\java\com\android\internal\telephony\Phone.java
在尾部增加
//Add AT tunnel
void sendAtToModem(String at_string, Message result);
frameworks\opt\telephony\src\java\com\android\internal\telephony\PhoneBase.java
增加一个成员变量,表示主动上发的消息
protected static final int EVENT_UNSOL_AT_TUNNEL = 31;
在尾部增加
@Override
public void sendAtToModem(String at_string, Message result){
Log.e(LOG_TAG, "sendAtToModem Error! This function is only for GSMPhone.");
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\PhoneProxy.java
在尾部增加
@Override public void sendAtToModem(String at_string, Message result) { mActivePhone.sendAtToModem(at_string, result); }
如果是2G网络,修改frameworks\opt\telephony\src\java\com\android\internal\telephony\gsm\GSMPhone.java
如果是3G网络,比如CDMA2000,修改frameworks\opt\telephony\src\java\com\android\internal\telephony\cdma\CDMAPhone.java
在构造函数增加
mCi.registerForAtTunnel(this, EVENT_UNSOL_AT_TUNNEL, null);
在dispose函数中添加
mCi.unregisterForAtTunnel(this);
在handleMessage中添加
case EVENT_UNSOL_AT_TUNNEL: ar = (AsyncResult)msg.obj; log("receive EVENT_UNSOL_AT_TUNNEL done"); if (ar.exception == null) { String result = (String)ar.result; log("result = " + result); sendResultBroadcast(result); } break;
在尾部添加
private void sendResultBroadcast(String result) { Intent intent = new Intent("android.intent.action.AtCommand.result"); intent.putExtra("result", result); mContext.sendBroadcast(intent); } @Override public void sendAtToModem(String at_string, Message result) { mCi.sendAtToModem(at_string, result); }
frameworks\opt\telephony\src\java\com\android\internal\telephony\CommandsInterface.java
在尾部添加
//Add for AT tunnel to modem
void sendAtToModem(String at_string, Message result);
void registerForAtTunnel(Handler h, int what, Object obj);
void unregisterForAtTunnel(Handler h);
frameworks\opt\telephony\src\java\com\android\internal\telephony\sip\SipCommandInterface.java
在尾部添加
@Override
public void sendAtToModem(String at_string, Message result){
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\test\SimulatedCommands.java
在尾部添加
@Override
public void sendAtToModem(String at_string, Message result){
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\BaseCommands.java
import android.os.Message;
添加一个成员变量,用于注册处理主动上发的消息
protected Registrant mAtTunnelRegistrant;
在尾部添加
/**
* Sets the handler for AT sync tunnel
*
* @param h Handler for notification message.
* @param what User-defined message code.
* @param obj User object.
*/
@Override
public void registerForAtTunnel(Handler h, int what, Object obj) {
mAtTunnelRegistrant = new Registrant(h, what, obj);
}
@Override
public void unregisterForAtTunnel(Handler h) {
mAtTunnelRegistrant.clear();
}
@Override
public void sendAtToModem(String at_string, Message result) {
}
frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java
在processSolicited中添加
case RIL_REQUEST_SEND_AT: ret = responseString(p); break;
在processUnsolicited中添加
case RIL_UNSOL_RESPONSE_TUNNEL_AT: ret = responseString(p); break;
case RIL_UNSOL_RESPONSE_TUNNEL_AT: { if (RILJ_LOGD) unsljLogRet(response, ret); if (mAtTunnelRegistrant != null) { mAtTunnelRegistrant.notifyRegistrant( new AsyncResult (null, ret, null)); } break; }
在requestToString中添加
case RIL_REQUEST_SEND_AT: return "SEND_AT";
在responseToString中添加
case RIL_UNSOL_RESPONSE_TUNNEL_AT: return "RESPONSE_TUNNEL_AT";
在尾部添加
@Override
public void sendAtToModem(String at_string, Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SEND_AT, result);
rr.mParcel.writeString(at_string);
if (RILJ_LOGD) riljLog(rr.serialString() +
"> sendAtToModem: " + requestToString(rr.mRequest)
+ " at_string: " + at_string);
send(rr);
}
packages\services\Telephony\src\com\android\phone\PhoneInterfaceManager.java
在尾部添加
/** * Send AT command via unsync tunnel, it should return true or false when AT command has been send. * @param cmd AT command * return boolean */ public boolean AtCommandSendUnSync(String cmd){ Log.d(LOG_TAG, "AtCommandSendUnSync send at command" + cmd); Phone phone = mPhone; if (phone == null) return false; final AtSendThread atSendThread = new AtSendThread("AtCommandSendUnSync", cmd, false); atSendThread.start(); String result = atSendThread.sendAt(phone); sendResultBroadcast(result); if (result != null && result.length() > 1 && result.contains("OK")) { return true; } else { return false; } } private void sendResultBroadcast(String result) { Intent intent = new Intent("android.intent.action.AtCommand.result"); intent.putExtra("result", result); mApp.getPhone().getContext().sendBroadcast(intent); } /** * 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){ Log.d(LOG_TAG, "AtCommandSendSync send at command" + cmd + " time = " + time); Phone phone = mPhone; if (phone == null) return null; final AtSendThread atSendThread = new AtSendThread("AtCommandSendSync", cmd, true, time); atSendThread.start(); return atSendThread.sendAt(phone); } private static class AtSendThread extends Thread { private String mCmd; private long mMaxTimeExcute; private String mAtResult; private boolean mIsSync; private Handler mAtHandler; private boolean mSuccess = false; private static final int SEND_AT_VIA_TUNNEL = 1; AtSendThread(String name, String cmd, boolean isSync) { super(name); mCmd = cmd; mAtResult = null; mMaxTimeExcute = 5; mIsSync = false; } AtSendThread(String name, String cmd, boolean isSync, int max) { super(name); mCmd = cmd; mMaxTimeExcute = (long)(max/100); mAtResult = null; mIsSync = isSync; } public void run() { Looper.prepare(); synchronized (AtSendThread.this) { mAtHandler = new Handler() { @Override public void handleMessage(Message msg) { AsyncResult ar = (AsyncResult) msg.obj; switch (msg.what) { case SEND_AT_VIA_TUNNEL: Log.d("AtSyncThread", "SEND_AT_VIA_TUNNEL"); synchronized (AtSendThread.this) { if (ar.exception == null && ar.result != null) { mAtResult = ar.result.toString(); }else{ mAtResult = "Error AT response"; } mSuccess = true; AtSendThread.this.notifyAll(); } break; } } }; AtSendThread.this.notifyAll(); } Looper.loop(); } synchronized String sendAt(Phone phone) { while (mAtHandler == null) { try { wait(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } Message callback = Message.obtain(mAtHandler, SEND_AT_VIA_TUNNEL); Log.e(LOG_TAG, "mCmd = " + mCmd); phone.sendAtToModem(mCmd, callback); while (!mSuccess) { try { Log.d("AtSendThread", "wait for done"); mMaxTimeExcute--; wait(100); if (mMaxTimeExcute == 0) { mAtResult = "Error AT TIME OUT"; return mAtResult; } } catch (InterruptedException e) { // Restore the interrupted status Thread.currentThread().interrupt(); } } Log.d("AtSendThread", "successfull! result = " + mAtResult); return mAtResult; } }
hardware\ril\include\telephony\ril.h和hardware\ril\reference-ril\ril.h
添加两条命令码
#define RIL_REQUEST_SEND_AT 114 ... #define RIL_UNSOL_RESPONSE_TUNNEL_AT 1038
注意要与上面的RILConstants.java添加的相同
hardware\ril\libril\ril_commands.h
在尾部添加
{RIL_REQUEST_SEND_AT, dispatchString, responseString},
hardware\ril\libril\ril_unsol_commands.h
在尾部添加
{RIL_UNSOL_RESPONSE_TUNNEL_AT, responseString, WAKE_PARTIAL},
hardware\ril\reference-ril\reference-ril.c
在onRequest中添加处理RILJ发送过来的AT命令
case RIL_REQUEST_SEND_AT:
requestSendAt(data, datalen, t);
break;
static void requestSendAt(void *data, size_t datalen, RIL_Token t) { int err; char *cmd; char *response; ATResponse *p_response = NULL; RLOGD("requestSendAt data = %s, datalen = %d", (char *)data, datalen); assert (datalen != 1); asprintf(&cmd, "%s", (char *)data+1); response = (char *)data; if(response[0] == '1'){ err = at_send_command(cmd, &p_response); }else if(response[0] == '2'){ err = at_send_command_singleline(cmd, "", &p_response); }else if(response[0] == '3'){ err = at_send_command_numeric(cmd, &p_response); }else if(response[0] == '4'){ err = at_send_command_multiline(cmd, "", &p_response); }else{ err = -1; } if (cmd != NULL) { free(cmd); cmd = NULL; } RLOGD("requestSendAt err = %d, p_response->success = %d", err, p_response->success); if (p_response->p_intermediates == NULL) { RLOGD("requestSendAt finalResponse = %s", p_response->finalResponse); asprintf(&response, "%s\r\n", p_response->finalResponse); } else { RLOGD("requestSendAt finalResponse = %s, p_intermediates->line = %s", p_response->finalResponse, p_response->p_intermediates->line); asprintf(&response, "%s, %s\r\n", p_response->p_intermediates->line, p_response->finalResponse); } if (err < 0 || p_response->success == 0) /*Maybe the at command from user is invalid, we also send successful response to user, the result should handle it itself*/ goto error; RLOGD("requestSendAt success, response = %s, len = ", response, strlen(response)); RIL_onRequestComplete(t, RIL_E_SUCCESS, response, strlen(response)); free(response); return; error: RLOGE("ERROR: requestSendAt failed, response = %d", response); RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); free(response); }
注意,你需要知道下发的命令要不要求返回数据,如果不要求一般用at_send_command即可,要求就用at_send_command_singleline。这个不能出错,否则RILJ和RILC之间的socket会断开。
在onUnsolicited中添加主动上发消息的处理
else{ if(!s) { line = strdup(s); memset(atReadStorage, 0, 1024); strncpy(atReadStorage, line, strlen(line)); p = atReadStorage + strlen(line); if(!sms_pdu) { strncpy(p, sms_pdu, strlen(sms_pdu)); } RIL_onUnsolicitedResponse ( RIL_UNSOL_RESPONSE_TUNNEL_AT, atReadStorage, strlen(atReadStorage)); free(line); } }
注意,这个要放在已有的if-else语句的最后,目的是把过滤剩下的消息全部当成RIL_UNSOL_RESPONSE_TUNNEL_AT上发,其中atReadStorage为静态内存块。
static char atReadStorage[1024];
调试的时候可以用logcat -b radio命令查看信息。
一些常见的LOG TAG是:
RIL: /hardware/ril/reference-ril/refereince-ril.c
AT: /hardware/ril/reference-ril/atchannel.c
RILD: /hardware/ril/rild/rild.c
RILC: /hardware/ril/libril/ril.cpp
RILB frameworks/base/telephony/java/com/android/internal/telephony/BaseCommands.java
RILJ: /frameworks/base/telephony/java/com/android/internal/telephony/gsm/RIL.java
GSM: /frameworks/base/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
相关文章推荐
- Android4.4 RIL的AT命令增加流程
- Android4.4 RIL的AT命令增加流程
- Android4.4蓝牙耳机HFP流程分析-3
- Android4.4 4.2keyguard锁屏流程梳理
- Android4.4 Telephony流程分析——GsmServiceStateTracker管理网络服务状态
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程
- Android4.4 Telephony流程分析——拨号应用(Dialer)的通话记录加载过程
- Android4.4 Telephony流程分析——通话状态更新
- Android4.4蓝牙耳机HFP流程分析-3
- android4.4 VSync事件处理流程
- 以增加收藏夹功能为实例,解析asp.net forums2结构流程及组件设计
- ccflow流程自动发起功能增加,如何按指定的时间触发方式发起流程?
- 在android4.4上新增加keycode
- Android4.4 wpa_supplicant深入分析之wpa_supplicant初始化流程续
- Delphi程序流程三(2)(while)PS:最简单的任务管理器( 组件LISTVIEW的用法 增加LISTVIEW的读取 删除)
- Android USB相关流程解析(android4.4)
- 增加RIL组件时编辑出现的问题
- android4.4 wifi 扫描流程分析
- android4.4 bluetooth上电代码流程一览
- Android4.4 Telephony流程分析——来电(MT)流程