浅析android通过jni控制service服务程序的简易流程

android_net_wifi_startSupplicant这个就是jni函数
=>wifi_start_supplicant
staticconstcharSUPP_CONFIG_TEMPLATE[]="/system/etc/wifi/wpa_supplicant.conf";
staticconstcharSUPP_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
...

staticconstcharSUPPLICANT_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启动的用户空间引用程序:
intmain(intargc,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操作也由该函数处理.
..
}
...
return0;
}

#definePROP_SERVICE_NAME"property_service"
intstart_property_service(void)
{
...
fd=create_socket(PROP_SERVICE_NAME,SOCK_STREAM,0666,0,0);
...
listen(fd,8);
returnfd;
}
#defineANDROID_SOCKET_DIR"/dev/socket"
intcreate_socket(constchar*name,inttype,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中的没有区别

更多相关文章

  1. Android之应用程序基础
  2. android(NDK+JNI)---Eclipse+CDT+gdb调试android ndk程序
  3. 第三章 Android程序设计基础
  4. [置顶] Android 跨进程通信Aidl的使用及注意事项
  5. 开机引导程序只执行一次的方法
  6. Android 开机自启动程序
  7. android获取正在运行的进程
  8. Android例子—直接通过Binder的onTransact完成跨进程通信
  9. AndRoid完全退出程序

随机推荐

  1. Android listview中嵌套Checkbox的布局文
  2. Android -- ViewRoot,关于子线程刷新UI
  3. iOS vs Android 系统架构
  4. Android系统启动流程分析
  5. 分环境配置
  6. SQLite的使用
  7. Android引用ttf图标字体库
  8. Android RSA 与标准Java RSA实现区别
  9. 通读Android文档系列 THREE
  10. Android仿人人客户端