Краткий анализ того, как контролировать сетевое соединение Wi -Fi, выполнение DHCPCD и управление источником питания через JNI под Android
=============================================== =============================================== =========
libs/android_runtime/android_net_wifi_wifi.cpp
Часть интерфейса JNI
Статический jninativemethod gwifimethods [] = {
{"loaddriver", "() z", (void *) android_net_wifi_loaddriver},
{"setPowerModeCommand", "(i) z", (void*) android_net_wifi_setpowermodecommand}, // управление питанием
{"connecttosupplicant", "() z", (void *) android_net_wifi_connecttosupplicant},
{"waitforevent", "() ljava/lang/string;", (void*) android_net_wifi_waitforevent},
{"DinnonnectCommand", "() z", (void *) android_net_wifi_disconnectcommand},
...
};
int Register_android_net_wifi_wifimanager (jnienv* env)
{
...
вернуть AndroidRuntime :: RegisterNativeMethods (env,
Wifi_pkg_name, gwifimethods, nelem (gwifimethods)); // jni
}
libs/android_runtime/androidruntime.cpp
статический констант regjnirec gregjni [] = {
...
Reg_jni (Register_android_net_wifi_wifimanager),
...
};
int androidruntime :: startreg (jnienv* env)
{
...
Register_jni_procs (gregjni, nelem (gregjni), env);
...
}
AndroidRuntime :: Start
=> Startreg (env) называет метод int androidruntime :: startreg (jnienv* env)
=============================================== =============================================== =========
wifi_load_driver
wifi_start_supplicant
=> Убедитесь, что_CONFIG_FILE_EXISTS
// Существует ли файл /data/misc/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); // Блокировка и ожидание данных netlink wpa_supplicant
=> Если в полученной области данных BUF, BUF [0] является '<', это означает, что есть информация о уровне, поэтому данные «<'...'> 'удаляются, а затем функция WiFi_wait_for_event возвращается [Luther. gliethttp].
Java/Android/Android/Net/WiFi/Wifimonitor.java
открытый класс Wifimonitor {
...
public void startMonitoring () {
New MonitorThreadRead (). Start (); // Start Java Thread
}
класс MonitorThread Extends Thread {
public monitorThread () {
Super ("Wifimonitor");
}
общественный недействительный запуск () {
для (;;) {
обеспечить upplicantConnection (); // => wifinative.connecttosupplicant вызывает функцию jni android_net_wifi_connecttosupplicant
String eventstr = wifinative.waitforevent (); // => вызовать функцию jni android_net_wifi_waitforevent
// частный статический конечный int connection = 1;
// частное статическое окончательное окончание int отключить = 2;
// частная статическая конечная строка EventPrefix = "ctrl-event-";
// private static final int eventPrefixlen = eventPrefix.length ();
// частная статическая конечная строка ConnecteVent = "Connected";
// частная статическая конечная строка Disconnedevent = "Densuncted";
String EventName = Eventtr.Substring (EventPrefixLen); // Удалить строку "ctrl-event-"
int nameend = eventname.indexof (''); // Найти последующую позицию в пространстве, которая и когда WPA_Supplicant отправляется
//#определить встроенные пространства WPA_EVENT_CONNECTED "CTRL-EVENT-Connected".
if (nameend! = -1)
EventName = EventName.SubString (0, nameend);
INT событие;
if (eventname.equals (connecteVent)) // Обнаружение типа действия строки из netlink
Event = подключено;
else if (eventname.equals (deanconedevent))
event = отключить;
...
int ind = eventstr.indexof (" -"); // ctrl -event -connected - соединение с ...
if (ind! = -1)
EventData = EventTr.SubString (Ind + 3);
// Удалить ведущие элементы управления, использовать строку описания после «-» в качестве реальных данных и продолжить обработку
...
if (event == state_change) {
HandlesUpplicantStateChange (EventData);
} else if (event == Driver_state) {
обработчик RideRiveRevent (EventData);
} еще {
handleevent (Event, EventData); // Для событий NetLink, таких как подключенная и отключенная, эта операция будет выполнена для обработки [luther.gliethttp]
// Если пропасть исчез, выйдите из потока
if (event == завершение) {
перерыв;
}
}
...
void handleevent (int event, string storing) {
Switch (Event) {
Случай отключен:
HandlenetWorkStateChange (networkInfo.detailedState.disconnected, остаток);
перерыв;
Случай связан:
HandlenetWorkStateChange (NetworkInfo.detailedState.connected, остаток); // дисплей управления интерфейсом
перерыв;
...
}
открытый класс WifistateTracker Extends NetworkstateTracker {
...
public void starteventLoop () {
mwifimonitor.startmonitoring (); // Запуск вышеуказанного потока MonitorThread
}
...
}
java/services/com/android/server/wifiservice.java
открытый класс Wifiservice Extens iwifimanager.stub {
...
Private Boolean SetwifienabledBlocking (boolean inable) {
final int vesurnwifistate = enable?
...
if (inable) {
if (wifinative.loaddriver ()) {
Log.e (Tag, "не удалось загрузить драйвер Wi-Fi.");
UpdateWifistate (wifi_state_unknown);
вернуть ложь;
}
if (wifinative.startsupplicant ()) {
Wifinative.unloaddriver ();
Log.e (Tag, "не удалось начать пропущенный демон.");
UpdateWifistate (wifi_state_unknown);
вернуть ложь;
}
mwifistatetracker.starteventloop ();
// Запустите поток MonitorThread, подождите, пока wpa_supplicant для пересылания данных netlink, а затем повлияет на отображение интерфейса в соответствии с типом действия Netlink [luther.gliethttp].
}
...
}
Java/Android/Android/Net/Wi -Fi/WifistateTracker.java
Управление питанием
private void handleconnectedState () {
...
mdhcptarget.obtainmessage (event_dhcp_start) .sendtotarget ();
...
}
public void onchange (логический самостоятель) {
...
HandleConnectedState ();
...
}
открытый класс WifistateTracker Extends NetworkstateTracker {
...
public void handlemessage (сообщение msg) {
Switch (msg.what) {
case event_supplicant_connection:
case event_network_state_changed:
HandleConnectedState (); // Вызов
...
Частный класс Dhcphandler Extends Handler {
частный обработчик Mtarget;
public dhcphandler (Looper Looper, Target) {
супер (Looper);
mtarget = target;
}
public void handlemessage (сообщение msg) {
INT событие;
// private static final int driver_power_mode_auto = 0;
// private static final driver_power_mode_active = 1;
Switch (msg.what) {
case event_dhcp_start:
синхронизированный (это) {
Wifinative.setPowerModeCommand (driver_power_mode_active); // Установите режим питания и вызовите Android_net_wifi_setpowermodecommand
}
Log.d (Tag, "dhcphandler: запуск запроса DHCP");
//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)) {// Выполнить приложение DHCP для операции IP -адреса
event = Event_Interface_Configuration_SuceDEDED;
if (local_logd) log.v (Tag, "dhcphandler: DHCP -запрос преуспел");
} еще {
Event = Event_Interface_Configuration_Failed;
Log.i (тег, "Dhcphandler: DHCP -запрос не удастся:" +
Networkutils.getdhcperror ());
// Если DHCPCD не может выделить IP, то сообщение
//Wifinative.disconnectCommand ();
// android_net_wifi_disconnectcommand отправляет "Dinnoncect" string [luther.gliethttp]
// затем выполнить WPA_SUPPLICANT_CTRL_IFACE_PROCESS на сервере WPA_SUPPLICANT
// wpa_supplicant_disassociate
}
синхронизированный (это) {
Wifinative.setPowerModeCommand (Driver_power_mode_auto);
}
Message.obtain (mtarget, event) .sendtotarget ();
перерыв;
}
}
}
...
/**
* Отправить трекер уведомление о том, что соединение с проклятием
* Демон был создан.
*/
// в приведенном выше публичном классе wifimonitor => ansupplicantconnection
// =>
// while (! suplicantConnected) {
// логическое соединение;
// синхронизированный (mwifistateTracker) {
// connection = wifinative.connecttosupplicant (); // Если соединение не успешное, то цикл wha
//=> mwifistateTracker.notifysupplicantConnection() ;//if wifinative.connecttosupplicant () удастся, он будет выполнен
// Call of mwifistateTracker.notifysupplicantConnection ();.
void notifySupplicantConnection () {// Отправить сообщение в объект
Message.obtain (это, event_supplicant_connection) .sendtotarget ();
}
void notifystateChange (SupplyState NewState) {
Message.obtain (это, event_supplicant_state_changed, newstate) .sendtotarget ();
}
...
}
Статический jboolean android_net_wifi_setpowermodecommand (jnienv* env, jobject clazz, jint mode)
{
char cmdstr [256];
sprintf (cmdstr, "Driver PowerMode %d", Mode);
вернуть dobooleancommand (cmdstr, "ok");
}
android_net_wifi_setpowermodecommand
=> dobooleancommand
=> DoCommand
=> wifi_command
=> wifi_send_command
=> wpa_ctrl_request
=> Отправить в wpa_supplicant
Затем WPA_SUPPLICANT выполнит следующие операции по получению:
System/extra/wpa_supplicant/main.c
=> wpa_supplicant_add_iface
=> wpa_supplicant_init_iface2
=> wpa_supplicant_ctrl_iface_init
=> Зарегистрировать функции обработки порта управления CTRL_CONN и порта прослушивания Monitor_conn
eloop_register_read_sock (priv-> sock, wpa_supplicant_ctrl_iface_receive, wpa_s, priv); // Функция обработки обработки обработки Ctrl_conn
WPA_MSG_REGISTER_CB (WPA_SUPPLICANT_CTRL_IFACE_MSG_CB); // Функция обработки обработки обратного вызова порта мониторинга_Конн, обрабатывает данные netlink во все порты прослушивания Monitore_conn
=> WPA_SUPPLICANT_CTRL_IFACE_RECEIVE // для метода связи UNIX
=> wpa_supplicant_ctrl_iface_process
=> Если wpa_cli отправляет команду в форме драйвера wpa_cli xxx, то вызовите эту функцию
if (os_strncmp (buf, "Driver", 7) == 0) {// Пропустить первый 7 и напрямую передавать команду
reply_len = wpa_supplicant_driver_cmd (wpa_s, buf + 7, reply, reply_size);
=> wpa_supplicant_driver_cmd
=> wpa_drv_driver_cmd
=> Настройте функцию обработки расширения драйвера, поэтому для команды управления питанием, передаваемой Java, WPA_DRV_DRIVER_CMD получит «PowerMode 0» или «PowerMode 1».
=============================================== =============================================== =========
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,
интерфейс);
Property_set (result_prop_name, ""); // set dhcp.eth0.result = "";
Property_set (ctrl_prop, daemon_name); // Отправить слово «ctrl.start» команды запуска в службу с именем dhcpcd, который находится в init.rc
// DHCPCD Сервисное процесс команды команды в init.rc
// обслуживание dhcpcd/system/bin/dhcpcd eth0
// неполноценный
// OneShot
wait_for_property (daemon_prop_name, desired_status, 10);
//init.c=> Инитно процесс
// => harder_property_set_fd - это командное слово «ctrl.start», поэтому для обработки управляющего сообщения вызывается лячных_контрол_message.
// => harder_control_message
// => msg_start
// =>
// Служба struct *svc = service_find_by_name (name);
// service_start (svc); // start svc, то есть execute:/system/bin/dhcpcd eth0
// => service_start
// => pid = fork ();
// if (pid == 0) execve (svc-> args [0], (char **) svc-> args, (char **) env); , параметры для ETH0
// => в противном случае родительский процесс, то есть процесс инициирования будет
// => notify_service_state (svc-> name "running");
// snprintf (pname, sizeof (pname), "init.svc.%s", name);
// Property_set (pname, state); // Таким образом, wait_for_property (daemon_prop_name, desire_status, 10);
waist_for_property (result_prop_name, null, 15); // ждать dhcp.eth0.result = non null
=============================================== =============================================== =========
System/Extra/DHCPCD-4.0.0-BETA9/DHCPCD.C.
DHCPCD
=> Главный
#define sysconfdir "/system/etc/dhcpcd"
#define пакет "dhcpcd"
# определить config sysconfdir "/" package ".conf"
# определить libexecdir "/system/etc/dhcpcd"
# определить сценарий libexecdir "/" пакет "-run-hooks"
=> strlcpy (options-> script, script, sizeof (options-> script)); // options-> script = "/system/etc/dhcpcd/dhcpcd-run-hooks"
=> f = fopen (cf? cf: config, "r"); // Если файл .conf не указан, используйте файл по умолчанию .conf
=> parse_config_line // parse "/system/etc/dhcpcd/dhcpcd.conf" Файл конфигурации по умолчанию
=> parse_option
=> Если есть раздел «Скрипт» в «/system/etc/dhcpcd/dhcpcd.conf"
=> Затем выполнить strlcpy (options-> script, oarg, sizeof (options-> script));
/*
{"script", udent_argument, null, 'c'},
{"опция", обязательный_аргумент, null, 'o'},
Часть контента в «/system/etc/dhcpcd/dhcpcd.conf» заключается в следующем:
...
опция domain_name_servers, domain_name, domain_search, host_name
...
*/
=> dhcp_run
=> handle_dhcp_packet
=> handle_dhcp
=> bind_dhcp
причина = "тайм -аут"; причина = "bound"; counse = "repind"; couns = "revenew";
System/Extra/DHCPCD-4.0.0-BETA9/configure.c
=> configure (iface, anouse, state-> new, state-> old, & state-> аренда, опции, 1);
// Если DHCP Times Out или DHCP достигнут успеха, exc_script будет вызван для выполнения скрипта.
// Выполнить SetProp DHCP. $ {Interface} .result "не удастся" или
// Выполнить SetProp DHCP. $ {Interface} .Result "OK"
=> exec_script (options, iface-> name, ancome, null, old);
=> Затем configure_env передает причину в сценарий через переменную среды
int exec_script (const struct options *options, const char *iface, const char *conse,
const struct dhcp_message *dhcpn, const struct dhcp_message *dhcpo)
=> pid = fork ();
=> if (pid == 0) execve (options-> script, argv, env); // Дочерний процесс выполняет скрипт, по умолчанию "/system/etc/dhcpcd/dhcpcd-run-hooks"
// скрипт DHCPCD-Run-Hooks решит, выполнить ли соответствующие файлы в каталоге System/ETC/DHCPCD/DHCPCD-Hook/* на основе значения уровня
// Наша система имеет следующие 3 файла в системе/etc/dhcpcd/dhcpcd-hook/*
// 95-конфигурированный
//20-dns.conf
// 01-тест
=> Родительский процесс возвращается в то время как (waitpid (pid и status, 0) == -1) и ожидает выполнения сценария дочернего процесса завершить
System/Extra/DHCPCD-4.0.0-BETA9/DHCPCD-Hooks/20-DNS.CONF
System/Extra/DHCPCD-4.0.0-BETA9/DHCPCD-Hooks/95-конфигурированный
...
SetProp DHCP. $ {interface} .ipaddress "$ {new_ip_address}"
SetProp DHCP. $ {интерфейс} .Result "OK" // Установить атрибут на OK
SetProp DHCP. $ {интерфейс} .Result "не удастся"
...
=============================================== =============================================== =========
inet_init, tcp_prot
sock-> ops-> sendmsg (iocb, sock, msg, size);
=> inetsw_array []
=> inet_stream_ops
=> tcp_sendmsg
=============================================== =============================================== =========
wpa_cli.c
=> Главный
=> wpa_cli_interactive
=> wpa_cli_recv_pending (monitor_conn, 0, 0); // Блокирование и ожидание WPA_Supplicant отправлять данные
=> Если action_monitor правда, будут выполнены некоторые простые операции обработки, в противном случае данные, отправленные WPA_Supplicant, будут напечатаны непосредственно на консоли [luther.gliethttp].