1 /* 2 * Copyright (C) 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 static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; 20 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; 21 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; 22 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; 23 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; 24 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; 25 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; 26 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK; 27 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI; 28 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; 29 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; 30 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; 31 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; 32 import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; 33 34 import android.net.wifi.EasyConnectStatusCallback; 35 import android.util.SparseIntArray; 36 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.server.wifi.proto.nano.WifiMetricsProto; 39 import com.android.server.wifi.util.IntHistogram; 40 41 import java.io.PrintWriter; 42 43 /** 44 * Provides metrics for Wi-Fi Easy Connect (DPP). Metrics include number of initiator requests, 45 * number of successes, failures and time completion histogram. 46 */ 47 public class DppMetrics { 48 private final WifiMetricsProto.WifiDppLog mWifiDppLogProto = new WifiMetricsProto.WifiDppLog(); 49 50 // Easy-Connect (DPP) Metrics 51 // Histogram for DPP operation time. Indicates the following 5 buckets (in seconds): 52 // < 1 53 // [1, 10) 54 // [10, 25) 55 // [25, 39) 56 // >= 39 - which means timeout. 57 @VisibleForTesting 58 public static final int[] DPP_OPERATION_TIME = {1, 10, 25, 39}; 59 private IntHistogram mHistogramDppOperationTime = new IntHistogram(DPP_OPERATION_TIME); 60 61 // Failure codes 62 private SparseIntArray mHistogramDppFailureCode = new SparseIntArray(); 63 64 // Configurator success codes 65 private SparseIntArray mHistogramDppConfiguratorSuccessCode = new SparseIntArray(); 66 67 private final Object mLock = new Object(); 68 69 /** 70 * Update DPP Configurator-Initiator requests 71 */ updateDppConfiguratorInitiatorRequests()72 public void updateDppConfiguratorInitiatorRequests() { 73 synchronized (mLock) { 74 mWifiDppLogProto.numDppConfiguratorInitiatorRequests++; 75 } 76 } 77 78 /** 79 * Update DPP Enrollee-Initiator requests 80 */ updateDppEnrolleeInitiatorRequests()81 public void updateDppEnrolleeInitiatorRequests() { 82 synchronized (mLock) { 83 mWifiDppLogProto.numDppEnrolleeInitiatorRequests++; 84 } 85 } 86 87 /** 88 * Update DPP Enrollee success counter 89 */ updateDppEnrolleeSuccess()90 public void updateDppEnrolleeSuccess() { 91 synchronized (mLock) { 92 mWifiDppLogProto.numDppEnrolleeSuccess++; 93 } 94 } 95 96 /** 97 * Update number of DPP R1 capable enrollee responder devices. 98 */ updateDppR1CapableEnrolleeResponderDevices()99 public void updateDppR1CapableEnrolleeResponderDevices() { 100 synchronized (mLock) { 101 mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices++; 102 } 103 } 104 105 /** 106 * Update number of DPP R2 capable enrollee responder devices. 107 */ updateDppR2CapableEnrolleeResponderDevices()108 public void updateDppR2CapableEnrolleeResponderDevices() { 109 synchronized (mLock) { 110 mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices++; 111 } 112 } 113 114 /** 115 * Update number of times DPP R2 compatibility check detected 116 * that enrollee responder device is incompatible with the 117 * network. 118 */ updateDppR2EnrolleeResponderIncompatibleConfiguration()119 public void updateDppR2EnrolleeResponderIncompatibleConfiguration() { 120 synchronized (mLock) { 121 mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration++; 122 } 123 } 124 125 /** 126 * Update DPP Configurator success counter 127 */ updateDppConfiguratorSuccess( @asyConnectStatusCallback.EasyConnectSuccessStatusCode int code)128 public void updateDppConfiguratorSuccess( 129 @EasyConnectStatusCallback.EasyConnectSuccessStatusCode int code) { 130 synchronized (mLock) { 131 switch (code) { 132 case EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT: 133 mHistogramDppConfiguratorSuccessCode.put(WifiMetricsProto.WifiDppLog 134 .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT, 135 mHistogramDppConfiguratorSuccessCode.get(WifiMetricsProto.WifiDppLog 136 .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT) + 1); 137 break; 138 case EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED: 139 mHistogramDppConfiguratorSuccessCode.put(WifiMetricsProto.WifiDppLog 140 .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED, 141 mHistogramDppConfiguratorSuccessCode.get(WifiMetricsProto.WifiDppLog 142 .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED) + 1); 143 break; 144 default: 145 break; 146 } 147 } 148 } 149 150 /** 151 * Update DPP failure counters 152 */ updateDppFailure(@asyConnectStatusCallback.EasyConnectFailureStatusCode int code)153 public void updateDppFailure(@EasyConnectStatusCallback.EasyConnectFailureStatusCode int code) { 154 synchronized (mLock) { 155 switch (code) { 156 case EASY_CONNECT_EVENT_FAILURE_INVALID_URI: 157 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 158 .EASY_CONNECT_EVENT_FAILURE_INVALID_URI, 159 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 160 .EASY_CONNECT_EVENT_FAILURE_INVALID_URI) + 1); 161 break; 162 case EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION: 163 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 164 .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION, 165 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 166 .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION) + 1); 167 break; 168 case EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE: 169 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 170 .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE, 171 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 172 .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE) + 1); 173 break; 174 case EASY_CONNECT_EVENT_FAILURE_CONFIGURATION: 175 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 176 .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, 177 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 178 .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION) + 1); 179 break; 180 case EASY_CONNECT_EVENT_FAILURE_BUSY: 181 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 182 .EASY_CONNECT_EVENT_FAILURE_BUSY, 183 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 184 .EASY_CONNECT_EVENT_FAILURE_BUSY) + 1); 185 break; 186 case EASY_CONNECT_EVENT_FAILURE_TIMEOUT: 187 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 188 .EASY_CONNECT_EVENT_FAILURE_TIMEOUT, 189 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 190 .EASY_CONNECT_EVENT_FAILURE_TIMEOUT) + 1); 191 break; 192 case EASY_CONNECT_EVENT_FAILURE_GENERIC: 193 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 194 .EASY_CONNECT_EVENT_FAILURE_GENERIC, 195 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 196 .EASY_CONNECT_EVENT_FAILURE_GENERIC) + 1); 197 break; 198 case EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED: 199 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 200 .EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED, 201 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 202 .EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED) + 1); 203 break; 204 case EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK: 205 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 206 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, 207 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 208 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK) + 1); 209 break; 210 case EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK: 211 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 212 .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK, 213 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 214 .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK) + 1); 215 break; 216 case EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION: 217 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 218 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION, 219 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 220 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION) + 1); 221 break; 222 case EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION: 223 mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog 224 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION, 225 mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog 226 .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION) 227 + 1); 228 break; 229 default: 230 break; 231 } 232 } 233 } 234 235 /** 236 * Update DPP operation time 237 * 238 * @param timeMs Time it took to complete the operation, in milliseconds 239 */ updateDppOperationTime(int timeMs)240 public void updateDppOperationTime(int timeMs) { 241 synchronized (mLock) { 242 mHistogramDppOperationTime.increment(timeMs / 1000); 243 } 244 } 245 246 /** 247 * Dump all DPP metrics 248 * 249 * @param pw PrintWriter handle 250 */ dump(PrintWriter pw)251 public void dump(PrintWriter pw) { 252 synchronized (mLock) { 253 pw.println("---Easy Connect/DPP metrics---"); 254 pw.println("mWifiDppLogProto.numDppConfiguratorInitiatorRequests=" 255 + mWifiDppLogProto.numDppConfiguratorInitiatorRequests); 256 pw.println("mWifiDppLogProto.numDppEnrolleeInitiatorRequests=" 257 + mWifiDppLogProto.numDppEnrolleeInitiatorRequests); 258 pw.println("mWifiDppLogProto.numDppEnrolleeSuccess=" 259 + mWifiDppLogProto.numDppEnrolleeSuccess); 260 pw.println("mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices=" 261 + mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices); 262 pw.println("mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices=" 263 + mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices); 264 pw.println("mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration=" 265 + mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration); 266 267 if (mHistogramDppFailureCode.size() > 0) { 268 pw.println("mHistogramDppFailureCode="); 269 pw.println(mHistogramDppFailureCode); 270 } 271 272 if (mHistogramDppConfiguratorSuccessCode.size() > 0) { 273 pw.println("mHistogramDppConfiguratorSuccessCode="); 274 pw.println(mHistogramDppConfiguratorSuccessCode); 275 } 276 277 if (mHistogramDppOperationTime.numNonEmptyBuckets() > 0) { 278 pw.println("mHistogramDppOperationTime="); 279 pw.println(mHistogramDppOperationTime); 280 } 281 pw.println("---End of Easy Connect/DPP metrics---"); 282 } 283 } 284 285 /** 286 * Clear all DPP metrics 287 */ clear()288 public void clear() { 289 synchronized (mLock) { 290 mWifiDppLogProto.numDppConfiguratorInitiatorRequests = 0; 291 mWifiDppLogProto.numDppEnrolleeInitiatorRequests = 0; 292 mWifiDppLogProto.numDppEnrolleeSuccess = 0; 293 mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices = 0; 294 mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices = 0; 295 mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration = 0; 296 mHistogramDppFailureCode.clear(); 297 mHistogramDppOperationTime.clear(); 298 mHistogramDppConfiguratorSuccessCode.clear(); 299 } 300 } 301 consolidateDppFailure( SparseIntArray data)302 private WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[] consolidateDppFailure( 303 SparseIntArray data) { 304 WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[] 305 dppFailureStatusHistogramBuckets = 306 new WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[data.size()]; 307 308 for (int i = 0; i < data.size(); i++) { 309 dppFailureStatusHistogramBuckets[i] = 310 new WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket(); 311 dppFailureStatusHistogramBuckets[i].dppStatusType = data.keyAt(i); 312 dppFailureStatusHistogramBuckets[i].count = data.valueAt(i); 313 } 314 315 return dppFailureStatusHistogramBuckets; 316 } 317 318 private WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket[] consolidateDppSuccess( SparseIntArray data)319 consolidateDppSuccess( 320 SparseIntArray data) { 321 WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket[] 322 dppConfiguratorSuccessStatusHistogramBuckets = 323 new WifiMetricsProto.WifiDppLog 324 .DppConfiguratorSuccessStatusHistogramBucket[data.size()]; 325 326 for (int i = 0; i < data.size(); i++) { 327 dppConfiguratorSuccessStatusHistogramBuckets[i] = 328 new WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket(); 329 dppConfiguratorSuccessStatusHistogramBuckets[i].dppStatusType = data.keyAt(i); 330 dppConfiguratorSuccessStatusHistogramBuckets[i].count = data.valueAt(i); 331 } 332 333 return dppConfiguratorSuccessStatusHistogramBuckets; 334 } 335 336 /** 337 * Consolidate all metrics into the proto. 338 */ consolidateProto()339 public WifiMetricsProto.WifiDppLog consolidateProto() { 340 WifiMetricsProto.WifiDppLog log = new WifiMetricsProto.WifiDppLog(); 341 synchronized (mLock) { 342 log.numDppConfiguratorInitiatorRequests = 343 mWifiDppLogProto.numDppConfiguratorInitiatorRequests; 344 log.numDppEnrolleeInitiatorRequests = mWifiDppLogProto.numDppEnrolleeInitiatorRequests; 345 log.numDppEnrolleeSuccess = mWifiDppLogProto.numDppEnrolleeSuccess; 346 log.numDppR1CapableEnrolleeResponderDevices = 347 mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices; 348 log.numDppR2CapableEnrolleeResponderDevices = 349 mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices; 350 log.numDppR2EnrolleeResponderIncompatibleConfiguration = 351 mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration; 352 log.dppFailureCode = consolidateDppFailure(mHistogramDppFailureCode); 353 log.dppConfiguratorSuccessCode = 354 consolidateDppSuccess(mHistogramDppConfiguratorSuccessCode); 355 log.dppOperationTime = mHistogramDppOperationTime.toProto(); 356 } 357 return log; 358 } 359 } 360