blob: 2c2f892bd19a35c2fdfb6d5a144de8d3d7fe49a1 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi.rtt;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.mockito.Mockito.when;
import android.net.MacAddress;
import android.net.wifi.rtt.RangingRequest;
import android.net.wifi.rtt.RangingResult;
import android.net.wifi.rtt.ResponderConfig;
import android.os.WorkSource;
import android.util.Log;
import androidx.test.filters.SmallTest;
import com.android.server.wifi.Clock;
import com.android.server.wifi.WifiBaseTest;
import com.android.server.wifi.proto.nano.WifiMetricsProto;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
/**
* Unit test harness for RttMetrics
*/
@SmallTest
public class RttMetricsTest extends WifiBaseTest {
private RttMetrics mDut;
@Mock
Clock mClock;
@Rule
public ErrorCollector collector = new ErrorCollector();
/**
* Pre-test configuration. Initialize and install mocks.
*/
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
setTime(1);
mDut = new RttMetrics(mClock);
}
/**
* Verify that recordRequest() records valid metrics.
*/
@Test
public void testRecordRequest() {
WifiMetricsProto.WifiRttLog log;
// no requests
log = mDut.consolidateProto();
checkMainStats("No requests", log, 0, 0, 0, 0);
checkPeerStats("No requests: AP", log.rttToAp, 0, 0, 0, 0, 0, 0, 0, 0);
checkPeerStats("No requests: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0);
// multiple AP requests from multiple sources
WorkSource ws1 = new WorkSource(10);
WorkSource ws2 = new WorkSource(20);
ws2.add(10);
RangingRequest requestAp1 = getDummyRangingRequest(1, 0);
RangingRequest requestAp2 = getDummyRangingRequest(2, 0);
RangingRequest requestAp5 = getDummyRangingRequest(5, 0);
RangingRequest requestAp6 = getDummyRangingRequest(6, 0);
mDut.clear();
mDut.recordRequest(ws1, requestAp1);
setTime(10); // delta = 9
mDut.recordRequest(ws1, requestAp2);
setTime(20); // delta = 10
mDut.recordRequest(ws1, requestAp5);
setTime(21); // delta = 1
mDut.recordRequest(ws1, requestAp6);
setTime(1000); // delta = 979
mDut.recordRequest(ws1, requestAp5);
setTime(5000); // delta = 4,000
mDut.recordRequest(ws1, requestAp5);
setTime(1000000); // delta = 995,000
mDut.recordRequest(ws1, requestAp2);
mDut.recordRequest(ws2, requestAp5);
mDut.recordRequest(ws2, requestAp5);
mDut.recordRequest(ws2, requestAp5);
log = mDut.consolidateProto();
checkMainStats("Sequence AP-only", log, 10, 0, 0, 0);
checkPeerStats("Sequence AP-only: AP", log.rttToAp, 10, 41, 2, 2, 4, 0, 0, 5);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumRequestsPerApp[0]",
log.rttToAp.histogramNumRequestsPerApp[0], 1, 10, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumRequestsPerApp[1]",
log.rttToAp.histogramNumRequestsPerApp[1], 10, 100, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[0]",
log.rttToAp.histogramNumPeersPerRequest[0], 1, 1, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[1]",
log.rttToAp.histogramNumPeersPerRequest[1], 2, 2, 2);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[2]",
log.rttToAp.histogramNumPeersPerRequest[2], 5, 5, 6);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramNumPeersPerRequest[3]",
log.rttToAp.histogramNumPeersPerRequest[3], 6, 6, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[0]",
log.rttToAp.histogramRequestIntervalMs[0], 1, 10, 5);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[1]",
log.rttToAp.histogramRequestIntervalMs[1], 10, 100, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[2]",
log.rttToAp.histogramRequestIntervalMs[2], 100, 1000, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[3]",
log.rttToAp.histogramRequestIntervalMs[3], 1000, 10000, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramRequestIntervalMs[4]",
log.rttToAp.histogramRequestIntervalMs[4], 100000, 1000000, 1);
checkPeerStats("Sequence AP-only: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0);
// mix of AP and Aware requests
WorkSource ws3 = new WorkSource(30);
ws3.add(20);
ws3.add(40);
RangingRequest requestMixed03 = getDummyRangingRequest(0, 3);
RangingRequest requestMixed25 = getDummyRangingRequest(2, 5);
RangingRequest requestMixed50 = getDummyRangingRequest(5, 0);
RangingRequest requestMixed08 = getDummyRangingRequest(0, 8);
mDut.clear();
setTime(100);
mDut.recordRequest(ws3, requestMixed03);
setTime(101);
mDut.recordRequest(ws3, requestMixed25);
setTime(102);
mDut.recordRequest(ws3, requestMixed50);
setTime(103);
mDut.recordRequest(ws3, requestMixed08);
log = mDut.consolidateProto();
checkMainStats("Sequence Mixed AP/Aware", log, 4, 0, 0, 0);
checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 2, 7, 3, 1, 2, 0, 0, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumRequestsPerApp[0]",
log.rttToAp.histogramNumRequestsPerApp[0], 1, 10, 3);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumPeersPerRequest[0]",
log.rttToAp.histogramNumPeersPerRequest[0], 2, 2, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramNumPeersPerRequest[1]",
log.rttToAp.histogramNumPeersPerRequest[1], 5, 5, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramRequestIntervalMs[0]",
log.rttToAp.histogramRequestIntervalMs[0], 1, 10, 1);
checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 3, 16, 3, 1, 3, 0, 0, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramNumRequestsPerApp[0]",
log.rttToAware.histogramNumRequestsPerApp[0], 1, 10, 3);
validateProtoHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[0]",
log.rttToAware.histogramNumPeersPerRequest[0], 3, 3, 1);
validateProtoHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[1]",
log.rttToAware.histogramNumPeersPerRequest[1], 5, 5, 1);
validateProtoHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramNumPeersPerRequest[2]",
log.rttToAware.histogramNumPeersPerRequest[2], 8, 8, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramRequestIntervalMs[0]",
log.rttToAware.histogramRequestIntervalMs[0], 1, 10, 2);
}
/**
* Verify that recordResult() records valid metrics.
*/
@Test
public void testRecordResult() {
WifiMetricsProto.WifiRttLog log;
// no requests
log = mDut.consolidateProto();
checkMainStats("No requests", log, 0, 0, 0, 0);
checkPeerStats("No requests: AP", log.rttToAp, 0, 0, 0, 0, 0, 0, 0, 0);
checkPeerStats("No requests: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0);
// multiple AP results
RangingRequest requestAp1 = getDummyRangingRequest(1, 0);
RangingRequest requestAp2 = getDummyRangingRequest(2, 0);
RangingRequest requestAp5 = getDummyRangingRequest(5, 0);
RangingRequest requestAp6 = getDummyRangingRequest(6, 0);
mDut.clear();
mDut.recordResult(requestAp1, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS,
requestAp1, 5, 0), 500);
mDut.recordResult(requestAp2, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS,
requestAp2, 10, 30), 1500);
mDut.recordResult(requestAp5, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS,
requestAp5, 0.3, -0.2), 700);
mDut.recordResult(requestAp6, getDummyRangingResults(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS,
requestAp6, 40, 30), 1800);
log = mDut.consolidateProto();
checkMainStats("Sequence AP-only", log, 0, 0, 2, 0);
checkPeerStats("Sequence AP-only: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 6, 0);
validateProtoHistBucket("Sequence AP-only: histogramMeasurementDurationApOnly[0]",
log.histogramMeasurementDurationApOnly[0], Integer.MIN_VALUE, 1 * 1000, 2);
validateProtoHistBucket("Sequence AP-only: histogramMeasurementDurationApOnly[1]",
log.histogramMeasurementDurationApOnly[1], 1 * 1000, 2 * 1000, 2);
validateProtoIndividualStatusHistBucket(
"Sequence AP-only: rttToAp.histogramIndividualStatus[0]",
log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 14);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[0]",
log.rttToAp.histogramDistance[0], Integer.MIN_VALUE, 0, 3);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[1]",
log.rttToAp.histogramDistance[1], 0, 5 * 1000, 2);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[2]",
log.rttToAp.histogramDistance[2], 5 * 1000, 15 * 1000, 2);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[3]",
log.rttToAp.histogramDistance[3], 30 * 1000, 60 * 1000, 2);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[4]",
log.rttToAp.histogramDistance[4], 60 * 1000, 100 * 1000, 1);
validateProtoHistBucket("Sequence AP-only: rttToAp.histogramDistance[5]",
log.rttToAp.histogramDistance[5], 100 * 1000, Integer.MAX_VALUE, 4);
checkPeerStats("Sequence AP-only: Aware", log.rttToAware, 0, 0, 0, 0, 0, 0, 0, 0);
// mix of AP and Aware requests
RangingRequest requestMixed03 = getDummyRangingRequest(0, 3);
RangingRequest requestMixed25 = getDummyRangingRequest(2, 5);
RangingRequest requestMixed50 = getDummyRangingRequest(5, 0);
RangingRequest requestMixed08 = getDummyRangingRequest(0, 8);
mDut.clear();
mDut.recordResult(requestMixed03, getDummyRangingResults(
RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed03, 5, 0), 6400);
mDut.recordResult(requestMixed25, getDummyRangingResults(
RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30), 7800);
mDut.recordResult(requestMixed50, getDummyRangingResults(
RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed50, 0.3, -0.2), 3100);
mDut.recordResult(requestMixed08, getDummyRangingResults(
RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed08, 40, 30), 9500);
log = mDut.consolidateProto();
checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 1, 2);
checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 4, 0);
validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationApOnly[0]",
log.histogramMeasurementDurationApOnly[0], 3 * 1000, 4 * 1000, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationWithAware[0]",
log.histogramMeasurementDurationWithAware[0], 6 * 1000, 8 * 1000, 2);
validateProtoHistBucket("Sequence Mixed AP/Aware: histogramMeasurementDurationWithAware[1]",
log.histogramMeasurementDurationWithAware[1], 8 * 1000, Integer.MAX_VALUE, 1);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[0]",
log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 7);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[0]",
log.rttToAp.histogramDistance[0], Integer.MIN_VALUE, 0, 3);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[1]",
log.rttToAp.histogramDistance[1], 0, 5 * 1000, 2);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[2]",
log.rttToAp.histogramDistance[2], 5 * 1000, 15 * 1000, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[3]",
log.rttToAp.histogramDistance[3], 30 * 1000, 60 * 1000, 1);
checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 1, 4, 0);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]",
log.rttToAware.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS,
16);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[0]",
log.rttToAware.histogramDistance[0], 5 * 1000, 15 * 1000, 3);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[1]",
log.rttToAware.histogramDistance[1], 30 * 1000, 60 * 1000, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[2]",
log.rttToAware.histogramDistance[2], 60 * 1000, 100 * 1000, 2);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[3]",
log.rttToAware.histogramDistance[3], 100 * 1000, Integer.MAX_VALUE, 10);
}
/**
* Verify the behavior when the HAL returns with missing results or some results set to null.
*/
@Test
public void testRecordMissingResults() {
WifiMetricsProto.WifiRttLog log;
mDut.clear();
RangingRequest requestMixed25 = getDummyRangingRequest(2, 5);
List<RangingResult> resultMixed25 = getDummyRangingResults(
RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, requestMixed25, 10, 30);
// remove some results
resultMixed25.remove(3); // Second Aware result: distance = 100
resultMixed25.remove(0); // First AP result: distance = 10
resultMixed25.add(null);
mDut.recordResult(requestMixed25, resultMixed25, 0);
log = mDut.consolidateProto();
checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 0, 1);
checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 2, 1, 0);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[0]",
log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 1);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[1]",
log.rttToAp.histogramIndividualStatus[1],
WifiMetricsProto.WifiRttLog.MISSING_RESULT, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAp.histogramDistance[0]",
log.rttToAp.histogramDistance[0], 30 * 1000, 60 * 1000, 1);
checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 2, 2, 0);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]",
log.rttToAware.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS,
4);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[1]",
log.rttToAware.histogramIndividualStatus[1],
WifiMetricsProto.WifiRttLog.MISSING_RESULT, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[0]",
log.rttToAware.histogramDistance[0], 60 * 1000, 100 * 1000, 1);
validateProtoHistBucket("Sequence Mixed AP/Aware: rttToAware.histogramDistance[1]",
log.rttToAware.histogramDistance[1], 100 * 1000, Integer.MAX_VALUE, 3);
}
/**
* Verify the behavior when the HAL returns with NULL array.
*/
@Test
public void testRecordNullArrayResults() {
WifiMetricsProto.WifiRttLog log;
mDut.clear();
RangingRequest requestMixed25 = getDummyRangingRequest(2, 5);
mDut.recordResult(requestMixed25, null, 0);
log = mDut.consolidateProto();
checkMainStats("Sequence Mixed AP/Aware", log, 0, 0, 0, 0);
checkPeerStats("Sequence Mixed AP/Aware: AP", log.rttToAp, 0, 0, 0, 0, 0, 1, 0, 0);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAp.histogramIndividualStatus[1]",
log.rttToAp.histogramIndividualStatus[0],
WifiMetricsProto.WifiRttLog.MISSING_RESULT, 2);
checkPeerStats("Sequence Mixed AP/Aware: Aware", log.rttToAware, 0, 0, 0, 0, 0, 1, 0, 0);
validateProtoIndividualStatusHistBucket(
"Sequence Mixed AP/Aware: rttToAware.histogramIndividualStatus[0]",
log.rttToAware.histogramIndividualStatus[0],
WifiMetricsProto.WifiRttLog.MISSING_RESULT, 5);
}
/**
* Verify that all individual status codes are translated correctly.
*/
@Test
public void testRecordResultsStatuses() {
WifiMetricsProto.WifiRttLog log;
mDut.clear();
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_SUCCESS, 5);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAILURE, 6);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_RSP, 7);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_REJECTED, 8);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NOT_SCHEDULED_YET, 9);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_TM_TIMEOUT, 10);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL, 11);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_NO_CAPABILITY, 12);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_ABORTED, 13);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_INVALID_TS, 14);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_PROTOCOL, 15);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_SCHEDULE, 16);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_BUSY_TRY_LATER, 17);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_INVALID_REQ, 18);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_NO_WIFI, 19);
recordResultNTimes(RttNative.FRAMEWORK_RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE, 20);
log = mDut.consolidateProto();
collector.checkThat("AP histogramIndividualStatus.length",
log.rttToAp.histogramIndividualStatus.length, equalTo(16));
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[0]",
log.rttToAp.histogramIndividualStatus[0], WifiMetricsProto.WifiRttLog.SUCCESS, 5);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[1]",
log.rttToAp.histogramIndividualStatus[1], WifiMetricsProto.WifiRttLog.FAILURE, 6);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[2]",
log.rttToAp.histogramIndividualStatus[2], WifiMetricsProto.WifiRttLog.FAIL_NO_RSP,
7);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[3]",
log.rttToAp.histogramIndividualStatus[3], WifiMetricsProto.WifiRttLog.FAIL_REJECTED,
8);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[4]",
log.rttToAp.histogramIndividualStatus[4],
WifiMetricsProto.WifiRttLog.FAIL_NOT_SCHEDULED_YET, 9);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[5]",
log.rttToAp.histogramIndividualStatus[5],
WifiMetricsProto.WifiRttLog.FAIL_TM_TIMEOUT, 10);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[6]",
log.rttToAp.histogramIndividualStatus[6],
WifiMetricsProto.WifiRttLog.FAIL_AP_ON_DIFF_CHANNEL, 11);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[7]",
log.rttToAp.histogramIndividualStatus[7],
WifiMetricsProto.WifiRttLog.FAIL_NO_CAPABILITY, 12);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[8]",
log.rttToAp.histogramIndividualStatus[8], WifiMetricsProto.WifiRttLog.ABORTED, 13);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[9]",
log.rttToAp.histogramIndividualStatus[9],
WifiMetricsProto.WifiRttLog.FAIL_INVALID_TS, 14);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[10]",
log.rttToAp.histogramIndividualStatus[10],
WifiMetricsProto.WifiRttLog.FAIL_PROTOCOL, 15);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[11]",
log.rttToAp.histogramIndividualStatus[11],
WifiMetricsProto.WifiRttLog.FAIL_SCHEDULE, 16);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[12]",
log.rttToAp.histogramIndividualStatus[12],
WifiMetricsProto.WifiRttLog.FAIL_BUSY_TRY_LATER, 17);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[13]",
log.rttToAp.histogramIndividualStatus[13], WifiMetricsProto.WifiRttLog.INVALID_REQ,
18);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[14]",
log.rttToAp.histogramIndividualStatus[14], WifiMetricsProto.WifiRttLog.NO_WIFI, 19);
validateProtoIndividualStatusHistBucket("rttToAp.histogramIndividualStatus[15]",
log.rttToAp.histogramIndividualStatus[15],
WifiMetricsProto.WifiRttLog.FAIL_FTM_PARAM_OVERRIDE, 20);
collector.checkThat("Aware histogramIndividualStatus.length",
log.rttToAware.histogramIndividualStatus.length, equalTo(0));
}
/**
* Verify that all overall status codes are recorded correctly.
*/
@Test
public void testRecordOverallStatus() {
WifiMetricsProto.WifiRttLog log;
mDut.clear();
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS, 5);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_FAIL, 6);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE, 7);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT, 8);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE, 9);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE, 10);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE,
11);
recordOverallStatusNTimes(WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING,
12);
log = mDut.consolidateProto();
collector.checkThat("histogramOverallStatus.length", log.histogramOverallStatus.length,
equalTo(8));
validateProtoOverallStatusHistBucket("histogramOverallStatus[0]",
log.histogramOverallStatus[0], WifiMetricsProto.WifiRttLog.OVERALL_SUCCESS, 5);
validateProtoOverallStatusHistBucket("histogramOverallStatus[1]",
log.histogramOverallStatus[1], WifiMetricsProto.WifiRttLog.OVERALL_FAIL, 6);
validateProtoOverallStatusHistBucket("histogramOverallStatus[2]",
log.histogramOverallStatus[2],
WifiMetricsProto.WifiRttLog.OVERALL_RTT_NOT_AVAILABLE, 7);
validateProtoOverallStatusHistBucket("histogramOverallStatus[3]",
log.histogramOverallStatus[3], WifiMetricsProto.WifiRttLog.OVERALL_TIMEOUT, 8);
validateProtoOverallStatusHistBucket("histogramOverallStatus[4]",
log.histogramOverallStatus[4], WifiMetricsProto.WifiRttLog.OVERALL_THROTTLE, 9);
validateProtoOverallStatusHistBucket("histogramOverallStatus[5]",
log.histogramOverallStatus[5], WifiMetricsProto.WifiRttLog.OVERALL_HAL_FAILURE, 10);
validateProtoOverallStatusHistBucket("histogramOverallStatus[6]",
log.histogramOverallStatus[6],
WifiMetricsProto.WifiRttLog.OVERALL_AWARE_TRANSLATION_FAILURE, 11);
validateProtoOverallStatusHistBucket("histogramOverallStatus[7]",
log.histogramOverallStatus[7],
WifiMetricsProto.WifiRttLog.OVERALL_LOCATION_PERMISSION_MISSING, 12);
}
// Utilities
/**
* Mock the elapsed time since boot to the input argument.
*/
private void setTime(long timeMs) {
when(mClock.getElapsedSinceBootMillis()).thenReturn(timeMs);
}
private void validateProtoHistBucket(String logPrefix,
WifiMetricsProto.WifiRttLog.HistogramBucket bucket, long start, long end, int count) {
collector.checkThat(logPrefix + ": start", bucket.start, equalTo(start));
collector.checkThat(logPrefix + ": end", bucket.end, equalTo(end));
collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count));
}
private void validateProtoOverallStatusHistBucket(String logPrefix,
WifiMetricsProto.WifiRttLog.RttOverallStatusHistogramBucket bucket, int status,
int count) {
collector.checkThat(logPrefix + ": statusType", bucket.statusType, equalTo(status));
collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count));
}
private void validateProtoIndividualStatusHistBucket(String logPrefix,
WifiMetricsProto.WifiRttLog.RttIndividualStatusHistogramBucket bucket, int status,
int count) {
collector.checkThat(logPrefix + ": statusType", bucket.statusType, equalTo(status));
collector.checkThat(logPrefix + ": count", bucket.count, equalTo(count));
}
private void checkMainStats(String msgPrefix, WifiMetricsProto.WifiRttLog log, int numRequests,
int histogramOverallStatusLength, int histogramMeasurementDurationApOnlyLength,
int histogramMeasurementDurationWithAwareLength) {
collector.checkThat(msgPrefix + ": numRequests", log.numRequests, equalTo(numRequests));
collector.checkThat(msgPrefix + ": histogramOverallStatus.length",
log.histogramOverallStatus.length,
equalTo(histogramOverallStatusLength));
collector.checkThat(msgPrefix + ": histogramMeasurementDurationApOnly.length",
log.histogramMeasurementDurationApOnly.length,
equalTo(histogramMeasurementDurationApOnlyLength));
collector.checkThat(msgPrefix + ": histogramMeasurementDurationWithAware.length",
log.histogramMeasurementDurationWithAware.length,
equalTo(histogramMeasurementDurationWithAwareLength));
}
private void checkPeerStats(String msgPrefix, WifiMetricsProto.WifiRttLog.RttToPeerLog log,
int numRequests, int numIndividualRequests,
int numApps, int histogramNumRequestsPerAppLength,
int histogramNumPeersPerRequestLength, int histogramIndividualStatusLength,
int histogramDistanceLength, int histogramRequestIntervalMsLength) {
collector.checkThat(msgPrefix + ": numRequests", log.numRequests, equalTo(numRequests));
collector.checkThat(msgPrefix + ": numIndividualRequests", log.numIndividualRequests,
equalTo(numIndividualRequests));
collector.checkThat(msgPrefix + ": numApps", log.numApps, equalTo(numApps));
collector.checkThat(msgPrefix + ": histogramNumRequestsPerApp.length",
log.histogramNumRequestsPerApp.length, equalTo(histogramNumRequestsPerAppLength));
collector.checkThat(msgPrefix + ": histogramNumPeersPerRequest.length",
log.histogramNumPeersPerRequest.length, equalTo(histogramNumPeersPerRequestLength));
collector.checkThat(msgPrefix + ": histogramIndividualStatus.length",
log.histogramIndividualStatus.length, equalTo(histogramIndividualStatusLength));
collector.checkThat(msgPrefix + ": histogramDistance.length",
log.histogramDistance.length, equalTo(histogramDistanceLength));
collector.checkThat(msgPrefix + ": histogramRequestIntervalMs.length",
log.histogramRequestIntervalMs.length, equalTo(histogramRequestIntervalMsLength));
}
private RangingRequest getDummyRangingRequest(int countAp, int countAware) {
RangingRequest.Builder builder = new RangingRequest.Builder();
byte[] placeholderMacBase = {0x0, 0x1, 0x2, 0x3, 0x4, 0x5};
for (int i = 0; i < countAp; ++i) {
placeholderMacBase[0]++;
builder.addResponder(new ResponderConfig(MacAddress.fromBytes(placeholderMacBase),
ResponderConfig.RESPONDER_AP, true, 0, 0, 0, 0, 0));
}
for (int i = 0; i < countAware; ++i) {
placeholderMacBase[0]++;
builder.addResponder(new ResponderConfig(MacAddress.fromBytes(placeholderMacBase),
ResponderConfig.RESPONDER_AWARE, true, 0, 0, 0, 0, 0));
}
return builder.build();
}
private List<RangingResult> getDummyRangingResults(int status, RangingRequest request,
double baseDistanceM, double incrDistanceM) {
List<RangingResult> rangingResults = new ArrayList<>();
double distance = baseDistanceM;
for (ResponderConfig peer : request.mRttPeers) {
RangingResult rttResult = new RangingResult(status, peer.macAddress,
(int) (distance * 1000), 0, 0, 8, 8, null, null, null, 0, true);
distance += incrDistanceM;
rangingResults.add(rttResult);
}
return rangingResults;
}
private void recordResultNTimes(int status, int n) {
RangingRequest request = getDummyRangingRequest(1, 0);
List<RangingResult> results = getDummyRangingResults(status, request, 0, 0);
for (int i = 0; i < n; ++i) {
mDut.recordResult(request, results, 0);
}
}
private void recordOverallStatusNTimes(int status, int n) {
for (int i = 0; i < n; ++i) {
mDut.recordOverallStatus(status);
}
}
private void dumpDut(String prefix) {
StringWriter sw = new StringWriter();
mDut.dump(null, new PrintWriter(sw), null);
Log.e("RttMetrics", prefix + sw.toString());
}
}