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