1 /* 2 * Copyright (C) 2018 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.rtt; 18 19 import static org.hamcrest.core.IsEqual.equalTo; 20 import static org.mockito.Mockito.when; 21 22 import android.net.MacAddress; 23 import android.net.wifi.rtt.RangingRequest; 24 import android.net.wifi.rtt.RangingResult; 25 import android.net.wifi.rtt.ResponderConfig; 26 import android.os.WorkSource; 27 import android.util.Log; 28 29 import androidx.test.filters.SmallTest; 30 31 import com.android.server.wifi.Clock; 32 import com.android.server.wifi.WifiBaseTest; 33 import com.android.server.wifi.proto.nano.WifiMetricsProto; 34 35 import org.junit.Before; 36 import org.junit.Rule; 37 import org.junit.Test; 38 import org.junit.rules.ErrorCollector; 39 import org.mockito.Mock; 40 import org.mockito.MockitoAnnotations; 41 42 import java.io.PrintWriter; 43 import java.io.StringWriter; 44 import java.util.ArrayList; 45 import java.util.List; 46 47 /** 48 * Unit test harness for RttMetrics 49 */ 50 @SmallTest 51 public class RttMetricsTest extends WifiBaseTest { 52 private RttMetrics mDut; 53 54 @Mock 55 Clock mClock; 56 57 @Rule 58 public ErrorCollector collector = new ErrorCollector(); 59 60 /** 61 * Pre-test configuration. Initialize and install mocks. 62 */ 63 @Before setUp()64 public void setUp() throws Exception { 65 MockitoAnnotations.initMocks(this); 66 67 setTime(1); 68 mDut = new RttMetrics(mClock); 69 } 70 71 /** 72 * Verify that recordRequest() records valid metrics. 73 */ 74 @Test testRecordRequest()75 public void testRecordRequest() { 76 WifiMetricsProto.WifiRttLog log; 77 78 // no requests 79 log = mDut.consolidateProto(); 80 checkMainStats("No requests", log, 0, 0, 0, 0); 81 checkPeerStats("No requests: AP", log.rttToAp, 0, 0, 0, 0, 0, 0, 0, 0); 82 checkPeerStats("No requests: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); 83 84 // multiple AP requests from multiple sources 85 WorkSource ws1 = new WorkSource(10); 86 WorkSource ws2 = new WorkSource(20); 87 ws2.add(10); 88 89 RangingRequest requestAp1 = getDummyRangingRequest(1, 0); 90 RangingRequest requestAp2 = getDummyRangingRequest(2, 0); 91 RangingRequest requestAp5 = getDummyRangingRequest(5, 0); 92 RangingRequest requestAp6 = getDummyRangingRequest(6, 0); 93 94 mDut.clear(); 95 mDut.recordRequest(ws1, requestAp1); 96 setTime(10); // delta = 9 97 mDut.recordRequest(ws1, requestAp2); 98 setTime(20); // delta = 10 99 mDut.recordRequest(ws1, requestAp5); 100 setTime(21); // delta = 1 101 mDut.recordRequest(ws1, requestAp6); 102 setTime(1000); // delta = 979 103 mDut.recordRequest(ws1, requestAp5); 104 setTime(5000); // delta = 4,000 105 mDut.recordRequest(ws1, requestAp5); 106 setTime(1000000); // delta = 995,000 107 mDut.recordRequest(ws1, requestAp2); 108 mDut.recordRequest(ws2, requestAp5); 109 mDut.recordRequest(ws2, requestAp5); 110 mDut.recordRequest(ws2, requestAp5); 111 112 log = mDut.consolidateProto(); 113 checkMainStats("Sequence AP-only", log, 10, 0, 0, 0); 114 115 checkPeerStats("Sequence AP-only: AP", log.rttToAp, 10, 41, 2, 2, 4, 0, 0, 5); 116 117 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumRequestsPerApp[0]", 118 log.rttToAp.histogramNumRequestsPerApp[0], 1, 10, 1); 119 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumRequestsPerApp[1]", 120 log.rttToAp.histogramNumRequestsPerApp[1], 10, 100, 1); 121 122 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[0]", 123 log.rttToAp.histogramNumPeersPerRequest[0], 1, 1, 1); 124 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[1]", 125 log.rttToAp.histogramNumPeersPerRequest[1], 2, 2, 2); 126 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[2]", 127 log.rttToAp.histogramNumPeersPerRequest[2], 5, 5, 6); 128 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[3]", 129 log.rttToAp.histogramNumPeersPerRequest[3], 6, 6, 1); 130 131 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[0]", 132 log.rttToAp.histogramRequestIntervalMs[0], 1, 10, 5); 133 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[1]", 134 log.rttToAp.histogramRequestIntervalMs[1], 10, 100, 1); 135 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[2]", 136 log.rttToAp.histogramRequestIntervalMs[2], 100, 1000, 1); 137 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[3]", 138 log.rttToAp.histogramRequestIntervalMs[3], 1000, 10000, 1); 139 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[4]", 140 log.rttToAp.histogramRequestIntervalMs[4], 100000, 1000000, 1); 141 142 checkPeerStats("Sequence AP-only: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); 143 144 // mix of AP and Aware requests 145 WorkSource ws3 = new WorkSource(30); 146 ws3.add(20); 147 ws3.add(40); 148 149 RangingRequest requestMixed03 = getDummyRangingRequest(0, 3); 150 RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); 151 RangingRequest requestMixed50 = getDummyRangingRequest(5, 0); 152 RangingRequest requestMixed08 = getDummyRangingRequest(0, 8); 153 154 mDut.clear(); 155 setTime(100); 156 mDut.recordRequest(ws3, requestMixed03); 157 setTime(101); 158 mDut.recordRequest(ws3, requestMixed25); 159 setTime(102); 160 mDut.recordRequest(ws3, requestMixed50); 161 setTime(103); 162 mDut.recordRequest(ws3, requestMixed08); 163 164 log = mDut.consolidateProto(); 165 checkMainStats("Sequence Mixed AP/Aware", log, 4, 0, 0, 0); 166 167 checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 2, 7, 3, 1, 2, 0, 0, 1); 168 169 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumRequestsPerApp[0]", 170 log.rttToAp.histogramNumRequestsPerApp[0], 1, 10, 3); 171 172 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumPeersPerRequest[0]", 173 log.rttToAp.histogramNumPeersPerRequest[0], 2, 2, 1); 174 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumPeersPerRequest[1]", 175 log.rttToAp.histogramNumPeersPerRequest[1], 5, 5, 1); 176 177 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramRequestIntervalMs[0]", 178 log.rttToAp.histogramRequestIntervalMs[0], 1, 10, 1); 179 180 checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 3, 16, 3, 1, 3, 0, 0, 1); 181 182 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramNumRequestsPerApp[0]", 183 log.rttToAware.histogramNumRequestsPerApp[0], 1, 10, 3); 184 185 validateProtoHistBucket( 186 "Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[0]", 187 log.rttToAware.histogramNumPeersPerRequest[0], 3, 3, 1); 188 validateProtoHistBucket( 189 "Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[1]", 190 log.rttToAware.histogramNumPeersPerRequest[1], 5, 5, 1); 191 validateProtoHistBucket( 192 "Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[2]", 193 log.rttToAware.histogramNumPeersPerRequest[2], 8, 8, 1); 194 195 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramRequestIntervalMs[0]", 196 log.rttToAware.histogramRequestIntervalMs[0], 1, 10, 2); 197 } 198 199 /** 200 * Verify that recordResult() records valid metrics. 201 */ 202 @Test testRecordResult()203 public void testRecordResult() { 204 WifiMetricsProto.WifiRttLog log; 205 206 // no requests 207 log = mDut.consolidateProto(); 208 checkMainStats("No requests", log, 0, 0, 0, 0); 209 checkPeerStats("No requests: AP", log.rttToAp, 0, 0, 0, 0, 0, 0, 0, 0); 210 checkPeerStats("No requests: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); 211 212 // multiple AP results 213 RangingRequest requestAp1 = getDummyRangingRequest(1, 0); 214 RangingRequest requestAp2 = getDummyRangingRequest(2, 0); 215 RangingRequest requestAp5 = getDummyRangingRequest(5, 0); 216 RangingRequest requestAp6 = getDummyRangingRequest(6, 0); 217 218 mDut.clear(); 219 mDut.recordResult(requestAp1, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 220 requestAp1, 5, 0), 500); 221 mDut.recordResult(requestAp2, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 222 requestAp2, 10, 30), 1500); 223 mDut.recordResult(requestAp5, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 224 requestAp5, 0.3, -0.2), 700); 225 mDut.recordResult(requestAp6, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 226 requestAp6, 40, 30), 1800); 227 log = mDut.consolidateProto(); 228 229 checkMainStats("Sequence AP-only", log, 0, 0, 2, 0); 230 checkPeerStats("Sequence AP-only: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 6, 0); 231 232 validateProtoHistBucket("Sequence AP-only: histogramMeasurementDurationApOnly[0]", 233 log.histogramMeasurementDurationApOnly[0], Integer.MIN_VALUE, 1 * 1000, 2); 234 validateProtoHistBucket("Sequence AP-only: histogramMeasurementDurationApOnly[1]", 235 log.histogramMeasurementDurationApOnly[1], 1 * 1000, 2 * 1000, 2); 236 237 validateProtoIndividualStatusHistBucket( 238 "Sequence AP-only: rttToAp.histogramIndividualStatus[0]", 239 log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 14); 240 241 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[0]", 242 log.rttToAp.histogramDistance[0], Integer.MIN_VALUE, 0, 3); 243 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[1]", 244 log.rttToAp.histogramDistance[1], 0, 5 * 1000, 2); 245 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[2]", 246 log.rttToAp.histogramDistance[2], 5 * 1000, 15 * 1000, 2); 247 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[3]", 248 log.rttToAp.histogramDistance[3], 30 * 1000, 60 * 1000, 2); 249 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[4]", 250 log.rttToAp.histogramDistance[4], 60 * 1000, 100 * 1000, 1); 251 validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[5]", 252 log.rttToAp.histogramDistance[5], 100 * 1000, Integer.MAX_VALUE, 4); 253 254 checkPeerStats("Sequence AP-only: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0); 255 256 // mix of AP and Aware requests 257 RangingRequest requestMixed03 = getDummyRangingRequest(0, 3); 258 RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); 259 RangingRequest requestMixed50 = getDummyRangingRequest(5, 0); 260 RangingRequest requestMixed08 = getDummyRangingRequest(0, 8); 261 262 mDut.clear(); 263 mDut.recordResult(requestMixed03, getDummyRangingResults( 264 RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed03, 5, 0), 6400); 265 mDut.recordResult(requestMixed25, getDummyRangingResults( 266 RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30), 7800); 267 mDut.recordResult(requestMixed50, getDummyRangingResults( 268 RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed50, 0.3, -0.2), 3100); 269 mDut.recordResult(requestMixed08, getDummyRangingResults( 270 RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed08, 40, 30), 9500); 271 log = mDut.consolidateProto(); 272 273 checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 1, 2); 274 275 checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 4, 0); 276 277 validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationApOnly[0]", 278 log.histogramMeasurementDurationApOnly[0], 3 * 1000, 4 * 1000, 1); 279 validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationWithAware[0]", 280 log.histogramMeasurementDurationWithAware[0], 6 * 1000, 8 * 1000, 2); 281 validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationWithAware[1]", 282 log.histogramMeasurementDurationWithAware[1], 8 * 1000, Integer.MAX_VALUE, 1); 283 284 validateProtoIndividualStatusHistBucket( 285 "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[0]", 286 log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 7); 287 288 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[0]", 289 log.rttToAp.histogramDistance[0], Integer.MIN_VALUE, 0, 3); 290 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[1]", 291 log.rttToAp.histogramDistance[1], 0, 5 * 1000, 2); 292 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[2]", 293 log.rttToAp.histogramDistance[2], 5 * 1000, 15 * 1000, 1); 294 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[3]", 295 log.rttToAp.histogramDistance[3], 30 * 1000, 60 * 1000, 1); 296 297 checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 1, 4, 0); 298 299 validateProtoIndividualStatusHistBucket( 300 "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]", 301 log.rttToAware.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 302 16); 303 304 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[0]", 305 log.rttToAware.histogramDistance[0], 5 * 1000, 15 * 1000, 3); 306 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[1]", 307 log.rttToAware.histogramDistance[1], 30 * 1000, 60 * 1000, 1); 308 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[2]", 309 log.rttToAware.histogramDistance[2], 60 * 1000, 100 * 1000, 2); 310 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[3]", 311 log.rttToAware.histogramDistance[3], 100 * 1000, Integer.MAX_VALUE, 10); 312 } 313 314 /** 315 * Verify the behavior when the HAL returns with missing results or some results set to null. 316 */ 317 @Test testRecordMissingResults()318 public void testRecordMissingResults() { 319 WifiMetricsProto.WifiRttLog log; 320 321 mDut.clear(); 322 RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); 323 List<RangingResult> resultMixed25 = getDummyRangingResults( 324 RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30); 325 // remove some results 326 resultMixed25.remove(3); // Second Aware result: distance = 100 327 resultMixed25.remove(0); // First AP result: distance = 10 328 resultMixed25.add(null); 329 mDut.recordResult(requestMixed25, resultMixed25, 0); 330 331 log = mDut.consolidateProto(); 332 333 checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 0, 1); 334 335 checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 2, 1, 0); 336 337 validateProtoIndividualStatusHistBucket( 338 "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[0]", 339 log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 1); 340 validateProtoIndividualStatusHistBucket( 341 "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[1]", 342 log.rttToAp.histogramIndividualStatus[1], 343 WifiMetricsProto.WifiRttLog.MISSING_RESULT, 1); 344 345 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[0]", 346 log.rttToAp.histogramDistance[0], 30 * 1000, 60 * 1000, 1); 347 348 checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 2, 2, 0); 349 350 validateProtoIndividualStatusHistBucket( 351 "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]", 352 log.rttToAware.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 353 4); 354 validateProtoIndividualStatusHistBucket( 355 "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[1]", 356 log.rttToAware.histogramIndividualStatus[1], 357 WifiMetricsProto.WifiRttLog.MISSING_RESULT, 1); 358 359 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[0]", 360 log.rttToAware.histogramDistance[0], 60 * 1000, 100 * 1000, 1); 361 validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[1]", 362 log.rttToAware.histogramDistance[1], 100 * 1000, Integer.MAX_VALUE, 3); 363 } 364 365 /** 366 * Verify the behavior when the HAL returns with NULL array. 367 */ 368 @Test testRecordNullArrayResults()369 public void testRecordNullArrayResults() { 370 WifiMetricsProto.WifiRttLog log; 371 372 mDut.clear(); 373 RangingRequest requestMixed25 = getDummyRangingRequest(2, 5); 374 mDut.recordResult(requestMixed25, null, 0); 375 376 log = mDut.consolidateProto(); 377 378 checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 0, 0); 379 380 checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 0, 0); 381 382 validateProtoIndividualStatusHistBucket( 383 "Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[1]", 384 log.rttToAp.histogramIndividualStatus[0], 385 WifiMetricsProto.WifiRttLog.MISSING_RESULT, 2); 386 387 checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 1, 0, 0); 388 389 validateProtoIndividualStatusHistBucket( 390 "Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]", 391 log.rttToAware.histogramIndividualStatus[0], 392 WifiMetricsProto.WifiRttLog.MISSING_RESULT, 5); 393 } 394 395 /** 396 * Verify that all individual status codes are translated correctly. 397 */ 398 @Test testRecordResultsStatuses()399 public void testRecordResultsStatuses() { 400 WifiMetricsProto.WifiRttLog log; 401 402 mDut.clear(); 403 404 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 5); 405 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAILURE, 6); 406 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, 7); 407 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_REJECTED, 8); 408 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, 9); 409 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, 10); 410 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, 11); 411 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, 12); 412 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_ABORTED, 13); 413 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, 14); 414 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, 15); 415 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, 16); 416 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, 17); 417 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_INVALID_REQ, 18); 418 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_NO_WIFI, 19); 419 recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE, 20); 420 421 log = mDut.consolidateProto(); 422 423 collector.checkThat("AP histogramIndividualStatus.length", 424 log.rttToAp.histogramIndividualStatus.length, equalTo(16)); 425 426 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[0]", 427 log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 5); 428 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[1]", 429 log.rttToAp.histogramIndividualStatus[1], WifiMetricsProto.WifiRttLog.FAILURE, 6); 430 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[2]", 431 log.rttToAp.histogramIndividualStatus[2], WifiMetricsProto.WifiRttLog.FAIL_NO_RSP, 432 7); 433 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[3]", 434 log.rttToAp.histogramIndividualStatus[3], WifiMetricsProto.WifiRttLog.FAIL_REJECTED, 435 8); 436 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[4]", 437 log.rttToAp.histogramIndividualStatus[4], 438 WifiMetricsProto.WifiRttLog.FAIL_NOT_SCHEDULED_YET, 9); 439 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[5]", 440 log.rttToAp.histogramIndividualStatus[5], 441 WifiMetricsProto.WifiRttLog.FAIL_TM_TIMEOUT, 10); 442 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[6]", 443 log.rttToAp.histogramIndividualStatus[6], 444 WifiMetricsProto.WifiRttLog.FAIL_AP_ON_DIFF_CHANNEL, 11); 445 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[7]", 446 log.rttToAp.histogramIndividualStatus[7], 447 WifiMetricsProto.WifiRttLog.FAIL_NO_CAPABILITY, 12); 448 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[8]", 449 log.rttToAp.histogramIndividualStatus[8], WifiMetricsProto.WifiRttLog.ABORTED, 13); 450 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[9]", 451 log.rttToAp.histogramIndividualStatus[9], 452 WifiMetricsProto.WifiRttLog.FAIL_INVALID_TS, 14); 453 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[10]", 454 log.rttToAp.histogramIndividualStatus[10], 455 WifiMetricsProto.WifiRttLog.FAIL_PROTOCOL, 15); 456 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[11]", 457 log.rttToAp.histogramIndividualStatus[11], 458 WifiMetricsProto.WifiRttLog.FAIL_SCHEDULE, 16); 459 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[12]", 460 log.rttToAp.histogramIndividualStatus[12], 461 WifiMetricsProto.WifiRttLog.FAIL_BUSY_TRY_LATER, 17); 462 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[13]", 463 log.rttToAp.histogramIndividualStatus[13], WifiMetricsProto.WifiRttLog.INVALID_REQ, 464 18); 465 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[14]", 466 log.rttToAp.histogramIndividualStatus[14], WifiMetricsProto.WifiRttLog.NO_WIFI, 19); 467 validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[15]", 468 log.rttToAp.histogramIndividualStatus[15], 469 WifiMetricsProto.WifiRttLog.FAIL_FTM_PARAM_OVERRIDE, 20); 470 471 collector.checkThat("Aware histogramIndividualStatus.length", 472 log.rttToAware.histogramIndividualStatus.length, equalTo(0)); 473 } 474 475 /** 476 * Verify that all overall status codes are recorded correctly. 477 */ 478 @Test testRecordOverallStatus()479 public void testRecordOverallStatus() { 480 WifiMetricsProto.WifiRttLog log; 481 482 mDut.clear(); 483 484 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS, 5); 485 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_FAIL, 6); 486 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE, 7); 487 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT, 8); 488 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE, 9); 489 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE, 10); 490 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE, 491 11); 492 recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING, 493 12); 494 495 log = mDut.consolidateProto(); 496 497 collector.checkThat("histogramOverallStatus.length", log.histogramOverallStatus.length, 498 equalTo(8)); 499 500 validateProtoOverallStatusHistBucket("histogramOverallStatus[0]", 501 log.histogramOverallStatus[0], WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS, 5); 502 validateProtoOverallStatusHistBucket("histogramOverallStatus[1]", 503 log.histogramOverallStatus[1], WifiMetricsProto.WifiRttLog.OVERALL_FAIL, 6); 504 validateProtoOverallStatusHistBucket("histogramOverallStatus[2]", 505 log.histogramOverallStatus[2], 506 WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE, 7); 507 validateProtoOverallStatusHistBucket("histogramOverallStatus[3]", 508 log.histogramOverallStatus[3], WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT, 8); 509 validateProtoOverallStatusHistBucket("histogramOverallStatus[4]", 510 log.histogramOverallStatus[4], WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE, 9); 511 validateProtoOverallStatusHistBucket("histogramOverallStatus[5]", 512 log.histogramOverallStatus[5], WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE, 10); 513 validateProtoOverallStatusHistBucket("histogramOverallStatus[6]", 514 log.histogramOverallStatus[6], 515 WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE, 11); 516 validateProtoOverallStatusHistBucket("histogramOverallStatus[7]", 517 log.histogramOverallStatus[7], 518 WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING, 12); 519 } 520 521 // Utilities 522 523 /** 524 * Mock the elapsed time since boot to the input argument. 525 */ setTime(long timeMs)526 private void setTime(long timeMs) { 527 when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs); 528 } 529 validateProtoHistBucket(String logPrefix, WifiMetricsProto.WifiRttLog.HistogramBucket bucket, long start, long end, int count)530 private void validateProtoHistBucket(String logPrefix, 531 WifiMetricsProto.WifiRttLog.HistogramBucket bucket, long start, long end, int count) { 532 collector.checkThat(logPrefix + ": start", bucket.start, equalTo(start)); 533 collector.checkThat(logPrefix + ": end", bucket.end, equalTo(end)); 534 collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); 535 } 536 validateProtoOverallStatusHistBucket(String logPrefix, WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket bucket, int status, int count)537 private void validateProtoOverallStatusHistBucket(String logPrefix, 538 WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket bucket, int status, 539 int count) { 540 collector.checkThat(logPrefix + ": statusType", bucket.statusType, equalTo(status)); 541 collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); 542 } 543 validateProtoIndividualStatusHistBucket(String logPrefix, WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket bucket, int status, int count)544 private void validateProtoIndividualStatusHistBucket(String logPrefix, 545 WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket bucket, int status, 546 int count) { 547 collector.checkThat(logPrefix + ": statusType", bucket.statusType, equalTo(status)); 548 collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count)); 549 } 550 checkMainStats(String msgPrefix, WifiMetricsProto.WifiRttLog log, int numRequests, int histogramOverallStatusLength, int histogramMeasurementDurationApOnlyLength, int histogramMeasurementDurationWithAwareLength)551 private void checkMainStats(String msgPrefix, WifiMetricsProto.WifiRttLog log, int numRequests, 552 int histogramOverallStatusLength, int histogramMeasurementDurationApOnlyLength, 553 int histogramMeasurementDurationWithAwareLength) { 554 collector.checkThat(msgPrefix + ": numRequests", log.numRequests, equalTo(numRequests)); 555 collector.checkThat(msgPrefix + ": histogramOverallStatus.length", 556 log.histogramOverallStatus.length, 557 equalTo(histogramOverallStatusLength)); 558 collector.checkThat(msgPrefix + ": histogramMeasurementDurationApOnly.length", 559 log.histogramMeasurementDurationApOnly.length, 560 equalTo(histogramMeasurementDurationApOnlyLength)); 561 collector.checkThat(msgPrefix + ": histogramMeasurementDurationWithAware.length", 562 log.histogramMeasurementDurationWithAware.length, 563 equalTo(histogramMeasurementDurationWithAwareLength)); 564 } 565 checkPeerStats(String msgPrefix, WifiMetricsProto.WifiRttLog.RttToPeerLog log, int numRequests, int numIndividualRequests, int numApps, int histogramNumRequestsPerAppLength, int histogramNumPeersPerRequestLength, int histogramIndividualStatusLength, int histogramDistanceLength, int histogramRequestIntervalMsLength)566 private void checkPeerStats(String msgPrefix, WifiMetricsProto.WifiRttLog.RttToPeerLog log, 567 int numRequests, int numIndividualRequests, 568 int numApps, int histogramNumRequestsPerAppLength, 569 int histogramNumPeersPerRequestLength, int histogramIndividualStatusLength, 570 int histogramDistanceLength, int histogramRequestIntervalMsLength) { 571 collector.checkThat(msgPrefix + ": numRequests", log.numRequests, equalTo(numRequests)); 572 collector.checkThat(msgPrefix + ": numIndividualRequests", log.numIndividualRequests, 573 equalTo(numIndividualRequests)); 574 collector.checkThat(msgPrefix + ": numApps", log.numApps, equalTo(numApps)); 575 collector.checkThat(msgPrefix + ": histogramNumRequestsPerApp.length", 576 log.histogramNumRequestsPerApp.length, equalTo(histogramNumRequestsPerAppLength)); 577 collector.checkThat(msgPrefix + ": histogramNumPeersPerRequest.length", 578 log.histogramNumPeersPerRequest.length, equalTo(histogramNumPeersPerRequestLength)); 579 collector.checkThat(msgPrefix + ": histogramIndividualStatus.length", 580 log.histogramIndividualStatus.length, equalTo(histogramIndividualStatusLength)); 581 collector.checkThat(msgPrefix + ": histogramDistance.length", 582 log.histogramDistance.length, equalTo(histogramDistanceLength)); 583 collector.checkThat(msgPrefix + ": histogramRequestIntervalMs.length", 584 log.histogramRequestIntervalMs.length, equalTo(histogramRequestIntervalMsLength)); 585 } 586 getDummyRangingRequest(int countAp, int countAware)587 private RangingRequest getDummyRangingRequest(int countAp, int countAware) { 588 RangingRequest.Builder builder = new RangingRequest.Builder(); 589 byte[] placeholderMacBase = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5}; 590 591 for (int i = 0; i < countAp; ++i) { 592 placeholderMacBase[0]++; 593 builder.addResponder(new ResponderConfig(MacAddress.fromBytes(placeholderMacBase), 594 ResponderConfig.RESPONDER_AP, true, 0, 0, 0, 0, 0)); 595 } 596 for (int i = 0; i < countAware; ++i) { 597 placeholderMacBase[0]++; 598 builder.addResponder(new ResponderConfig(MacAddress.fromBytes(placeholderMacBase), 599 ResponderConfig.RESPONDER_AWARE, true, 0, 0, 0, 0, 0)); 600 } 601 602 return builder.build(); 603 } 604 getDummyRangingResults(int status, RangingRequest request, double baseDistanceM, double incrDistanceM)605 private List<RangingResult> getDummyRangingResults(int status, RangingRequest request, 606 double baseDistanceM, double incrDistanceM) { 607 List<RangingResult> rangingResults = new ArrayList<>(); 608 double distance = baseDistanceM; 609 610 for (ResponderConfig peer : request.mRttPeers) { 611 612 RangingResult rttResult = new RangingResult(status, peer.macAddress, 613 (int) (distance * 1000), 0, 0, 8, 8, null, null, null, 0, true); 614 distance += incrDistanceM; 615 rangingResults.add(rttResult); 616 } 617 618 return rangingResults; 619 } 620 recordResultNTimes(int status, int n)621 private void recordResultNTimes(int status, int n) { 622 RangingRequest request = getDummyRangingRequest(1, 0); 623 List<RangingResult> results = getDummyRangingResults(status, request, 0, 0); 624 625 for (int i = 0; i < n; ++i) { 626 mDut.recordResult(request, results, 0); 627 } 628 } 629 recordOverallStatusNTimes(int status, int n)630 private void recordOverallStatusNTimes(int status, int n) { 631 for (int i = 0; i < n; ++i) { 632 mDut.recordOverallStatus(status); 633 } 634 } 635 dumpDut(String prefix)636 private void dumpDut(String prefix) { 637 StringWriter sw = new StringWriter(); 638 mDut.dump(null, new PrintWriter(sw), null); 639 Log.e("RttMetrics", prefix + sw.toString()); 640 } 641 } 642