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

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].

更多相关文章

  1. [置顶] Android上传文件到Web服务器,PHP接收文件(二)
  2. 基于Apache mina 的android 客户端tcp长连接实现
  3. 浅析android通过jni控制service服务程序的简易流程
  4. Android(安卓)Jetpack-ViewModel
  5. Android访问WCF服务(使用json实现参数传递)
  6. Android灯光系统(硬件访问服务框架)
  7. ANDROID AIDL
  8. android socket编程实例
  9. 《Android和PHP最佳实践》官方站

随机推荐

  1. android是什么
  2. 有关Android线程的学习
  3. Android(安卓)Sensor传感器系统架构初探
  4. android中AVD的使用
  5. 初识Android
  6. 【转】有关Android线程的学习
  7. 【Android】Android开发规范详解
  8. Android智能电视应用程序开发浅谈(一)
  9. Android单元测试初探——Instrumentation
  10. android:layout_gravity 和 android:grav