浅析android下如何通过jni监控wifi(二)

来源:互联网 发布:观星软件 编辑:程序博客网 时间:2024/05/14 03:51
//剔除前导控制字符,将" - "后面的描述字符串作为真实数据,继续处理
    ...
            if (event == STATE_CHANGE) {
                    handleSupplicantStateChange(eventData);
                } else if (event == DRIVER_STATE) {
                    handleDriverEvent(eventData);
                } else {
                    handleEvent(event, eventData);
//对于CONNECTED和DISCONNECTED等netlink事件将执行此操作来处理[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);
//控制界面显示
                    break;
    ...
}
public class WifiStateTracker extends NetworkStateTracker {
    ...
        public void startEventLoop() {
        mWifiMonitor.startMonitoring();//启动上面的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();
//启动MonitorThread线程,等待wpa_supplicant将netlink数据转发过来,然后根据netlink动作类型,进一步影响界面显示[luther.gliethttp].
        }
    ...
}
java/android/android/net/wifi/WifiStateTracker.java
电源管理
private void handleConnectedState() {
    ...
    mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget();
//传递到下面的handleMessage方法
    ...
}
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();//调用
    ...
    private class DhcpHandler extends Handler {

        private Handler mTarget;

        public DhcpHandler(Looper looper, Handler target) {
            super(looper);
            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);//设置电源模式,调用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)) {
//执行dhcp申请ip地址操作
                        event = EVENT_INTERFACE_CONFIGURATION_SUCCEEDED;
                        if (LOCAL_LOGD) Log.v(TAG, "DhcpHandler: DHCP request succeeded");
                    } else {
                        event = EVENT_INTERFACE_CONFIGURATION_FAILED;
                        Log.i(TAG, "DhcpHandler: DHCP request failed: " +
                            NetworkUtils.getDhcpError());
//如果dhcpcd分配ip失败,那么Message.obtain(mTarget, event).sendToTarget();将执行
//WifiNative.disconnectCommand();即:static JNINativeMethod gWifiMethods[] = {
//android_net_wifi_disconnectCommand发送"DISCONNECT"字符串[luther.gliethttp]
//然后在wpa_supplicant服务端执行wpa_supplicant_ctrl_iface_process
//wpa_supplicant_disassociate
                    }
                    synchronized (this) {
                        WifiNative.setPowerModeCommand(DRIVER_POWER_MODE_AUTO);
                    }
                    Message.obtain(mTarget, event).sendToTarget();
                    break;
            }
        }
    }
    ...
    
/**
     * Send the tracker a notification that a connection to the supplicant
     * daemon has been established.
     */

//在上面的public class WifiMonitor=>ensureSupplicantConnection
//=>
//while (!supplicantConnected) {
// boolean connected;
//synchronized (mWifiStateTracker) {
//connected = WifiNative.connectToSupplicant();//如果没有连接成功,那么while循环尝试,直到尝试成功,或者定义了oneShot,仅一次尝试
//=>mWifiStateTracker.notifySupplicantConnection();//如果WifiNative.connectToSupplicant()成功,那么将执行
//mWifiStateTracker.notifySupplicantConnection();的调用.
    void notifySupplicantConnection() {
//向对象发送message
        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 cmdstr[256];

    sprintf(cmdstr, "DRIVER POWERMODE %d", mode);
    return doBooleanCommand(cmdstr, "OK");
}
android_net_wifi_setPowerModeCommand
=>doBooleanCommand
=>doCommand
=>wifi_command
=>wifi_send_command
=>wpa_ctrl_request
=>send给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端口的handler处理函数
  wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
//monitor_conn端口的回调处理函数,处理netlink数据到所有monitor_conn监听端口
=>wpa_supplicant_ctrl_iface_receive
//对于unix通信方式
=>wpa_supplicant_ctrl_iface_process
=>如果wpa_cli发送的是wpa_cli driver 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
=>自定义DRIVER扩展处理函数,所以对于java传递过来的power电源管理命令,wpa_drv_driver_cmd将收到"POWERMODE 0"或者"POWERMODE 1"字符串[luther.gliethttp]
=============================================================================================================

原创粉丝点击