summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiao Ma <xiaom@google.com>2020-01-30 17:00:05 +0900
committerXiao Ma <xiaom@google.com>2020-02-10 21:11:04 +0900
commitc3a28323623f0ff3b98ab15e61141437a0fee90b (patch)
tree74465ab500597d71c265b40414c54d38fadc66b7
parent738b6c361469af87d6eaa20680184bf5ef8dded4 (diff)
Add ScanResultInfo object in ProvisioningConfiguration parcel.
Since wifi.ScanResult doesn't implement specific equals() yet, for comparing the ProvisioningConfiguration object better, this change encapuslates ScanResult#SSID and ScanResult#InformationElement member into a new class: ScanResultInfo inside ProvisioningConfiguration. Adding ScanResultInfo object in ProvisioningConfiguration parcelable is to check the InformationElement filed when starting IpClient and detect whether or not the specific OUI is included in the IEs. Bug: 137835398 Test: atest FrameworksNetTests NetworkStackTests NetworkStackNextTests Change-Id: I247ac7f343ef3e99b64b93b45549e2a25980a407
-rw-r--r--common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java182
-rw-r--r--common/networkstackclient/Android.bp3
-rw-r--r--common/networkstackclient/src/android/net/InformationElementParcelable.aidl22
-rw-r--r--common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl2
-rw-r--r--common/networkstackclient/src/android/net/ScanResultInfoParcelable.aidl24
-rw-r--r--tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java27
6 files changed, 257 insertions, 3 deletions
diff --git a/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java b/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
index 00b4e19..7de376a 100644
--- a/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
+++ b/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
@@ -16,14 +16,25 @@
package android.net.shared;
+import static android.net.shared.ParcelableUtil.fromParcelableArray;
+import static android.net.shared.ParcelableUtil.toParcelableArray;
+
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.INetd;
+import android.net.InformationElementParcelable;
import android.net.Network;
import android.net.ProvisioningConfigurationParcelable;
+import android.net.ScanResultInfoParcelable;
import android.net.StaticIpConfiguration;
import android.net.apf.ApfCapabilities;
import android.net.ip.IIpClient;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
@@ -193,6 +204,17 @@ public class ProvisioningConfiguration {
}
/**
+ * Specify the information elements included in wifi scan result that was obtained
+ * prior to connecting to the access point, if this is a WiFi network.
+ *
+ * <p>The scan result can be used to infer whether the network is metered.
+ */
+ public Builder withScanResultInfo(ScanResultInfo scanResultInfo) {
+ mConfig.mScanResultInfo = scanResultInfo;
+ return this;
+ }
+
+ /**
* Build the configuration using previously specified parameters.
*/
public ProvisioningConfiguration build() {
@@ -200,6 +222,158 @@ public class ProvisioningConfiguration {
}
}
+ /**
+ * Class wrapper of {@link android.net.wifi.ScanResult} to encapsulate the SSID and
+ * InformationElements fields of ScanResult.
+ */
+ public static class ScanResultInfo {
+ private final String mSsid;
+ private final List<InformationElement> mInformationElements;
+
+ /**
+ * Class wrapper of {@link android.net.wifi.ScanResult.InformationElement} to encapsulate
+ * the specific IE id and payload fields.
+ */
+ public static class InformationElement {
+ private final int mId;
+ private final byte[] mPayload;
+
+ public InformationElement(int id, @NonNull ByteBuffer payload) {
+ mId = id;
+ mPayload = convertToByteArray(payload.asReadOnlyBuffer());
+ }
+
+ /**
+ * Get the element ID of the information element.
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * Get the specific content of the information element.
+ */
+ public ByteBuffer getPayload() {
+ return ByteBuffer.wrap(mPayload).asReadOnlyBuffer();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof InformationElement)) return false;
+ InformationElement other = (InformationElement) o;
+ return mId == other.mId && Arrays.equals(mPayload, other.mPayload);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mId, mPayload);
+ }
+
+ @Override
+ public String toString() {
+ return "ID: " + mId + ", " + Arrays.toString(mPayload);
+ }
+
+ /**
+ * Convert this InformationElement to a {@link InformationElementParcelable}.
+ */
+ public InformationElementParcelable toStableParcelable() {
+ final InformationElementParcelable p = new InformationElementParcelable();
+ p.id = mId;
+ p.payload = mPayload.clone();
+ return p;
+ }
+
+ /**
+ * Create an instance of {@link InformationElement} based on the contents of the
+ * specified {@link InformationElementParcelable}.
+ */
+ public static InformationElement fromStableParcelable(InformationElementParcelable p) {
+ if (p == null) return null;
+ return new InformationElement(p.id,
+ ByteBuffer.wrap(p.payload.clone()).asReadOnlyBuffer());
+ }
+ }
+
+ public ScanResultInfo(String ssid, @NonNull List<InformationElement> informationElements) {
+ mSsid = ssid;
+ mInformationElements =
+ Collections.unmodifiableList(new ArrayList<>(informationElements));
+ }
+
+ /**
+ * Get the scanned network name.
+ */
+ public String getSsid() {
+ return mSsid;
+ }
+
+ /**
+ * Get all information elements found in the beacon.
+ */
+ public List<InformationElement> getInformationElements() {
+ return mInformationElements;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer str = new StringBuffer();
+ str.append("SSID: ").append(mSsid);
+ str.append(", Information Elements: {");
+ for (InformationElement ie : mInformationElements) {
+ str.append("[").append(ie.toString()).append("]");
+ }
+ str.append("}");
+ return str.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof ScanResultInfo)) return false;
+ ScanResultInfo other = (ScanResultInfo) o;
+ return Objects.equals(mSsid, other.mSsid)
+ && mInformationElements.equals(other.mInformationElements);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSsid, mInformationElements);
+ }
+
+ /**
+ * Convert this ScanResultInfo to a {@link ScanResultInfoParcelable}.
+ */
+ public ScanResultInfoParcelable toStableParcelable() {
+ final ScanResultInfoParcelable p = new ScanResultInfoParcelable();
+ p.ssid = mSsid;
+ p.informationElements = toParcelableArray(mInformationElements,
+ InformationElement::toStableParcelable, InformationElementParcelable.class);
+ return p;
+ }
+
+ /**
+ * Create an instance of {@link ScanResultInfo} based on the contents of the specified
+ * {@link ScanResultInfoParcelable}.
+ */
+ public static ScanResultInfo fromStableParcelable(ScanResultInfoParcelable p) {
+ if (p == null) return null;
+ final List<InformationElement> ies = new ArrayList<InformationElement>();
+ ies.addAll(fromParcelableArray(p.informationElements,
+ InformationElement::fromStableParcelable));
+ return new ScanResultInfo(p.ssid, ies);
+ }
+
+ private static byte[] convertToByteArray(final ByteBuffer buffer) {
+ if (buffer == null) return null;
+ byte[] bytes = new byte[buffer.limit()];
+ final ByteBuffer copy = buffer.asReadOnlyBuffer();
+ copy.get(bytes);
+ return bytes;
+ }
+ }
+
public boolean mEnableIPv4 = true;
public boolean mEnableIPv6 = true;
public boolean mEnablePreconnection = false;
@@ -213,6 +387,7 @@ public class ProvisioningConfiguration {
public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
public Network mNetwork = null;
public String mDisplayName = null;
+ public ScanResultInfo mScanResultInfo;
public ProvisioningConfiguration() {} // used by Builder
@@ -232,6 +407,7 @@ public class ProvisioningConfiguration {
mIPv6AddrGenMode = other.mIPv6AddrGenMode;
mNetwork = other.mNetwork;
mDisplayName = other.mDisplayName;
+ mScanResultInfo = other.mScanResultInfo;
}
/**
@@ -254,6 +430,7 @@ public class ProvisioningConfiguration {
p.ipv6AddrGenMode = mIPv6AddrGenMode;
p.network = mNetwork;
p.displayName = mDisplayName;
+ p.scanResultInfo = mScanResultInfo == null ? null : mScanResultInfo.toStableParcelable();
return p;
}
@@ -279,6 +456,7 @@ public class ProvisioningConfiguration {
config.mIPv6AddrGenMode = p.ipv6AddrGenMode;
config.mNetwork = p.network;
config.mDisplayName = p.displayName;
+ config.mScanResultInfo = ScanResultInfo.fromStableParcelable(p.scanResultInfo);
return config;
}
@@ -298,6 +476,7 @@ public class ProvisioningConfiguration {
.add("mIPv6AddrGenMode: " + mIPv6AddrGenMode)
.add("mNetwork: " + mNetwork)
.add("mDisplayName: " + mDisplayName)
+ .add("mScanResultInfo: " + mScanResultInfo)
.toString();
}
@@ -317,7 +496,8 @@ public class ProvisioningConfiguration {
&& mProvisioningTimeoutMs == other.mProvisioningTimeoutMs
&& mIPv6AddrGenMode == other.mIPv6AddrGenMode
&& Objects.equals(mNetwork, other.mNetwork)
- && Objects.equals(mDisplayName, other.mDisplayName);
+ && Objects.equals(mDisplayName, other.mDisplayName)
+ && Objects.equals(mScanResultInfo, other.mScanResultInfo);
}
public boolean isValid() {
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
index 31f3384..dbe8ff0 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -45,6 +45,7 @@ aidl_interface {
include_dirs: [
"frameworks/base/core/java", // For framework parcelables.
"frameworks/native/aidl/binder/android/os", // For PersistableBundle.aidl
+ "frameworks/base/wifi/aidl-export", // For wifi parcelables.
],
srcs: [
"src/android/net/DhcpResultsParcelable.aidl",
@@ -53,10 +54,12 @@ aidl_interface {
"src/android/net/INetworkStackConnector.aidl",
"src/android/net/INetworkStackStatusCallback.aidl",
"src/android/net/InitialConfigurationParcelable.aidl",
+ "src/android/net/InformationElementParcelable.aidl",
"src/android/net/Layer2PacketParcelable.aidl",
"src/android/net/NattKeepalivePacketDataParcelable.aidl",
"src/android/net/PrivateDnsConfigParcel.aidl",
"src/android/net/ProvisioningConfigurationParcelable.aidl",
+ "src/android/net/ScanResultInfoParcelable.aidl",
"src/android/net/TcpKeepalivePacketDataParcelable.aidl",
"src/android/net/dhcp/DhcpServingParamsParcel.aidl",
"src/android/net/dhcp/IDhcpServer.aidl",
diff --git a/common/networkstackclient/src/android/net/InformationElementParcelable.aidl b/common/networkstackclient/src/android/net/InformationElementParcelable.aidl
new file mode 100644
index 0000000..c70bf6f
--- /dev/null
+++ b/common/networkstackclient/src/android/net/InformationElementParcelable.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2020 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;
+
+parcelable InformationElementParcelable {
+ int id;
+ byte[] payload;
+}
diff --git a/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
index 0b6d7d5..9fcb036 100644
--- a/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
+++ b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
@@ -19,6 +19,7 @@ package android.net;
import android.net.InitialConfigurationParcelable;
import android.net.Network;
+import android.net.ScanResultInfoParcelable;
import android.net.StaticIpConfiguration;
import android.net.apf.ApfCapabilities;
@@ -36,4 +37,5 @@ parcelable ProvisioningConfigurationParcelable {
Network network;
String displayName;
boolean enablePreconnection;
+ ScanResultInfoParcelable scanResultInfo;
}
diff --git a/common/networkstackclient/src/android/net/ScanResultInfoParcelable.aidl b/common/networkstackclient/src/android/net/ScanResultInfoParcelable.aidl
new file mode 100644
index 0000000..f5f101d
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ScanResultInfoParcelable.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.net.InformationElementParcelable;
+
+parcelable ScanResultInfoParcelable {
+ String ssid;
+ InformationElementParcelable[] informationElements;
+}
diff --git a/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java b/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
index e645a2c..e9384c8 100644
--- a/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
+++ b/tests/unit/src/android/net/shared/ProvisioningConfigurationTest.java
@@ -28,6 +28,7 @@ import android.net.LinkAddress;
import android.net.Network;
import android.net.StaticIpConfiguration;
import android.net.apf.ApfCapabilities;
+import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -36,6 +37,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.nio.ByteBuffer;
+import java.util.Collections;
import java.util.function.Consumer;
/**
@@ -46,6 +49,17 @@ import java.util.function.Consumer;
public class ProvisioningConfigurationTest {
private ProvisioningConfiguration mConfig;
+ private ScanResultInfo makeScanResultInfo(final String ssid) {
+ final byte[] payload = new byte[] {
+ (byte) 0x00, (byte) 0x17, (byte) 0xF2, (byte) 0x06, (byte) 0x01,
+ (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+ };
+ final ScanResultInfo.InformationElement ie =
+ new ScanResultInfo.InformationElement(0xdd /* vendor specific IE id */,
+ ByteBuffer.wrap(payload));
+ return new ScanResultInfo(ssid, Collections.singletonList(ie));
+ }
+
@Before
public void setUp() {
mConfig = new ProvisioningConfiguration();
@@ -67,8 +81,9 @@ public class ProvisioningConfigurationTest {
mConfig.mNetwork = new Network(321);
mConfig.mDisplayName = "test_config";
mConfig.mEnablePreconnection = false;
+ mConfig.mScanResultInfo = makeScanResultInfo("ssid");
// Any added field must be included in equals() to be tested properly
- assertFieldCountEquals(13, ProvisioningConfiguration.class);
+ assertFieldCountEquals(14, ProvisioningConfiguration.class);
}
@Test
@@ -101,6 +116,12 @@ public class ProvisioningConfigurationTest {
}
@Test
+ public void testParcelUnparcel_NullScanResultInfo() {
+ mConfig.mScanResultInfo = null;
+ doParcelUnparcelTest();
+ }
+
+ @Test
public void testParcelUnparcel_WithPreDhcpConnection() {
mConfig.mEnablePreconnection = true;
doParcelUnparcelTest();
@@ -136,7 +157,9 @@ public class ProvisioningConfigurationTest {
assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test");
assertNotEqualsAfterChange(c -> c.mDisplayName = null);
assertNotEqualsAfterChange(c -> c.mEnablePreconnection = true);
- assertFieldCountEquals(13, ProvisioningConfiguration.class);
+ assertNotEqualsAfterChange(c -> c.mScanResultInfo = null);
+ assertNotEqualsAfterChange(c -> c.mScanResultInfo = makeScanResultInfo("another ssid"));
+ assertFieldCountEquals(14, ProvisioningConfiguration.class);
}
private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) {