WifiScoreReport.java revision 9b256a5cb87062b7ae1696324e2bd7c9b1ceca27
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi;
18
19import android.content.Context;
20import android.net.NetworkAgent;
21import android.net.wifi.WifiConfiguration;
22import android.net.wifi.WifiInfo;
23import android.util.Log;
24
25import com.android.internal.R;
26
27/**
28 * Class used to calculate scores for connected wifi networks and report it to the associated
29 * network agent.
30 * TODO: Add unit tests for this class.
31*/
32public class WifiScoreReport {
33    private static final String TAG = "WifiScoreReport";
34
35    // TODO: This score was hardcorded to 56.  Need to understand why after finishing code refactor
36    private static final int STARTING_SCORE = 56;
37
38    // TODO: Understand why these values are used
39    private static final int MAX_BAD_LINKSPEED_COUNT = 6;
40    private static final int SCAN_CACHE_VISIBILITY_MS = 12000;
41    private static final int HOME_VISIBLE_NETWORK_MAX_COUNT = 6;
42    private static final int SCAN_CACHE_COUNT_PENALTY = 2;
43    private static final int AGGRESSIVE_HANDOVER_PENALTY = 6;
44    private static final int MIN_SUCCESS_COUNT = 5;
45    private static final int MAX_SUCCESS_COUNT_OF_STUCK_LINK = 3;
46    private static final int MAX_STUCK_LINK_COUNT = 5;
47    private static final int MIN_NUM_TICKS_AT_STATE = 1000;
48    private static final int USER_DISCONNECT_PENALTY = 5;
49    private static final int MAX_BAD_RSSI_COUNT = 7;
50    private static final int BAD_RSSI_COUNT_PENALTY = 2;
51    private static final int MAX_LOW_RSSI_COUNT = 1;
52    private static final double MIN_TX_RATE_FOR_WORKING_LINK = 0.3;
53    private static final int MIN_SUSTAINED_LINK_STUCK_COUNT = 1;
54    private static final int LINK_STUCK_PENALTY = 2;
55    private static final int BAD_LINKSPEED_PENALTY = 4;
56    private static final int GOOD_LINKSPEED_BONUS = 4;
57
58    // Device configs. The values are examples.
59    private final int mThresholdMinimumRssi5;      // -82
60    private final int mThresholdQualifiedRssi5;    // -70
61    private final int mThresholdSaturatedRssi5;    // -57
62    private final int mThresholdMinimumRssi24;     // -85
63    private final int mThresholdQualifiedRssi24;   // -73
64    private final int mThresholdSaturatedRssi24;   // -60
65    private final int mBadLinkSpeed24;             //  6 Mbps
66    private final int mBadLinkSpeed5;              // 12 Mbps
67    private final int mGoodLinkSpeed24;            // 24 Mbps
68    private final int mGoodLinkSpeed5;             // 36 Mbps
69    private final boolean mEnableWifiCellularHandoverUserTriggeredAdjustment; // true
70
71    private final WifiConfigManager mWifiConfigManager;
72    private boolean mVerboseLoggingEnabled = false;
73
74    // Cache of the last score report.
75    private String mReport;
76    private int mBadLinkspeedcount = 0;
77    private boolean mReportValid = false;
78
79    WifiScoreReport(Context context, WifiConfigManager wifiConfigManager) {
80        // Fetch all the device configs.
81        mThresholdMinimumRssi5 = context.getResources().getInteger(
82                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz);
83        mThresholdQualifiedRssi5 = context.getResources().getInteger(
84                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_5GHz);
85        mThresholdSaturatedRssi5 = context.getResources().getInteger(
86                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_5GHz);
87        mThresholdMinimumRssi24 = context.getResources().getInteger(
88                R.integer.config_wifi_framework_wifi_score_bad_rssi_threshold_24GHz);
89        mThresholdQualifiedRssi24 = context.getResources().getInteger(
90                R.integer.config_wifi_framework_wifi_score_low_rssi_threshold_24GHz);
91        mThresholdSaturatedRssi24 = context.getResources().getInteger(
92                R.integer.config_wifi_framework_wifi_score_good_rssi_threshold_24GHz);
93        mBadLinkSpeed24 = context.getResources().getInteger(
94                R.integer.config_wifi_framework_wifi_score_bad_link_speed_24);
95        mBadLinkSpeed5 = context.getResources().getInteger(
96                R.integer.config_wifi_framework_wifi_score_bad_link_speed_5);
97        mGoodLinkSpeed24 = context.getResources().getInteger(
98                R.integer.config_wifi_framework_wifi_score_good_link_speed_24);
99        mGoodLinkSpeed5 = context.getResources().getInteger(
100                R.integer.config_wifi_framework_wifi_score_good_link_speed_5);
101        mEnableWifiCellularHandoverUserTriggeredAdjustment = context.getResources().getBoolean(
102                R.bool.config_wifi_framework_cellular_handover_enable_user_triggered_adjustment);
103
104        mWifiConfigManager = wifiConfigManager;
105    }
106
107    /**
108     * Method returning the String representation of the last score report.
109     *
110     *  @return String score report
111     */
112    public String getLastReport() {
113        return mReport;
114    }
115
116    /**
117     * Method returning the bad link speed count at the time of the last score report.
118     *
119     *  @return int bad linkspeed count
120     */
121    public int getLastBadLinkspeedcount() {
122        return mBadLinkspeedcount;
123    }
124
125    /**
126     * Reset the last calculated score.
127     */
128    public void reset() {
129        mBadLinkspeedcount = 0;
130        mReport = "";
131        mReportValid = false;
132    }
133
134    /**
135     * Checks if the last report data is valid or not. This will be cleared when {@link #reset()} is
136     * invoked.
137     *
138     * @return true if valid, false otherwise.
139     */
140    public boolean isLastReportValid() {
141        return mReportValid;
142    }
143
144    /**
145     * Enable/Disable verbose logging in score report generation.
146     */
147    public void enableVerboseLogging(boolean enable) {
148        mVerboseLoggingEnabled = enable;
149    }
150
151    /**
152     * Calculate wifi network score based on updated link layer stats and send the score to
153     * the provided network agent.
154     *
155     * If the score has changed from the previous value, update the WifiNetworkAgent.
156     *
157     * Called periodically (POLL_RSSI_INTERVAL_MSECS) about every 3 seconds.
158     *
159     * @param wifiInfo WifiInfo instance pointing to the currently connected network.
160     * @param networkAgent NetworkAgent to be notified of new score.
161     * @param aggressiveHandover int current aggressiveHandover setting.
162     * @param wifiMetrics for reporting our scores.
163     */
164    public void calculateAndReportScore(
165            WifiInfo wifiInfo, NetworkAgent networkAgent, int aggressiveHandover,
166            WifiMetrics wifiMetrics) {
167        WifiInfo checkWifiInfo = new WifiInfo(wifiInfo);
168        StringBuilder sb = new StringBuilder();
169
170        int score = STARTING_SCORE;
171        boolean isBadLinkspeed = (wifiInfo.is24GHz()
172                && wifiInfo.getLinkSpeed() < mBadLinkSpeed24)
173                || (wifiInfo.is5GHz() && wifiInfo.getLinkSpeed()
174                < mBadLinkSpeed5);
175        boolean isGoodLinkspeed = (wifiInfo.is24GHz()
176                && wifiInfo.getLinkSpeed() >= mGoodLinkSpeed24)
177                || (wifiInfo.is5GHz() && wifiInfo.getLinkSpeed()
178                >= mGoodLinkSpeed5);
179
180        if (isBadLinkspeed) {
181            if (mBadLinkspeedcount < MAX_BAD_LINKSPEED_COUNT) {
182                mBadLinkspeedcount++;
183            }
184        } else {
185            if (mBadLinkspeedcount > 0) {
186                mBadLinkspeedcount--;
187            }
188        }
189
190        if (isBadLinkspeed) sb.append(" bl(").append(mBadLinkspeedcount).append(")");
191        if (isGoodLinkspeed) sb.append(" gl");
192
193        WifiConfiguration currentConfiguration =
194                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
195        ScanDetailCache scanDetailCache =
196                mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId());
197        /**
198         * We want to make sure that we use the 2.4GHz RSSI thresholds if
199         * there are 2.4GHz scan results otherwise we end up lowering the score based on 5GHz values
200         * which may cause a switch to LTE before roaming has a chance to try 2.4GHz
201         * We also might unblacklist the configuation based on 2.4GHz
202         * thresholds but joining 5GHz anyhow, and failing over to 2.4GHz because 5GHz is not good
203         */
204        boolean use24Thresholds = false;
205        boolean homeNetworkBoost = false;
206        if (currentConfiguration != null && scanDetailCache != null) {
207            currentConfiguration.setVisibility(
208                    scanDetailCache.getVisibility(SCAN_CACHE_VISIBILITY_MS));
209            if (currentConfiguration.visibility != null) {
210                if (currentConfiguration.visibility.rssi24 != WifiConfiguration.INVALID_RSSI
211                        && currentConfiguration.visibility.rssi24
212                        >= (currentConfiguration.visibility.rssi5 - SCAN_CACHE_COUNT_PENALTY)) {
213                    use24Thresholds = true;
214                }
215            }
216            if (scanDetailCache.size() <= HOME_VISIBLE_NETWORK_MAX_COUNT
217                    && currentConfiguration.allowedKeyManagement.cardinality() == 1
218                    && currentConfiguration.allowedKeyManagement
219                            .get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
220                // A PSK network with less than 6 known BSSIDs
221                // This is most likely a home network and thus we want to stick to wifi more
222                homeNetworkBoost = true;
223            }
224        }
225        if (homeNetworkBoost) sb.append(" hn");
226        if (use24Thresholds) sb.append(" u24");
227
228        int rssi = wifiInfo.getRssi() - AGGRESSIVE_HANDOVER_PENALTY * aggressiveHandover
229                + (homeNetworkBoost ? WifiConfiguration.HOME_NETWORK_RSSI_BOOST : 0);
230        sb.append(String.format(" rssi=%d ag=%d", rssi, aggressiveHandover));
231
232        boolean is24GHz = use24Thresholds || wifiInfo.is24GHz();
233
234        boolean isBadRSSI = (is24GHz && rssi < mThresholdMinimumRssi24)
235                || (!is24GHz && rssi < mThresholdMinimumRssi5);
236        boolean isLowRSSI = (is24GHz && rssi < mThresholdQualifiedRssi24)
237                || (!is24GHz
238                        && rssi < mThresholdQualifiedRssi5);
239        boolean isHighRSSI = (is24GHz && rssi >= mThresholdSaturatedRssi24)
240                || (!is24GHz
241                        && rssi >= mThresholdSaturatedRssi5);
242
243        if (isBadRSSI) sb.append(" br");
244        if (isLowRSSI) sb.append(" lr");
245        if (isHighRSSI) sb.append(" hr");
246
247        if (mVerboseLoggingEnabled) {
248            String rssiStatus = "";
249            if (isBadRSSI) {
250                rssiStatus += " badRSSI ";
251            } else if (isHighRSSI) {
252                rssiStatus += " highRSSI ";
253            } else if (isLowRSSI) {
254                rssiStatus += " lowRSSI ";
255            }
256            if (isBadLinkspeed) rssiStatus += " lowSpeed ";
257            Log.d(TAG, " wifi scoring details freq=" + Integer.toString(wifiInfo.getFrequency())
258                    + " speed=" + Integer.toString(wifiInfo.getLinkSpeed())
259                    + " score=" + Integer.toString(wifiInfo.score) // Previous score
260                    + rssiStatus
261                    + " -> txbadrate=" + String.format("%.2f", wifiInfo.txBadRate)
262                    + " txgoodrate=" + String.format("%.2f", wifiInfo.txSuccessRate)
263                    + " txretriesrate=" + String.format("%.2f", wifiInfo.txRetriesRate)
264                    + " rxrate=" + String.format("%.2f", wifiInfo.rxSuccessRate));
265        }
266
267        if ((wifiInfo.txBadRate >= 1)
268                && (wifiInfo.txSuccessRate < MAX_SUCCESS_COUNT_OF_STUCK_LINK)
269                && (isBadRSSI || isLowRSSI)) {
270            // Link is stuck
271            if (wifiInfo.linkStuckCount < MAX_STUCK_LINK_COUNT) {
272                wifiInfo.linkStuckCount += 1;
273            }
274            sb.append(String.format(" ls+=%d", wifiInfo.linkStuckCount));
275            if (mVerboseLoggingEnabled) {
276                Log.d(TAG, " bad link -> stuck count ="
277                        + Integer.toString(wifiInfo.linkStuckCount));
278            }
279        } else if (wifiInfo.txBadRate < MIN_TX_RATE_FOR_WORKING_LINK) {
280            if (wifiInfo.linkStuckCount > 0) {
281                wifiInfo.linkStuckCount -= 1;
282            }
283            sb.append(String.format(" ls-=%d", wifiInfo.linkStuckCount));
284            if (mVerboseLoggingEnabled) {
285                Log.d(TAG, " good link -> stuck count ="
286                        + Integer.toString(wifiInfo.linkStuckCount));
287            }
288        }
289
290        sb.append(String.format(" [%d", score));
291
292        if (wifiInfo.linkStuckCount > MIN_SUSTAINED_LINK_STUCK_COUNT) {
293            // Once link gets stuck for more than 3 seconds, start reducing the score
294            score = score - LINK_STUCK_PENALTY * (wifiInfo.linkStuckCount - 1);
295        }
296        sb.append(String.format(",%d", score));
297
298        if (isBadLinkspeed) {
299            score -= BAD_LINKSPEED_PENALTY;
300            if (mVerboseLoggingEnabled) {
301                Log.d(TAG, " isBadLinkspeed   ---> count=" + mBadLinkspeedcount
302                        + " score=" + Integer.toString(score));
303            }
304        } else if ((isGoodLinkspeed) && (wifiInfo.txSuccessRate > 5)) {
305            score += GOOD_LINKSPEED_BONUS; // So as bad rssi alone dont kill us
306        }
307        sb.append(String.format(",%d", score));
308
309        if (isBadRSSI) {
310            if (wifiInfo.badRssiCount < MAX_BAD_RSSI_COUNT) {
311                wifiInfo.badRssiCount += 1;
312            }
313        } else if (isLowRSSI) {
314            wifiInfo.lowRssiCount = MAX_LOW_RSSI_COUNT; // Dont increment the lowRssi count above 1
315            if (wifiInfo.badRssiCount > 0) {
316                // Decrement bad Rssi count
317                wifiInfo.badRssiCount -= 1;
318            }
319        } else {
320            wifiInfo.badRssiCount = 0;
321            wifiInfo.lowRssiCount = 0;
322        }
323
324        score -= wifiInfo.badRssiCount * BAD_RSSI_COUNT_PENALTY + wifiInfo.lowRssiCount;
325        sb.append(String.format(",%d", score));
326
327        if (mVerboseLoggingEnabled) {
328            Log.d(TAG, " badRSSI count" + Integer.toString(wifiInfo.badRssiCount)
329                    + " lowRSSI count" + Integer.toString(wifiInfo.lowRssiCount)
330                    + " --> score " + Integer.toString(score));
331        }
332
333        if (isHighRSSI) {
334            score += 5;
335            if (mVerboseLoggingEnabled) Log.d(TAG, " isHighRSSI       ---> score=" + score);
336        }
337        sb.append(String.format(",%d]", score));
338
339        sb.append(String.format(" brc=%d lrc=%d", wifiInfo.badRssiCount, wifiInfo.lowRssiCount));
340
341        //sanitize boundaries
342        if (score > NetworkAgent.WIFI_BASE_SCORE) {
343            score = NetworkAgent.WIFI_BASE_SCORE;
344        }
345        if (score < 0) {
346            score = 0;
347        }
348
349        updateScoringState(checkWifiInfo, aggressiveHandover);
350        int checkScore = calculateScore(checkWifiInfo, aggressiveHandover);
351
352        if (score != checkScore) {
353            Log.e(TAG, "recalculated score does not match: " +  score + "," + checkScore);
354        }
355        if (wifiInfo.linkStuckCount != checkWifiInfo.linkStuckCount) {
356            Log.e(TAG, "recalculated linkStuckCount does not match: "
357                    + wifiInfo.linkStuckCount  + "," + checkWifiInfo.linkStuckCount);
358        }
359        if (wifiInfo.badRssiCount != checkWifiInfo.badRssiCount) {
360            Log.e(TAG, "recalculated badRssiCount does not match: "
361                    + wifiInfo.badRssiCount  + "," + checkWifiInfo.badRssiCount);
362        }
363        if (wifiInfo.lowRssiCount != checkWifiInfo.lowRssiCount) {
364            Log.e(TAG, "recalculated lowRssiCount does not match: "
365                    + wifiInfo.lowRssiCount  + "," + checkWifiInfo.lowRssiCount);
366        }
367
368        //report score
369        if (score != wifiInfo.score) {
370            if (mVerboseLoggingEnabled) {
371                Log.d(TAG, " report new wifi score " + Integer.toString(score));
372            }
373            wifiInfo.score = score;
374            if (networkAgent != null) {
375                networkAgent.sendNetworkScore(score);
376            }
377        }
378
379        mReport = sb.toString();
380        mReportValid = true;
381        wifiMetrics.incrementWifiScoreCount(score);
382        Log.e(TAG, mReport); // fur debug
383    }
384
385    /**
386     * Updates the state.
387     */
388    public void updateScoringState(WifiInfo wifiInfo, int aggressiveHandover) {
389        int rssiThreshBad = mThresholdMinimumRssi24;
390        int rssiThreshLow = mThresholdQualifiedRssi24;
391
392        if (wifiInfo.is5GHz()) {
393            if (!multiBandScanResults(wifiInfo)) {
394                rssiThreshBad = mThresholdMinimumRssi5;
395                rssiThreshLow = mThresholdQualifiedRssi5;
396            }
397        }
398
399        int rssi =  wifiInfo.getRssi();
400        if (aggressiveHandover != 0) {
401            rssi -= AGGRESSIVE_HANDOVER_PENALTY * aggressiveHandover;
402        }
403        if (isHomeNetwork(wifiInfo)) {
404            rssi += WifiConfiguration.HOME_NETWORK_RSSI_BOOST;
405        }
406
407        if ((wifiInfo.txBadRate >= 1)
408                && (wifiInfo.txSuccessRate < MAX_SUCCESS_COUNT_OF_STUCK_LINK)
409                && rssi < rssiThreshLow) {
410            // Link is stuck
411            if (wifiInfo.linkStuckCount < MAX_STUCK_LINK_COUNT) {
412                wifiInfo.linkStuckCount += 1;
413            }
414        } else if (wifiInfo.txBadRate < MIN_TX_RATE_FOR_WORKING_LINK) {
415            if (wifiInfo.linkStuckCount > 0) {
416                wifiInfo.linkStuckCount -= 1;
417            }
418        }
419
420        if (rssi < rssiThreshBad) {
421            if (wifiInfo.badRssiCount < MAX_BAD_RSSI_COUNT) {
422                wifiInfo.badRssiCount += 1;
423            }
424        } else if (rssi < rssiThreshLow) {
425            wifiInfo.lowRssiCount = MAX_LOW_RSSI_COUNT; // Dont increment the lowRssi count above 1
426            if (wifiInfo.badRssiCount > 0) {
427                // Decrement bad Rssi count
428                wifiInfo.badRssiCount -= 1;
429            }
430        } else {
431            wifiInfo.badRssiCount = 0;
432            wifiInfo.lowRssiCount = 0;
433        }
434
435    }
436
437    /**
438     * Calculates the score, without all the cruft.
439     */
440    public int calculateScore(WifiInfo wifiInfo, int aggressiveHandover) {
441        int score = STARTING_SCORE;
442
443        int rssiThreshSaturated = mThresholdSaturatedRssi24;
444        int linkspeedThreshBad = mBadLinkSpeed24;
445        int linkspeedThreshGood = mGoodLinkSpeed24;
446
447        if (wifiInfo.is24GHz() != !(wifiInfo.is5GHz())) {
448            throw new AssertionError("What is happening here?");
449        }
450
451        if (wifiInfo.is5GHz()) {
452            if (!multiBandScanResults(wifiInfo)) {
453                rssiThreshSaturated = mThresholdSaturatedRssi5;
454            }
455            linkspeedThreshBad = mBadLinkSpeed5;
456            linkspeedThreshGood = mGoodLinkSpeed5;
457        }
458
459        int rssi =  wifiInfo.getRssi();
460        if (aggressiveHandover != 0) {
461            rssi -= AGGRESSIVE_HANDOVER_PENALTY * aggressiveHandover;
462        }
463        if (isHomeNetwork(wifiInfo)) {
464            rssi += WifiConfiguration.HOME_NETWORK_RSSI_BOOST;
465        }
466
467        int linkSpeed = wifiInfo.getLinkSpeed();
468
469        // Updates to wifiInfo.linkStuckCount skipped here
470
471        if (wifiInfo.linkStuckCount > MIN_SUSTAINED_LINK_STUCK_COUNT) {
472            // Once link gets stuck for more than 3 seconds, start reducing the score
473            score = score - LINK_STUCK_PENALTY * (wifiInfo.linkStuckCount - 1);
474        }
475
476        if (linkSpeed < linkspeedThreshBad) {
477            score -= BAD_LINKSPEED_PENALTY;
478        } else if ((linkSpeed >= linkspeedThreshGood) && (wifiInfo.txSuccessRate > 5)) {
479            score += GOOD_LINKSPEED_BONUS; // So as bad rssi alone doesn't kill us
480        }
481
482        // Updates to wifiInfo.badRssiCount skipped here
483
484        score -= wifiInfo.badRssiCount * BAD_RSSI_COUNT_PENALTY + wifiInfo.lowRssiCount;
485
486        if (rssi >= rssiThreshSaturated) score += 5;
487
488        if (score > NetworkAgent.WIFI_BASE_SCORE) score = NetworkAgent.WIFI_BASE_SCORE;
489        if (score < 0) score = 0;
490
491        return score;
492    }
493
494    /**
495     * Determines if we can see both 2.4GHz and 5GHz for current config
496     */
497    private boolean multiBandScanResults(WifiInfo wifiInfo) {
498        WifiConfiguration currentConfiguration =
499                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
500        if (currentConfiguration == null) return false;
501        ScanDetailCache scanDetailCache =
502                mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId());
503        if (scanDetailCache == null) return false;
504        // TODO(b/36364366): Nasty that we change state here...
505        currentConfiguration.setVisibility(scanDetailCache.getVisibility(SCAN_CACHE_VISIBILITY_MS));
506        if (currentConfiguration.visibility == null) return false;
507        if (currentConfiguration.visibility.rssi24 == WifiConfiguration.INVALID_RSSI) return false;
508        // TODO: this does not do exactly what is claimed!
509        if (currentConfiguration.visibility.rssi24
510                >= currentConfiguration.visibility.rssi5 - SCAN_CACHE_COUNT_PENALTY) {
511            return true;
512        }
513        return false;
514    }
515
516    /**
517     * Decides whether the current network is a "home" network
518     */
519    private boolean isHomeNetwork(WifiInfo wifiInfo) {
520        WifiConfiguration currentConfiguration =
521                mWifiConfigManager.getConfiguredNetwork(wifiInfo.getNetworkId());
522        if (currentConfiguration == null) return false;
523        // TODO: This seems like it will only return true for really old routers!
524        if (currentConfiguration.allowedKeyManagement.cardinality() != 1) return false;
525        if (!currentConfiguration.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.WPA_PSK)) {
526            return false;
527        }
528        ScanDetailCache scanDetailCache =
529                mWifiConfigManager.getScanDetailCacheForNetwork(wifiInfo.getNetworkId());
530        if (scanDetailCache == null) return false;
531        if (scanDetailCache.size() <= HOME_VISIBLE_NETWORK_MAX_COUNT) {
532            return true;
533        }
534        return false;
535    }
536}
537