WiFI 扫描时选择固定频率(只扫2.4G或者5G的AP)

2020-07-15 11:27:32 浏览数 (1)

最近遇到一个新需求,成品如下,就是WiFi扫描界面增加一个选项,可以只扫描2.4G或者5G的AP。

方案一

/frameworks/opt/net/wifi/service/java/com/android/server/wifi/ScanRequestProxy.java 从代码里可以看到WiFi扫描默认是全扫描的,不会对 2.4G 和 5G 做筛选。

代码语言:javascript复制
public boolean startScan(int callingUid, String packageName) {
    .............
    // always do full scans
    settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
    .............
}

下面是我的修改,frequencyBand 是写入数据库的标志位,UI 界面选择了以后改变这个数据,然后这里读取,再做相应的操作。关于Settings数据库的使用可以看 Settings数据库的使用 。

代码语言:javascript复制
private static final String Ap_Frequency_Band = "ap_frequency_band";
public static final int WIFI_BAND_24_GHZ = 1;
public static final int WIFI_BAND_5_GHZ_WITH_DFS  = 6;
public static final int WIFI_BAND_BOTH_WITH_DFS = 7;

public boolean startScan(int callingUid, String packageName) {
    .............
    int frequencyBand = Settings.Global.getInt(mContext.getContentResolver(), Ap_Frequency_Band, 0);
    switch (frequencyBand) {
        case WIFI_BAND_24_GHZ:
            settings.band = WifiScanner.WIFI_BAND_24_GHZ;
            break;
        case WIFI_BAND_5_GHZ_WITH_DFS:
            settings.band = WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS;
            break;
        case WIFI_BAND_BOTH_WITH_DFS:
            settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
            break;
        default:
            settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
            break;
    }
        //settings.band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
    .............
}

这么做有一个弊端就是底层依然会扫描,但是上传到 framework 会根据 ScannerSettings 做筛选。这样的话如果你之前连过一个2.4G的AP,现在选择只扫描5G的AP,手机还是会自动重连到你之前保存过的那个2.4GAP,因为底层已经扫描到了。

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiConnectivityManager.java 下面是我在连接网络时做的处理,在连接AP时判断用户选择的频率扫描选项,如果用户选了5G,则连接网络时如果是2.4G的AP则直接返回空,不连接。这样就解决了上面的问题。

代码语言:javascript复制
private void connectToNetwork(WifiConfiguration candidate) {
    ScanResult scanResultCandidate = candidate.getNetworkSelectionStatus().getCandidate();
    if (scanResultCandidate == null) {
        localLog("connectToNetwork: bad candidate - "    candidate
                  " scanResult: "   scanResultCandidate);
        return;
    }

添加的代码:

    frequencyBand = Settings.Global.getInt(mContext.getContentResolver(), Ap_Frequency_Band, 7);
    if (!((frequencyBand == WIFI_BAND_24_GHZ && scanResultCandidate.is24GHz())
               || (frequencyBand == WIFI_BAND_5_GHZ_WITH_DFS && scanResultCandidate.is5GHz())
               || (frequencyBand == WIFI_BAND_BOTH_WITH_DFS))) {
        return;
    }
    
}

方案二

frameworks/opt/net/wifi/service/java/com/android/server/wifi/scanner/WificondScannerImpl.java

后来就想能不能让底层扫描的时候就只扫描某个band的AP呢?结果找到了扫描时 framework 传给底层的参数中就有 freqs 参数,那我修改这个参数不就好了。一看代码果然是不区分,直接全扫描,如何就是修改,和UI通信的方式还是Settings数据库,上面说过了,这里不赘述。

原代码:

代码语言:javascript复制
public boolean startSingleScan(WifiNative.ScanSettings settings,
        WifiNative.ScanEventHandler eventHandler) {
    synchronized (mSettingsLock) {

        boolean success = false;
        Set<Integer> freqs;
        if (!allFreqs.isEmpty()) {
            freqs = allFreqs.getScanFreqs();
            success = mWifiNative.scan(
                    mIfaceName, settings.scanType, freqs, hiddenNetworkSSIDSet);
            if (!success) {
                Log.e(TAG, "Failed to start scan, freqs="   freqs);
            }
        } else {
}

channels 是有函数去获取2.4G或者5G对应的频率的,我们把这个写入 freq 就可以。

修改的代码:

代码语言:javascript复制
public boolean startSingleScan(WifiNative.ScanSettings settings,
        WifiNative.ScanEventHandler eventHandler) {
    synchronized (mSettingsLock) {
        boolean success = false;
   
修改的代码:

        //Set<Integer> freqs;
        int[] channels = null;
        int[] channelDfs = null;
        int frequencyBand = Settings.Global.getInt(mContext.getContentResolver(), Ap_Frequency_Band, 7);
        Log.d(TAG, "Ap_Frequency_Band = "   frequencyBand);
        if (!allFreqs.isEmpty()) {
            //freqs = allFreqs.getScanFreqs();
            ArraySet<Integer> mChannels = new ArraySet<Integer>();
			switch (frequencyBand) {
			  case WIFI_BAND_24_GHZ:
			channels = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_24_GHZ);
			break;
			  case WIFI_BAND_5_GHZ:
			channels = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ);
			                    channelDfs = mWifiNative.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY);
			break;
			  default:
			break;
			}
            if (null != channels){
                for (int chan : channels) {
                    mChannels.add(chan);
                }
                if (null != channelDfs){
                    for (int chan : channelDfs) {
                        mChannels.add(chan);
                    }
                }
                freqs= new ArraySet<Integer>(mChannels);
            } else {
                freqs = allFreqs.getScanFreqs();
            }
            Log.d(TAG, "freqs="   freqs);

0 人点赞