/*
 * 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 android.net.wifi.rtt.cts;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;

import android.net.MacAddress;
import android.net.wifi.ScanResult;
import android.net.wifi.aware.PeerHandle;
import android.net.wifi.cts.WifiBuildCompat;
import android.net.wifi.cts.WifiFeature;
import android.net.wifi.rtt.RangingRequest;
import android.net.wifi.rtt.RangingResult;
import android.net.wifi.rtt.ResponderConfig;
import android.net.wifi.rtt.ResponderLocation;
import android.platform.test.annotations.AppModeFull;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;

import com.android.compatibility.common.util.DeviceReportLog;
import com.android.compatibility.common.util.ResultType;
import com.android.compatibility.common.util.ResultUnit;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Wi-Fi RTT CTS test: range to all available Access Points which support IEEE 802.11mc.
 */
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@LargeTest
@RunWith(AndroidJUnit4.class)
public class WifiRttTest extends TestBase {
    // Number of scans to do while searching for APs supporting IEEE 802.11mc
    private static final int NUM_SCANS_SEARCHING_FOR_IEEE80211MC_AP = 5;

    // Number of RTT measurements per AP
    private static final int NUM_OF_RTT_ITERATIONS = 10;

    // Maximum failure rate of RTT measurements (percentage)
    private static final int MAX_FAILURE_RATE_PERCENT = 20;

    // Maximum variation from the average measurement (measures consistency)
    private static final int MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM = 2000;

    // Maximum failure rate of one-sided RTT measurements (percentage)
    private static final int MAX_NON11MC_FAILURE_RATE_PERCENT = 40;

    // Maximum non-8011mc variation from the average measurement (measures consistency)
    private static final int MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM = 4000;

    // Minimum valid RSSI value
    private static final int MIN_VALID_RSSI = -100;

    // Valid Mac Address
    private static final MacAddress MAC = MacAddress.fromString("00:01:02:03:04:05");

    // Interval between two ranging request.
    private static final int INTERVAL_MS = 1000;

    /**
     * Test Wi-Fi RTT ranging operation using ScanResults in request:
     * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc)
     * - Perform N (constant) RTT operations
     * - Validate:
     *   - Failure ratio < threshold (constant)
     *   - Result margin < threshold (constant)
     */
    @Test
    public void testRangingToTest11mcApUsingScanResult() throws InterruptedException {
        // Scan for IEEE 802.11mc supporting APs
        ScanResult testAp = getS11McScanResult();
        assertNotNull(
                "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that "
                        + "your test setup includes them!", testAp);
        // Perform RTT operations
        RangingRequest.Builder builder = new RangingRequest.Builder();
        builder.addAccessPoint(testAp);

        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
            assertTrue(RangingRequest.getDefaultRttBurstSize()
                    >= RangingRequest.getMinRttBurstSize());
            assertTrue(RangingRequest.getDefaultRttBurstSize()
                    <= RangingRequest.getMaxRttBurstSize());
        }

        RangingRequest request = builder.build();
        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            assertEquals(1, request.getRttResponders().size());
        }
        range11mcApRequest(request, testAp);
    }

    /**
     * Test Wi-Fi RTT ranging using ResponderConfig in the single responder RangingRequest API.
     * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc)
     * - Perform N (constant) RTT operations
     * - Validate:
     *   - Failure ratio < threshold (constant)
     *   - Result margin < threshold (constant)
     */
    @Test
    public void testRangingToTest11mcApUsingResponderConfig() throws InterruptedException {
        // Scan for IEEE 802.11mc supporting APs
        ScanResult testAp = getS11McScanResult();
        assertNotNull(
                "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that "
                        + "your test setup includes them!", testAp);
        int preamble = ResponderConfig.fromScanResult(testAp).getPreamble();

        // Create a ResponderConfig from the builder API.
        ResponderConfig.Builder responderBuilder = new ResponderConfig.Builder();
        ResponderConfig responder = responderBuilder
                .setMacAddress(MacAddress.fromString(testAp.BSSID))
                .set80211mcSupported(testAp.is80211mcResponder())
                .setChannelWidth(testAp.channelWidth)
                .setFrequencyMhz(testAp.frequency)
                .setCenterFreq0Mhz(testAp.centerFreq0)
                .setCenterFreq1Mhz(testAp.centerFreq1)
                .setPreamble(preamble)
                .build();

        // Validate ResponderConfig.Builder set method arguments match getter methods.
        assertTrue(responder.getMacAddress().toString().equalsIgnoreCase(testAp.BSSID)
                        && responder.is80211mcSupported() == testAp.is80211mcResponder()
                        && responder.getChannelWidth() == testAp.channelWidth
                        && responder.getFrequencyMhz() == testAp.frequency
                        && responder.getCenterFreq0Mhz() == testAp.centerFreq0
                        && responder.getCenterFreq1Mhz() == testAp.centerFreq1
                        && responder.getPreamble() == preamble);

        // Perform RTT operations
        RangingRequest.Builder builder = new RangingRequest.Builder();
        builder.addResponder(responder);

        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
            assertTrue(RangingRequest.getDefaultRttBurstSize()
                    >= RangingRequest.getMinRttBurstSize());
            assertTrue(RangingRequest.getDefaultRttBurstSize()
                    <= RangingRequest.getMaxRttBurstSize());
        }

        RangingRequest request = builder.build();

        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            assertEquals(1, request.getRttResponders().size());
        }
        range11mcApRequest(request, testAp);
    }

    /**
     * Test Wi-Fi RTT ranging using ResponderConfig in the multi-Responder RangingRequest API.
     * - Scan for visible APs for the test AP (which is validated to support IEEE 802.11mc)
     * - Perform N (constant) RTT operations
     * - Validate:
     *   - Failure ratio < threshold (constant)
     *   - Result margin < threshold (constant)
     */
    @Test
    public void testRangingToTest11mcApUsingListResponderConfig() throws InterruptedException {
        // Scan for IEEE 802.11mc supporting APs
        ScanResult testAp = getS11McScanResult();
        assertNotNull(
                "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that "
                        + "your test setup includes them!", testAp);
        ResponderConfig responder = ResponderConfig.fromScanResult(testAp);
        // Perform RTT operations
        RangingRequest.Builder builder = new RangingRequest.Builder();
        List<ResponderConfig> responders = new ArrayList<>();
        responders.add(responder);
        builder.addResponders(responders);

        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
            assertTrue(RangingRequest.getDefaultRttBurstSize()
                    >= RangingRequest.getMinRttBurstSize());
            assertTrue(RangingRequest.getDefaultRttBurstSize()
                    <= RangingRequest.getMaxRttBurstSize());
        }

        RangingRequest request = builder.build();

        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            assertEquals(1, request.getRttResponders().size());
        }
        range11mcApRequest(request, testAp);
    }

    /**
     * Utility method for validating a ranging request.
     *
     * @param request the ranging request that is being tested
     * @param testAp the original test scan result to provide feedback on failure conditions
     */
    private void range11mcApRequest(RangingRequest request, ScanResult testAp)
            throws InterruptedException {
        Thread.sleep(5000);
        List<RangingResult> allResults = new ArrayList<>();
        int numFailures = 0;
        int distanceSum = 0;
        int distanceMin = 0;
        int distanceMax = 0;
        int[] statuses = new int[NUM_OF_RTT_ITERATIONS];
        int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS];
        int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS];
        int[] rssis = new int[NUM_OF_RTT_ITERATIONS];
        int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS];
        int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS];
        long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS];
        byte[] lastLci = null;
        byte[] lastLcr = null;
        for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) {
            ResultCallback callback = new ResultCallback();
            mWifiRttManager.startRanging(request, mExecutor, callback);
            assertTrue("Wi-Fi RTT results: no callback on iteration " + i,
                    callback.waitForCallback());

            List<RangingResult> currentResults = callback.getResults();
            assertNotNull("Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i,
                    currentResults);
            assertEquals("Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i,
                    1, currentResults.size());
            RangingResult result = currentResults.get(0);
            assertEquals("Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i,
                    result.getMacAddress().toString(), testAp.BSSID);
            assertNull("Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration "
                    + i, result.getPeerHandle());

            allResults.add(result);
            int status = result.getStatus();
            statuses[i] = status;
            if (status == RangingResult.STATUS_SUCCESS) {
                if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
                    assertEquals(
                            "Wi-Fi RTT results: invalid result (wrong rttBurstSize) entry on "
                                    + "iteration "
                                    + i,
                            result.getNumAttemptedMeasurements(),
                            RangingRequest.getMaxRttBurstSize());
                    assertTrue("Wi-Fi RTT results: should be a 802.11MC measurement",
                            result.is80211mcMeasurement());
                }
                distanceSum += result.getDistanceMm();
                if (i == 0) {
                    distanceMin = result.getDistanceMm();
                    distanceMax = result.getDistanceMm();
                } else {
                    distanceMin = Math.min(distanceMin, result.getDistanceMm());
                    distanceMax = Math.max(distanceMax, result.getDistanceMm());
                }

                assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i,
                        result.getRssi() >= MIN_VALID_RSSI);

                distanceMms[i - numFailures] = result.getDistanceMm();
                distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm();
                rssis[i - numFailures] = result.getRssi();
                numAttempted[i - numFailures] = result.getNumAttemptedMeasurements();
                numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements();
                timestampsMs[i - numFailures] = result.getRangingTimestampMillis();

                byte[] currentLci = result.getLci();
                byte[] currentLcr = result.getLcr();
                if (i - numFailures > 0) {
                    assertArrayEquals(
                            "Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i,
                            currentLci, lastLci);
                    assertArrayEquals(
                            "Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i,
                            currentLcr, lastLcr);
                }
                lastLci = currentLci;
                lastLcr = currentLcr;
            } else {
                numFailures++;
            }
            // Sleep a while to avoid stress AP.
            Thread.sleep(INTERVAL_MS);
        }

        // Save results to log
        int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures;
        DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp");
        reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("distance_stddev_mm", Arrays.copyOf(distanceStdDevMms, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults), ResultType.NEUTRAL,
                ResultUnit.NONE);
        reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.submit();

        // Analyze results
        assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures + ", ITERATIONS="
                        + NUM_OF_RTT_ITERATIONS + ", AP=" + testAp,
                numFailures <= NUM_OF_RTT_ITERATIONS * MAX_FAILURE_RATE_PERCENT / 100);
        if (numFailures != NUM_OF_RTT_ITERATIONS) {
            double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
            assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation ="
                            + (distanceMax - distanceAvg),
                    (distanceMax - distanceAvg) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
            assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation ="
                            + (distanceAvg - distanceMin),
                    (distanceAvg - distanceMin) <= MAX_VARIATION_FROM_AVERAGE_DISTANCE_MM);
            for (int i = 0; i < numGoodResults; ++i) {
                assertNotEquals("Number of attempted measurements is 0", 0, numAttempted[i]);
                assertNotEquals("Number of successful measurements is 0", 0, numSuccessful[i]);
            }
        }
    }



    /**
     * Validate that when a request contains more range operations than allowed (by API) that we
     * get an exception.
     */
    @Test
    public void testRequestTooLarge() throws InterruptedException {
        ScanResult testAp = getS11McScanResult();
        assertNotNull(
                "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that "
                        + "your test setup includes them!", testAp);

        RangingRequest.Builder builder = new RangingRequest.Builder();
        List<ScanResult> scanResults = new ArrayList<>();
        for (int i = 0; i < RangingRequest.getMaxPeers() - 2; ++i) {
            scanResults.add(testAp);
        }
        builder.addAccessPoints(scanResults);

        ScanResult testApNon80211mc = null;
        if (WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            testApNon80211mc = getNone11McScanResult();
        }
        if (testApNon80211mc == null) {
            builder.addAccessPoints(List.of(testAp, testAp, testAp));
        } else {
            builder.addNon80211mcCapableAccessPoints(List.of(testApNon80211mc, testApNon80211mc,
                    testApNon80211mc));
        }

        try {
            mWifiRttManager.startRanging(builder.build(), mExecutor, new ResultCallback());
        } catch (IllegalArgumentException e) {
            return;
        }

        fail("Did not receive expected IllegalArgumentException when tried to range to too "
                + "many peers");
    }

    /**
     * Verify ResponderLocation API
     */
    @Test
    public void testRangingToTestApWithResponderLocation() throws InterruptedException {
        // Scan for IEEE 802.11mc supporting APs
        ScanResult testAp = getS11McScanResult();
        assertNotNull(
                "Cannot find any test APs which support RTT / IEEE 802.11mc - please verify that "
                        + "your test setup includes them!", testAp);

        // Perform RTT operations
        RangingRequest request = new RangingRequest.Builder().addAccessPoint(testAp).build();
        ResultCallback callback = new ResultCallback();
        mWifiRttManager.startRanging(request, mExecutor, callback);
        assertTrue("Wi-Fi RTT results: no callback! ",
                callback.waitForCallback());

        RangingResult result = callback.getResults().get(0);
        assertEquals("Ranging request not success",
                result.getStatus(), RangingResult.STATUS_SUCCESS);
        ResponderLocation responderLocation = result.getUnverifiedResponderLocation();
        if (responderLocation == null) {
            return;
        }
        assertTrue("ResponderLocation is not valid", responderLocation.isLciSubelementValid());

        // Check LCI related APIs
        int exceptionCount = 0;
        int apiCount = 0;
        try {
            apiCount++;
            responderLocation.getLatitudeUncertainty();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getLatitude();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getLongitudeUncertainty();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getLongitude();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getAltitudeType();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getAltitudeUncertainty();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getAltitude();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getDatum();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getRegisteredLocationAgreementIndication();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            responderLocation.getLciVersion();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        try {
            apiCount++;
            assertNotNull(responderLocation.toLocation());
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        // If LCI is not valid, all APIs should throw exception, otherwise no exception.
        assertEquals("Exception number should equal to API number",
                responderLocation.isLciSubelementValid()? 0 : apiCount, exceptionCount);

        // Verify ZaxisSubelement APIs
        apiCount = 0;
        exceptionCount = 0;

        try {
            apiCount++;
            responderLocation.getExpectedToMove();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }

        try {
            apiCount++;
            responderLocation.getFloorNumber();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }

        try {
            apiCount++;
            responderLocation.getHeightAboveFloorMeters();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }

        try {
            apiCount++;
            responderLocation.getHeightAboveFloorUncertaintyMeters();
        } catch (IllegalStateException e) {
            exceptionCount++;
        }
        // If Zaxis is not valid, all APIs should throw exception, otherwise no exception.
        assertEquals("Exception number should equal to API number",
                responderLocation.isZaxisSubelementValid() ? 0 : apiCount, exceptionCount);
        // Verify civic location
        if (responderLocation.toCivicLocationAddress() == null) {
            assertNull(responderLocation.toCivicLocationSparseArray());
        } else {
            assertNotNull(responderLocation.toCivicLocationSparseArray());
        }
        // Verify map image
        if (responderLocation.getMapImageUri() == null) {
            assertNull(responderLocation.getMapImageMimeType());
        } else {
            assertNotNull(responderLocation.getMapImageMimeType());
        }
        boolean extraInfoOnAssociationIndication =
                responderLocation.getExtraInfoOnAssociationIndication();
        assertNotNull("ColocatedBSSID list should be nonNull",
                responderLocation.getColocatedBssids());
    }

    /**
     * Verify ranging request with aware peer Mac address and peer handle.
     */
    @Test
    public void testAwareRttWithMacAddress() throws InterruptedException {
        if (!WifiFeature.isAwareSupported(getContext())) {
            return;
        }
        RangingRequest request = new RangingRequest.Builder()
                .addWifiAwarePeer(MAC).build();
        ResultCallback callback = new ResultCallback();
        mWifiRttManager.startRanging(request, mExecutor, callback);
        assertTrue("Wi-Fi RTT results: no callback",
                callback.waitForCallback());
        List<RangingResult> rangingResults = callback.getResults();
        assertNotNull("Wi-Fi RTT results: null results", rangingResults);
        assertEquals(1, rangingResults.size());
        assertEquals(RangingResult.STATUS_FAIL, rangingResults.get(0).getStatus());
    }

    /**
     * Verify ranging request with aware peer handle.
     */
    @Test
    public void testAwareRttWithPeerHandle() throws InterruptedException {
        if (!WifiFeature.isAwareSupported(getContext())) {
            return;
        }
        PeerHandle peerHandle = mock(PeerHandle.class);
        RangingRequest request = new RangingRequest.Builder()
                .addWifiAwarePeer(peerHandle).build();
        ResultCallback callback = new ResultCallback();
        mWifiRttManager.startRanging(request, mExecutor, callback);
        assertTrue("Wi-Fi RTT results: no callback",
                callback.waitForCallback());
        List<RangingResult> rangingResults = callback.getResults();
        assertNotNull("Wi-Fi RTT results: null results", rangingResults);
        assertEquals("Invalid peerHandle should return 0 result", 0, rangingResults.size());
    }

    /**
     * Test Wi-Fi One-sided RTT ranging operation using ScanResult in request:
     * - Scan for visible APs for the test AP (which do not support IEEE 802.11mc) and are operating
     * - in the 5GHz band.
     * - Perform N (constant) RTT operations
     * - Remove outliers while insuring greater than 50% of the results still remain
     * - Validate:
     *   - Failure ratio < threshold (constant)
     *   - Result margin < threshold (constant)
     */
    @Test
    public void testRangingToTestNon11mcApUsingScanResult() throws InterruptedException {
        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            return;
        }

        // Scan for Non-IEEE 802.11mc supporting APs
        ScanResult testAp = getNone11McScanResult();
        assertNotNull(
                "Cannot find any test APs which are Non-IEEE 802.11mc - please verify that"
                        + " your test setup includes them!", testAp);

        // Perform RTT operations
        RangingRequest.Builder builder = new RangingRequest.Builder();
        builder.addNon80211mcCapableAccessPoint(testAp);
        builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
        RangingRequest request = builder.build();

        // Perform the request
        rangeNon11mcApRequest(request, testAp, MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM);
    }

    /**
     * Test Wi-Fi one-sided RTT ranging operation using ResponderConfig in request:
     * - Scan for visible APs for the test AP (which do not support IEEE 802.11mc) and are operating
     * - in the 5GHz band.
     * - Perform N (constant) RTT operations
     * - Remove outliers while insuring greater than 50% of the results still remain
     * - Validate:
     *   - Failure ratio < threshold (constant)
     *   - Result margin < threshold (constant)
     */
    @Test
    public void testRangingToTestNon11mcApUsingResponderConfig() throws InterruptedException {
        if (!WifiBuildCompat.isPlatformOrWifiModuleAtLeastS(getContext())) {
            return;
        }

        // Scan for Non-IEEE 802.11mc supporting APs
        ScanResult testAp = getNone11McScanResult();
        assertNotNull(
                "Cannot find any test APs which are Non-IEEE 802.11mc - please verify that"
                        + " your test setup includes them!", testAp);

        ResponderConfig responder = ResponderConfig.fromScanResult(testAp);

        // Perform RTT operations
        RangingRequest.Builder builder = new RangingRequest.Builder();
        builder.addResponder(responder);
        builder.setRttBurstSize(RangingRequest.getMaxRttBurstSize());
        RangingRequest request = builder.build();



        // Perform the request
        rangeNon11mcApRequest(request, testAp, MAX_NON11MC_VARIATION_FROM_AVERAGE_DISTANCE_MM);
    }

    /**
     * Utility method for validating a ranging request to a non-80211mc AP.
     *
     * @param request the ranging request that is being tested
     * @param testAp the original test scan result to provide feedback on failure conditions
     */
    private void rangeNon11mcApRequest(RangingRequest request, ScanResult testAp,
            int variationLimit) throws InterruptedException {
        Thread.sleep(5000);
        List<RangingResult> allResults = new ArrayList<>();
        int numFailures = 0;
        int distanceSum = 0;
        int distanceMin = 0;
        int distanceMax = 0;
        int[] statuses = new int[NUM_OF_RTT_ITERATIONS];
        int[] distanceMms = new int[NUM_OF_RTT_ITERATIONS];
        boolean[] distanceInclusionMap = new boolean[NUM_OF_RTT_ITERATIONS];
        int[] distanceStdDevMms = new int[NUM_OF_RTT_ITERATIONS];
        int[] rssis = new int[NUM_OF_RTT_ITERATIONS];
        int[] numAttempted = new int[NUM_OF_RTT_ITERATIONS];
        int[] numSuccessful = new int[NUM_OF_RTT_ITERATIONS];
        long[] timestampsMs = new long[NUM_OF_RTT_ITERATIONS];
        byte[] lastLci = null;
        byte[] lastLcr = null;
        for (int i = 0; i < NUM_OF_RTT_ITERATIONS; ++i) {
            ResultCallback callback = new ResultCallback();
            mWifiRttManager.startRanging(request, mExecutor, callback);
            assertTrue("Wi-Fi RTT results: no callback on iteration " + i,
                    callback.waitForCallback());

            List<RangingResult> currentResults = callback.getResults();
            assertNotNull(
                    "Wi-Fi RTT results: null results (onRangingFailure) on iteration " + i,
                    currentResults);
            assertEquals(
                    "Wi-Fi RTT results: unexpected # of results (expect 1) on iteration " + i,
                    1, currentResults.size());
            RangingResult result = currentResults.get(0);
            assertEquals(
                    "Wi-Fi RTT results: invalid result (wrong BSSID) entry on iteration " + i,
                    result.getMacAddress().toString(), testAp.BSSID);

            assertNull(
                    "Wi-Fi RTT results: invalid result (non-null PeerHandle) entry on iteration "
                            + i, result.getPeerHandle());

            allResults.add(result);
            int status = result.getStatus();
            statuses[i] = status;
            if (status == RangingResult.STATUS_SUCCESS) {
                assertFalse("Wi-Fi RTT results: should not be a 802.11MC measurement",
                        result.is80211mcMeasurement());
                distanceSum += result.getDistanceMm();

                assertTrue("Wi-Fi RTT results: invalid RSSI on iteration " + i,
                        result.getRssi() >= MIN_VALID_RSSI);

                distanceMms[i - numFailures] = result.getDistanceMm();
                distanceStdDevMms[i - numFailures] = result.getDistanceStdDevMm();
                rssis[i - numFailures] = result.getRssi();
                // For one-sided RTT the number of packets attempted in a burst is not available,
                // So we set the result to be the same as used in the request.
                numAttempted[i - numFailures] = request.getRttBurstSize();
                numSuccessful[i - numFailures] = result.getNumSuccessfulMeasurements();
                timestampsMs[i - numFailures] = result.getRangingTimestampMillis();

                byte[] currentLci = result.getLci();
                byte[] currentLcr = result.getLcr();
                if (i - numFailures > 0) {
                    assertArrayEquals(
                            "Wi-Fi RTT results: invalid result (LCI mismatch) on iteration " + i,
                            currentLci, lastLci);
                    assertArrayEquals(
                            "Wi-Fi RTT results: invalid result (LCR mismatch) on iteration " + i,
                            currentLcr, lastLcr);
                }
                lastLci = currentLci;
                lastLcr = currentLcr;
            } else {
                numFailures++;
            }
            // Sleep a while to avoid stress AP.
            Thread.sleep(INTERVAL_MS);
        }
        // Save results to log
        int numGoodResults = NUM_OF_RTT_ITERATIONS - numFailures;
        DeviceReportLog reportLog = new DeviceReportLog(TAG, "testRangingToTestAp");
        reportLog.addValues("status_codes", statuses, ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("distance_mm", Arrays.copyOf(distanceMms, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("distance_stddev_mm",
                Arrays.copyOf(distanceStdDevMms, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("rssi_dbm", Arrays.copyOf(rssis, numGoodResults),
                ResultType.NEUTRAL,
                ResultUnit.NONE);
        reportLog.addValues("num_attempted", Arrays.copyOf(numAttempted, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("num_successful", Arrays.copyOf(numSuccessful, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.addValues("timestamps", Arrays.copyOf(timestampsMs, numGoodResults),
                ResultType.NEUTRAL, ResultUnit.NONE);
        reportLog.submit();

        /** TODO(b/237011062): enable the performance verification new API to check capabilities
         // Analyze results
        assertTrue("Wi-Fi RTT failure rate exceeds threshold: FAIL=" + numFailures
                        + ", ITERATIONS="
                        + NUM_OF_RTT_ITERATIONS + ", AP=" + testAp,
                numFailures <= NUM_OF_RTT_ITERATIONS * MAX_NON11MC_FAILURE_RATE_PERCENT / 100);
         */

        if (numFailures != NUM_OF_RTT_ITERATIONS) {
            // Calculate an initial average using all measurements to determine distance outliers
            double distanceAvg = (double) distanceSum / (NUM_OF_RTT_ITERATIONS - numFailures);
            // Now figure out the distance outliers and mark them in the distance inclusion map
            int validDistances = 0;
            for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
                if (distanceMms[i] - variationLimit < distanceAvg) {
                    // Distances that are in range for the distribution are included in the map
                    distanceInclusionMap[i] = true;
                    validDistances++;
                } else {
                    // Distances that are out of range for the distribution are excluded in the map
                    distanceInclusionMap[i] = false;
                }
            }

            assertTrue("After fails+outlier removal greater that 50% distances must remain: "
                    + NUM_OF_RTT_ITERATIONS / 2, validDistances > NUM_OF_RTT_ITERATIONS / 2);

            // Remove the distance outliers and find the new average, min and max.
            distanceSum = 0;
            distanceMax = Integer.MIN_VALUE;
            distanceMin = Integer.MAX_VALUE;
            for (int i = 0; i < (NUM_OF_RTT_ITERATIONS - numFailures); i++) {
                if (distanceInclusionMap[i]) {
                    distanceSum += distanceMms[i];
                    distanceMin = Math.min(distanceMin, distanceMms[i]);
                    distanceMax = Math.max(distanceMax, distanceMms[i]);
                }
            }
            distanceAvg = (double) distanceSum / validDistances;
            assertTrue("Wi-Fi RTT: Variation (max direction) exceeds threshold, Variation ="
                            + (distanceMax - distanceAvg),
                    (distanceMax - distanceAvg) <= variationLimit);
            assertTrue("Wi-Fi RTT: Variation (min direction) exceeds threshold, Variation ="
                            + (distanceAvg - distanceMin),
                    (distanceAvg - distanceMin) <= variationLimit);
            for (int i = 0; i < numGoodResults; ++i) {
                assertNotEquals("Number of attempted measurements is 0", 0, numAttempted[i]);
                assertNotEquals("Number of successful measurements is 0", 0, numSuccessful[i]);
            }
        }

    }
}
