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