i.mx6 android ap6612,android的wifi扫描流程及管理(framework层的wifi扫描分析)

前言:

本文介绍wifi framework层的扫描处理流程,所介绍的流程的代码

全部在下面的文件中:

(android\frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMachine.java)

一、wifi状态的转变

没连接ap时打开wifi的状态转变:

InitialState->SupplicantStartingState-> DriverStartedState->DisconnectedState

已连接过ap时打开wifi的状态转变:

InitialState->SupplicantStartingState->DriverStartedState->DisconnectedState-> ObtainingIpState-> ConnectedState

二、打开wifi首次扫描的触发

不管之前连接过ap,还是没连接过ap,在进入

DriverStartedState时,在enter函数内调用了

setFrequencyBand,最后发送了CMD_SET_FREQUENCY_BAND

消息。

setFrequencyBand()->setFrequencyBand(a,b)->sendMessage(CMD_SET_FREQUENCY_BAND, band, 0)

CMD_SET_FREQUENCY_BAND消息由DriverStartedState的

processMessage处理,调用下面函数:

mFrequencyBand.set(band);

// Flush old data - like scan results

mWifiNative.bssFlush();

// Fetch the latest scan results when frequency band is set

startScanNative(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, null);

startScanNative调用mWifiNative.scan进行最后扫描触发,一种返

回值情况如下:当之前没有连接过ap时,mWifiNative.scan返回

true,mIsFullScanOngoing就会被设置为true,最后扫描结果就会

发送sendScanResultsAvailableBroadcast广播,如果之前连接过

ap,由于这时还没连接上ap,mWifiNative.scan返回false,

mIsFullScanOngoing保持为false,最后扫描结果不会发送

sendScanResultsAvailableBroadcast广播。所以在之前连接过ap

的情况下,打开wifi后,ap还没连接上,这时应用层发起scan,由

于mWifiNative.scan返回false,这次应用层发起的scan结果不会发

送sendScanResultsAvailableBroadcast广播,应用层是监测不到

这次scan结果消息的。这种情况就会导致有时打开wifi,需要过很久

才能显示扫描到ap列表。可以在WifiStateMachine.java的

handleScanRequest函数加下面patch解决:

fa7c923a20140b32d90e82c173a4110e.png

mWifiNative.scan的返回值由supplicant中的wpas_ctrl_scan

函数决定,当supplicant当前正在扫描、或正在调度扫描,或正在

处理连接ap的状态时,这次发起的scan就会被拒绝,上层

mWifiNative.scan的返回值就是flase,若允许这次发起的scan,

mWifiNative.scan的返回值为true。

三、没连接过ap的扫描

在之前没有连接ap的情况下,进入DisconnectedState时,在亮屏

的情况下,在DisconnectedState的enter函数中调用

startDelayedScan,发送一个10s后的CMD_START_SCAN消息,

消息源为SCAN_ALARM_SOURCE,该消息在DisconnectedState

的processMessage中处理,处理CMD_START_SCAN消息时,先

调用checkAndRestartDelayedScan检查

mDelayedScanCounter(后面有该机制的说明),判断是否执行

这次扫描,需要再执行这次扫描时,再发送一个10s后的

CMD_START_SCAN消息,然后执行扫描动作,扫描由函数

handleScanRequest调用startScanNative进行,不停反复这样扫

描过程。暗屏时这个扫描会停止,亮屏后会再启动。

同时在进入DisconnectedState状态时,检测到没有保存连接

过的ap信息,在enter时还会延后15s发送一个

CMD_NO_NETWORKS_PERIODIC_SCAN消息,

mSupplicantScanIntervalMs(15s)。

sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,

++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);

CMD_NO_NETWORKS_PERIODIC_SCAN消息在

DisconnectedState状态的processMessage中处理,启动一次扫

描,延后15s发送下一个CMD_NO_NETWORKS_PERIODIC_SCAN

消息。

startScan(UNKNOWN_SCAN_SOURCE, -1, null, null);

sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,

++mPeriodicScanToken, 0), mSupplicantScanIntervalMs);

只要没有连接ap,并没有保存连接ap的信息,这个扫描每15s进行

一次。startScan函数中发送sendMessage(CMD_START_SCAN,

callingUid, scanCounter, bundle)。由于这次startScan 的消息源

为UNKNOWN_SCAN_SOURCE,这次的CMD_START_SCAN消息

不在DisconnectedState状态的processMessage中处理,而最后由

DriverStartedState状态的processMessage处理,最后调用

handleScanRequest及startScanNative进行扫描。

同时如果使用了后台wifi扫描,那在暗屏的状态下,由

mAlarmManager启动RTC_WAKEUP进行周期性扫描,时间到时会

广播(ACTION_START_SCAN, SCAN_REQUEST),由注册的一个消

息接收函数处理;

mContext.registerReceiver(

new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

sScanAlarmIntentCount++; // Used for debug only

startScan(SCAN_ALARM_SOURCE, mDelayedScanCounter.incrementAndGet(), null, null);

if (VDBG)

loge("WiFiStateMachine SCAN ALARM -> " + mDelayedScanCounter.get());

}

}, new IntentFilter(ACTION_START_SCAN));

这个扫描暗屏时启动,亮屏时停止。

在DisconnectedState的状态下,当android 应用层发起一次扫

描时,首先调用到

android\frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl.java

下面的startScan,startScan函数中发送

sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle)。由于这次startScan 的消息源为应用的uid,这次的

CMD_START_SCAN消息不在DisconnectedState状态的

processMessage中处理,而最后由DriverStartedState状态的

processMessage处理,最后调用handleScanRequest及

startScanNative进行扫描。

由于亮屏、暗屏的扫描,都是利用sendMessageDelayed进

行,为了避免过多的sendMessageDelayed消息存在,频繁进行扫

描,在每个利用sendMessageDelayed发送消息的扫描类型中,都

有一个变量计算延后扫描的次数,如mDelayedScanCounter,在

每次startDelayedScan中,mDelayedScanCounter都会加1,然

后把该值作为消息的一部分发送。在一段时间后收到扫描消息后,

调用checkAndRestartDelayedScan比较消息当时发送过来的

mDelayedScanCounter与当前的mDelayedScanCounter值,两

个值相等时,才进行扫描,否则丢掉这一次扫描,这样,即使发送

了多个Delayed Scan还没有处理,也只有最后一个Delayed Scan

会真正进行扫描动作,前面的Delayed Scan会被丢掉。

三、接过过ap的扫描

若打开wifi之前连接过ap,则不会发起

CMD_NO_NETWORKS_PERIODIC_SCAN消息,也不会有

CMD_NO_NETWORKS_PERIODIC_SCAN扫描,后台扫描允许的

话,与没连接ap的情况是一样的。

而消息源为SCAN_ALARM_SOURCE的周期性扫描

CMD_START_SCAN,由没连接ap时的10s变成20s,并且

CMD_START_SCAN消息由L2ConnectedState状态的

processMessage处理,在处理CMD_START_SCAN,还会根据扫

描的时间间隔,分别进行全频段的扫描或所连接的ap所在信道的单

独扫描。实际执行扫描由handleScanRequest、startScanNative

进行,与没连接ap的情况一样。在全频段扫描的情况下,扫描结束

后会发送sendScanResultsAvailableBroadcast广播。而单信道的

扫描,扫描结束后不会发送sendScanResultsAvailableBroadcast

广播。

在L2ConnectedState的状态下,当android 应用层发起一次

扫描时,首先调用到

android\frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl.java

里面的startScan函数,由startScan再调用WifiStateMachine.java下面的startScan,startScan函数中发送

sendMessage(CMD_START_SCAN, callingUid, scanCounter, bundle)。由于这次startScan 的源为应用的uid,这次的

CMD_START_SCAN消息不在L2ConnectedState状态的

processMessage中处理,而最后由DriverStartedState状态的

processMessage处理,最后调用handleScanRequest及

startScanNative进行扫描。

暗屏、亮屏的Delayed Scan计数机制,与没连接ap的情况是一样的。

四、其它

Wifi作为station时,大部分情况下都是处理连接

ap(L2ConnectedState状态),或没连接

ap(DisconnectedState状态),上面介绍的也只是这两种状态,

其它中间连接状态,ap切换状态等等的情况,请自行分析。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值