android_net_wifi_startSupplicant这个就是jni函数
=>wifi_start_supplicant
static const
char SUPP_CONFIG_TEMPLATE[]=
"/system/etc/wifi/wpa_supplicant.conf";
static const
char SUPP_CONFIG_FILE[]
= "/data/misc/wifi/wpa_supplicant.conf";
=>ensure_config_file_exists该函数将SUPP_CONFIG_TEMPLATE文件拷贝到SUPP_CONFIG_FILE目录下,然后chown改变SUPP_CONFIG_FILE属组
=>control_supplicant(1),开启wpa_supplicant.
首先会检测当前property_get(SUPP_PROP_NAME, supp_status,
NULL)是否已经开启,如果没有,那么调用
property_set(ctrl_prop, SUPPLICANT_NAME);设置prop来开启,然后最长等待20s,直到期望的控制状态正确.
也就是等待system/rootdir/init.rc脚本中名为wpa_supplicant的服务进程运行.
system/rootdir/init.rc脚本中的service后台服务进程定义如下:
...
service wpa_supplicant /system/bin/wpa_supplicant
-Dwext -ieth0
-c/data/misc/wifi/wpa_supplicant.conf
disabled
...
static const
char SUPPLICANT_NAME[]
= "wpa_supplicant";
"wpa_supplicant"为prop字符串,上面property_set(ctrl_prop, SUPPLICANT_NAME);
=>handle_property_set_fd 如果为"ctl."字符串,那么将调用service服务进程控制函数
if(memcmp(msg.name,"ctl.",4)
== 0)
{
handle_control_message((char*) msg.name
+ 4,
(char*) msg.value);
}
=>handle_control_message
=>msg_start
=>service_start
execve(svc->args[0],
(char**) svc->args,
(char**) ENV);
//执行/system/bin/wpa_supplicant程序,为什么是这个,如下:[luther.gliethttp]
/init/init.c进程是这样对service后台服务进程解析的
1.parse_config_file("/init.rc");
2.printf(tmp,
"/init.%s.rc", hardware);
parse_config_file(tmp);
3.sprintf(tmp,
"/system/etc/init.%s.rc", hardware);
parse_config_file(tmp);
parse_config_file
=>parse_config
=>state->context
= parse_service(state, nargs, args)
=>
nargs -= 2;
svc->name
= args[1];
svc->classname
= "default";
memcpy(svc->args, args
+ 2,
sizeof(char*)
* nargs);
//这样svc->args[0]..[3]为"/system/bin/wpa_supplicant -Dwext -ieth0 -c/data/misc/wifi/wpa_supplicant.conf"了[luther.glithttp]
svc->args[nargs]
= 0;//参数结尾添0
svc->nargs
= nargs;
list_add_tail(&service_list,
&svc->slist);
=>state->parse_line
= parse_line_service;
=>parse_line_service
那么handle_property_set_fd又是怎么来的呢,那么我们继续看,
init/init.c第一个kernel启动的用户空间引用程序:
int main(int argc,
char **argv)
{
...
property_set_fd = start_property_service();
...
ufds[1].fd
= property_set_fd;
ufds[1].events
= POLLIN;
...
for(;;)
{
...
nr = poll(ufds, 3, timeout);
//做poll等待[luther.gliethttp].
...
if
(ufds[1].revents
== POLLIN)
handle_property_set_fd(property_set_fd);//从java层通过unix管道传来了控制数据,java层执行的reboot和powerdown操作也由该函数处理.
..
}
...
return 0;
}
#define PROP_SERVICE_NAME
"property_service"
int start_property_service(void)
{
...
fd = create_socket(PROP_SERVICE_NAME,
SOCK_STREAM, 0666, 0, 0);
...
listen(fd, 8);
return fd;
}
#define ANDROID_SOCKET_DIR "/dev/socket"
int create_socket(const
char *name,
int type, mode_t perm, uid_t uid, gid_t gid)
{
...
snprintf(addr.sun_path,
sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
name);
...
}
所以这个property_set的unix通信文件位于:"/dev/socket/property_service"下.
当然java的jni应用程序链接调用的是system/lib/libandroid_runtime.so这个so库中的服务,不过和init中的没有区别[luther.gliethttp].
android通过jni控制wifi service服务的流程分析
最新推荐文章于 2025-06-25 16:16:43 发布