Android-WiFi module-JNI monitoring Wi-Fi network connection, dhcpcd execution, and power supply control

Source: Internet
Author: User

How to monitor Wi-Fi network connection, dhcpcd execution, and power supply control through JNI in Android

========================================================== ========================================================== ==================================
Libs/android_runtime/android_net_wifi_wifi.cpp
Some JNI Interfaces
Static jninativemethod gwifimethods [] = {
{"Loaddriver", "() Z", (void *) android_net_wifi_loaddriver },
{"Setpowermodecommand", "(I) Z", (void *) android_net_wifi_setpowermodecommand}, // Power Management
{"Connecttosupplicant", "() Z", (void *) android_net_wifi_connecttosupplicant },
{"Waitforevent", "() ljava/lang/string;", (void *) android_net_wifi_waitforevent },
{"Disconnectcommand", "() Z", (void *) android_net_wifi_disconnectcommand },
...
};
Int register_android_net_wifi_wifimanager (jnienv * env)
{
...
Return androidruntime: registernativemethods (ENV,
Wifi_pkg_name, gwifimethods, nelem (gwifimethods); // register JNI
}
Libs/android_runtime/androidruntime. cpp
Static const regjnirec gregjni [] = {
...
Reg_jni (register_android_net_wifi_wifimanager ),
...
};
Int androidruntime: starregulatory (jnienv * env)
{
...
Register_jni_procs (gregjni, nelem (gregjni), ENV );
...
}
Androidruntime: Start
=> Starregulatory (ENV): Call method intandroidruntime: starregulatory (jnienv * env)
========================================================== ========================================================== ==================================
Wifi_load_driver
Wifi_start_supplicant
=> Ensure_config_file_exists
// Check whether the/data/MISC/WiFi/wpa_supplicant.conf file exists. If not, dynamically copy one copy from/system/etc/WiFi/wpa_supplicant.conf.
Android_net_wifi_connecttosupplicant
=> Wifi_connect_to_supplicant
=>
Ctrl_conn = wpa_ctrl_open (ifname );
Monitor_conn = wpa_ctrl_open (ifname );
Wpa_ctrl_attach (monitor_conn );

Android_net_wifi_waitforevent
=> Wifi_wait_for_event
=> Wpa_ctrl_recv (monitor_conn, Buf, & nread );
=> Recv (CTRL-> S, reply, * reply_len, 0); // block the Netlink data waiting for wpa_supplicant
=> If the received Buf data zone and Buf [0] is '<', the level information is displayed '... '>' remove the data, and then the wifi_wait_for_event function returns [Luther. gliethttp].
Java/Android/NET/WiFi/wifimonitor. Java
Public class wifimonitor {
...
Public void startmonitoring (){
New monitorthread (). Start (); // start the Java thread
}
Class monitorthread extends thread {
Public monitorthread (){
Super ("wifimonitor ");
}
Public void run (){
For (;;){
Ensuresupplicantconnecti

On (); // => wifinative. connecttosupplicant call the JNI function android_net_wifi_connecttosupplicant
String eventstr = wifinative. waitforevent (); // => call the JNI function android_net_wifi_waitforevent
// Private Static final int connected = 1;
// Private Static final int disconnected = 2;
// Private Static final string eventprefix = "CTRL-EVENT -";
// Private Static final int eventprefixlen = eventprefix. Length ();
// Private Static final string connectedevent = "connected ";
// Private Static final string disconnectedevent = "disconnected ";
String eventname = eventstr. substring (eventprefixlen); // remove "CTRL-EVENT-" String
Int nameend = eventname. indexof (''); // locate the subsequent space position, which is when wpa_supplicant sends
// # Define wpa_event_connected "CTRL-EVENT-CONNECTED", has built-in space.
If (nameend! =-1)
Eventname = eventname. substring (0, nameend );
Int event;
If (eventname. Equals (connectedevent) // detects the action type of the string from Netlink.
Event = connected;
Else if (eventname. Equals (disconnectedevent ))
Event = disconnected;
...
Int ind = eventstr. indexof ("-"); // CTRL-EVENT-CONNECTED-connection...
If (IND! =-1)
Eventdata = eventstr. substring (IND + 3 );
// Remove the leading control character and use the description string after "-" as the real data to continue processing
...
If (event = state_change ){
Handlesupplicantstatecha Nge (eventdata );
} Else if (event = driver_state ){
Handledriverevent (eventdata );
} Else {
Handleevent (event, eventdata); // this operation is performed on Netlink events such as connected and disconnected to process [Luther. gliethttp]
// If Supplicant is gone, exit the thread
If (event = terminating ){
Break;
}
}
...
Void handleevent (INT event, string remainder ){
Switch (event ){
Case disconnected:
Handlenetworkstatechange (Networkinfo. detailedstate. Disconnected, remainder );
Break;

Case connected:
Handlenetworkstatechange(Networkinfo. detailedstate. Connected, remainder); // control interface display
Break;
...
}
Public class wifistatetracker extends networkstatetracker {
...
Public void starteventloop (){
Mwifimonitor. startmonitoring (); // start the above monitorthread
}
...
}
Java/services/COM/Android/Server/wifiservice. Java
Public class wifiservice extends iwifimanager. Stub {
...
Private Boolean setwifienabledblocking (Boolean enable ){
Final int eventualwifistate = Enable? Wifi_state_enabled: wifi_state_disabled;
...
If (enable ){
If (wifinative. loaddriver ()){
Log. E (TAG, "failed to load wi-fi Driver .");
Updatewifistate (wifi_state_unknown );
Return false;
}
If (wifinative. startsupplicant ()){
Wifinative. unloaddriver ();
Log. E (TAG, "failed to start supplicant daemon .");
Updatewifistate (wifi_state_unknown );
Return false;
}
Mwifistatetracker. starteventloop ();
// Start the monitorthread and wait for wpa_supplicant to forward the Netlink data. Then, according to the Netlink action type, the interface displays [Luther. gliethttp].
}
...
}
Java/Android/NET/WiFi/wifistatetracker. Java
Power Management
Private void handleconnectedstate (){
...
Mdhcptarget. obtainmessage (event_dhcp_start). sendtotarget (); // The handlemessage method passed
...
}
Public void onchange (Boolean selfchange ){
...
Handleconnectedstate ();
...
}
Public class wifistatetracker extends networkstatetracker {
...
Public void handlemessage (Message MSG ){
Switch (msg. What ){
Case event_supplicant_connection:
Case event_network_state_changed:
Handleconnectedstate (); // call
...
Private class dhcphandler extends handler {

Private handler mtarget;

Public dhcphandler (Looper, Handler target ){
Super (logoff );
Mtarget = target;
}

Public void handlemessage (Message MSG ){
Int event;
// Private Static final int driver_power_mode_auto = 0;
// Private Static final int driver_power_mode_active = 1;
Switch (msg. What ){
Case event_dhcp_start:
Synchronized (this ){
Wifinative. setpowermodecommand (driver_power_mode_active); // sets the power mode and calls android_net_wifi_setpowermodecommand
}
Log. D (TAG, "dhcphandler: DHCP request started ");
// Libs/android_runtime/android_net_netutils.cpp
// Static jninativemethod gnetworkutilmethods [] = {
// {"Rundhcp", "(ljava/lang/string; landroid/NET/dhcpinfo;) Z", (void *) android_net_utils_rundhcp },
//...
//};

If (networkutils. rundhcp (minterfacename, mdhcpinfo) {// execute the DHCP request IP address operation
Event = event_interface_configuration_succeeded;
If (local_logd) log. V (TAG, "dhcphandler: DHCP requestsucceeded ");
} Else {
Event = event_interface_configuration_failed;
Log. I (TAG, "dhcphandler: DHCP request failed:" +
Networkutils. getdhcperror ());
// If IP Address Allocation fails for dhcpcd, message. Obtain (mtarget, event). sendtotarget ();
// Wifinative. disconnectcommand (); that is, static jninativemethowifimethods [] = {
// Android_net_wifi_disconnectcommand sends the "Disconnect" string [Luther. gliethttp]
// Then run wpa_supplicant on the wpa_supplicant_ctrl_iface_process server.
// Wpa_supplicant_disassociate
}
Synchronized (this ){
Wifinative. setpowermodecommand (driver_power_mode_auto );
}
Message. Obtain (mtarget, event). sendtotarget ();
Break;
}
}
}
...
  
// Public classwifimonitor => ensuresupplicantconnectiOn
// =>
// While (! Supplicantconnected ){
// Boolean connected;
// Synchronized (mwifistatetracker ){
// Connected = wifinative. connecttosupplicant (); // If the connection is not successful, the while loop attempts until the attempt is successful, or if oneshot is defined, only one attempt
// => Mwifistatetracker. yysupplicantconnectiOn (); // If wifinative. connecttosupplicant () is successful,
// Mwifistatetracker. yysupplicantconnectiOn.
Void yysupplicantconnectiOn () {// send a message to the object
Message. Obtain (this, event_supplicant_connection). sendtotarget ();
}
Void notifystatechange (supplicantstate newstate ){
Message. Obtain (this, event_supplicant_state_changed, newstate). sendtotarget ();
}
...
}
Static jboolean android_net_wifi_setpowermodecommand (jnienv * ENV, jobject clazz, jint Mode)
{
Char comment STR [256];

Sprintf (short STR, "Driver powermode % d", mode );
Return dobooleancommand (Response STR, "OK ");
}
Android_net_wifi_setpowermodecommand
=> Dobooleancommand
=> Docommand
=> Wifi_command
=> Wifi_send_command
=> Wpa_ctrl_request
=> Send to wpa_supplicant
Then wpa_supplicant will perform the following receiving operation:
System/extra/wpa_supplicant/Main. c
=> Wpa_supplicant_add_iface
=> Wpa_supplicant_init_iface2
=> Wpa_supplicant_ctrl_iface_init
=> Register the processing function of ctrl_conn control port and monitor_conn listening port
Eloop_register_read_sock (priv-> sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv); // handler processing function of ctrl_conn Port
Wpa_msg_register_cb (wpa_supplicant_ctrl_iface_msg_cb); // callback handler for the monitor_conn port to process Netlink data to all monitor_conn listening ports
=> Wpa_supplicant_ctrl_iface_receive // for Unix communication methods
=> Wpa_supplicant_ctrl_iface_process
=> If wpa_cli sends a command in the form of wpa_cli driverxxx, call this function.
If (OS _strncmp (BUF, "driver", 7) = 0) {// pass the first seven commands directly
Reply_len = wpa_supplicant_driver_cmd (wpa_s, BUF + 7, reply, reply_size );
=> Wpa_supplicant_driver_cmd
=> Wpa_drv_driver_cmd
=> Custom driver extended processing functions. Therefore, for the power management commands passed by Java, wpa_drv_driver_cmd receives the "powermode0" or "powermode 1" string [Luther. gliethttp]
========================================================== ========================================================== ==================================
JNI
=> Rundhcp
=> Android_net_utils_rundhcp
Libs/netutils/dhcp_utils.c
=> Dhcp_do_request
=>
Static const char daemon_name [] = "dhcpcd ";
Static const char daemon_prop_name [] = "init. SVC. dhcpcd ";
Static const char dhcp_prop_name_prefix [] = "DHCP ";
Const char * ctrl_prop = "CTL. Start ";
Const char * desired_status = "running ";
Snprintf (result_prop_name, sizeof (result_prop_name), "% S. % S. Result ",
Dhcp_prop_name_prefix,
Interface );
Property_set (result_prop_name, ""); // sets DHCP. eth0.result = ""; after DHCP is successfully completed,
Property_set (ctrl_prop, daemon_name); // send the "Ctrl. Start" Start command to the service named dhcpcd, which is in init. RC.
// Dhcpcd service process command in init. RC
// Service dhcpcd/system/bin/dhcpcd eth0
// Disabled
// Oneshot
Wait_for_property (daemon_prop_name, desired_status, 10 );
// Init. c => INIT process
// => Handle_property_set_fd is called to process control information because it is a "Ctrl. Start" command.
// => Handle_control_message
// => Msg_start
// =>
// Struct Service * SVC = service_find_by_name (name );
// Service_start (SVC); // start SVC, that is, run:/system/bin/dhcpcd eth0
// => Service_start
// => Pid = fork ();
// If (pid = 0) execve (SVC-> ARGs [0], (char **) SVC-> ARGs, (char **) ENV ); execve the sub-process to run/system/bin/dhcpcd. The parameter is eth0.
// => Otherwise, the parent process, that is, the INIT process will
// => Policy_service_state (SVC-> name, "running"); sets the status of the SVC prop
// Snprintf (pname, sizeof (pname), "init. SVC. % s", name );
// Property_set (pname, State); // in this case, wait_for_property (daemon_prop_name, desired_status, 10) above can pass [Luther. gliethttp] Normally.
Wait_for_property (result_prop_name, null, 15); // wait for DHCP. eth0.result = not empty
========================================================== ========================================================== ==================================
System/extra/dhcpcd-4.0.0-beta9/dhcpcd. c
Dhcpcd
=> Main
# Define sysconfdir "/system/etc/dhcpcd"
# Define package "dhcpcd"
# Define config sysconfdir "/" package ". conf"
# Define libexecdir "/system/etc/dhcpcd"
# Define script libexecdir "/" package "-run-hooks"
=> Strlcpy (options-> script, script, sizeof (options-> script )); // default options-> script = "/system/etc/dhcpcd-run-hooks"
=> F = fopen (CF? Cf: config, "R"); // If the. conf file is not specified, use the default. conf file.
=> Parse_config_line // parse "/system/etc/dhcpcd. conf" Default Configuration File
=> Parse_option
=> If there is a "script" section in "/system/etc/dhcpcd. conf ",
=> Then execute strlcpy (options-> script, oarg, sizeof (options-> script); directly copy

=> Dhcp_run
=> Handle_dhcp_packet
=> Handle_dhcp
=> Bind_dhcp
Reason = "timeout"; reason = "Bound"; reason = "rebind"; reason = "renew ";
System/extra/dhcpcd-4.0.0-beta9/configure. c
=> Configure (iface, reason, State-> new, state-> old, & State-> lease, options, 1 );
// If DHCP times out or DHCP succeeds, exec_script is called to execute the script,
// Execute setprop DHCP. $ {interface}. Result "failed" or
// Execute setprop DHCP. $ {interface}. Result "OK"
=> Exec_script (options, iface-> name, reason, null, old );
=> Configure_env then passes the reason to the script through the Environment Variable
Int exec_script (const struct options * options, const char * iface, const char * reason,
Const struct dhcp_message * dhcpn, const structdhcp_message * dhcpo)
=> Pid = fork ();
=> If (pid = 0) execve (options-> script, argv, ENV); // The sub-process executes the script, default Value: "/system/etc/dhcpcd-run-hooks"
// The dhcpcd-run-hooks script determines whether to execute the corresponding files in the system/etc/dhcpcd-hook/* directory based on the level value.
// Our system has the following three files in the system/etc/dhcpcd-hook/* directory:
// 95-configured
// 20-dns.conf
// 01-test
=> The parent process returns while (waitpid (PID, & status, 0) =-1) waiting for the sub-process script to be executed.

System/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/20-dns.conf
System/extra/dhcpcd-4.0.0-beta9/dhcpcd-hooks/95-configured
...
Setprop DHCP. $ {interface}. IPaddress "$ {new_ip_address }"
Setprop DHCP. $ {interface}. Result "OK" // set the property to OK.
Setprop DHCP. $ {interface}. Result "failed"
...
========================================================== ========================================================== ==================================
Inet_init, tcp_prot
Sock-> OPS-> sendmsg (iocb, Sock, MSG, size );
=> Inetsw_array []
=> Inet_stream_ops
=> Tcp_sendmsg
========================================================== ========================================================== ==================================
Wpa_cli.c
=> Main
=> Wpa_cli_interactive
=> Wpa_cli_recv_pending (monitor_conn,); // blocking waits for wpa_supplicant to send data
=> If action_monitor is true, some simple processing operations will be performed. Otherwise, the data sent from wpa_supplicant will be printed directly to the console [Luther. gliethttp]

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.