• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 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 
17 package com.android.server.wifi;
18 
19 import android.annotation.NonNull;
20 import android.net.wifi.ScanResult;
21 
22 import com.android.server.wifi.WifiCandidates.Candidate;
23 import com.android.server.wifi.WifiCandidates.ScoredCandidate;
24 import com.android.server.wifi.proto.WifiScoreCardProto;
25 import com.android.server.wifi.proto.WifiScoreCardProto.Event;
26 
27 import java.util.Collection;
28 
29 /**
30  * A candidate scorer that uses the scorecard to influence the choice.
31  */
32 final class ScoreCardBasedScorer implements WifiCandidates.CandidateScorer {
33 
34     /**
35      * This should match WifiNetworkSelector.experimentIdFromIdentifier(getIdentifier())
36      * when using the default ScoringParams.
37      */
38     public static final int SCORE_CARD_BASED_SCORER_DEFAULT_EXPID = 42902385;
39 
40     private final ScoringParams mScoringParams;
41 
42     // config_wifi_framework_RSSI_SCORE_OFFSET
43     public static final int RSSI_SCORE_OFFSET = 85;
44 
45     // config_wifi_framework_RSSI_SCORE_SLOPE
46     public static final int RSSI_SCORE_SLOPE_IS_4 = 4;
47 
48     // config_wifi_framework_5GHz_preference_boost_factor
49     public static final int BAND_5GHZ_AWARD_IS_40 = 40;
50 
51     // config_wifiFramework6ghzPreferenceBoostFactor
52     public static final int BAND_6GHZ_AWARD_IS_40 = 40;
53 
54     // config_wifi_framework_SECURITY_AWARD
55     public static final int SECURITY_AWARD_IS_80 = 80;
56 
57     // config_wifi_framework_LAST_SELECTION_AWARD
58     public static final int LAST_SELECTION_AWARD_IS_480 = 480;
59 
60     // config_wifi_framework_current_network_boost
61     public static final int CURRENT_NETWORK_BOOST_IS_16 = 16;
62 
63     // config_wifi_framework_SAME_BSSID_AWARD
64     public static final int SAME_BSSID_AWARD_IS_24 = 24;
65 
66     // Only use scorecard id we have data from this many polls
67     public static final int MIN_POLLS_FOR_SIGNIFICANCE = 30;
68 
69     // Maximum allowable adjustment of the cutoff rssi (dB)
70     public static final int RSSI_RAIL = 5;
71 
72     private static final boolean USE_USER_CONNECT_CHOICE = true;
73 
ScoreCardBasedScorer(ScoringParams scoringParams)74     ScoreCardBasedScorer(ScoringParams scoringParams) {
75         mScoringParams = scoringParams;
76     }
77 
78     @Override
getIdentifier()79     public String getIdentifier() {
80         return "ScoreCardBasedScorer";
81     }
82 
83     /**
84      * Calculates an individual candidate's score.
85      */
scoreCandidate(Candidate candidate)86     private ScoredCandidate scoreCandidate(Candidate candidate) {
87         int rssiSaturationThreshold = mScoringParams.getGoodRssi(candidate.getFrequency());
88         int rssi = Math.min(candidate.getScanRssi(), rssiSaturationThreshold);
89         int cutoff = estimatedCutoff(candidate);
90         int score = (rssi - cutoff) * RSSI_SCORE_SLOPE_IS_4;
91 
92         if (ScanResult.is6GHz(candidate.getFrequency())) {
93             score += BAND_6GHZ_AWARD_IS_40;
94         } else if (ScanResult.is5GHz(candidate.getFrequency())) {
95             score += BAND_5GHZ_AWARD_IS_40;
96         }
97         score += (int) (candidate.getLastSelectionWeight() * LAST_SELECTION_AWARD_IS_480);
98 
99         if (candidate.isCurrentNetwork()) {
100             score += CURRENT_NETWORK_BOOST_IS_16 + SAME_BSSID_AWARD_IS_24;
101         }
102 
103         if (!candidate.isOpenNetwork()) {
104             score += SECURITY_AWARD_IS_80;
105         }
106 
107         // To simulate the old strict priority rule, subtract a penalty based on
108         // which nominator added the candidate.
109         score -= 1000 * candidate.getNominatorId();
110 
111         return new ScoredCandidate(score, 10,
112                                    USE_USER_CONNECT_CHOICE, candidate);
113     }
114 
estimatedCutoff(Candidate candidate)115     private int estimatedCutoff(Candidate candidate) {
116         int cutoff = -RSSI_SCORE_OFFSET;
117         int lowest = cutoff - RSSI_RAIL;
118         int highest = cutoff + RSSI_RAIL;
119         WifiScoreCardProto.Signal signal = candidate.getEventStatistics(Event.SIGNAL_POLL);
120         if (signal == null) return cutoff;
121         if (!signal.hasRssi()) return cutoff;
122         if (signal.getRssi().getCount() > MIN_POLLS_FOR_SIGNIFICANCE) {
123             double mean = signal.getRssi().getSum() / signal.getRssi().getCount();
124             double mean_square = signal.getRssi().getSumOfSquares() / signal.getRssi().getCount();
125             double variance = mean_square - mean * mean;
126             double sigma = Math.sqrt(variance);
127             double value = mean - 2.0 * sigma;
128             cutoff = (int) Math.min(Math.max(value, lowest), highest);
129         }
130         return cutoff;
131     }
132 
133     @Override
scoreCandidates(@onNull Collection<Candidate> candidates)134     public ScoredCandidate scoreCandidates(@NonNull Collection<Candidate> candidates) {
135         ScoredCandidate choice = ScoredCandidate.NONE;
136         for (Candidate candidate : candidates) {
137             ScoredCandidate scoredCandidate = scoreCandidate(candidate);
138             if (scoredCandidate.value > choice.value) {
139                 choice = scoredCandidate;
140             }
141         }
142         // Here we just return the highest scored candidate; we could
143         // compute a new score, if desired.
144         return choice;
145     }
146 
147 }
148