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