blob: 67b0cd88701c30fbc563f4c5e445f56840e358bb [file] [log] [blame]
/*
* Copyright (C) 2017 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.aware;
import android.hardware.wifi.V1_0.NanStatusType;
import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.Clock;
import com.android.server.wifi.proto.nano.WifiMetricsProto;
import com.android.server.wifi.util.MetricsUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Wi-Fi Aware metric container/processor.
*/
public class WifiAwareMetrics {
private static final String TAG = "WifiAwareMetrics";
private static final boolean VDBG = false;
/* package */ boolean mDbg = false;
// Histogram: 8 buckets (i=0, ..., 7) of 9 slots in range 10^i -> 10^(i+1)
// Buckets:
// 1 -> 10: 9 @ 1
// 10 -> 100: 9 @ 10
// 100 -> 1000: 9 @ 10^2
// 10^3 -> 10^4: 9 @ 10^3
// 10^4 -> 10^5: 9 @ 10^4
// 10^5 -> 10^6: 9 @ 10^5
// 10^6 -> 10^7: 9 @ 10^6
// 10^7 -> 10^8: 9 @ 10^7 --> 10^8 ms -> 10^5s -> 28 hours
private static final MetricsUtils.LogHistParms DURATION_LOG_HISTOGRAM =
new MetricsUtils.LogHistParms(0, 1, 10, 9, 8);
// Histogram for ranging limits in discovery. Indicates the following 5 buckets (in meters):
// < 10
// [10, 30)
// [30, 60)
// [60, 100)
// >= 100
private static final int[] RANGING_LIMIT_METERS = { 10, 30, 60, 100 };
private final Object mLock = new Object();
private final Clock mClock;
// enableUsage/disableUsage data
private long mLastEnableUsageMs = 0;
private long mLastEnableUsageInThisSampleWindowMs = 0;
private long mAvailableTimeMs = 0;
private SparseIntArray mHistogramAwareAvailableDurationMs = new SparseIntArray();
// enabled data
private long mLastEnableAwareMs = 0;
private long mLastEnableAwareInThisSampleWindowMs = 0;
private long mEnabledTimeMs = 0;
private SparseIntArray mHistogramAwareEnabledDurationMs = new SparseIntArray();
// attach data
private static class AttachData {
boolean mUsesIdentityCallback; // do any attach sessions of the UID use identity callback
int mMaxConcurrentAttaches;
}
private Map<Integer, AttachData> mAttachDataByUid = new HashMap<>();
private SparseIntArray mAttachStatusData = new SparseIntArray();
private SparseIntArray mHistogramAttachDuration = new SparseIntArray();
// discovery data
private int mMaxPublishInApp = 0;
private int mMaxSubscribeInApp = 0;
private int mMaxDiscoveryInApp = 0;
private int mMaxPublishInSystem = 0;
private int mMaxSubscribeInSystem = 0;
private int mMaxDiscoveryInSystem = 0;
private SparseIntArray mPublishStatusData = new SparseIntArray();
private SparseIntArray mSubscribeStatusData = new SparseIntArray();
private SparseIntArray mHistogramPublishDuration = new SparseIntArray();
private SparseIntArray mHistogramSubscribeDuration = new SparseIntArray();
private Set<Integer> mAppsWithDiscoverySessionResourceFailure = new HashSet<>();
// discovery with ranging data
private int mMaxPublishWithRangingInApp = 0;
private int mMaxSubscribeWithRangingInApp = 0;
private int mMaxPublishWithRangingInSystem = 0;
private int mMaxSubscribeWithRangingInSystem = 0;
private SparseIntArray mHistogramSubscribeGeofenceMin = new SparseIntArray();
private SparseIntArray mHistogramSubscribeGeofenceMax = new SparseIntArray();
private int mNumSubscribesWithRanging = 0;
private int mNumMatchesWithRanging = 0;
private int mNumMatchesWithoutRangingForRangingEnabledSubscribes = 0;
// data-path (NDI/NDP) data
private int mMaxNdiInApp = 0;
private int mMaxNdpInApp = 0;
private int mMaxSecureNdpInApp = 0;
private int mMaxNdiInSystem = 0;
private int mMaxNdpInSystem = 0;
private int mMaxSecureNdpInSystem = 0;
private int mMaxNdpPerNdi = 0;
private SparseIntArray mInBandNdpStatusData = new SparseIntArray();
private SparseIntArray mOutOfBandNdpStatusData = new SparseIntArray();
private SparseIntArray mNdpCreationTimeDuration = new SparseIntArray();
private long mNdpCreationTimeMin = -1;
private long mNdpCreationTimeMax = 0;
private long mNdpCreationTimeSum = 0;
private long mNdpCreationTimeSumSq = 0;
private long mNdpCreationTimeNumSamples = 0;
private SparseIntArray mHistogramNdpDuration = new SparseIntArray();
public WifiAwareMetrics(Clock clock) {
mClock = clock;
}
/**
* Push usage stats for WifiAwareStateMachine.enableUsage() to
* histogram_aware_available_duration_ms.
*/
public void recordEnableUsage() {
synchronized (mLock) {
if (mLastEnableUsageMs != 0) {
Log.w(TAG, "enableUsage: mLastEnableUsage*Ms initialized!?");
}
mLastEnableUsageMs = mClock.getElapsedSinceBootMillis();
mLastEnableUsageInThisSampleWindowMs = mLastEnableUsageMs;
}
}
/**
* Push usage stats for WifiAwareStateMachine.disableUsage() to
* histogram_aware_available_duration_ms.
*/
public void recordDisableUsage() {
synchronized (mLock) {
if (mLastEnableUsageMs == 0) {
Log.e(TAG, "disableUsage: mLastEnableUsage not initialized!?");
return;
}
long now = mClock.getElapsedSinceBootMillis();
MetricsUtils.addValueToLogHistogram(now - mLastEnableUsageMs,
mHistogramAwareAvailableDurationMs, DURATION_LOG_HISTOGRAM);
mAvailableTimeMs += now - mLastEnableUsageInThisSampleWindowMs;
mLastEnableUsageMs = 0;
mLastEnableUsageInThisSampleWindowMs = 0;
}
}
/**
* Push usage stats of Aware actually being enabled on-the-air: start
*/
public void recordEnableAware() {
synchronized (mLock) {
if (mLastEnableAwareMs != 0) {
return; // already enabled
}
mLastEnableAwareMs = mClock.getElapsedSinceBootMillis();
mLastEnableAwareInThisSampleWindowMs = mLastEnableAwareMs;
}
}
/**
* Push usage stats of Aware actually being enabled on-the-air: stop (disable)
*/
public void recordDisableAware() {
synchronized (mLock) {
if (mLastEnableAwareMs == 0) {
return; // already disabled
}
long now = mClock.getElapsedSinceBootMillis();
MetricsUtils.addValueToLogHistogram(now - mLastEnableAwareMs,
mHistogramAwareEnabledDurationMs, DURATION_LOG_HISTOGRAM);
mEnabledTimeMs += now - mLastEnableAwareInThisSampleWindowMs;
mLastEnableAwareMs = 0;
mLastEnableAwareInThisSampleWindowMs = 0;
}
}
/**
* Push information about a new attach session.
*/
public void recordAttachSession(int uid, boolean usesIdentityCallback,
SparseArray<WifiAwareClientState> clients) {
// count the number of clients with the specific uid
int currentConcurrentCount = 0;
for (int i = 0; i < clients.size(); ++i) {
if (clients.valueAt(i).getUid() == uid) {
++currentConcurrentCount;
}
}
synchronized (mLock) {
AttachData data = mAttachDataByUid.get(uid);
if (data == null) {
data = new AttachData();
mAttachDataByUid.put(uid, data);
}
data.mUsesIdentityCallback |= usesIdentityCallback;
data.mMaxConcurrentAttaches = Math.max(data.mMaxConcurrentAttaches,
currentConcurrentCount);
recordAttachStatus(NanStatusType.SUCCESS);
}
}
/**
* Push information about a new attach session status (recorded when attach session is created).
*/
public void recordAttachStatus(int status) {
synchronized (mLock) {
addNanHalStatusToHistogram(status, mAttachStatusData);
}
}
/**
* Push duration information of an attach session.
*/
public void recordAttachSessionDuration(long creationTime) {
synchronized (mLock) {
MetricsUtils.addValueToLogHistogram(mClock.getElapsedSinceBootMillis() - creationTime,
mHistogramAttachDuration, DURATION_LOG_HISTOGRAM);
}
}
/**
* Push information about the new discovery session.
*/
public void recordDiscoverySession(int uid, SparseArray<WifiAwareClientState> clients) {
recordDiscoverySessionInternal(uid, clients, false, -1, -1);
}
/**
* Push information about the new discovery session with ranging enabled
*/
public void recordDiscoverySessionWithRanging(int uid, boolean isSubscriberWithRanging,
int minRange, int maxRange, SparseArray<WifiAwareClientState> clients) {
recordDiscoverySessionInternal(uid, clients, isSubscriberWithRanging, minRange, maxRange);
}
/**
* Internal combiner of discovery session information.
*/
private void recordDiscoverySessionInternal(int uid, SparseArray<WifiAwareClientState> clients,
boolean isRangingEnabledSubscriber, int minRange, int maxRange) {
// count the number of sessions per uid and overall
int numPublishesInSystem = 0;
int numSubscribesInSystem = 0;
int numPublishesOnUid = 0;
int numSubscribesOnUid = 0;
int numPublishesWithRangingInSystem = 0;
int numSubscribesWithRangingInSystem = 0;
int numPublishesWithRangingOnUid = 0;
int numSubscribesWithRangingOnUid = 0;
for (int i = 0; i < clients.size(); ++i) {
WifiAwareClientState client = clients.valueAt(i);
boolean sameUid = client.getUid() == uid;
SparseArray<WifiAwareDiscoverySessionState> sessions = client.getSessions();
for (int j = 0; j < sessions.size(); ++j) {
WifiAwareDiscoverySessionState session = sessions.valueAt(j);
boolean isRangingEnabledForThisSession = session.isRangingEnabled();
if (session.isPublishSession()) {
numPublishesInSystem += 1;
if (isRangingEnabledForThisSession) {
numPublishesWithRangingInSystem += 1;
}
if (sameUid) {
numPublishesOnUid += 1;
if (isRangingEnabledForThisSession) {
numPublishesWithRangingOnUid += 1;
}
}
} else {
numSubscribesInSystem += 1;
if (isRangingEnabledForThisSession) {
numSubscribesWithRangingInSystem += 1;
}
if (sameUid) {
numSubscribesOnUid += 1;
if (isRangingEnabledForThisSession) {
numSubscribesWithRangingOnUid += 1;
}
}
}
}
}
synchronized (mLock) {
mMaxPublishInApp = Math.max(mMaxPublishInApp, numPublishesOnUid);
mMaxSubscribeInApp = Math.max(mMaxSubscribeInApp, numSubscribesOnUid);
mMaxDiscoveryInApp = Math.max(mMaxDiscoveryInApp,
numPublishesOnUid + numSubscribesOnUid);
mMaxPublishInSystem = Math.max(mMaxPublishInSystem, numPublishesInSystem);
mMaxSubscribeInSystem = Math.max(mMaxSubscribeInSystem, numSubscribesInSystem);
mMaxDiscoveryInSystem = Math.max(mMaxDiscoveryInSystem,
numPublishesInSystem + numSubscribesInSystem);
mMaxPublishWithRangingInApp = Math.max(mMaxPublishWithRangingInApp,
numPublishesWithRangingOnUid);
mMaxSubscribeWithRangingInApp = Math.max(mMaxSubscribeWithRangingInApp,
numSubscribesWithRangingOnUid);
mMaxPublishWithRangingInSystem = Math.max(mMaxPublishWithRangingInSystem,
numPublishesWithRangingInSystem);
mMaxSubscribeWithRangingInSystem = Math.max(mMaxSubscribeWithRangingInSystem,
numSubscribesWithRangingInSystem);
if (isRangingEnabledSubscriber) {
mNumSubscribesWithRanging += 1;
}
if (minRange != -1) {
MetricsUtils.addValueToLinearHistogram(minRange, mHistogramSubscribeGeofenceMin,
RANGING_LIMIT_METERS);
}
if (maxRange != -1) {
MetricsUtils.addValueToLinearHistogram(maxRange, mHistogramSubscribeGeofenceMax,
RANGING_LIMIT_METERS);
}
}
}
/**
* Push information about a new discovery session status (recorded when the discovery session is
* created).
*/
public void recordDiscoveryStatus(int uid, int status, boolean isPublish) {
synchronized (mLock) {
if (isPublish) {
addNanHalStatusToHistogram(status, mPublishStatusData);
} else {
addNanHalStatusToHistogram(status, mSubscribeStatusData);
}
if (status == NanStatusType.NO_RESOURCES_AVAILABLE) {
mAppsWithDiscoverySessionResourceFailure.add(uid);
}
}
}
/**
* Push duration information of a discovery session.
*/
public void recordDiscoverySessionDuration(long creationTime, boolean isPublish) {
synchronized (mLock) {
MetricsUtils.addValueToLogHistogram(mClock.getElapsedSinceBootMillis() - creationTime,
isPublish ? mHistogramPublishDuration : mHistogramSubscribeDuration,
DURATION_LOG_HISTOGRAM);
}
}
/**
* Push information about Match indication (aka service discovered) for subscribe sessions
* which enabled ranging. Collect information about whether or not service discovery was
* triggered with ranging information or without (i.e. ranging disabled for some reason).
*/
public void recordMatchIndicationForRangeEnabledSubscribe(boolean rangeProvided) {
if (rangeProvided) {
mNumMatchesWithRanging++;
} else {
mNumMatchesWithoutRangingForRangingEnabledSubscribes++;
}
}
/**
* Record NDP (and by extension NDI) usage - on successful creation of an NDP.
*/
public void recordNdpCreation(int uid, String packageName,
Map<WifiAwareNetworkSpecifier, WifiAwareDataPathStateManager
.AwareNetworkRequestInformation> networkRequestCache) {
int numNdpInApp = 0;
int numSecureNdpInApp = 0;
int numNdpInSystem = 0;
int numSecureNdpInSystem = 0;
Map<String, Integer> ndpPerNdiMap = new HashMap<>();
Set<String> ndiInApp = new HashSet<>();
Set<String> ndiInSystem = new HashSet<>();
for (WifiAwareDataPathStateManager.AwareNetworkRequestInformation anri :
networkRequestCache.values()) {
if (anri.state
!= WifiAwareDataPathStateManager.AwareNetworkRequestInformation
.STATE_CONFIRMED) {
continue; // only count completed (up-and-running) NDPs
}
boolean sameApp = (anri.uid == uid) && TextUtils.equals(anri.packageName, packageName);
boolean isSecure = !TextUtils.isEmpty(anri.networkSpecifier.passphrase) || (
anri.networkSpecifier.pmk != null && anri.networkSpecifier.pmk.length != 0);
// in-app stats
if (sameApp) {
numNdpInApp += 1;
if (isSecure) {
numSecureNdpInApp += 1;
}
ndiInApp.add(anri.interfaceName);
}
// system stats
numNdpInSystem += 1;
if (isSecure) {
numSecureNdpInSystem += 1;
}
// ndp/ndi stats
Integer ndpCount = ndpPerNdiMap.get(anri.interfaceName);
if (ndpCount == null) {
ndpPerNdiMap.put(anri.interfaceName, 1);
} else {
ndpPerNdiMap.put(anri.interfaceName, ndpCount + 1);
}
// ndi stats
ndiInSystem.add(anri.interfaceName);
}
synchronized (mLock) {
mMaxNdiInApp = Math.max(mMaxNdiInApp, ndiInApp.size());
mMaxNdpInApp = Math.max(mMaxNdpInApp, numNdpInApp);
mMaxSecureNdpInApp = Math.max(mMaxSecureNdpInApp, numSecureNdpInApp);
mMaxNdiInSystem = Math.max(mMaxNdiInSystem, ndiInSystem.size());
mMaxNdpInSystem = Math.max(mMaxNdpInSystem, numNdpInSystem);
mMaxSecureNdpInSystem = Math.max(mMaxSecureNdpInSystem, numSecureNdpInSystem);
mMaxNdpPerNdi = Math.max(mMaxNdpPerNdi, Collections.max(ndpPerNdiMap.values()));
}
}
/**
* Record the completion status of NDP negotiation. There are multiple steps in NDP negotiation
* a failure on any aborts the process and is recorded. A success on intermediate stages is
* not recorded - only the final success.
*/
public void recordNdpStatus(int status, boolean isOutOfBand, long startTimestamp) {
synchronized (mLock) {
if (isOutOfBand) {
addNanHalStatusToHistogram(status, mOutOfBandNdpStatusData);
} else {
addNanHalStatusToHistogram(status, mInBandNdpStatusData);
}
if (status == NanStatusType.SUCCESS) {
long creationTime = mClock.getElapsedSinceBootMillis() - startTimestamp;
MetricsUtils.addValueToLogHistogram(creationTime, mNdpCreationTimeDuration,
DURATION_LOG_HISTOGRAM);
mNdpCreationTimeMin = (mNdpCreationTimeMin == -1) ? creationTime : Math.min(
mNdpCreationTimeMin, creationTime);
mNdpCreationTimeMax = Math.max(mNdpCreationTimeMax, creationTime);
mNdpCreationTimeSum += creationTime;
mNdpCreationTimeSumSq += creationTime * creationTime;
mNdpCreationTimeNumSamples += 1;
}
}
}
/**
* Record the duration of the NDP session. The creation time is assumed to be the time at
* which a confirm message was received (i.e. the end of the setup negotiation).
*/
public void recordNdpSessionDuration(long creationTime) {
synchronized (mLock) {
MetricsUtils.addValueToLogHistogram(mClock.getElapsedSinceBootMillis() - creationTime,
mHistogramNdpDuration, DURATION_LOG_HISTOGRAM);
}
}
/**
* Consolidate all metrics into the proto.
*/
public WifiMetricsProto.WifiAwareLog consolidateProto() {
WifiMetricsProto.WifiAwareLog log = new WifiMetricsProto.WifiAwareLog();
long now = mClock.getElapsedSinceBootMillis();
synchronized (mLock) {
log.histogramAwareAvailableDurationMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mHistogramAwareAvailableDurationMs,
DURATION_LOG_HISTOGRAM));
log.availableTimeMs = mAvailableTimeMs;
if (mLastEnableUsageInThisSampleWindowMs != 0) {
log.availableTimeMs += now - mLastEnableUsageInThisSampleWindowMs;
}
log.histogramAwareEnabledDurationMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mHistogramAwareEnabledDurationMs,
DURATION_LOG_HISTOGRAM));
log.enabledTimeMs = mEnabledTimeMs;
if (mLastEnableAwareInThisSampleWindowMs != 0) {
log.enabledTimeMs += now - mLastEnableAwareInThisSampleWindowMs;
}
log.numApps = mAttachDataByUid.size();
log.numAppsUsingIdentityCallback = 0;
log.maxConcurrentAttachSessionsInApp = 0;
for (AttachData ad: mAttachDataByUid.values()) {
if (ad.mUsesIdentityCallback) {
++log.numAppsUsingIdentityCallback;
}
log.maxConcurrentAttachSessionsInApp = Math.max(
log.maxConcurrentAttachSessionsInApp, ad.mMaxConcurrentAttaches);
}
log.histogramAttachSessionStatus = histogramToProtoArray(mAttachStatusData);
log.histogramAttachDurationMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mHistogramAttachDuration,
DURATION_LOG_HISTOGRAM));
log.maxConcurrentPublishInApp = mMaxPublishInApp;
log.maxConcurrentSubscribeInApp = mMaxSubscribeInApp;
log.maxConcurrentDiscoverySessionsInApp = mMaxDiscoveryInApp;
log.maxConcurrentPublishInSystem = mMaxPublishInSystem;
log.maxConcurrentSubscribeInSystem = mMaxSubscribeInSystem;
log.maxConcurrentDiscoverySessionsInSystem = mMaxDiscoveryInSystem;
log.histogramPublishStatus = histogramToProtoArray(mPublishStatusData);
log.histogramSubscribeStatus = histogramToProtoArray(mSubscribeStatusData);
log.numAppsWithDiscoverySessionFailureOutOfResources =
mAppsWithDiscoverySessionResourceFailure.size();
log.histogramPublishSessionDurationMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mHistogramPublishDuration,
DURATION_LOG_HISTOGRAM));
log.histogramSubscribeSessionDurationMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mHistogramSubscribeDuration,
DURATION_LOG_HISTOGRAM));
log.maxConcurrentPublishWithRangingInApp = mMaxPublishWithRangingInApp;
log.maxConcurrentSubscribeWithRangingInApp = mMaxSubscribeWithRangingInApp;
log.maxConcurrentPublishWithRangingInSystem = mMaxPublishWithRangingInSystem;
log.maxConcurrentSubscribeWithRangingInSystem = mMaxSubscribeWithRangingInSystem;
log.histogramSubscribeGeofenceMin = histogramToProtoArray(
MetricsUtils.linearHistogramToGenericBuckets(mHistogramSubscribeGeofenceMin,
RANGING_LIMIT_METERS));
log.histogramSubscribeGeofenceMax = histogramToProtoArray(
MetricsUtils.linearHistogramToGenericBuckets(mHistogramSubscribeGeofenceMax,
RANGING_LIMIT_METERS));
log.numSubscribesWithRanging = mNumSubscribesWithRanging;
log.numMatchesWithRanging = mNumMatchesWithRanging;
log.numMatchesWithoutRangingForRangingEnabledSubscribes =
mNumMatchesWithoutRangingForRangingEnabledSubscribes;
log.maxConcurrentNdiInApp = mMaxNdiInApp;
log.maxConcurrentNdiInSystem = mMaxNdiInSystem;
log.maxConcurrentNdpInApp = mMaxNdpInApp;
log.maxConcurrentNdpInSystem = mMaxNdpInSystem;
log.maxConcurrentSecureNdpInApp = mMaxSecureNdpInApp;
log.maxConcurrentSecureNdpInSystem = mMaxSecureNdpInSystem;
log.maxConcurrentNdpPerNdi = mMaxNdpPerNdi;
log.histogramRequestNdpStatus = histogramToProtoArray(mInBandNdpStatusData);
log.histogramRequestNdpOobStatus = histogramToProtoArray(mOutOfBandNdpStatusData);
log.histogramNdpCreationTimeMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mNdpCreationTimeDuration,
DURATION_LOG_HISTOGRAM));
log.ndpCreationTimeMsMin = mNdpCreationTimeMin;
log.ndpCreationTimeMsMax = mNdpCreationTimeMax;
log.ndpCreationTimeMsSum = mNdpCreationTimeSum;
log.ndpCreationTimeMsSumOfSq = mNdpCreationTimeSumSq;
log.ndpCreationTimeMsNumSamples = mNdpCreationTimeNumSamples;
log.histogramNdpSessionDurationMs = histogramToProtoArray(
MetricsUtils.logHistogramToGenericBuckets(mHistogramNdpDuration,
DURATION_LOG_HISTOGRAM));
}
return log;
}
/**
* clear Wi-Fi Aware metrics
*/
public void clear() {
long now = mClock.getElapsedSinceBootMillis();
synchronized (mLock) {
// don't clear mLastEnableUsage since could be valid for next measurement period
mHistogramAwareAvailableDurationMs.clear();
mAvailableTimeMs = 0;
if (mLastEnableUsageInThisSampleWindowMs != 0) {
mLastEnableUsageInThisSampleWindowMs = now;
}
// don't clear mLastEnableAware since could be valid for next measurement period
mHistogramAwareEnabledDurationMs.clear();
mEnabledTimeMs = 0;
if (mLastEnableAwareInThisSampleWindowMs != 0) {
mLastEnableAwareInThisSampleWindowMs = now;
}
mAttachDataByUid.clear();
mAttachStatusData.clear();
mHistogramAttachDuration.clear();
mMaxPublishInApp = 0;
mMaxSubscribeInApp = 0;
mMaxDiscoveryInApp = 0;
mMaxPublishInSystem = 0;
mMaxSubscribeInSystem = 0;
mMaxDiscoveryInSystem = 0;
mPublishStatusData.clear();
mSubscribeStatusData.clear();
mHistogramPublishDuration.clear();
mHistogramSubscribeDuration.clear();
mAppsWithDiscoverySessionResourceFailure.clear();
mMaxPublishWithRangingInApp = 0;
mMaxSubscribeWithRangingInApp = 0;
mMaxPublishWithRangingInSystem = 0;
mMaxSubscribeWithRangingInSystem = 0;
mHistogramSubscribeGeofenceMin.clear();
mHistogramSubscribeGeofenceMax.clear();
mNumSubscribesWithRanging = 0;
mNumMatchesWithRanging = 0;
mNumMatchesWithoutRangingForRangingEnabledSubscribes = 0;
mMaxNdiInApp = 0;
mMaxNdpInApp = 0;
mMaxSecureNdpInApp = 0;
mMaxNdiInSystem = 0;
mMaxNdpInSystem = 0;
mMaxSecureNdpInSystem = 0;
mMaxNdpPerNdi = 0;
mInBandNdpStatusData.clear();
mOutOfBandNdpStatusData.clear();
mNdpCreationTimeDuration.clear();
mNdpCreationTimeMin = -1;
mNdpCreationTimeMax = 0;
mNdpCreationTimeSum = 0;
mNdpCreationTimeSumSq = 0;
mNdpCreationTimeNumSamples = 0;
mHistogramNdpDuration.clear();
}
}
/**
* Dump all WifiAwareMetrics to console (pw) - this method is never called to dump the
* serialized metrics (handled by parent WifiMetrics).
*
* @param fd unused
* @param pw PrintWriter for writing dump to
* @param args unused
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mLock) {
pw.println("mLastEnableUsageMs:" + mLastEnableUsageMs);
pw.println(
"mLastEnableUsageInThisSampleWindowMs:" + mLastEnableUsageInThisSampleWindowMs);
pw.println("mAvailableTimeMs:" + mAvailableTimeMs);
pw.println("mHistogramAwareAvailableDurationMs:");
for (int i = 0; i < mHistogramAwareAvailableDurationMs.size(); ++i) {
pw.println(" " + mHistogramAwareAvailableDurationMs.keyAt(i) + ": "
+ mHistogramAwareAvailableDurationMs.valueAt(i));
}
pw.println("mLastEnableAwareMs:" + mLastEnableAwareMs);
pw.println(
"mLastEnableAwareInThisSampleWindowMs:" + mLastEnableAwareInThisSampleWindowMs);
pw.println("mEnabledTimeMs:" + mEnabledTimeMs);
pw.println("mHistogramAwareEnabledDurationMs:");
for (int i = 0; i < mHistogramAwareEnabledDurationMs.size(); ++i) {
pw.println(" " + mHistogramAwareEnabledDurationMs.keyAt(i) + ": "
+ mHistogramAwareEnabledDurationMs.valueAt(i));
}
pw.println("mAttachDataByUid:");
for (Map.Entry<Integer, AttachData> ade: mAttachDataByUid.entrySet()) {
pw.println(" " + "uid=" + ade.getKey() + ": identity="
+ ade.getValue().mUsesIdentityCallback + ", maxConcurrent="
+ ade.getValue().mMaxConcurrentAttaches);
}
pw.println("mAttachStatusData:");
for (int i = 0; i < mAttachStatusData.size(); ++i) {
pw.println(" " + mAttachStatusData.keyAt(i) + ": "
+ mAttachStatusData.valueAt(i));
}
pw.println("mHistogramAttachDuration:");
for (int i = 0; i < mHistogramAttachDuration.size(); ++i) {
pw.println(" " + mHistogramAttachDuration.keyAt(i) + ": "
+ mHistogramAttachDuration.valueAt(i));
}
pw.println("mMaxPublishInApp:" + mMaxPublishInApp);
pw.println("mMaxSubscribeInApp:" + mMaxSubscribeInApp);
pw.println("mMaxDiscoveryInApp:" + mMaxDiscoveryInApp);
pw.println("mMaxPublishInSystem:" + mMaxPublishInSystem);
pw.println("mMaxSubscribeInSystem:" + mMaxSubscribeInSystem);
pw.println("mMaxDiscoveryInSystem:" + mMaxDiscoveryInSystem);
pw.println("mPublishStatusData:");
for (int i = 0; i < mPublishStatusData.size(); ++i) {
pw.println(" " + mPublishStatusData.keyAt(i) + ": "
+ mPublishStatusData.valueAt(i));
}
pw.println("mSubscribeStatusData:");
for (int i = 0; i < mSubscribeStatusData.size(); ++i) {
pw.println(" " + mSubscribeStatusData.keyAt(i) + ": "
+ mSubscribeStatusData.valueAt(i));
}
pw.println("mHistogramPublishDuration:");
for (int i = 0; i < mHistogramPublishDuration.size(); ++i) {
pw.println(" " + mHistogramPublishDuration.keyAt(i) + ": "
+ mHistogramPublishDuration.valueAt(i));
}
pw.println("mHistogramSubscribeDuration:");
for (int i = 0; i < mHistogramSubscribeDuration.size(); ++i) {
pw.println(" " + mHistogramSubscribeDuration.keyAt(i) + ": "
+ mHistogramSubscribeDuration.valueAt(i));
}
pw.println("mAppsWithDiscoverySessionResourceFailure:");
for (Integer uid: mAppsWithDiscoverySessionResourceFailure) {
pw.println(" " + uid);
}
pw.println("mMaxPublishWithRangingInApp:" + mMaxPublishWithRangingInApp);
pw.println("mMaxSubscribeWithRangingInApp:" + mMaxSubscribeWithRangingInApp);
pw.println("mMaxPublishWithRangingInSystem:" + mMaxPublishWithRangingInSystem);
pw.println("mMaxSubscribeWithRangingInSystem:" + mMaxSubscribeWithRangingInSystem);
pw.println("mHistogramSubscribeGeofenceMin:");
for (int i = 0; i < mHistogramSubscribeGeofenceMin.size(); ++i) {
pw.println(" " + mHistogramSubscribeGeofenceMin.keyAt(i) + ": "
+ mHistogramSubscribeGeofenceMin.valueAt(i));
}
pw.println("mHistogramSubscribeGeofenceMax:");
for (int i = 0; i < mHistogramSubscribeGeofenceMax.size(); ++i) {
pw.println(" " + mHistogramSubscribeGeofenceMax.keyAt(i) + ": "
+ mHistogramSubscribeGeofenceMax.valueAt(i));
}
pw.println("mNumSubscribesWithRanging:" + mNumSubscribesWithRanging);
pw.println("mNumMatchesWithRanging:" + mNumMatchesWithRanging);
pw.println("mNumMatchesWithoutRangingForRangingEnabledSubscribes:"
+ mNumMatchesWithoutRangingForRangingEnabledSubscribes);
pw.println("mMaxNdiInApp:" + mMaxNdiInApp);
pw.println("mMaxNdpInApp:" + mMaxNdpInApp);
pw.println("mMaxSecureNdpInApp:" + mMaxSecureNdpInApp);
pw.println("mMaxNdiInSystem:" + mMaxNdiInSystem);
pw.println("mMaxNdpInSystem:" + mMaxNdpInSystem);
pw.println("mMaxSecureNdpInSystem:" + mMaxSecureNdpInSystem);
pw.println("mMaxNdpPerNdi:" + mMaxNdpPerNdi);
pw.println("mInBandNdpStatusData:");
for (int i = 0; i < mInBandNdpStatusData.size(); ++i) {
pw.println(" " + mInBandNdpStatusData.keyAt(i) + ": "
+ mInBandNdpStatusData.valueAt(i));
}
pw.println("mOutOfBandNdpStatusData:");
for (int i = 0; i < mOutOfBandNdpStatusData.size(); ++i) {
pw.println(" " + mOutOfBandNdpStatusData.keyAt(i) + ": "
+ mOutOfBandNdpStatusData.valueAt(i));
}
pw.println("mNdpCreationTimeDuration:");
for (int i = 0; i < mNdpCreationTimeDuration.size(); ++i) {
pw.println(" " + mNdpCreationTimeDuration.keyAt(i) + ": "
+ mNdpCreationTimeDuration.valueAt(i));
}
pw.println("mNdpCreationTimeMin:" + mNdpCreationTimeMin);
pw.println("mNdpCreationTimeMax:" + mNdpCreationTimeMax);
pw.println("mNdpCreationTimeSum:" + mNdpCreationTimeSum);
pw.println("mNdpCreationTimeSumSq:" + mNdpCreationTimeSumSq);
pw.println("mNdpCreationTimeNumSamples:" + mNdpCreationTimeNumSamples);
pw.println("mHistogramNdpDuration:");
for (int i = 0; i < mHistogramNdpDuration.size(); ++i) {
pw.println(" " + mHistogramNdpDuration.keyAt(i) + ": "
+ mHistogramNdpDuration.valueAt(i));
}
}
}
// histogram utilities
/**
* Convert a generic bucket to Aware HistogramBucket proto.
*/
@VisibleForTesting
public static WifiMetricsProto.WifiAwareLog.HistogramBucket[] histogramToProtoArray(
MetricsUtils.GenericBucket[] buckets) {
WifiMetricsProto.WifiAwareLog.HistogramBucket[] protoArray =
new WifiMetricsProto.WifiAwareLog.HistogramBucket[buckets.length];
for (int i = 0; i < buckets.length; ++i) {
protoArray[i] = new WifiMetricsProto.WifiAwareLog.HistogramBucket();
protoArray[i].start = buckets[i].start;
protoArray[i].end = buckets[i].end;
protoArray[i].count = buckets[i].count;
}
return protoArray;
}
/**
* Adds the NanStatusType to the histogram (translating to the proto enumeration of the status).
*/
public static void addNanHalStatusToHistogram(int halStatus, SparseIntArray histogram) {
int protoStatus = convertNanStatusTypeToProtoEnum(halStatus);
int newValue = histogram.get(protoStatus) + 1;
histogram.put(protoStatus, newValue);
}
/**
* Converts a histogram of proto NanStatusTypeEnum to a raw proto histogram.
*/
@VisibleForTesting
public static WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[] histogramToProtoArray(
SparseIntArray histogram) {
WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[] protoArray =
new WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket[histogram.size()];
for (int i = 0; i < histogram.size(); ++i) {
protoArray[i] = new WifiMetricsProto.WifiAwareLog.NanStatusHistogramBucket();
protoArray[i].nanStatusType = histogram.keyAt(i);
protoArray[i].count = histogram.valueAt(i);
}
return protoArray;
}
/**
* Convert a HAL NanStatusType enum to a Metrics proto enum NanStatusTypeEnum.
*/
public static int convertNanStatusTypeToProtoEnum(int nanStatusType) {
switch (nanStatusType) {
case NanStatusType.SUCCESS:
return WifiMetricsProto.WifiAwareLog.SUCCESS;
case NanStatusType.INTERNAL_FAILURE:
return WifiMetricsProto.WifiAwareLog.INTERNAL_FAILURE;
case NanStatusType.PROTOCOL_FAILURE:
return WifiMetricsProto.WifiAwareLog.PROTOCOL_FAILURE;
case NanStatusType.INVALID_SESSION_ID:
return WifiMetricsProto.WifiAwareLog.INVALID_SESSION_ID;
case NanStatusType.NO_RESOURCES_AVAILABLE:
return WifiMetricsProto.WifiAwareLog.NO_RESOURCES_AVAILABLE;
case NanStatusType.INVALID_ARGS:
return WifiMetricsProto.WifiAwareLog.INVALID_ARGS;
case NanStatusType.INVALID_PEER_ID:
return WifiMetricsProto.WifiAwareLog.INVALID_PEER_ID;
case NanStatusType.INVALID_NDP_ID:
return WifiMetricsProto.WifiAwareLog.INVALID_NDP_ID;
case NanStatusType.NAN_NOT_ALLOWED:
return WifiMetricsProto.WifiAwareLog.NAN_NOT_ALLOWED;
case NanStatusType.NO_OTA_ACK:
return WifiMetricsProto.WifiAwareLog.NO_OTA_ACK;
case NanStatusType.ALREADY_ENABLED:
return WifiMetricsProto.WifiAwareLog.ALREADY_ENABLED;
case NanStatusType.FOLLOWUP_TX_QUEUE_FULL:
return WifiMetricsProto.WifiAwareLog.FOLLOWUP_TX_QUEUE_FULL;
case NanStatusType.UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
return WifiMetricsProto.WifiAwareLog.UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
default:
Log.e(TAG, "Unrecognized NanStatusType: " + nanStatusType);
return WifiMetricsProto.WifiAwareLog.UNKNOWN_HAL_STATUS;
}
}
}