| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wifi; |
| |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED; |
| import static android.net.wifi.EasyConnectStatusCallback.EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT; |
| |
| import android.net.wifi.EasyConnectStatusCallback; |
| import android.util.SparseIntArray; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.server.wifi.proto.nano.WifiMetricsProto; |
| import com.android.server.wifi.util.IntHistogram; |
| |
| import java.io.PrintWriter; |
| |
| /** |
| * Provides metrics for Wi-Fi Easy Connect (DPP). Metrics include number of initiator requests, |
| * number of successes, failures and time completion histogram. |
| */ |
| public class DppMetrics { |
| private final WifiMetricsProto.WifiDppLog mWifiDppLogProto = new WifiMetricsProto.WifiDppLog(); |
| |
| // Easy-Connect (DPP) Metrics |
| // Histogram for DPP operation time. Indicates the following 5 buckets (in seconds): |
| // < 1 |
| // [1, 10) |
| // [10, 25) |
| // [25, 39) |
| // >= 39 - which means timeout. |
| @VisibleForTesting |
| public static final int[] DPP_OPERATION_TIME = {1, 10, 25, 39}; |
| private IntHistogram mHistogramDppOperationTime = new IntHistogram(DPP_OPERATION_TIME); |
| |
| // Failure codes |
| private SparseIntArray mHistogramDppFailureCode = new SparseIntArray(); |
| |
| // Configurator success codes |
| private SparseIntArray mHistogramDppConfiguratorSuccessCode = new SparseIntArray(); |
| |
| private final Object mLock = new Object(); |
| |
| /** |
| * Update DPP Configurator-Initiator requests |
| */ |
| public void updateDppConfiguratorInitiatorRequests() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppConfiguratorInitiatorRequests++; |
| } |
| } |
| |
| /** |
| * Update DPP Enrollee-Initiator requests |
| */ |
| public void updateDppEnrolleeInitiatorRequests() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppEnrolleeInitiatorRequests++; |
| } |
| } |
| |
| /** |
| * Update DPP Enrollee success counter |
| */ |
| public void updateDppEnrolleeSuccess() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppEnrolleeSuccess++; |
| } |
| } |
| |
| /** |
| * Update number of DPP R1 capable enrollee responder devices. |
| */ |
| public void updateDppR1CapableEnrolleeResponderDevices() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices++; |
| } |
| } |
| |
| /** |
| * Update number of DPP R2 capable enrollee responder devices. |
| */ |
| public void updateDppR2CapableEnrolleeResponderDevices() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices++; |
| } |
| } |
| |
| /** |
| * Update number of times DPP R2 compatibility check detected |
| * that enrollee responder device is incompatible with the |
| * network. |
| */ |
| public void updateDppR2EnrolleeResponderIncompatibleConfiguration() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration++; |
| } |
| } |
| |
| /** |
| * Update DPP Configurator success counter |
| */ |
| public void updateDppConfiguratorSuccess( |
| @EasyConnectStatusCallback.EasyConnectSuccessStatusCode int code) { |
| synchronized (mLock) { |
| switch (code) { |
| case EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT: |
| mHistogramDppConfiguratorSuccessCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT, |
| mHistogramDppConfiguratorSuccessCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT) + 1); |
| break; |
| case EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED: |
| mHistogramDppConfiguratorSuccessCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED, |
| mHistogramDppConfiguratorSuccessCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED) + 1); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Update DPP failure counters |
| */ |
| public void updateDppFailure(@EasyConnectStatusCallback.EasyConnectFailureStatusCode int code) { |
| synchronized (mLock) { |
| switch (code) { |
| case EASY_CONNECT_EVENT_FAILURE_INVALID_URI: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_INVALID_URI, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_INVALID_URI) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_CONFIGURATION: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_BUSY: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_BUSY, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_BUSY) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_TIMEOUT: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_TIMEOUT, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_TIMEOUT) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_GENERIC: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_GENERIC, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_GENERIC) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION) + 1); |
| break; |
| case EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION: |
| mHistogramDppFailureCode.put(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION, |
| mHistogramDppFailureCode.get(WifiMetricsProto.WifiDppLog |
| .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION) |
| + 1); |
| break; |
| default: |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Update DPP operation time |
| * |
| * @param timeMs Time it took to complete the operation, in milliseconds |
| */ |
| public void updateDppOperationTime(int timeMs) { |
| synchronized (mLock) { |
| mHistogramDppOperationTime.increment(timeMs / 1000); |
| } |
| } |
| |
| /** |
| * Dump all DPP metrics |
| * |
| * @param pw PrintWriter handle |
| */ |
| public void dump(PrintWriter pw) { |
| synchronized (mLock) { |
| pw.println("---Easy Connect/DPP metrics---"); |
| pw.println("mWifiDppLogProto.numDppConfiguratorInitiatorRequests=" |
| + mWifiDppLogProto.numDppConfiguratorInitiatorRequests); |
| pw.println("mWifiDppLogProto.numDppEnrolleeInitiatorRequests=" |
| + mWifiDppLogProto.numDppEnrolleeInitiatorRequests); |
| pw.println("mWifiDppLogProto.numDppEnrolleeSuccess=" |
| + mWifiDppLogProto.numDppEnrolleeSuccess); |
| pw.println("mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices=" |
| + mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices); |
| pw.println("mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices=" |
| + mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices); |
| pw.println("mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration=" |
| + mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration); |
| |
| if (mHistogramDppFailureCode.size() > 0) { |
| pw.println("mHistogramDppFailureCode="); |
| pw.println(mHistogramDppFailureCode); |
| } |
| |
| if (mHistogramDppConfiguratorSuccessCode.size() > 0) { |
| pw.println("mHistogramDppConfiguratorSuccessCode="); |
| pw.println(mHistogramDppConfiguratorSuccessCode); |
| } |
| |
| if (mHistogramDppOperationTime.numNonEmptyBuckets() > 0) { |
| pw.println("mHistogramDppOperationTime="); |
| pw.println(mHistogramDppOperationTime); |
| } |
| pw.println("---End of Easy Connect/DPP metrics---"); |
| } |
| } |
| |
| /** |
| * Clear all DPP metrics |
| */ |
| public void clear() { |
| synchronized (mLock) { |
| mWifiDppLogProto.numDppConfiguratorInitiatorRequests = 0; |
| mWifiDppLogProto.numDppEnrolleeInitiatorRequests = 0; |
| mWifiDppLogProto.numDppEnrolleeSuccess = 0; |
| mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices = 0; |
| mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices = 0; |
| mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration = 0; |
| mHistogramDppFailureCode.clear(); |
| mHistogramDppOperationTime.clear(); |
| mHistogramDppConfiguratorSuccessCode.clear(); |
| } |
| } |
| |
| private WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[] consolidateDppFailure( |
| SparseIntArray data) { |
| WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[] |
| dppFailureStatusHistogramBuckets = |
| new WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket[data.size()]; |
| |
| for (int i = 0; i < data.size(); i++) { |
| dppFailureStatusHistogramBuckets[i] = |
| new WifiMetricsProto.WifiDppLog.DppFailureStatusHistogramBucket(); |
| dppFailureStatusHistogramBuckets[i].dppStatusType = data.keyAt(i); |
| dppFailureStatusHistogramBuckets[i].count = data.valueAt(i); |
| } |
| |
| return dppFailureStatusHistogramBuckets; |
| } |
| |
| private WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket[] |
| consolidateDppSuccess( |
| SparseIntArray data) { |
| WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket[] |
| dppConfiguratorSuccessStatusHistogramBuckets = |
| new WifiMetricsProto.WifiDppLog |
| .DppConfiguratorSuccessStatusHistogramBucket[data.size()]; |
| |
| for (int i = 0; i < data.size(); i++) { |
| dppConfiguratorSuccessStatusHistogramBuckets[i] = |
| new WifiMetricsProto.WifiDppLog.DppConfiguratorSuccessStatusHistogramBucket(); |
| dppConfiguratorSuccessStatusHistogramBuckets[i].dppStatusType = data.keyAt(i); |
| dppConfiguratorSuccessStatusHistogramBuckets[i].count = data.valueAt(i); |
| } |
| |
| return dppConfiguratorSuccessStatusHistogramBuckets; |
| } |
| |
| /** |
| * Consolidate all metrics into the proto. |
| */ |
| public WifiMetricsProto.WifiDppLog consolidateProto() { |
| WifiMetricsProto.WifiDppLog log = new WifiMetricsProto.WifiDppLog(); |
| synchronized (mLock) { |
| log.numDppConfiguratorInitiatorRequests = |
| mWifiDppLogProto.numDppConfiguratorInitiatorRequests; |
| log.numDppEnrolleeInitiatorRequests = mWifiDppLogProto.numDppEnrolleeInitiatorRequests; |
| log.numDppEnrolleeSuccess = mWifiDppLogProto.numDppEnrolleeSuccess; |
| log.numDppR1CapableEnrolleeResponderDevices = |
| mWifiDppLogProto.numDppR1CapableEnrolleeResponderDevices; |
| log.numDppR2CapableEnrolleeResponderDevices = |
| mWifiDppLogProto.numDppR2CapableEnrolleeResponderDevices; |
| log.numDppR2EnrolleeResponderIncompatibleConfiguration = |
| mWifiDppLogProto.numDppR2EnrolleeResponderIncompatibleConfiguration; |
| log.dppFailureCode = consolidateDppFailure(mHistogramDppFailureCode); |
| log.dppConfiguratorSuccessCode = |
| consolidateDppSuccess(mHistogramDppConfiguratorSuccessCode); |
| log.dppOperationTime = mHistogramDppOperationTime.toProto(); |
| } |
| return log; |
| } |
| } |