Wifi知识点累积

一: Wifi热点后台定时扫描间隔

1.如果在 xml 设置了 "wifi_supplicant_scan_interval_ms" 【Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS】项 那么wifi扫描间 优先取这个值

2.如果是亮屏 使用 config_wifi_supplicant_scan_interval   大约15秒当做间隔
<integer translatable="false" name="config_wifi_supplicant_scan_interval">15000</integer>

3.如果是灭屏 使用 config_wifi_framework_scan_interval    大约5分钟 当做间隔
<integer translatable="false" name="config_wifi_framework_scan_interval">300000</integer>

分析如下:
4.WifiStateMachine.java
public static final String WIFI_SUPPLICANT_SCAN_INTERVAL_MS ="wifi_supplicant_scan_interval_ms";   //wifi扫描间隔设置项 

mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),
Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
PowerManager.isScreenOn() ? mContext.getResources().getInteger(R.integer.config_wifi_supplicant_scan_interval) 
 : mContext.getResources().getInteger(R.integer.config_wifi_framework_scan_interval));
 
mWifiNative.setScanInterval((int) mSupplicantScanIntervalMs / 1000);

5.SwitchToWifiUtils.java
public void setAlarm() {
int mSupplicantScanIntervalMs = Settings.Global.getLong(
                    context.getContentResolver(),
                    Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,
                    context.getResources().getInteger(com.android.internal.R.integer.config_wifi_supplicant_scan_interval));

long time = SystemClock.elapsedRealtime()+ (mPowerManager.isScreenOn() ? mSupplicantScanIntervalMs : context.getResources().getInteger(R.integer.config_wifi_framework_scan_interval));
Intent intent = new Intent("com.android.settings.action.START_SCAN_WIFI"); // Wifi扫描的Action
PendingIntent mPendingIntent = PendingIntent.getBroadcast(context,0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager.set(AlarmManager.ELAPSED_REALTIME, time, mPendingIntent); //在AlarMmanager设置在time时间后执行发送mPendingIntent
}


亮屏  灭屏 后台自动扫描的LOG
adb logcat | findstr "CTRL-EVENT-SCAN-STARTED"
09-30 15:57:02.441  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 15:57:02.441  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 15:57:02.445  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED
09-30 15:57:08.439  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 15:57:08.439  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 15:57:08.443  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED

【大概6秒】
09-30 15:57:14.470  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 15:57:14.471  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 15:57:14.472  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED


【大概6秒】
09-30 15:57:20.498  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 15:57:20.498  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 15:57:20.504  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED

【大概6秒】
09-30 15:57:26.568  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 15:57:26.568  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 15:57:26.569  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED

【五分钟】
09-30 16:02:22.272  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 16:02:22.272  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 16:02:22.275  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED

【五分钟】
09-30 16:07:22.267  1001 27326 D WifiHW  : [1] get event: IFNAME=wlan0 <3>CTRL-EVENT-SCAN-STARTED
09-30 16:07:22.267  1001 27326 D WifiHW  : [2] get event: IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED
09-30 16:07:22.273  1001 27326 E WifiMonitor: handleEvent unknown: 14  CTRL-EVENT-SCAN-STARTED



二: Wif的Mac地址获取流程分析

WIFI的Mac地址获取流程( 未完待续 )

cat /sys/class/net/wlan0/address   ##查看mac地址

#1.APP层
WifiManager mWifiManager = (WifiManager) getActivity().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
wifiInfo.getMacAddress();

#2. android.net.WifiInfo.java
public class WifiInfo implements Parcelable {
public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
private String mMacAddress = DEFAULT_MAC_ADDRESS;

    public String getMacAddress() {
        return mMacAddress;
    }
	
    public WifiInfo(WifiInfo source) {
	......
	mMacAddress = source.mMacAddress;
	......
	}
	
    public void setMacAddress(String macAddress) {
        this.mMacAddress = macAddress;
    }
}

#3. frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMachine.java
public class WifiStateMachine {
WifiInfo  mWifiInfo;
WifiNative  mWifiNative;

public WifiStateMachine(Context context, String wlanInterface,WifiTrafficPoller trafficPoller) {
	mWifiNative = new WifiNative(mInterfaceName);	
    mWifiInfo = new WifiInfo();
    mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
	}
}

        
#4. frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiNative.java

// 调用本地的 doStringCommand 方法得到一个字符串   "MACADDR=XX.XX.XX.XX.XX.XX" 然后分割返回 XX.XX.XX.XX.XX.XX
    public String getMacAddress() {
//Macaddr = XX.XX.XX.XX.XX.XX
        String ret = doStringCommand("DRIVER MACADDR"); 
        if (!TextUtils.isEmpty(ret)) {
            String[] tokens = ret.split(" = ");
            if (tokens.length == 2) return tokens[1];
        }
        return null;
    }
	
    private static int sCmdId; // 一个用于标记发送命令的标志 每次发送自增
	private static int getNewCmdIdLocked() {
        return sCmdId++;
    }

	interfaceName = "wlan0";
	mInterfacePrefix ="IFNAME=" + interfaceName + " ";
	
    private String doStringCommand(String command) {
        synchronized (mLock) {
            int cmdId = getNewCmdIdLocked();
            String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command; //类似于 88:IFNAME=wlan0 DRIVER MACADDR
			
//调用本地 doStringCommandNative方法(Java层的JNI方法) 方法传入 IFNAME=wlan0 DRIVER MACADDR  
            String result = doStringCommandNative(mInterfacePrefix + command); 
            if (result == null) {
                if (DBG) Log.d(mTAG, "doStringCommandNative no result");
            } else {
                if (!command.startsWith("STATUS-")) {
                    localLog(toLog + " -> " + result);
                }
            }
            return result;
        }
    }



private native String doStringCommandNative(String command); //JNI方法调用到  com_android_server_wifi_WifiNative.cpp JNI文件

#4.frameworks\opt\net\wifi\service\jni\com_android_server_wifi_WifiNative.cpp  包含 Wifi.h Wifi.cpp 的引用
// 找到对应的 C方法  android_net_wifi_doStringCommand
{"doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;",(void*) android_net_wifi_doStringCommand } 


static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring javaCommand) {
    return doStringCommand(env,javaCommand);
}

#define REPLY_BUF_SIZE 4096 
static jstring doStringCommand(JNIEnv* env, jstring javaCommand) {
    char reply[REPLY_BUF_SIZE]= {0}; // 4096个字节的字符串
    if (!doCommand(env, javaCommand, reply, sizeof(reply))) { //调用本地 doCommand 方法  reply是C语言的字符数组
        return NULL;
    }
    return env->NewStringUTF(reply); // 把reply是C语言的字符数组 转为JAVA 可识别的字符 返回
}



static bool doCommand(JNIEnv* env, jstring javaCommand,char* reply, size_t reply_len) {
    ScopedUtfChars command(env, javaCommand); // 把 jstring 转为 C语言能识别处理的字符串
    if (command.c_str() == NULL) {
        return false; // ScopedUtfChars already threw on error.
    }
	
    --reply_len; // 保留最后的字节 用来填充 "\0" 字符串结束标志 
    if (::wifi_command(command.c_str(), reply, &reply_len) != 0) {  // 调用 wifi_command 方法
        return false;
    }

    if (reply_len > 0 && reply[reply_len-1] == '\n') {
        reply[reply_len-1] = '\0';
    } else {
        reply[reply_len] = '\0';
    }
    return true;
}

#5.Wifi.h (hardware\libhardware_legacy\include\hardware_legacy)
int wifi_command(const char *command, char *reply, size_t *reply_len); //在Wifi.h 声明了 wifi_command 函数

Wifi.c

static struct wpa_ctrl *ctrl_conn;【ctrl_conn = wpa_ctrl_open(path); 用于通信连接的信息结构体】


struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
	struct wpa_ctrl *ctrl;
	DWORD mode;
	TCHAR name[256];
	int i, ret;

	ctrl = os_malloc(sizeof(*ctrl));
	if (ctrl == NULL) return NULL;
	os_memset(ctrl, 0, sizeof(*ctrl));
	if (os_snprintf_error(256, ret)) {
		os_free(ctrl);
		return NULL;
	}
	for (i = 0; i < 10; i++) {
		ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,NULL, OPEN_EXISTING, 0, NULL); // ctrl->pipe创建 管道
		if (ctrl->pipe != INVALID_HANDLE_VALUE ||GetLastError() != ERROR_PIPE_BUSY) break;
		WaitNamedPipe(name, 1000);
	}
	
	if (ctrl->pipe == INVALID_HANDLE_VALUE) {
		os_free(ctrl);
		return NULL;
	}
	mode = PIPE_READMODE_MESSAGE;
	if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
		CloseHandle(ctrl->pipe);
		os_free(ctrl);
		return NULL;
	}

	return ctrl;
}


int wifi_command(const char *command, char *reply, size_t *reply_len)
{
    return wifi_send_command(command, reply, reply_len);  // 调用本地的 wifi_send_command 函数
}



int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
{
    int ret;
    if (ctrl_conn == NULL) {
        ALOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
        return -1;
    }
	
// 调用 wpa_ctrl_request函数  ctrl_conn已经完成初始化 , 并完成对 OUT参数 char *reply的赋值
    ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL); 
    if (ret == -2) {
        ALOGD("'%s' command timed out.\n", cmd);
        TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
        return -2;
    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
        return -1;
    }
    if (strncmp(cmd, "PING", 4) == 0) {
        reply[*reply_len] = '\0';
    }
    return 0;
}


//完成数据的请求?  正常处理返回0  出现异常返回-1
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,char *reply, size_t *reply_len, void (*msg_cb)(char *msg, size_t len))
{
	DWORD written;
	DWORD readlen = *reply_len;

	if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL)) // 往 ctrl->pipe 管道( 文件 ) 写数据? 写入 【IFNAME=wlan0 DRIVER MACADDR】
		return -1;

	if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL)) // 从ctrl->pipe管道( 文件 ) 读取数据?  reply在ReadFile完成赋值
		return -1;
	*reply_len = readlen;

	return 0;
}



WriteFile 用于往ctrl->pipe管道 写数据 
bool WriteFile(HANDLE hFile, LPCVOID buffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, void* dummyforAPI)
{
    int written_len = 0;
    //usleep(3000);
    fd_set	writefd;

    struct timeval timeout;
    //Ruoyao: timeout from 500ms to 5s
    //timeout.tv_sec = 0;
    //timeout.tv_usec = 500000;
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

    bool is_written = false;
    while(!is_written)
    {
        FD_ZERO(&writefd);
        FD_SET(hFile, &writefd);
        if( select(hFile+1, NULL , &writefd, NULL, &timeout) > 0)
        {
            int ifd;
            for(ifd=0; ifd < hFile+1; ifd++)
            {
                if (FD_ISSET(ifd, &writefd))
                {
                    if(ifd == hFile)
                    {
// buffer就是 【IFNAME=wlan0 DRIVER MACADDR】通过把该字符串写入到 管道  使得驱动得到命令?
                        written_len = write(hFile, buffer, nNumberOfBytesToWrite);
                        is_written = true;
                    }
                }
            }
        }
        else
        {
            //log_linux_errno("WriteFile.select()");
            break;
        }
    }

    if(written_len >= 0)
    {
        if(lpNumberOfBytesWritten != NULL)
        {
            *lpNumberOfBytesWritten = written_len;
        }
        return true;
    }
    else
    {
        //log_linux_errno("WriteFile.write()");
        if(lpNumberOfBytesWritten != NULL)
        {
            *lpNumberOfBytesWritten = 0;
        }
    	return false;
    }
}


ReadFile 用于往ctrl->pipe管道 读取数据 
bool ReadFile(HANDLE hFile, LPVOID buffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, void* dummyforAPI)
{
    int read_len = 0;

    //usleep(3000);
    fd_set	readfd;
    struct timeval timeout;
	//Ruoyao: timeout from 500ms to 5s
    //timeout.tv_sec = 0;
    //timeout.tv_usec = 50000; //50ms
    timeout.tv_sec = 5;
    timeout.tv_usec = 0;

    bool is_read = false;
    while(!is_read)
    {
        FD_ZERO(&readfd);
        FD_SET(hFile, &readfd);
        if( select(hFile+1, &readfd , NULL, NULL, &timeout) > 0)
        {
            int ifd;
            for(ifd=0; ifd < hFile+1; ifd++)
            {
                if (FD_ISSET(ifd, &readfd))
                {
                    if(ifd == hFile)
                    {
// buffer就是cahr* reply 就是需要返回到的数据  通过读取 管道 得到数据
                        read_len = read(hFile, buffer, nNumberOfBytesToRead); 
                        is_read = true;

                    }
                }
            }
        }
        else
        {
            //log_linux_errno("ReadFile.select()");
            break;
        }
    }

    if(read_len >= 0)
    {
        if(lpNumberOfBytesRead != NULL)
        {
            *lpNumberOfBytesRead = read_len;
        }
        return true;
    }
    else
    {
        //log_linux_errno("ReadFile.read()");
        if(lpNumberOfBytesRead != NULL)
        {
            *lpNumberOfBytesRead = 0;
        }
        return false;
	}
}


## hFile 文件对应的驱动 怎么实现  还需要跟踪( 未完待续 )


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值