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