http://blog.chinaunix.net/u2/66024/showart_1933469.html

浅析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] .
转自:http://blog.chinaunix.net/u1/38994/showart_1178284.html

更多相关文章

  1. 箭头函数的基础使用
  2. Python技巧匿名函数、回调函数和高阶函数
  3. 浅析android通过jni控制service服务程序的简易流程
  4. Android(安卓)Service AIDL
  5. Android(安卓)bluetooth介绍(四): a2dp connect流程分析
  6. Android架构分析之使用自定义硬件抽象层(HAL)模块
  7. 2011年Android(安卓)Camera学习笔记之一
  8. android 定位服务
  9. 【安卓笔记】android客户端与服务端交互的三种方式

随机推荐

  1. Android身份证件识别的OCR技术SDK
  2. Android触摸屏驱动屏幕翻转
  3. android常用调试工具fiddle、wireshark和
  4. 关于Android的自动化测试,你需要了解的5个
  5. android之wifi开发
  6. [转]Android都支持那些Java特性
  7. Android 的提权 (root) 原理是什么?修改
  8. 【入门篇】Android学习笔记——常用布局
  9. Android cardview覆盖问题
  10. android为HttpClient和HttpURLConnection