浅析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. 基于Apache mina 的android 客户端tcp长连接实现
  2. 《Android和PHP最佳实践》官方站
  3. Android核心分析(21)----Android应用框架之AndroidApplication
  4. 箭头函数的基础使用
  5. Python技巧匿名函数、回调函数和高阶函数
  6. 浅析android通过jni控制service服务程序的简易流程
  7. Android(安卓)Service AIDL
  8. Android(安卓)bluetooth介绍(四): a2dp connect流程分析
  9. Android架构分析之使用自定义硬件抽象层(HAL)模块

随机推荐

  1. 超全的pandas数据分析常用函数总结:上篇
  2. 10 行 Python 代码,批量压缩图片 500 张,简
  3. 聊聊 Python 的内置电池
  4. 一文读懂 Serverless,将配置化思想复用到
  5. 当 Python 中混进一只薛定谔的猫……
  6. 为什么 Python 3 把 print 改为函数?
  7. 如何用python制作动态二维码,来哄女朋友开
  8. MySQL 8 OCP(1Z0-908)认证考试题库原题(第
  9. 肝了一个月的编程导航诞生!轻松发现优质编
  10. mysql 常用命令