Android TVSetting Wifi连接分析(四)

基于Android 9.0 ATV版 TVSetting源码,研究TVSetting Wifi连接方法

Android TVSetting Wifi连接分析(一)

Android TVSetting Wifi连接分析(二)

Android TVSetting Wifi连接分析(三)

Android TVSetting Wifi连接分析(四)

一、概述

上一章 分析WifiTracker的启动和扫描,从WifiTracker源码上看,WifiTracker 获得了wifi列表(mWifiManager.getScanResults()),并不是直接使用结果,而是采用了相关的缓存以及打分集中应用了打分的机制,来对wifi进行排序,从而在UI显示上以优先级的形式给用户选择。这一章主要分析WifiTracker wifi结果的获取,缓存以及打分应用

二、WIFI结果的获取

OnStart

------fetchScansAndConfigsAndUpdateAccessPoints(mWifiManager.getScanResults();获得当前的扫描结果)

----------updateAccessPoints(将ScanResults转换成AccessPoints)

    private void fetchScansAndConfigsAndUpdateAccessPoints() {
        //取得扫描结果
        final List<ScanResult> newScanResults = mWifiManager.getScanResults();
        if (isVerboseLoggingEnabled()) {
            Log.i(TAG, "Fetched scan results: " + newScanResults);
        }

        List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
        //进一步处理
        updateAccessPoints(newScanResults, configs);
    }

获得 ScanResult后,调用 updateAccessPoints进一步处理

updateAccessPoints中首先调用updateScanResultCache来更新ScanResult缓存


    /** Update the internal list of access points. */
    private void updateAccessPoints(final List<ScanResult> newScanResults,
            List<WifiConfiguration> configs) {

                 ..........
            //更新updateScanResultCache
        ArrayMap<String, List<ScanResult>> scanResultsByApKey =
                updateScanResultCache(newScanResults);

                ..........
        }

updateScanResultCache--更新ScanResultCache并返回一个ArrayMap

    private ArrayMap<String, List<ScanResult>> updateScanResultCache(
            final List<ScanResult> newResults) {
        // TODO(sghuman): Delete this and replace it with the Map of Ap Keys to ScanResults for
        // memory efficiency
        //首先遍历结果,去除SSID为空的wifi
        for (ScanResult newResult : newResults) {
            if (newResult.SSID == null || newResult.SSID.isEmpty()) {
                continue;
            }
            //mScanResultCache为hash map,SSID作为键值名
            mScanResultCache.put(newResult.BSSID, newResult);
        }

        // Don't evict old results if no new scan results
        //wifitrack会设置一个超时时间,如果扫描结果中有热点超时,会被移除
        if (!mStaleScanResults) {
            evictOldScans();
        }

        ArrayMap<String, List<ScanResult>> scanResultsByApKey = new ArrayMap<>();
        //将mScanResultCache的结果存放到scanResultsByApKey ,提供给外部使用
        for (ScanResult result : mScanResultCache.values()) {
            // Ignore hidden and ad-hoc networks.
            //过滤SSID为空的
            if (result.SSID == null || result.SSID.length() == 0 ||
                    result.capabilities.contains("[IBSS]")) {
                continue;
            }
            //将结果获得AccessPoint Key
           //AccessPoint Key 由SSID+Security 组成
            //SECURITY_NONE = 0;
            //SECURITY_WEP = 1;
            // SECURITY_PSK = 2;
            //SECURITY_EAP = 3;
            String apKey = AccessPoint.getKey(result);
            List<ScanResult> resultList;
            if (scanResultsByApKey.containsKey(apKey)) {
                resultList = scanResultsByApKey.get(apKey);
            } else {
                resultList = new ArrayList<>();
                scanResultsByApKey.put(apKey, resultList);
            }

            resultList.add(result);
        }

        return scanResultsByApKey;
    }

 获得scanResultsByApKey后,进行进一步处理

    /** Update the internal list of access points. */
    private void updateAccessPoints(final List<ScanResult> newScanResults,
            List<WifiConfiguration> configs) {

         ....
        // once for efficiency of lock acquisition time and readability
        synchronized (mLock) {
            // Swap the current access points into a cached list for maintaining AP listeners
            //创建一个AccessPoints List,数据从mInternalAccessPoints拷贝获得
            List<AccessPoint> cachedAccessPoints;
            cachedAccessPoints = new ArrayList<>(mInternalAccessPoints);

            ArrayList<AccessPoint> accessPoints = new ArrayList<>();

            final List<NetworkKey> scoresToRequest = new ArrayList<>();
			
            //遍历scanResultsByApKey
            for (Map.Entry<String, List<ScanResult>> entry : scanResultsByApKey.entrySet()) {
                for (ScanResult result : entry.getValue()) {
                    //用result 创建NetworkKey 
					Log.i(TAG, "ScanResult ssid: " + result.SSID);
                    NetworkKey key = NetworkKey.createFromScanResult(result);
                    if (key != null && !mRequestedScores.contains(key)) {
                        //加入打分数组
                        scoresToRequest.add(key);
                    }
                }
                
                //创建accessPoint或者从Cached中获得一个accessPoint
                AccessPoint accessPoint =
                        getCachedOrCreate(entry.getValue(), cachedAccessPoints);

                //更新accessPoint状态
                if (mLastInfo != null && mLastNetworkInfo != null) {
                    accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
                }

                // Update the matching config if there is one, to populate saved network info
                accessPoint.update(configsByKey.get(entry.getKey()));

                accessPoints.add(accessPoint);
            }

            // If there were no scan results, create an AP for the currently connected network (if
            // it exists).
            // TODO(b/b/73076869): Add support for passpoint (ephemeral) networks
            //accessPoints点数组为空处理
            if (accessPoints.isEmpty() && connectionConfig != null) {
                AccessPoint activeAp = new AccessPoint(mContext, connectionConfig);
                activeAp.update(connectionConfig, mLastInfo, mLastNetworkInfo);
                accessPoints.add(activeAp);
                scoresToRequest.add(NetworkKey.createFromWifiInfo(mLastInfo));
            }
            
            //将scoresToRequest 的数据传入,去获得分数?
            requestScoresForNetworkKeys(scoresToRequest);
            for (AccessPoint ap : accessPoints) {
                ap.update(mScoreCache, mNetworkScoringUiEnabled, mMaxSpeedLabelScoreCacheAge);
            }

            // Pre-sort accessPoints to speed preference insertion
            Collections.sort(accessPoints);

            

            mInternalAccessPoints.clear();
            //更新mInternalAccessPoints
            mInternalAccessPoints.addAll(accessPoints);
        }

        conditionallyNotifyListeners();
    }

三、WIFI打分管理

3.1 涉及类及列表

➢WifiNetworkScoreCache-wifi网络的打分缓存

➢NetworkScoreManager-网络打分管理类

import android.net.wifi.WifiNetworkScoreCache;
import android.net.wifi.WifiNetworkScoreCache.CacheListener;

private WifiNetworkScoreCache mScoreCache;
private final NetworkScoreManager mNetworkScoreManager;

在WifiTracker的构造函数中setWorkThread函数里,完成了mScoreCache的初始化

    void setWorkThread(HandlerThread workThread) {
        mWorkThread = workThread;
        mWorkHandler = new Handler(workThread.getLooper());
        //创建mScoreCache 及监听,在抓log时,这里并没有调用
        mScoreCache = new WifiNetworkScoreCache(mContext, new CacheListener(mWorkHandler) {
            @Override
            public void networkCacheUpdated(List<ScoredNetwork> networks) {
                if (!mRegistered) return;

                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "Score cache was updated with networks: " + networks);
                }
                updateNetworkScores();
            }
        });
    }

在onStart中,会调用函数registerScoreCache,实现完成mScoreCache mNetworkScoreManager的绑定。

    private void registerScoreCache() {
        mNetworkScoreManager.registerNetworkScoreCache(
                NetworkKey.TYPE_WIFI,
                mScoreCache,
                NetworkScoreManager.CACHE_FILTER_SCAN_RESULTS);
    }

在updateAccessPoints数组中,会调用 requestScoresForNetworkKeys(scoresToRequest);去请求给wifi打分。

    private void requestScoresForNetworkKeys(Collection<NetworkKey> keys) {
        if (keys.isEmpty()) return;

        if (DBG()) {
            Log.d(TAG, "Requesting scores for Network Keys: " + keys);
        }
        //将NetworkKey传入mNetworkScoreManager,去请求打分
        mNetworkScoreManager.requestScores(keys.toArray(new NetworkKey[keys.size()]));
        synchronized (mLock) {
            //将已经申请过打分的key加入到mRequestedScores队列中,避免重复申请
            mRequestedScores.addAll(keys);
        }
    }

四、总结

这章分析了WIFI结果的获取,及打分的处理过程。下一章分析拿到这个结果后,TVSetting是如何排序及显示的

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值