• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.util;
18 
19 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
20 import android.util.SparseIntArray;
21 
22 import com.android.server.wifi.WifiBlocklistMonitor;
23 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
24 
25 /**
26  * Utilities for Metrics collections.
27  */
28 public class MetricsUtils {
29     /**
30      * A generic bucket containing a start, end, and count. The utility classes will convert to
31      * such a generic bucket which can then be copied into the specific bucket of the proto.
32      */
33     public static class GenericBucket {
34         public long start;
35         public long end;
36         public int count;
37     }
38 
39     /**
40      * Specifies a ~log histogram consisting of two levels of buckets - a set of N big buckets:
41      *
42      * Buckets starts at: B + P * M^i, where i=0, ... , N-1 (N big buckets)
43      * Each big bucket is divided into S sub-buckets
44      *
45      * Each (big) bucket is M times bigger than the previous one.
46      *
47      * The buckets are then:
48      * #0: B + P * M^0 with S buckets each of width (P*M^1-P*M^0)/S
49      * #1: B + P * M^1 with S buckets each of width (P*M^2-P*M^1)/S
50      * ...
51      * #N-1: B + P * M^(N-1) with S buckets each of width (P*M^N-P*M^(N-1))/S
52      */
53     public static class LogHistParms {
LogHistParms(int b, int p, int m, int s, int n)54         public LogHistParms(int b, int p, int m, int s, int n) {
55             this.b = b;
56             this.p = p;
57             this.m = m;
58             this.s = s;
59             this.n = n;
60 
61             // derived values
62             mLog = Math.log(m);
63             bb = new double[n];
64             sbw = new double[n];
65             bb[0] = b + p;
66             sbw[0] = p * (m - 1.0) / (double) s;
67             for (int i = 1; i < n; ++i) {
68                 bb[i] = m * (bb[i - 1] - b) + b;
69                 sbw[i] = m * sbw[i - 1];
70             }
71         }
72 
73         // spec
74         public int b;
75         public int p;
76         public int m;
77         public int s;
78         public int n;
79 
80         // derived
81         public double mLog;
82         public double[] bb; // bucket base
83         public double[] sbw; // sub-bucket width
84     }
85 
86     /**
87      * Adds the input value to the log histogram based on the histogram parameters.
88      */
addValueToLogHistogram(long x, SparseIntArray histogram, LogHistParms hp)89     public static int addValueToLogHistogram(long x, SparseIntArray histogram, LogHistParms hp) {
90         double logArg = (double) (x - hp.b) / (double) hp.p;
91         int bigBucketIndex = -1;
92         if (logArg > 0) {
93             bigBucketIndex = (int) (Math.log(logArg) / hp.mLog);
94         }
95         int subBucketIndex;
96         if (bigBucketIndex < 0) {
97             bigBucketIndex = 0;
98             subBucketIndex = 0;
99         } else if (bigBucketIndex >= hp.n) {
100             bigBucketIndex = hp.n - 1;
101             subBucketIndex = hp.s - 1;
102         } else {
103             subBucketIndex = (int) ((x - hp.bb[bigBucketIndex]) / hp.sbw[bigBucketIndex]);
104             if (subBucketIndex >= hp.s) { // probably a rounding error so move to next big bucket
105                 bigBucketIndex++;
106                 if (bigBucketIndex >= hp.n) {
107                     bigBucketIndex = hp.n - 1;
108                     subBucketIndex = hp.s - 1;
109                 } else {
110                     subBucketIndex = (int) ((x - hp.bb[bigBucketIndex]) / hp.sbw[bigBucketIndex]);
111                 }
112             }
113         }
114         int key = bigBucketIndex * hp.s + subBucketIndex;
115 
116         // note that get() returns 0 if index not there already
117         int newValue = histogram.get(key) + 1;
118         histogram.put(key, newValue);
119 
120         return newValue;
121     }
122 
123     /**
124      * Converts the log histogram (with the specified histogram parameters) to an array of generic
125      * histogram buckets.
126      */
logHistogramToGenericBuckets(SparseIntArray histogram, LogHistParms hp)127     public static GenericBucket[] logHistogramToGenericBuckets(SparseIntArray histogram,
128             LogHistParms hp) {
129         GenericBucket[] protoArray = new GenericBucket[histogram.size()];
130         for (int i = 0; i < histogram.size(); ++i) {
131             int key = histogram.keyAt(i);
132 
133             protoArray[i] = new GenericBucket();
134             protoArray[i].start = (long) (hp.bb[key / hp.s] + hp.sbw[key / hp.s] * (key % hp.s));
135             protoArray[i].end = (long) (protoArray[i].start + hp.sbw[key / hp.s]);
136             protoArray[i].count = histogram.valueAt(i);
137         }
138 
139         return protoArray;
140     }
141 
142     /**
143      * Adds the input value to the histogram based on the lineaer histogram parameters.
144      *
145      * The 'int[] hp' contains a list of bucket limits. The number of buckets is hp.length() + 1
146      * where buckets are:
147      * - < hp[0]
148      * - [hp[0], hp[1])
149      * ...
150      * - >= hp[hp.length() - 1]
151      */
addValueToLinearHistogram(int x, SparseIntArray histogram, int[] hp)152     public static int addValueToLinearHistogram(int x, SparseIntArray histogram, int[] hp) {
153         int bucket = 0;
154         for (int limit : hp) {
155             if (x >= limit) {
156                 bucket++;
157                 continue;
158             }
159             break;
160         }
161 
162         // note that get() returns 0 if index not there already
163         int newValue = histogram.get(bucket) + 1;
164         histogram.put(bucket, newValue);
165 
166         return newValue;
167     }
168 
169     /**
170      * Converts the histogram (with the specified linear histogram parameters) to an array of
171      * generic histogram buckets.
172      */
linearHistogramToGenericBuckets(SparseIntArray histogram, int[] linearHistParams)173     public static GenericBucket[] linearHistogramToGenericBuckets(SparseIntArray histogram,
174             int[] linearHistParams) {
175         GenericBucket[] protoArray = new GenericBucket[histogram.size()];
176         for (int i = 0; i < histogram.size(); ++i) {
177             int bucket = histogram.keyAt(i);
178 
179             protoArray[i] = new GenericBucket();
180             if (bucket == 0) {
181                 protoArray[i].start = Integer.MIN_VALUE;
182                 protoArray[i].end = linearHistParams[0];
183             } else if (bucket != linearHistParams.length) {
184                 protoArray[i].start = linearHistParams[bucket - 1];
185                 protoArray[i].end = linearHistParams[bucket];
186             } else {
187                 protoArray[i].start = linearHistParams[linearHistParams.length - 1];
188                 protoArray[i].end = Integer.MAX_VALUE;
189             }
190             protoArray[i].count = histogram.valueAt(i);
191         }
192 
193         return protoArray;
194     }
195 
196     /**
197      * Converts NetworkSelectionStatus.NetworkSelectionDisableReason to
198      * WifiMetricsProto.NetworkDisableReason.DisableReason
199      */
convertNetworkSelectionDisableReasonToWifiProtoEnum(int reason)200     public static int convertNetworkSelectionDisableReasonToWifiProtoEnum(int reason) {
201         switch (reason) {
202             case NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
203                 return NetworkDisableReason.REASON_ASSOCIATION_REJECTION;
204             case NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
205                 return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE;
206             case NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
207                 return NetworkDisableReason.REASON_DHCP_FAILURE;
208             case NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY:
209             case NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT:
210                 return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE;
211             case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS:
212                 return NetworkDisableReason.REASON_AUTHENTICATION_NO_CREDENTIALS;
213             case NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
214                 return NetworkDisableReason.REASON_WRONG_PASSWORD;
215             case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION:
216                 return NetworkDisableReason.REASON_AUTHENTICATION_NO_SUBSCRIPTION;
217             default:
218                 return NetworkDisableReason.REASON_UNKNOWN;
219         }
220     }
221 
222     /**
223      * Converts WifiBlocklistMonitor.FailureReason to
224      * WifiMetricsProto.NetworkDisableReason.DisableReason
225      */
convertBssidBlocklistReasonToWifiProtoEnum(int reason)226     public static int convertBssidBlocklistReasonToWifiProtoEnum(int reason) {
227         switch (reason) {
228             case WifiBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA:
229                 return NetworkDisableReason.REASON_AP_UNABLE_TO_HANDLE_NEW_STA;
230             case WifiBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE:
231                 return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE;
232             case WifiBlocklistMonitor.REASON_WRONG_PASSWORD:
233                 return NetworkDisableReason.REASON_WRONG_PASSWORD;
234             case WifiBlocklistMonitor.REASON_EAP_FAILURE:
235                 return NetworkDisableReason.REASON_EAP_FAILURE;
236             case WifiBlocklistMonitor.REASON_ASSOCIATION_REJECTION:
237                 return NetworkDisableReason.REASON_ASSOCIATION_REJECTION;
238             case WifiBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT:
239                 return NetworkDisableReason.REASON_ASSOCIATION_TIMEOUT;
240             case WifiBlocklistMonitor.REASON_AUTHENTICATION_FAILURE:
241                 return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE;
242             case WifiBlocklistMonitor.REASON_DHCP_FAILURE:
243                 return NetworkDisableReason.REASON_DHCP_FAILURE;
244             case WifiBlocklistMonitor.REASON_ABNORMAL_DISCONNECT:
245                 return NetworkDisableReason.REASON_ABNORMAL_DISCONNECT;
246             case WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE:
247                 return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_MBO_OCE;
248             case WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT:
249                 return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT;
250             case WifiBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE:
251                 return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE;
252             default:
253                 return NetworkDisableReason.REASON_UNKNOWN;
254         }
255     }
256 }
257