/*
 * 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]);
            }
        }

    }
}
