1. 程式人生 > >Android -- 無線網路配置資訊的管理者WifiConfigStore簡介

Android -- 無線網路配置資訊的管理者WifiConfigStore簡介

  1. 從wp_s讀取儲存的網路配置列表,並儲存到mConfiguredNetworks中
  2. 呼叫readIpAndProxyConfigurations()方法,從ipconfig.txt中讀取儲存的IpConfiguration物件,更新到mConfiguredNetworks儲存的各WifiConfiguration物件中
  3. 呼叫mConfiguredNetworks()方法,從/misc/wifi/networkHistory.txt檔案中讀取儲存的資訊,更新到mConfiguredNetworks儲存的各WifiConfiguration物件中
讀取的方式跟前面介紹的寫入的方式基本相似。經過上所述的兩次讀取操作,我們持有的WifiConfiguration物件的資訊就是比較完整的了。 如果有我們前面說過的無線PPPoE的場景,readIpAndProxyConfigurations()方法中就會把我們事先寫入的賬號密碼資訊也讀取出來,存到mConfiguredNetworks中。走auto_connect流程時,獲取到最近一次連線的網路netId,從mConfiguredNetworks中取出的對應的WifiConfiguration物件中就儲存有PPPoE的賬號密碼,這樣我們在PPPoE獲取IP時,就有可用的賬戶資訊了。

PS:

WifiConfigStore中定義了一個比較有意義的預設變數值:
    /**
     * The maximum number of times we will retry a connection to an access point
     * for which we have failed in acquiring an IP address from DHCP. A value of
     * N means that we will make N+1 connection attempts in all.
     * <p>
     * See {@link Settings.Secure#WIFI_MAX_DHCP_RETRY_COUNT}. This is the default
     * value if a Settings value is not present.
     */
    private static final int DEFAULT_MAX_DHCP_RETRIES = 9;
從原生註釋中,我們得知這個變數控制了當一個網路獲取IP失敗時,之後會繼續重試的次數;如果值定義為9,那麼實際的重連次數將是9+1,為10。 如果我們有定製這個值,那麼重連次數將以我們自定義配置的值為準:
    int WifiConfigStore::getMaxDhcpRetries() {
        return Settings.Global.getInt(mContext.getContentResolver(),
                Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT,
                DEFAULT_MAX_DHCP_RETRIES);
    }
我們可以配置Settings.Global.WIFI_MAX_DHCP_RETRY_COUNT這個欄位值來定製這部分:
       /**
        * The maximum number of times we will retry a connection to an access
        * point for which we have failed in acquiring an IP address from DHCP.
        * A value of N means that we will make N+1 connection attempts in all.
        */
       public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
getMaxDhcpRetries()在WifiConfigStore中只在handleSSIDStateChange()函式中有使用:
void handleSSIDStateChange(int netId, boolean enabled, String message, String BSSID) {
        WifiConfiguration config = mConfiguredNetworks.get(netId);
        if (config != null) {
            if (enabled) {
                loge("Ignoring SSID re-enabled from supplicant:  " + config.configKey() +
                        " had autoJoinStatus=" + Integer.toString(config.autoJoinStatus)
                        + " self added " + config.selfAdded + " ephemeral " + config.ephemeral);
                //We should not re-enable the BSSID based on Supplicant reanable.
                // Framework will re-enable it after its own blacklist timer expires
            } else {
                loge("SSID temp disabled for  " + config.configKey() +
                        " had autoJoinStatus=" + Integer.toString(config.autoJoinStatus)
                        + " self added " + config.selfAdded + " ephemeral " + config.ephemeral);
                if (message != null) {
                    loge(" message=" + message);
                }
                if (config.selfAdded && config.lastConnected == 0) {
                    // This is a network we self added, and we never succeeded,
                    // the user did not create this network and never entered its credentials,
                    // so we want to be very aggressive in disabling it completely.
                    removeConfigAndSendBroadcastIfNeeded(config.networkId);
                } else {
                    if (message != null) {
                        if (message.contains("no identity")) {
                            config.setAutoJoinStatus(
                                    WifiConfiguration.AUTO_JOIN_DISABLED_NO_CREDENTIALS);
                            if (DBG) {
                                loge("no identity blacklisted " + config.configKey() + " to "
                                        + Integer.toString(config.autoJoinStatus));
                            }
                        } else if (message.contains("WRONG_KEY")
                                || message.contains("AUTH_FAILED")) {
                            // This configuration has received an auth failure, so disable it
                            // temporarily because we don't want auto-join to try it out.
                            // this network may be re-enabled by the "usual"
                            // enableAllNetwork function
                            config.numAuthFailures++;
                            if (config.numAuthFailures > maxAuthErrorsToBlacklist) {
                                config.setAutoJoinStatus
                                        (WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE);
                                disableNetwork(netId,
                                        WifiConfiguration.DISABLED_AUTH_FAILURE);
                                loge("Authentication failure, blacklist " + config.configKey() + " "
                                            + Integer.toString(config.networkId)
                                            + " num failures " + config.numAuthFailures);
                            }
                        } else if (message.contains("DHCP FAILURE")) {
                            config.numIpConfigFailures++;
                            config.lastConnectionFailure = System.currentTimeMillis();
                            int maxRetries = getMaxDhcpRetries();
                            // maxRetries == 0 means keep trying forever
                            if (maxRetries > 0 && config.numIpConfigFailures > maxRetries) {
                                /**
                                 * If we've exceeded the maximum number of retries for DHCP
                                 * to a given network, disable the network
                                 */
                                config.setAutoJoinStatus
                                        (WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE);
                                disableNetwork(netId, WifiConfiguration.DISABLED_DHCP_FAILURE);
                                loge("DHCP failure, blacklist " + config.configKey() + " "
                                        + Integer.toString(config.networkId)
                                        + " num failures " + config.numIpConfigFailures);
                            }

                            // Also blacklist the BSSId if we find it
                            ScanResult result = null;
                            String bssidDbg = "";
                            if (getScanDetailCache(config) != null && BSSID != null) {
                                result = getScanDetailCache(config).get(BSSID);
                            }
                            if (result != null) {
                                result.numIpConfigFailures ++;
                                bssidDbg = BSSID + " ipfail=" + result.numIpConfigFailures;
                                if (result.numIpConfigFailures > 3) {
                                    // Tell supplicant to stop trying this BSSID
                                    mWifiNative.addToBlacklist(BSSID);
                                    result.setAutoJoinStatus(ScanResult.AUTO_JOIN_DISABLED);
                                }
                            }

                            if (DBG) {
                                loge("blacklisted " + config.configKey() + " to "
                                        + config.autoJoinStatus
                                        + " due to IP config failures, count="
                                        + config.numIpConfigFailures
                                        + " disableReason=" + config.disableReason
                                        + " " + bssidDbg);
                            }
                        } else if (message.contains("CONN_FAILED")) {
                            config.numConnectionFailures++;
                            if (config.numConnectionFailures > maxConnectionErrorsToBlacklist) {
                                config.setAutoJoinStatus
                                        (WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE);
                                disableNetwork(netId,
                                        WifiConfiguration.DISABLED_ASSOCIATION_REJECT);
                                loge("Connection failure, blacklist " + config.configKey() + " "
                                        + config.networkId
                                        + " num failures " + config.numConnectionFailures);
                            }
                        }
                        message.replace("\n", "");
                        message.replace("\r", "");
                        config.lastFailure = message;
                    }
                }
            }
        }
    }
在WifiStateMachine中,如果一個網路DHCP獲取IP失敗、或STATIC IP配置失敗、或網路的配置資訊丟失,都會間接呼叫到handleSSIDStateChange()函式,在配置的次數內嘗試網路重連。我們看一個例子:
    private void WifiStateMachine::handleIpConfigurationLost() {
        mWifiInfo.setInetAddress(null);
        mWifiInfo.setMeteredHint(false);

        mWifiConfigStore.handleSSIDStateChange(mLastNetworkId, false,
                "DHCP FAILURE", mWifiInfo.getBSSID());//函式呼叫

        /* DHCP times out after about 30 seconds, we do a
         * disconnect thru supplicant, we will let autojoin retry connecting to the network
         */
        mWifiNative.disconnect();
    }
這裡呼叫時,netId為當前使用的網路的netId,用以在WifiConfigStore獲取到對應的WifiConfiguration,enabled為false,message為DHCP_FALURE;對照handleSSIDStateChange()實現,我們可以分析得出: