diff options
author | Etan Cohen <etancohen@google.com> | 2018-03-13 07:27:40 -0700 |
---|---|---|
committer | Etan Cohen <etancohen@google.com> | 2018-03-14 11:44:11 -0700 |
commit | 05dbaa4579483e9f53f4b6c6e02c02d620f1890f (patch) | |
tree | 0dd1cb3b09a8f1fcbdb4d0d2a8a3112686c5895d | |
parent | b7dc1893e5c56a443e162a6147518046583f73bf (diff) |
[AWARE] Metrics for Discovery + Ranging
Add metrics for Wi-Fi Aware discovery with ranging constraints.
Bug: 63906015
Test: unit tests for aware
Test: integration tests ThroughputTest
Change-Id: I06330edb906a72de33b8777587deed4f27fc6f41
6 files changed, 396 insertions, 34 deletions
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java index 062b5d953..18b917799 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java @@ -48,6 +48,7 @@ public class WifiAwareDiscoverySessionState { private byte mPubSubId; private IWifiAwareDiscoverySessionCallback mCallback; private boolean mIsPublishSession; + private boolean mIsRangingEnabled; private final long mCreationTime; static class PeerInfo { @@ -71,12 +72,13 @@ public class WifiAwareDiscoverySessionState { public WifiAwareDiscoverySessionState(WifiAwareNativeApi wifiAwareNativeApi, int sessionId, byte pubSubId, IWifiAwareDiscoverySessionCallback callback, boolean isPublishSession, - long creationTime) { + boolean isRangingEnabled, long creationTime) { mWifiAwareNativeApi = wifiAwareNativeApi; mSessionId = sessionId; mPubSubId = pubSubId; mCallback = callback; mIsPublishSession = isPublishSession; + mIsRangingEnabled = isRangingEnabled; mCreationTime = creationTime; } @@ -92,6 +94,10 @@ public class WifiAwareDiscoverySessionState { return mIsPublishSession; } + public boolean isRangingEnabled() { + return mIsRangingEnabled; + } + public long getCreationTime() { return mCreationTime; } diff --git a/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java b/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java index 4f5f46b0c..e85ade115 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareMetrics.java @@ -55,6 +55,14 @@ public class WifiAwareMetrics { // 10^7 -> 10^8: 9 @ 10^7 --> 10^8 ms -> 10^5s -> 28 hours private static final HistParms DURATION_LOG_HISTOGRAM = new HistParms(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; @@ -92,6 +100,17 @@ public class WifiAwareMetrics { 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; @@ -231,14 +250,34 @@ public class WifiAwareMetrics { /** * Push information about the new discovery session. */ - public void recordDiscoverySession(int uid, boolean isPublish, - SparseArray<WifiAwareClientState> clients) { + 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; @@ -246,16 +285,29 @@ public class WifiAwareMetrics { 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; + } } } } @@ -270,6 +322,27 @@ public class WifiAwareMetrics { 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) { + addLinearValueToHistogram(minRange, mHistogramSubscribeGeofenceMin, + RANGING_LIMIT_METERS); + } + if (maxRange != -1) { + addLinearValueToHistogram(maxRange, mHistogramSubscribeGeofenceMax, + RANGING_LIMIT_METERS); + } } } @@ -303,6 +376,19 @@ public class WifiAwareMetrics { } /** + * 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, @@ -456,6 +542,19 @@ public class WifiAwareMetrics { log.histogramSubscribeSessionDurationMs = histogramToProtoArray( mHistogramSubscribeDuration, DURATION_LOG_HISTOGRAM); + log.maxConcurrentPublishWithRangingInApp = mMaxPublishWithRangingInApp; + log.maxConcurrentSubscribeWithRangingInApp = mMaxSubscribeWithRangingInApp; + log.maxConcurrentPublishWithRangingInSystem = mMaxPublishWithRangingInSystem; + log.maxConcurrentSubscribeWithRangingInSystem = mMaxSubscribeWithRangingInSystem; + log.histogramSubscribeGeofenceMin = histogramToProtoArray( + mHistogramSubscribeGeofenceMin, RANGING_LIMIT_METERS); + log.histogramSubscribeGeofenceMax = histogramToProtoArray( + mHistogramSubscribeGeofenceMax, RANGING_LIMIT_METERS); + log.numSubscribesWithRanging = mNumSubscribesWithRanging; + log.numMatchesWithRanging = mNumMatchesWithRanging; + log.numMatchesWithoutRangingForRangingEnabledSubscribes = + mNumMatchesWithoutRangingForRangingEnabledSubscribes; + log.maxConcurrentNdiInApp = mMaxNdiInApp; log.maxConcurrentNdiInSystem = mMaxNdiInSystem; log.maxConcurrentNdpInApp = mMaxNdpInApp; @@ -516,6 +615,16 @@ public class WifiAwareMetrics { 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; @@ -613,7 +722,27 @@ public class WifiAwareMetrics { 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); @@ -762,6 +891,63 @@ public class WifiAwareMetrics { } /** + * Adds the input value to the histogram based on the lineaer histogram parameters. + * + * The 'int[] hp' contains a list of bucket limits. The number of buckets is hp.length() + 1 + * where buckets are: + * - < hp[0] + * - [hp[0], hp[1]) + * ... + * - >= hp[hp.length() - 1] + */ + @VisibleForTesting + public static int addLinearValueToHistogram(int x, SparseIntArray histogram, int[] hp) { + int bucket = 0; + for (int limit : hp) { + if (x >= limit) { + bucket++; + continue; + } + break; + } + + // note that get() returns 0 if index not there already + int newValue = histogram.get(bucket) + 1; + histogram.put(bucket, newValue); + + return newValue; + } + + /** + * Converts the histogram (with the specified linear histogram parameters) to an array of + * proto histogram buckets. + */ + @VisibleForTesting + public static WifiMetricsProto.WifiAwareLog.HistogramBucket[] histogramToProtoArray( + SparseIntArray histogram, int[] linearHistParams) { + WifiMetricsProto.WifiAwareLog.HistogramBucket[] protoArray = + new WifiMetricsProto.WifiAwareLog.HistogramBucket[histogram.size()]; + for (int i = 0; i < histogram.size(); ++i) { + int bucket = histogram.keyAt(i); + + protoArray[i] = new WifiMetricsProto.WifiAwareLog.HistogramBucket(); + if (bucket == 0) { + protoArray[i].start = Integer.MIN_VALUE; + protoArray[i].end = linearHistParams[0]; + } else if (bucket != linearHistParams.length) { + protoArray[i].start = linearHistParams[bucket - 1]; + protoArray[i].end = linearHistParams[bucket]; + } else { + protoArray[i].start = linearHistParams[linearHistParams.length - 1]; + protoArray[i].end = Integer.MAX_VALUE; + } + protoArray[i].count = histogram.valueAt(i); + } + + return protoArray; + } + + /** * Adds the NanStatusType to the histogram (translating to the proto enumeration of the status). */ public static void addNanHalStatusToHistogram(int halStatus, SparseIntArray histogram) { diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java index 8eb31cc6b..2ec3f7578 100644 --- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java +++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java @@ -2656,14 +2656,39 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe return; } + boolean isRangingEnabled = false; + int minRange = -1; + int maxRange = -1; + if (completedCommand.arg1 == COMMAND_TYPE_PUBLISH) { + PublishConfig publishConfig = completedCommand.getData().getParcelable( + MESSAGE_BUNDLE_KEY_CONFIG); + isRangingEnabled = publishConfig.mEnableRanging; + } else { + SubscribeConfig subscribeConfig = completedCommand.getData().getParcelable( + MESSAGE_BUNDLE_KEY_CONFIG); + isRangingEnabled = + subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet; + if (subscribeConfig.mMinDistanceMmSet) { + minRange = subscribeConfig.mMinDistanceMm; + } + if (subscribeConfig.mMaxDistanceMmSet) { + maxRange = subscribeConfig.mMaxDistanceMm; + } + } + WifiAwareDiscoverySessionState session = new WifiAwareDiscoverySessionState( - mWifiAwareNativeApi, sessionId, pubSubId, callback, isPublish, + mWifiAwareNativeApi, sessionId, pubSubId, callback, isPublish, isRangingEnabled, SystemClock.elapsedRealtime()); session.mDbg = mDbg; client.addSession(session); - mAwareMetrics.recordDiscoverySession(client.getUid(), - completedCommand.arg1 == COMMAND_TYPE_PUBLISH, mClients); + if (isRangingEnabled) { + mAwareMetrics.recordDiscoverySessionWithRanging(client.getUid(), + completedCommand.arg1 != COMMAND_TYPE_PUBLISH, minRange, maxRange, + mClients); + } else { + mAwareMetrics.recordDiscoverySession(client.getUid(), mClients); + } mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.SUCCESS, completedCommand.arg1 == COMMAND_TYPE_PUBLISH); @@ -2957,6 +2982,9 @@ public class WifiAwareStateManager implements WifiAwareShellCommand.DelegatedShe return; } + if (data.second.isRangingEnabled()) { + mAwareMetrics.recordMatchIndicationForRangeEnabledSubscribe(rangingIndication != 0); + } data.second.onMatch(requestorInstanceId, peerMac, serviceSpecificInfo, matchFilter, rangingIndication, rangeMm); } diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java index a2b934ce4..1b17219ed 100644 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java @@ -1379,8 +1379,7 @@ public class WifiAwareDataPathStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), doPublish, pubSubId); mMockLooper.dispatchAll(); inOrder.verify(mMockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(Process.myUid()), - eq(doPublish), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(Process.myUid()), any()); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(Process.myUid(), NanStatusType.SUCCESS, doPublish); diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java index 4252cfe6a..c303602e1 100644 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java +++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareMetricsTest.java @@ -79,6 +79,14 @@ public class WifiAwareMetricsTest { private static final WifiAwareMetrics.HistParms HIST2 = new WifiAwareMetrics.HistParms(-20, 2, 5, 40, 3); + // Linear histogram of following buckets: + // <10 + // [10, 30) + // [30, 60) + // [60, 100) + // >100 + private static final int[] HIST_LINEAR = { 10, 30, 60, 100 }; + /** * Pre-test configuration. Initialize and install mocks. */ @@ -287,6 +295,7 @@ public class WifiAwareMetricsTest { public void testDiscoverySessionMetrics() { final int uid1 = 1005; final int uid2 = 1006; + final int uid3 = 1007; final SparseArray<WifiAwareClientState> clients = new SparseArray<>(); WifiMetricsProto.WifiAwareLog log; @@ -295,33 +304,60 @@ public class WifiAwareMetricsTest { null, null, false, 0); WifiAwareClientState client2 = new WifiAwareClientState(mMockContext, 11, uid2, 0, null, null, null, false, 0); + WifiAwareClientState client3 = new WifiAwareClientState(mMockContext, 12, uid3, 0, null, + null, null, false, 0); clients.put(10, client1); clients.put(11, client2); + clients.put(12, client3); // uid1: publish session 1 client1.addSession(new WifiAwareDiscoverySessionState(null, 100, (byte) 0, null, true, - mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid1, true, clients); + false, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySession(uid1, clients); mDut.recordDiscoveryStatus(uid1, NanStatusType.SUCCESS, true); // uid1: publish session 2 client1.addSession(new WifiAwareDiscoverySessionState(null, 101, (byte) 0, null, true, - mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid1, true, clients); + false, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySession(uid1, clients); mDut.recordDiscoveryStatus(uid1, NanStatusType.SUCCESS, true); + // uid3: publish session 3 with ranging + client3.addSession(new WifiAwareDiscoverySessionState(null, 111, (byte) 0, null, true, + true, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySessionWithRanging(uid3, false, -1, -1, clients); + mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, true); + // uid2: subscribe session 1 client2.addSession(new WifiAwareDiscoverySessionState(null, 102, (byte) 0, null, false, - mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid2, false, clients); + false, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySession(uid2, clients); mDut.recordDiscoveryStatus(uid2, NanStatusType.SUCCESS, false); // uid2: publish session 2 client2.addSession(new WifiAwareDiscoverySessionState(null, 103, (byte) 0, null, true, - mClock.getElapsedSinceBootMillis())); - mDut.recordDiscoverySession(uid2, false, clients); + false, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySession(uid2, clients); mDut.recordDiscoveryStatus(uid2, NanStatusType.SUCCESS, false); + // uid3: subscribe session 3 with ranging: min + client3.addSession(new WifiAwareDiscoverySessionState(null, 112, (byte) 0, null, false, + true, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySessionWithRanging(uid3, true, 10, -1, clients); + mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); + + // uid3: subscribe session 3 with ranging: max + client3.addSession(new WifiAwareDiscoverySessionState(null, 113, (byte) 0, null, false, + true, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySessionWithRanging(uid3, true, -1, 50, clients); + mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); + + // uid3: subscribe session 3 with ranging: minmax + client3.addSession(new WifiAwareDiscoverySessionState(null, 114, (byte) 0, null, false, + true, mClock.getElapsedSinceBootMillis())); + mDut.recordDiscoverySessionWithRanging(uid3, true, 0, 110, clients); + mDut.recordDiscoveryStatus(uid3, NanStatusType.SUCCESS, false); + // uid1: delete session 1 setTime(10); mDut.recordDiscoverySessionDuration(client1.getSession(100).getCreationTime(), @@ -335,9 +371,9 @@ public class WifiAwareMetricsTest { client2.removeSession(102); // uid2: subscribe session 3 - mDut.recordDiscoverySession(uid2, false, clients); + mDut.recordDiscoverySession(uid2, clients); client2.addSession(new WifiAwareDiscoverySessionState(null, 104, (byte) 0, null, false, - mClock.getElapsedSinceBootMillis())); + false, mClock.getElapsedSinceBootMillis())); // a few failures mDut.recordDiscoveryStatus(uid1, NanStatusType.INTERNAL_FAILURE, true); @@ -350,15 +386,15 @@ public class WifiAwareMetricsTest { collector.checkThat("maxConcurrentPublishInApp", log.maxConcurrentPublishInApp, equalTo(2)); collector.checkThat("maxConcurrentSubscribeInApp", log.maxConcurrentSubscribeInApp, - equalTo(1)); + equalTo(3)); collector.checkThat("maxConcurrentDiscoverySessionsInApp", - log.maxConcurrentDiscoverySessionsInApp, equalTo(2)); + log.maxConcurrentDiscoverySessionsInApp, equalTo(4)); collector.checkThat("maxConcurrentPublishInSystem", log.maxConcurrentPublishInSystem, - equalTo(3)); + equalTo(4)); collector.checkThat("maxConcurrentSubscribeInSystem", log.maxConcurrentSubscribeInSystem, - equalTo(1)); + equalTo(4)); collector.checkThat("maxConcurrentDiscoverySessionsInSystem", - log.maxConcurrentDiscoverySessionsInSystem, equalTo(4)); + log.maxConcurrentDiscoverySessionsInSystem, equalTo(8)); collector.checkThat("histogramPublishStatus.length", log.histogramPublishStatus.length, equalTo(2)); // 2 buckets collector.checkThat("histogramSubscribeStatus.length", @@ -369,6 +405,28 @@ public class WifiAwareMetricsTest { 6, 1); validateProtoHistBucket("Subscribe Duration[0]", log.histogramSubscribeSessionDurationMs[0], 10, 20, 1); + + collector.checkThat("maxConcurrentPublishWithRangingInApp", + log.maxConcurrentPublishWithRangingInApp, equalTo(1)); + collector.checkThat("maxConcurrentSubscribeWithRangingInApp", + log.maxConcurrentSubscribeWithRangingInApp, equalTo(3)); + collector.checkThat("maxConcurrentPublishWithRangingInSystem", + log.maxConcurrentPublishWithRangingInSystem, equalTo(1)); + collector.checkThat("maxConcurrentSubscribeWithRangingInSystem", + log.maxConcurrentSubscribeWithRangingInSystem, equalTo(3)); + collector.checkThat("numSubscribesWithRanging", log.numSubscribesWithRanging, equalTo(3)); + collector.checkThat("histogramSubscribeGeofenceMin.length", + log.histogramSubscribeGeofenceMin.length, equalTo(2)); + collector.checkThat("histogramSubscribeGeofenceMax.length", + log.histogramSubscribeGeofenceMax.length, equalTo(2)); + validateProtoHistBucket("histogramSubscribeGeofenceMin[0]", + log.histogramSubscribeGeofenceMin[0], Integer.MIN_VALUE, 10, 1); + validateProtoHistBucket("histogramSubscribeGeofenceMin[1]", + log.histogramSubscribeGeofenceMin[1], 10, 30, 1); + validateProtoHistBucket("histogramSubscribeGeofenceMax[0]", + log.histogramSubscribeGeofenceMax[0], 30, 60, 1); + validateProtoHistBucket("histogramSubscribeGeofenceMax[1]", + log.histogramSubscribeGeofenceMax[1], 100, Integer.MAX_VALUE, 1); } /** @@ -569,6 +627,41 @@ public class WifiAwareMetricsTest { } /** + * Validate that a set of values are bucketed correctly into the linear histogram, and that + * they are converted to a primitive proto-buffer array correctly. + */ + @Test + public void testLinearHistBucketing() { + SparseIntArray hist = new SparseIntArray(); + + bucketValueAndVerify("HIST_LINEAR: x=", -5, hist, HIST_LINEAR, 0, 1); + bucketValueAndVerify("HIST_LINEAR: x=", 0, hist, HIST_LINEAR, 0, 2); + bucketValueAndVerify("HIST_LINEAR: x=", 1, hist, HIST_LINEAR, 0, 3); + bucketValueAndVerify("HIST_LINEAR: x=", 9, hist, HIST_LINEAR, 0, 4); + bucketValueAndVerify("HIST_LINEAR: x=", 10, hist, HIST_LINEAR, 1, 1); + bucketValueAndVerify("HIST_LINEAR: x=", 20, hist, HIST_LINEAR, 1, 2); + bucketValueAndVerify("HIST_LINEAR: x=", 30, hist, HIST_LINEAR, 2, 1); + bucketValueAndVerify("HIST_LINEAR: x=", 40, hist, HIST_LINEAR, 2, 2); + bucketValueAndVerify("HIST_LINEAR: x=", 50, hist, HIST_LINEAR, 2, 3); + bucketValueAndVerify("HIST_LINEAR: x=", 60, hist, HIST_LINEAR, 3, 1); + bucketValueAndVerify("HIST_LINEAR: x=", 70, hist, HIST_LINEAR, 3, 2); + bucketValueAndVerify("HIST_LINEAR: x=", 80, hist, HIST_LINEAR, 3, 3); + bucketValueAndVerify("HIST_LINEAR: x=", 90, hist, HIST_LINEAR, 3, 4); + bucketValueAndVerify("HIST_LINEAR: x=", 100, hist, HIST_LINEAR, 4, 1); + bucketValueAndVerify("HIST_LINEAR: x=", 110, hist, HIST_LINEAR, 4, 2); + bucketValueAndVerify("HIST_LINEAR: x=", 98999, hist, HIST_LINEAR, 4, 3); + + WifiMetricsProto.WifiAwareLog.HistogramBucket[] phb = histogramToProtoArray(hist, + HIST_LINEAR); + collector.checkThat("Number of buckets", phb.length, equalTo(hist.size())); + validateProtoHistBucket("Bucket[0]", phb[0], Integer.MIN_VALUE, 10, 4); + validateProtoHistBucket("Bucket[1]", phb[1], 10, 30, 2); + validateProtoHistBucket("Bucket[2]", phb[2], 30, 60, 3); + validateProtoHistBucket("Bucket[3]", phb[3], 60, 100, 4); + validateProtoHistBucket("Bucket[4]", phb[4], 100, Integer.MAX_VALUE, 3); + } + + /** * Validate the conversion to a NanStatusType proto raw histogram. */ @Test @@ -633,6 +726,12 @@ public class WifiAwareMetricsTest { collector.checkThat(logPrefix + value, h.get(expectedKey), equalTo(expectedValue)); } + private void bucketValueAndVerify(String logPrefix, int value, SparseIntArray h, + int[] hp, int expectedKey, int expectedValue) { + WifiAwareMetrics.addLinearValueToHistogram(value, h, hp); + collector.checkThat(logPrefix + value, h.get(expectedKey), equalTo(expectedValue)); + } + private void validateProtoHistBucket(String logPrefix, WifiMetricsProto.WifiAwareLog.HistogramBucket bucket, long start, long end, int count) { collector.checkThat(logPrefix + ": start", bucket.start, equalTo(start)); diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java index e6586e3e7..c77d76283 100644 --- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java +++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java @@ -16,6 +16,8 @@ package com.android.server.wifi.aware; +import static android.hardware.wifi.V1_0.NanRangingIndication.EGRESS_MET_MASK; + import static org.hamcrest.core.IsEqual.equalTo; import static org.hamcrest.core.IsNull.notNullValue; import static org.hamcrest.core.IsNull.nullValue; @@ -703,7 +705,7 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, (byte) 99); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), eq(true), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback, mAwareMetricsMock); @@ -829,7 +831,7 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), eq(true), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); // (3) publish termination (from firmware - not app!) @@ -874,7 +876,7 @@ public class WifiAwareStateManagerTest { final int reasonFail = NanStatusType.INTERNAL_FAILURE; ConfigRequest configRequest = new ConfigRequest.Builder().build(); - PublishConfig publishConfig = new PublishConfig.Builder().build(); + PublishConfig publishConfig = new PublishConfig.Builder().setRangingEnabled(true).build(); IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( @@ -911,7 +913,8 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), true, publishId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), eq(true), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(false), + eq(-1), eq(-1), any()); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); // (3) update publish @@ -1027,7 +1030,7 @@ public class WifiAwareStateManagerTest { inOrder.verify(mockSessionCallback).onSessionStarted(anyInt()); inOrder.verify(mMockNative).stopPublish(transactionId.capture(), eq(publishId)); inOrder.verify(mMockNative).disable(anyShort()); - inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), eq(true), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true); inOrderM.verify(mAwareMetricsMock).recordAttachSessionDuration(anyLong()); inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(true)); @@ -1057,10 +1060,12 @@ public class WifiAwareStateManagerTest { IWifiAwareDiscoverySessionCallback.class); ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); + InOrder inOrderM = inOrder(mAwareMetricsMock); mDut.enableUsage(); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); mMockLooper.dispatchAll(); @@ -1072,6 +1077,7 @@ public class WifiAwareStateManagerTest { mDut.onConfigSuccessResponse(transactionId.getValue()); mMockLooper.dispatchAll(); inOrder.verify(mockCallback).onConnectSuccess(clientId); + inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); // (1) initial subscribe mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); @@ -1083,6 +1089,7 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigFailResponse(transactionId.getValue(), false, reasonFail); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); validateInternalNoSessions(clientId); // (3) subscribe and get immediate failure (i.e. HAL failed) @@ -1095,9 +1102,10 @@ public class WifiAwareStateManagerTest { eq(subscribeConfig)); inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); validateInternalNoSessions(clientId); - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); } /** @@ -1124,10 +1132,12 @@ public class WifiAwareStateManagerTest { ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); + InOrder inOrderM = inOrder(mAwareMetricsMock); mDut.enableUsage(); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); mMockLooper.dispatchAll(); @@ -1139,6 +1149,7 @@ public class WifiAwareStateManagerTest { mDut.onConfigSuccessResponse(transactionId.getValue()); mMockLooper.dispatchAll(); inOrder.verify(mockCallback).onConnectSuccess(clientId); + inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); // (1) initial subscribe mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); @@ -1150,11 +1161,14 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySession(eq(uid), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); // (3) subscribe termination (from firmware - not app!) mDut.onSessionTerminatedNotification(subscribeId, reasonTerminate, false); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionTerminated(reasonTerminate); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionDuration(anyLong(), eq(false)); // (4) app update session (race condition: app didn't get termination // yet) @@ -1171,7 +1185,7 @@ public class WifiAwareStateManagerTest { validateInternalSessionInfoCleanedUp(clientId, sessionId.getValue()); - verifyNoMoreInteractions(mockSessionCallback, mMockNative); + verifyNoMoreInteractions(mockSessionCallback, mMockNative, mAwareMetricsMock); } /** @@ -1188,9 +1202,11 @@ public class WifiAwareStateManagerTest { final String callingPackage = "com.google.somePackage"; final byte subscribeId = 15; final int reasonFail = NanStatusType.INTERNAL_FAILURE; + final int rangeMax = 10; ConfigRequest configRequest = new ConfigRequest.Builder().build(); - SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().build(); + SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setMaxDistanceMm( + rangeMax).build(); IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); IWifiAwareDiscoverySessionCallback mockSessionCallback = mock( @@ -1198,10 +1214,12 @@ public class WifiAwareStateManagerTest { ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); + InOrder inOrderM = inOrder(mAwareMetricsMock); mDut.enableUsage(); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); mMockLooper.dispatchAll(); @@ -1213,6 +1231,7 @@ public class WifiAwareStateManagerTest { mDut.onConfigSuccessResponse(transactionId.getValue()); mMockLooper.dispatchAll(); inOrder.verify(mockCallback).onConnectSuccess(clientId); + inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); // (1) initial subscribe mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); @@ -1224,6 +1243,9 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), + eq(-1), eq(rangeMax), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); // (3) update subscribe mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); @@ -1235,6 +1257,7 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigFailResponse(transactionId.getValue(), false, reasonFail); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); // (5) another update subscribe mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig); @@ -1246,6 +1269,7 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionConfigSuccess(); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); // (7) another update + immediate failure when(mMockNative.subscribe(anyShort(), anyByte(), any())) @@ -1256,8 +1280,9 @@ public class WifiAwareStateManagerTest { inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId), eq(subscribeConfig)); inOrder.verify(mockSessionCallback).onSessionConfigFail(reasonFail); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, reasonFail, false); - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); } /** @@ -1342,11 +1367,16 @@ public class WifiAwareStateManagerTest { final String peerMsg = "some message from peer"; final int messageId = 6948; final int messageId2 = 6949; + final int rangeMin = 0; + final int rangeMax = 55; + final int rangedDistance = 30; ConfigRequest configRequest = new ConfigRequest.Builder().build(); SubscribeConfig subscribeConfig = new SubscribeConfig.Builder().setServiceName(serviceName) .setServiceSpecificInfo(ssi.getBytes()) .setSubscribeType(SubscribeConfig.SUBSCRIBE_TYPE_PASSIVE) + .setMinDistanceMm(rangeMin) + .setMaxDistanceMm(rangeMax) .build(); IWifiAwareEventCallback mockCallback = mock(IWifiAwareEventCallback.class); @@ -1356,10 +1386,12 @@ public class WifiAwareStateManagerTest { ArgumentCaptor<Integer> sessionId = ArgumentCaptor.forClass(Integer.class); ArgumentCaptor<Integer> peerIdCaptor = ArgumentCaptor.forClass(Integer.class); InOrder inOrder = inOrder(mockCallback, mockSessionCallback, mMockNative); + InOrder inOrderM = inOrder(mAwareMetricsMock); mDut.enableUsage(); mMockLooper.dispatchAll(); inOrder.verify(mMockNative).getCapabilities(transactionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordEnableUsage(); mDut.onCapabilitiesUpdateResponse(transactionId.getValue(), getCapabilities()); mMockLooper.dispatchAll(); @@ -1371,6 +1403,7 @@ public class WifiAwareStateManagerTest { mDut.onConfigSuccessResponse(transactionId.getValue()); mMockLooper.dispatchAll(); inOrder.verify(mockCallback).onConnectSuccess(clientId); + inOrderM.verify(mAwareMetricsMock).recordAttachSession(eq(uid), eq(false), any()); // (1) subscribe mDut.subscribe(clientId, subscribeConfig, mockSessionCallback); @@ -1380,13 +1413,24 @@ public class WifiAwareStateManagerTest { mDut.onSessionConfigSuccessResponse(transactionId.getValue(), false, subscribeId); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onSessionStarted(sessionId.capture()); + inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true), + eq(rangeMin), eq(rangeMax), any()); + inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false); - // (2) match + // (2) 2 matches : with and w/o range mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), peerMatchFilter.getBytes(), 0, 0); mMockLooper.dispatchAll(); inOrder.verify(mockSessionCallback).onMatch(peerIdCaptor.capture(), eq(peerSsi.getBytes()), eq(peerMatchFilter.getBytes())); + inOrderM.verify(mAwareMetricsMock).recordMatchIndicationForRangeEnabledSubscribe(false); + + mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(), + peerMatchFilter.getBytes(), EGRESS_MET_MASK, rangedDistance); + mMockLooper.dispatchAll(); + inOrder.verify(mockSessionCallback).onMatchWithDistance(peerIdCaptor.capture(), + eq(peerSsi.getBytes()), eq(peerMatchFilter.getBytes()), eq(rangedDistance)); + inOrderM.verify(mAwareMetricsMock).recordMatchIndicationForRangeEnabledSubscribe(true); // (3) message Rx mDut.onMessageReceivedNotification(subscribeId, requestorId, peerMac, peerMsg.getBytes()); @@ -1423,7 +1467,7 @@ public class WifiAwareStateManagerTest { validateInternalSendMessageQueuesCleanedUp(messageId); validateInternalSendMessageQueuesCleanedUp(messageId2); - verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative); + verifyNoMoreInteractions(mockCallback, mockSessionCallback, mMockNative, mAwareMetricsMock); } /** |