diff options
| -rw-r--r-- | wifi/java/android/net/wifi/ScanResult.java | 70 | ||||
| -rw-r--r-- | wifi/tests/src/android/net/wifi/ScanResultTest.java | 193 |
2 files changed, 263 insertions, 0 deletions
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index b6ad92614bfe..eaad137b9b6e 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -21,7 +21,9 @@ import android.os.Parcel; import android.os.Parcelable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Objects; /** * Describes information about a detected access point. In addition @@ -227,6 +229,50 @@ public class ScanResult implements Parcelable { public long seen; /** + * On devices with multiple hardware radio chains, this class provides metadata about + * each radio chain that was used to receive this scan result (probe response or beacon). + * {@hide} + */ + public static class RadioChainInfo { + /** Vendor defined id for a radio chain. */ + public int id; + /** Detected signal level in dBm (also known as the RSSI) on this radio chain. */ + public int level; + + @Override + public String toString() { + return "RadioChainInfo: id=" + id + ", level=" + level; + } + + @Override + public boolean equals(Object otherObj) { + if (this == otherObj) { + return true; + } + if (!(otherObj instanceof RadioChainInfo)) { + return false; + } + RadioChainInfo other = (RadioChainInfo) otherObj; + return id == other.id && level == other.level; + } + + @Override + public int hashCode() { + return Objects.hash(id, level); + } + }; + + /** + * Information about the list of the radio chains used to receive this scan result + * (probe response or beacon). + * + * For Example: On devices with 2 hardware radio chains, this list could hold 1 or 2 + * entries based on whether this scan result was received using one or both the chains. + * {@hide} + */ + public RadioChainInfo[] radioChainInfos; + + /** * @hide * Update RSSI of the scan result * @param previousRssi @@ -481,6 +527,7 @@ public class ScanResult implements Parcelable { this.isCarrierAp = false; this.carrierApEapType = UNSPECIFIED; this.carrierName = null; + this.radioChainInfos = null; } /** {@hide} */ @@ -502,6 +549,7 @@ public class ScanResult implements Parcelable { this.isCarrierAp = false; this.carrierApEapType = UNSPECIFIED; this.carrierName = null; + this.radioChainInfos = null; } /** {@hide} */ @@ -530,6 +578,7 @@ public class ScanResult implements Parcelable { this.isCarrierAp = false; this.carrierApEapType = UNSPECIFIED; this.carrierName = null; + this.radioChainInfos = null; } /** {@hide} */ @@ -572,6 +621,7 @@ public class ScanResult implements Parcelable { isCarrierAp = source.isCarrierAp; carrierApEapType = source.carrierApEapType; carrierName = source.carrierName; + radioChainInfos = source.radioChainInfos; } } @@ -615,6 +665,7 @@ public class ScanResult implements Parcelable { sb.append(", Carrier AP: ").append(isCarrierAp ? "yes" : "no"); sb.append(", Carrier AP EAP Type: ").append(carrierApEapType); sb.append(", Carrier name: ").append(carrierName); + sb.append(", Radio Chain Infos: ").append(Arrays.toString(radioChainInfos)); return sb.toString(); } @@ -687,6 +738,16 @@ public class ScanResult implements Parcelable { dest.writeInt(isCarrierAp ? 1 : 0); dest.writeInt(carrierApEapType); dest.writeString(carrierName); + + if (radioChainInfos != null) { + dest.writeInt(radioChainInfos.length); + for (int i = 0; i < radioChainInfos.length; i++) { + dest.writeInt(radioChainInfos[i].id); + dest.writeInt(radioChainInfos[i].level); + } + } else { + dest.writeInt(0); + } } /** Implement the Parcelable interface {@hide} */ @@ -759,6 +820,15 @@ public class ScanResult implements Parcelable { sr.isCarrierAp = in.readInt() != 0; sr.carrierApEapType = in.readInt(); sr.carrierName = in.readString(); + n = in.readInt(); + if (n != 0) { + sr.radioChainInfos = new RadioChainInfo[n]; + for (int i = 0; i < n; i++) { + sr.radioChainInfos[i] = new RadioChainInfo(); + sr.radioChainInfos[i].id = in.readInt(); + sr.radioChainInfos[i].level = in.readInt(); + } + } return sr; } diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java new file mode 100644 index 000000000000..689ebbafe527 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java @@ -0,0 +1,193 @@ +/* + * 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; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.validateMockitoUsage; + +import android.os.Parcel; +import android.test.suitebuilder.annotation.SmallTest; +import android.net.wifi.WifiScanner.ScanSettings; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockitoAnnotations; + + +/** + * Unit tests for {@link android.net.wifi.WifiScanner}. + */ +@SmallTest +public class ScanResultTest { + public static final String TEST_SSID = "\"test_ssid\""; + public static final String TEST_BSSID = "04:ac:fe:45:34:10"; + public static final String TEST_CAPS = "CCMP"; + public static final int TEST_LEVEL = -56; + public static final int TEST_FREQUENCY = 2412; + public static final long TEST_TSF = 04660l; + + /** + * Setup before tests. + */ + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + } + + /** + * Clean up after tests. + */ + @After + public void cleanup() { + validateMockitoUsage(); + } + + /** + * Verify parcel read/write for ScanResult. + */ + @Test + public void verifyScanResultParcelWithoutRadioChainInfo() throws Exception { + ScanResult writeScanResult = createScanResult(); + ScanResult readScanResult = parcelReadWrite(writeScanResult); + assertScanResultEquals(writeScanResult, readScanResult); + } + + /** + * Verify parcel read/write for ScanResult. + */ + @Test + public void verifyScanResultParcelWithZeroRadioChainInfo() throws Exception { + ScanResult writeScanResult = createScanResult(); + writeScanResult.radioChainInfos = new ScanResult.RadioChainInfo[0]; + ScanResult readScanResult = parcelReadWrite(writeScanResult); + assertNull(readScanResult.radioChainInfos); + } + + /** + * Verify parcel read/write for ScanResult. + */ + @Test + public void verifyScanResultParcelWithRadioChainInfo() throws Exception { + ScanResult writeScanResult = createScanResult(); + writeScanResult.radioChainInfos = new ScanResult.RadioChainInfo[2]; + writeScanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo(); + writeScanResult.radioChainInfos[0].id = 0; + writeScanResult.radioChainInfos[0].level = -45; + writeScanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo(); + writeScanResult.radioChainInfos[1].id = 1; + writeScanResult.radioChainInfos[1].level = -54; + ScanResult readScanResult = parcelReadWrite(writeScanResult); + assertScanResultEquals(writeScanResult, readScanResult); + } + + /** + * Verify copy constructor for ScanResult. + */ + @Test + public void verifyScanResultCopyWithoutRadioChainInfo() throws Exception { + ScanResult scanResult = createScanResult(); + ScanResult copyScanResult = new ScanResult(scanResult); + assertScanResultEquals(scanResult, copyScanResult); + } + + /** + * Verify copy constructor for ScanResult. + */ + @Test + public void verifyScanResultCopyWithRadioChainInfo() throws Exception { + ScanResult scanResult = createScanResult(); + scanResult.radioChainInfos = new ScanResult.RadioChainInfo[2]; + scanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo(); + scanResult.radioChainInfos[0].id = 0; + scanResult.radioChainInfos[0].level = -45; + scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo(); + scanResult.radioChainInfos[1].id = 1; + scanResult.radioChainInfos[1].level = -54; + ScanResult copyScanResult = new ScanResult(scanResult); + assertScanResultEquals(scanResult, copyScanResult); + } + + /** + * Verify toString for ScanResult. + */ + @Test + public void verifyScanResultToStringWithoutRadioChainInfo() throws Exception { + ScanResult scanResult = createScanResult(); + assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " + + "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), distanceSd: 0(cm), " + + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " + + "80211mcResponder: is not supported, Carrier AP: no, " + + "Carrier AP EAP Type: 0, Carrier name: null, " + + "Radio Chain Infos: null", scanResult.toString()); + } + + /** + * Verify toString for ScanResult. + */ + @Test + public void verifyScanResultToStringWithRadioChainInfo() throws Exception { + ScanResult scanResult = createScanResult(); + scanResult.radioChainInfos = new ScanResult.RadioChainInfo[2]; + scanResult.radioChainInfos[0] = new ScanResult.RadioChainInfo(); + scanResult.radioChainInfos[0].id = 0; + scanResult.radioChainInfos[0].level = -45; + scanResult.radioChainInfos[1] = new ScanResult.RadioChainInfo(); + scanResult.radioChainInfos[1].id = 1; + scanResult.radioChainInfos[1].level = -54; + assertEquals("SSID: \"test_ssid\", BSSID: 04:ac:fe:45:34:10, capabilities: CCMP, " + + "level: -56, frequency: 2412, timestamp: 2480, distance: 0(cm), distanceSd: 0(cm), " + + "passpoint: no, ChannelBandwidth: 0, centerFreq0: 0, centerFreq1: 0, " + + "80211mcResponder: is not supported, Carrier AP: no, " + + "Carrier AP EAP Type: 0, Carrier name: null, " + + "Radio Chain Infos: [RadioChainInfo: id=0, level=-45, " + + "RadioChainInfo: id=1, level=-54]", scanResult.toString()); + } + + /** + * Write the provided {@link ScanResult} to a parcel and deserialize it. + */ + private static ScanResult parcelReadWrite(ScanResult writeResult) throws Exception { + Parcel parcel = Parcel.obtain(); + writeResult.writeToParcel(parcel, 0); + parcel.setDataPosition(0); // Rewind data position back to the beginning for read. + return ScanResult.CREATOR.createFromParcel(parcel); + } + + private static ScanResult createScanResult() { + ScanResult result = new ScanResult(); + result.wifiSsid = WifiSsid.createFromAsciiEncoded(TEST_SSID); + result.BSSID = TEST_BSSID; + result.capabilities = TEST_CAPS; + result.level = TEST_LEVEL; + result.frequency = TEST_FREQUENCY; + result.timestamp = TEST_TSF; + return result; + } + + private static void assertScanResultEquals(ScanResult expected, ScanResult actual) { + assertEquals(expected.SSID, actual.SSID); + assertEquals(expected.BSSID, actual.BSSID); + assertEquals(expected.capabilities, actual.capabilities); + assertEquals(expected.level, actual.level); + assertEquals(expected.frequency, actual.frequency); + assertEquals(expected.timestamp, actual.timestamp); + assertArrayEquals(expected.radioChainInfos, actual.radioChainInfos); + } +} |