转自 https://blog.youkuaiyun.com/u013686019/article/details/53580878
三、Telephony数据业务的RILC层
现在,建立移动数据业务的任务通过socket传递给C/C++的RIL进行处理了:
-
hardware\ril\rild\rild.c: -
int main(int argc, char **argv) -
{ -
char libPath[PROPERTY_VALUE_MAX]; -
/**启动rild并解析/init.rc传进来的参数: -
* rild -l /system/lib/libreference-ril.so -- -d /dev/mux2 -
*/ -
for (i = 1; i < argc ;) { -
if (0 == strcmp(argv[i], "-l") && (argc - i > 1)) { -
rilLibPath = argv[i + 1]; // ril库的路径,即"/system/lib/libreference-ril.so" -
i += 2; -
} else if (0 == strcmp(argv[i], "--")) { -
i++; -
hasLibArgs = 1; -
break; -
} else { -
usage(argv[0]); -
} -
} -
/** 启动/system/bin/muxd,生成/dev/mux2节点 */ -
startmux(bpID); -
/** 加载传进来的/system/lib/libreference-ril.so库*/ -
dlHandle = dlopen(rilLibPath, RTLD_NOW); -
if (dlHandle == NULL) { -
RLOGE("dlopen failed: %s", dlerror()); -
exit(-1); -
} -
/** 事件监听 */ -
RIL_startEventLoop(); -
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init"); -
if (rilInit == NULL) { -
RLOGE("RIL_Init not defined or exported in %s\n", rilLibPath); -
exit(-1); -
} -
/**注册事件回调函数 -
*static struct RIL_Env s_rilEnv = { -
* RIL_onRequestComplete, -
* RIL_onUnsolicitedResponse, -
* RIL_requestTimedCallback -
*}; -
*/ -
funcs = rilInit(&s_rilEnv, argc, rilArgv); -
RIL_register(funcs); -
done: -
while(1) { -
sleep(0x00ffffff); -
} -
}
rild用来对RIL进行管理。对于不同的Modem,尤其不同无线通信技术(GSM、CDMA)之间,其差别是很大的;就算是同种技术的Modem,不同厂商也有区别。所以管理部分处理它们共通的业务逻辑,而把具体的实现交给xxxril.so。管理部分涉及文件:hardware\ril\libril\ril.cpp、hardware\ril\libril\ril_event.cpp,本文不对该部分进行分析。
/system/lib/libreference-ril.so库处理AT指令相关操作,/dev/mux2用作数据通道。我们知道,Modem和CPU之间是通过串口连接的,为了使AT指令和数据分开管理,系统对串口进行了复用。原理和实现参见:hardware/ril/gsm0710muxd/src/gsm0710muxd.c。
回到数据业务建立上面。在RIL的具体实现上,每一个操作,比如短信、电话、查询信号强度等都有独有的Request,且RILC/C++和RILJava定义一致。建立数据连接的Request是RIL_REQUEST_SETUP_DATA_CALL:
-
frameworks\opt\telephony\src\java\com\android\internal\telephony\RIL.java -
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);
响应该request的地方是:
-
hardware\ril\reference-ril\reference-ril.c -
/** -
* Call from RIL to us to make a RIL_REQUEST -
*/ -
static void onRequest (int request, void *data, size_t datalen, RIL_Token t) -
{ -
switch (request) { -
case RIL_REQUEST_SETUP_DATA_CALL: -
requestSetupDataCall(data, datalen, t); -
break; -
} -
} -
static void requestSetupDataCall(void *data, size_t datalen, RIL_Token t) -
{ -
char value[PROPERTY_VALUE_MAX] = ""; -
char dns1[64]=""; -
char dns2[64]=""; -
char *cmd; -
int err,i,fd; -
char *response[3] = { "ppp0", "IP", ip_address }; -
RIL_Data_Call_Response_v6 response_v6; -
int mypppstatus; -
char strTemp[32]; -
ATResponse *p_response = NULL; -
char *dialup = NULL; -
int cid = 1; -
int channel = 0; -
char dev_path[32]; -
char gateway[PROPERTY_VALUE_MAX] = ""; -
const char* radioTechnology = ((const char**)data)[0]; -
const char* profile = ((const char**)data)[1]; -
const char* apn = ((const char**)data)[2]; -
const char* user = ((const char**)data)[3]; -
const char* password = ((const char**)data)[4]; -
const char* authType = ((const char**)data)[5]; -
char *auth_option; -
memset(ip_address,0,32); -
LOGD("radioTechnology:%s", radioTechnology); -
LOGD("profile:%s", profile); -
LOGD("apn:%s", apn); -
LOGD("user:%s", user); -
LOGD("password:%s", password); -
LOGD("authType:%s", authType); -
/** -
* 数据业务建立的方式,依据不同Modem而有所不同 -
*/ -
asprintf(&cmd, "/etc/ppp/call-pppd " -
"\"%s 115200\" " // $1 -
"\"novj novjccomp noccp ipcp-accept-local ipcp-accept-remote\" " // $2 -
"\"%s\" \"%s\" " // $3 $4 -
"\"%s\" \"%s\" &", // $5 $6 -
s_pppChannel, user, password, conn_script, disconn_script); -
ret = system(cmd); -
RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0); -
at_response_free(p_response); -
}
据业务建立的方式,依据不同Modem而有所不同,对于PPP方式,Android下的一个实现是通过/etc/ppp/call-pppd脚本进行:
-
/etc/ppp/call-pppd -
#!/system/bin/sh -
# An unforunate wrapper script -
# so that the exit code of pppd may be retrieved -
#PPPD_PID="" -
PPPD_EXIT="" -
/system/bin/setprop "net.gprs.ppp-exit" "" -
/system/bin/pppd $1 debug defaultroute noauth nodetach nocrtscts $2 noipdefault usepeerdns user "$3" password "$4" connect "$5" disconnect "$6" -
PPPD_EXIT=$? -
#PPPD_PID=$! -
/system/bin/setprop "net.gprs.ppp-exit" "$PPPD_EXIT"
call-pppd脚本需要我们传进来6个参数,比如:
-
asprintf(&cmd, "/etc/ppp/call-pppd " -
"\"%s 115200\" " // $1 -
"\"novj novjccomp noccp ipcp-accept-local ipcp-accept-remote\" " // $2 -
"\"%s\" \"%s\" " // $3 $4 -
"\"%s\" \"%s\" &", // $5 $6 -
s_pppChannel, user, password, conn_script, disconn_script); -
ret = system(cmd);
system(const char *command)函数用来执行call-pppd脚本,log:

至此,数据业务建立完成,通过ifconfig命令查看,生成由ppp设备节点。
本文详细介绍了Android系统中数据业务的建立过程,包括RIL层处理、PPP方式的数据连接建立等关键技术点。
6377

被折叠的 条评论
为什么被折叠?



