Snap for 5925869 from 3c9f687c97393a15d238a3272f62c595052e6b2e to sdk-release
Change-Id: I2aa3beab9ab9e716851c4b8e15d24f99af49774d
diff --git a/Android.bp b/Android.bp
index 9ba4f98..5c6ca9b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,25 +14,58 @@
// limitations under the License.
//
-java_library {
- name: "captiveportal-lib",
- srcs: ["common/**/*.java"],
- libs: [
- "androidx.annotation_annotation",
- ],
- sdk_version: "system_current",
-}
+// The network stack can be compiled using system_current (non-finalized) SDK, or finalized system_X
+// SDK. There is also a variant that uses system_current SDK and runs in the system process
+// (InProcessNetworkStack). The following structure is used to create the build rules:
+//
+// NetworkStackAndroidLibraryDefaults <-- common defaults for android libs
+// / \
+// +NetworkStackApiStableShims --> / \ <-- +NetworkStackApiCurrentShims
+// +NetworkStackApiStableLevel / \ +NetworkStackApiCurrentLevel
+// / \
+// NetworkStackApiStableLib NetworkStackApiCurrentLib <-- android libs w/ all code
+// | | (also used in unit tests)
+// | <-- +NetworkStackAppDefaults --> |
+// | (APK build params) |
+// | |
+// | <-- +NetworkStackApiStableLevel | <-- +NetworkStackApiCurrentLevel
+// | |
+// | |
+// NetworkStackApiStable NetworkStack, InProcessNetworkStack, <-- output APKs
+// TestNetworkStack
+// Common defaults to define SDK level
java_defaults {
- name: "NetworkStackCommon",
+ name: "NetworkStackApiCurrentLevel",
sdk_version: "system_current",
min_sdk_version: "28",
}
-// Library including the network stack, used to compile both variants of the network stack
-android_library {
- name: "NetworkStackBase",
- defaults: ["NetworkStackCommon"],
+java_defaults {
+ name: "NetworkStackApiStableLevel",
+ sdk_version: "system_current", // TODO: change to system_29
+ min_sdk_version: "28",
+}
+
+// Java libraries for the API shims
+filegroup {
+ name: "NetworkStackApiCurrentShims",
+ srcs: [
+ "apishim/current/**/*.java"
+ ],
+}
+
+filegroup {
+ name: "NetworkStackApiStableShims",
+ srcs: [
+ "apishim/29/**/*.java"
+ ],
+}
+
+// Common defaults for android libraries containing network stack code, used to compile variants of
+// the network stack in the system process and in the network_stack process
+java_defaults {
+ name: "NetworkStackAndroidLibraryDefaults",
srcs: [
"src/**/*.java",
":framework-networkstack-shared-srcs",
@@ -41,9 +74,8 @@
],
static_libs: [
"androidx.annotation_annotation",
- "ipmemorystore-client",
"netd_aidl_interface-V2-java",
- "networkstack-aidl-interfaces-V3-java",
+ "networkstack-client",
"datastallprotosnano",
"networkstackprotosnano",
"captiveportal-lib",
@@ -51,6 +83,85 @@
manifest: "AndroidManifestBase.xml",
}
+// The versions of the android library containing network stack code compiled for each SDK variant
+android_library {
+ name: "NetworkStackApiCurrentLib",
+ defaults: ["NetworkStackApiCurrentLevel", "NetworkStackAndroidLibraryDefaults"],
+ srcs: [
+ ":NetworkStackApiCurrentShims",
+ ],
+}
+
+android_library {
+ name: "NetworkStackApiStableLib",
+ defaults: ["NetworkStackApiStableLevel", "NetworkStackAndroidLibraryDefaults"],
+ srcs: [
+ ":NetworkStackApiStableShims",
+ ],
+}
+
+// Common defaults for compiling the actual APK, based on the NetworkStackApiXBase android libraries
+java_defaults {
+ name: "NetworkStackAppDefaults",
+ privileged: true,
+ jni_libs: [
+ "libnativehelper_compat_libc++",
+ "libnetworkstackutilsjni",
+ ],
+ // Resources already included in NetworkStackBase
+ resource_dirs: [],
+ jarjar_rules: "jarjar-rules-shared.txt",
+ use_embedded_native_libs: true,
+ optimize: {
+ proguard_flags_files: ["proguard.flags"],
+ },
+}
+
+// Non-updatable network stack running in the system server process for devices not using the module
+android_app {
+ name: "InProcessNetworkStack",
+ defaults: [ "NetworkStackAppDefaults", "NetworkStackApiCurrentLevel"],
+ static_libs: ["NetworkStackApiCurrentLib"],
+ certificate: "platform",
+ manifest: "AndroidManifest_InProcess.xml",
+ // InProcessNetworkStack is a replacement for NetworkStack
+ overrides: ["NetworkStack"],
+ // The permission configuration *must* be included to ensure security of the device
+ // The InProcessNetworkStack goes together with the PlatformCaptivePortalLogin, which replaces
+ // the default CaptivePortalLogin.
+ required: ["PlatformNetworkPermissionConfig", "PlatformCaptivePortalLogin"],
+}
+
+// Updatable network stack packaged as an application
+android_app {
+ name: "NetworkStack",
+ defaults: ["NetworkStackAppDefaults", "NetworkStackApiCurrentLevel"],
+ static_libs: ["NetworkStackApiCurrentLib"],
+ certificate: "networkstack",
+ manifest: "AndroidManifest.xml",
+ // The permission configuration *must* be included to ensure security of the device
+ required: ["NetworkPermissionConfig"],
+}
+
+// Updatable network stack for finalized API
+android_app {
+ name: "NetworkStackApiStable",
+ defaults: ["NetworkStackAppDefaults", "NetworkStackApiStableLevel"],
+ static_libs: ["NetworkStackApiStableLib"],
+ certificate: "networkstack",
+ manifest: "AndroidManifest.xml",
+ // The permission configuration *must* be included to ensure security of the device
+ required: ["NetworkPermissionConfig"],
+}
+
+// Android library to derive test APKs for integration tests
+android_library {
+ name: "TestNetworkStackLib",
+ defaults: ["NetworkStackAppDefaults", "NetworkStackApiCurrentLevel"],
+ static_libs: ["NetworkStackApiCurrentLib"],
+ manifest: "AndroidManifest.xml",
+}
+
cc_library_shared {
name: "libnetworkstackutilsjni",
srcs: [
@@ -81,50 +192,6 @@
],
}
-java_defaults {
- name: "NetworkStackAppCommon",
- defaults: ["NetworkStackCommon"],
- privileged: true,
- static_libs: [
- "NetworkStackBase",
- ],
- jni_libs: [
- "libnativehelper_compat_libc++",
- "libnetworkstackutilsjni",
- ],
- // Resources already included in NetworkStackBase
- resource_dirs: [],
- jarjar_rules: "jarjar-rules-shared.txt",
- optimize: {
- proguard_flags_files: ["proguard.flags"],
- },
-}
-
-// Non-updatable network stack running in the system server process for devices not using the module
-android_app {
- name: "InProcessNetworkStack",
- defaults: ["NetworkStackAppCommon"],
- certificate: "platform",
- manifest: "AndroidManifest_InProcess.xml",
- // InProcessNetworkStack is a replacement for NetworkStack
- overrides: ["NetworkStack"],
- // The permission configuration *must* be included to ensure security of the device
- // The InProcessNetworkStack goes together with the PlatformCaptivePortalLogin, which replaces
- // the default CaptivePortalLogin.
- required: ["PlatformNetworkPermissionConfig", "PlatformCaptivePortalLogin"],
-}
-
-// Updatable network stack packaged as an application
-android_app {
- name: "NetworkStack",
- defaults: ["NetworkStackAppCommon"],
- certificate: "networkstack",
- manifest: "AndroidManifest.xml",
- use_embedded_native_libs: true,
- // The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
-}
-
genrule {
name: "statslog-networkstack-java-gen",
tools: ["stats-log-api-gen"],
@@ -142,11 +209,10 @@
android_app {
name: "TestNetworkStack",
- defaults: ["NetworkStackAppCommon"],
+ defaults: ["NetworkStackAppDefaults", "NetworkStackApiCurrentLevel"],
+ static_libs: ["NetworkStackApiCurrentLib"],
certificate: "networkstack",
manifest: ":NetworkStackTestAndroidManifest",
- use_embedded_native_libs: true,
// The permission configuration *must* be included to ensure security of the device
required: ["NetworkPermissionConfig"],
}
-
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index bb838a2..249e510 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -17,9 +17,13 @@
*/
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack"
- android:sharedUserId="android.uid.networkstack">
- <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+ package="com.android.networkstack"
+ android:sharedUserId="android.uid.networkstack"
+ android:versionCode="290000000"
+ android:versionName="2019-09"
+>
+
+ <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
<!-- Permissions must be defined here, and not in the base manifest, as the network stack
running in the system server process does not need any permission, and having privileged
@@ -39,8 +43,10 @@
<uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
<application
android:extractNativeLibs="false"
- android:persistent="true">
- <service android:name="com.android.server.NetworkStackService">
+ android:persistent="true"
+ android:process="com.android.networkstack.process">
+ <service android:name="com.android.server.NetworkStackService"
+ android:permission="android.permission.MAINLINE_NETWORK_STACK">
<intent-filter>
<action android:name="android.net.INetworkStackConnector"/>
</intent-filter>
diff --git a/AndroidManifest_InProcess.xml b/AndroidManifest_InProcess.xml
index 2778a2a..723df09 100644
--- a/AndroidManifest_InProcess.xml
+++ b/AndroidManifest_InProcess.xml
@@ -22,7 +22,9 @@
android:process="system">
<uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
<application>
- <service android:name="com.android.server.NetworkStackService" android:process="system">
+ <service android:name="com.android.server.NetworkStackService"
+ android:process="system"
+ android:permission="android.permission.MAINLINE_NETWORK_STACK">
<intent-filter>
<action android:name="android.net.INetworkStackConnector.InProcess"/>
</intent-filter>
diff --git a/apishim/29/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/29/com/android/networkstack/apishim/SocketUtilsShimImpl.java
new file mode 100644
index 0000000..0e41e19
--- /dev/null
+++ b/apishim/29/com/android/networkstack/apishim/SocketUtilsShimImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.net.util.SocketUtils;
+
+import androidx.annotation.NonNull;
+
+import java.net.SocketAddress;
+
+/**
+ * Implementation of SocketUtilsShim for API 29.
+ */
+public class SocketUtilsShimImpl implements SocketUtilsShim {
+ @NonNull
+ @Override
+ public SocketAddress makePacketSocketAddress(
+ int protocol, int ifIndex, @NonNull byte[] hwAddr) {
+ // Not available for API <= 29: fallback to older behavior.
+ return SocketUtils.makePacketSocketAddress(ifIndex, hwAddr);
+ }
+}
diff --git a/apishim/current/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/current/com/android/networkstack/apishim/SocketUtilsShimImpl.java
new file mode 100644
index 0000000..92f8438
--- /dev/null
+++ b/apishim/current/com/android/networkstack/apishim/SocketUtilsShimImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import android.net.util.SocketUtils;
+
+import androidx.annotation.NonNull;
+
+import java.net.SocketAddress;
+
+/**
+ * Implementation of {@link SocketUtilsShim} for API 30.
+ */
+public class SocketUtilsShimImpl implements SocketUtilsShim {
+ @NonNull
+ @Override
+ public SocketAddress makePacketSocketAddress(
+ int protocol, int ifIndex, @NonNull byte[] hwAddr) {
+ // TODO: use new API (which takes protocol, ifIndex, hwAddr) once implemented
+ return SocketUtils.makePacketSocketAddress(ifIndex, hwAddr);
+ }
+}
diff --git a/common/captiveportal/Android.bp b/common/captiveportal/Android.bp
new file mode 100644
index 0000000..d34ab85
--- /dev/null
+++ b/common/captiveportal/Android.bp
@@ -0,0 +1,24 @@
+//
+// 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.
+//
+
+java_library {
+ name: "captiveportal-lib",
+ srcs: ["src/**/*.java"],
+ libs: [
+ "androidx.annotation_annotation",
+ ],
+ sdk_version: "system_current",
+}
\ No newline at end of file
diff --git a/common/CaptivePortalProbeResult.java b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
similarity index 100%
rename from common/CaptivePortalProbeResult.java
rename to common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
diff --git a/common/CaptivePortalProbeSpec.java b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeSpec.java
similarity index 100%
rename from common/CaptivePortalProbeSpec.java
rename to common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeSpec.java
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
new file mode 100644
index 0000000..ccb3f45
--- /dev/null
+++ b/common/networkstackclient/Android.bp
@@ -0,0 +1,92 @@
+//
+// 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.
+//
+
+// AIDL interfaces between the core system and the networking mainline module.
+aidl_interface {
+ name: "ipmemorystore-aidl-interfaces",
+ local_include_dir: "src",
+ srcs: [
+ "src/android/net/IIpMemoryStore.aidl",
+ "src/android/net/IIpMemoryStoreCallbacks.aidl",
+ "src/android/net/ipmemorystore/**/*.aidl",
+ ],
+ backend: {
+ ndk: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+ api_dir: "aidl/ipmemorystore",
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
+}
+
+aidl_interface {
+ name: "networkstack-aidl-interfaces",
+ local_include_dir: "src",
+ include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
+ srcs: [
+ "src/android/net/DhcpResultsParcelable.aidl",
+ "src/android/net/INetworkMonitor.aidl",
+ "src/android/net/INetworkMonitorCallbacks.aidl",
+ "src/android/net/INetworkStackConnector.aidl",
+ "src/android/net/INetworkStackStatusCallback.aidl",
+ "src/android/net/InitialConfigurationParcelable.aidl",
+ "src/android/net/NattKeepalivePacketDataParcelable.aidl",
+ "src/android/net/PrivateDnsConfigParcel.aidl",
+ "src/android/net/ProvisioningConfigurationParcelable.aidl",
+ "src/android/net/TcpKeepalivePacketDataParcelable.aidl",
+ "src/android/net/dhcp/DhcpServingParamsParcel.aidl",
+ "src/android/net/dhcp/IDhcpServer.aidl",
+ "src/android/net/dhcp/IDhcpServerCallbacks.aidl",
+ "src/android/net/ip/IIpClient.aidl",
+ "src/android/net/ip/IIpClientCallbacks.aidl",
+ ],
+ backend: {
+ ndk: {
+ enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+ api_dir: "aidl/networkstack",
+ imports: ["ipmemorystore-aidl-interfaces"],
+ versions: [
+ "1",
+ "2",
+ "3",
+ ],
+}
+
+java_library {
+ name: "networkstack-client",
+ sdk_version: "system_current",
+ srcs: [
+ ":framework-annotations",
+ "src/android/net/IpMemoryStoreClient.java",
+ "src/android/net/ipmemorystore/**/*.java",
+ ],
+ static_libs: [
+ "ipmemorystore-aidl-interfaces-V3-java",
+ "networkstack-aidl-interfaces-V3-java",
+ ],
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..a8cbab2
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,9 @@
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..cf02c26
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..291dbef
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..52f40d4
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..7853514
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..3dd2ae6
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..46d4ecb
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..54e654b
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..9531ea3
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..414272b
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..92c6779
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/1/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..a8cbab2
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,9 @@
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..cf02c26
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..291dbef
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..52f40d4
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..7853514
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..3dd2ae6
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..46d4ecb
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..54e654b
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..9531ea3
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..414272b
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,6 @@
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..92c6779
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/2/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,4 @@
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..30893b2
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+interface IIpMemoryStore {
+ oneway void storeNetworkAttributes(String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void storeBlob(String l2Key, String clientId, String name, in android.net.ipmemorystore.Blob data, android.net.ipmemorystore.IOnStatusListener listener);
+ oneway void findL2Key(in android.net.ipmemorystore.NetworkAttributesParcelable attributes, android.net.ipmemorystore.IOnL2KeyResponseListener listener);
+ oneway void isSameNetwork(String l2Key1, String l2Key2, android.net.ipmemorystore.IOnSameL3NetworkResponseListener listener);
+ oneway void retrieveNetworkAttributes(String l2Key, android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener listener);
+ oneway void retrieveBlob(String l2Key, String clientId, String name, android.net.ipmemorystore.IOnBlobRetrievedListener listener);
+ oneway void factoryReset();
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..535ae2c
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+interface IIpMemoryStoreCallbacks {
+ oneway void onIpMemoryStoreFetched(in android.net.IIpMemoryStore ipMemoryStore);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..6d2dc0c
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+parcelable Blob {
+ byte[] data;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..48c1fb8
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+interface IOnBlobRetrievedListener {
+ oneway void onBlobRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in String name, in android.net.ipmemorystore.Blob data);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..aebc724
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+interface IOnL2KeyResponseListener {
+ oneway void onL2KeyResponse(in android.net.ipmemorystore.StatusParcelable status, in String l2Key);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..b66db5a
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+interface IOnNetworkAttributesRetrievedListener {
+ oneway void onNetworkAttributesRetrieved(in android.net.ipmemorystore.StatusParcelable status, in String l2Key, in android.net.ipmemorystore.NetworkAttributesParcelable attributes);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..e9f2db4
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+interface IOnSameL3NetworkResponseListener {
+ oneway void onSameL3NetworkResponse(in android.net.ipmemorystore.StatusParcelable status, in android.net.ipmemorystore.SameL3NetworkResponseParcelable response);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..49172ce
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+interface IOnStatusListener {
+ oneway void onComplete(in android.net.ipmemorystore.StatusParcelable status);
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..188db20
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ android.net.ipmemorystore.Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..7a2ed48
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..d9b0678
--- /dev/null
+++ b/common/networkstackclient/aidl/ipmemorystore/3/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ipmemorystore;
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..92b5345
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,8 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..b19f522
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkMonitor.aidl
@@ -0,0 +1,17 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..95a1574
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/ip/IIpClient.aidl
@@ -0,0 +1,14 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+}
diff --git a/common/networkstackclient/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/1/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..31891de
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,9 @@
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..029968b
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkMonitor.aidl
@@ -0,0 +1,24 @@
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ee9871d
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,8 @@
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..7da11e4
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,7 @@
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..f6ca6f7
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,4 @@
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..c80a787
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..65de883
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,7 @@
+package android.net;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..2de790b
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,5 @@
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..3a6c304
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,15 @@
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e121c06
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,13 @@
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..67193ae
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,11 @@
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..9143158
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,10 @@
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..dcc4489
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,4 @@
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..77d5917
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/ip/IIpClient.aidl
@@ -0,0 +1,15 @@
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+}
diff --git a/common/networkstackclient/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..d6bc808
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/2/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,16 @@
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..07ff321
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable DhcpResultsParcelable {
+ android.net.StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/INetworkMonitor.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..8aa68bd
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkMonitor.aidl
@@ -0,0 +1,41 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+interface INetworkMonitor {
+ oneway void start();
+ oneway void launchCaptivePortalApp();
+ oneway void notifyCaptivePortalAppFinished(int response);
+ oneway void setAcceptPartialConnectivity();
+ oneway void forceReevaluation(int uid);
+ oneway void notifyPrivateDnsChanged(in android.net.PrivateDnsConfigParcel config);
+ oneway void notifyDnsResponse(int returnCode);
+ oneway void notifyNetworkConnected(in android.net.LinkProperties lp, in android.net.NetworkCapabilities nc);
+ oneway void notifyNetworkDisconnected();
+ oneway void notifyLinkPropertiesChanged(in android.net.LinkProperties lp);
+ oneway void notifyNetworkCapabilitiesChanged(in android.net.NetworkCapabilities nc);
+ const int NETWORK_TEST_RESULT_VALID = 0;
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+ const int NETWORK_VALIDATION_RESULT_VALID = 1;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 2;
+ const int NETWORK_VALIDATION_PROBE_DNS = 4;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 8;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 16;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 32;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 64;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..ea93729
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+interface INetworkMonitorCallbacks {
+ oneway void onNetworkMonitorCreated(in android.net.INetworkMonitor networkMonitor);
+ oneway void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ oneway void notifyPrivateDnsConfigResolved(in android.net.PrivateDnsConfigParcel config);
+ oneway void showProvisioningNotification(String action, String packageName);
+ oneway void hideProvisioningNotification();
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/INetworkStackConnector.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..e3a83d1
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+interface INetworkStackConnector {
+ oneway void makeDhcpServer(in String ifName, in android.net.dhcp.DhcpServingParamsParcel params, in android.net.dhcp.IDhcpServerCallbacks cb);
+ oneway void makeNetworkMonitor(in android.net.Network network, String name, in android.net.INetworkMonitorCallbacks cb);
+ oneway void makeIpClient(in String ifName, in android.net.ip.IIpClientCallbacks callbacks);
+ oneway void fetchIpMemoryStore(in android.net.IIpMemoryStoreCallbacks cb);
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..3112a08
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+interface INetworkStackStatusCallback {
+ oneway void onStatusAvailable(int statusCode);
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..f846b26
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable InitialConfigurationParcelable {
+ android.net.LinkAddress[] ipAddresses;
+ android.net.IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..de75940
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..cf0fbce
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..c0f2d4d
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ android.net.InitialConfigurationParcelable initialConfig;
+ android.net.StaticIpConfiguration staticIpConfig;
+ android.net.apf.ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ android.net.Network network;
+ String displayName;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..5926794
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,30 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net;
+parcelable TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..7ab156f
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..d281ecf
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+interface IDhcpServer {
+ oneway void start(in android.net.INetworkStackStatusCallback cb);
+ oneway void updateParams(in android.net.dhcp.DhcpServingParamsParcel params, in android.net.INetworkStackStatusCallback cb);
+ oneway void stop(in android.net.INetworkStackStatusCallback cb);
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..98be0ab
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,21 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.dhcp;
+interface IDhcpServerCallbacks {
+ oneway void onDhcpServerCreated(int statusCode, in android.net.dhcp.IDhcpServer server);
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/ip/IIpClient.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..85c8676
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/ip/IIpClient.aidl
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+interface IIpClient {
+ oneway void completedPreDhcpAction();
+ oneway void confirmConfiguration();
+ oneway void readPacketFilterComplete(in byte[] data);
+ oneway void shutdown();
+ oneway void startProvisioning(in android.net.ProvisioningConfigurationParcelable req);
+ oneway void stop();
+ oneway void setTcpBufferSizes(in String tcpBufferSizes);
+ oneway void setHttpProxy(in android.net.ProxyInfo proxyInfo);
+ oneway void setMulticastFilter(boolean enabled);
+ oneway void addKeepalivePacketFilter(int slot, in android.net.TcpKeepalivePacketDataParcelable pkt);
+ oneway void removeKeepalivePacketFilter(int slot);
+ oneway void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+ oneway void addNattKeepalivePacketFilter(int slot, in android.net.NattKeepalivePacketDataParcelable pkt);
+}
diff --git a/common/networkstackclient/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..7fe39ed
--- /dev/null
+++ b/common/networkstackclient/aidl/networkstack/3/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,33 @@
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a frozen snapshot of an AIDL interface (or parcelable). Do not
+// try to edit this file. It looks like you are doing that because you have
+// modified an AIDL interface in a backward-incompatible way, e.g., deleting a
+// function from an interface or a field from a parcelable and it broke the
+// build. That breakage is intended.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.net.ip;
+interface IIpClientCallbacks {
+ oneway void onIpClientCreated(in android.net.ip.IIpClient ipClient);
+ oneway void onPreDhcpAction();
+ oneway void onPostDhcpAction();
+ oneway void onNewDhcpResults(in android.net.DhcpResultsParcelable dhcpResults);
+ oneway void onProvisioningSuccess(in android.net.LinkProperties newLp);
+ oneway void onProvisioningFailure(in android.net.LinkProperties newLp);
+ oneway void onLinkPropertiesChange(in android.net.LinkProperties newLp);
+ oneway void onReachabilityLost(in String logMsg);
+ oneway void onQuit();
+ oneway void installPacketFilter(in byte[] filter);
+ oneway void startReadPacketFilter();
+ oneway void setFallbackMulticastFilter(boolean enabled);
+ oneway void setNeighborDiscoveryOffload(boolean enable);
+}
diff --git a/common/networkstackclient/src/android/net/DhcpResultsParcelable.aidl b/common/networkstackclient/src/android/net/DhcpResultsParcelable.aidl
new file mode 100644
index 0000000..c98d9c2
--- /dev/null
+++ b/common/networkstackclient/src/android/net/DhcpResultsParcelable.aidl
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2019, 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 perNmissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.StaticIpConfiguration;
+
+parcelable DhcpResultsParcelable {
+ StaticIpConfiguration baseConfiguration;
+ int leaseDuration;
+ int mtu;
+ String serverAddress;
+ String vendorInfo;
+ String serverHostName;
+}
diff --git a/common/networkstackclient/src/android/net/IIpMemoryStore.aidl b/common/networkstackclient/src/android/net/IIpMemoryStore.aidl
new file mode 100644
index 0000000..add221a
--- /dev/null
+++ b/common/networkstackclient/src/android/net/IIpMemoryStore.aidl
@@ -0,0 +1,118 @@
+/*
+ * 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;
+
+import android.net.ipmemorystore.Blob;
+import android.net.ipmemorystore.NetworkAttributesParcelable;
+import android.net.ipmemorystore.IOnBlobRetrievedListener;
+import android.net.ipmemorystore.IOnL2KeyResponseListener;
+import android.net.ipmemorystore.IOnNetworkAttributesRetrievedListener;
+import android.net.ipmemorystore.IOnSameL3NetworkResponseListener;
+import android.net.ipmemorystore.IOnStatusListener;
+
+/** {@hide} */
+oneway interface IIpMemoryStore {
+ /**
+ * Store network attributes for a given L2 key.
+ * If L2Key is null, choose automatically from the attributes ; passing null is equivalent to
+ * calling findL2Key with the attributes and storing in the returned value.
+ *
+ * @param l2Key The L2 key for the L2 network. Clients that don't know or care about the L2
+ * key and only care about grouping can pass a unique ID here like the ones
+ * generated by {@code java.util.UUID.randomUUID()}, but keep in mind the low
+ * relevance of such a network will lead to it being evicted soon if it's not
+ * refreshed. Use findL2Key to try and find a similar L2Key to these attributes.
+ * @param attributes The attributes for this network.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * @return (through the listener) The L2 key. This is useful if the L2 key was not specified.
+ * If the call failed, the L2 key will be null.
+ */
+ void storeNetworkAttributes(String l2Key, in NetworkAttributesParcelable attributes,
+ IOnStatusListener listener);
+
+ /**
+ * Store a binary blob associated with an L2 key and a name.
+ *
+ * @param l2Key The L2 key for this network.
+ * @param clientId The ID of the client.
+ * @param name The name of this data.
+ * @param data The data to store.
+ * @param listener A listener to inform of the completion of this call, or null if the client
+ * is not interested in learning about success/failure.
+ * @return (through the listener) A status to indicate success or failure.
+ */
+ void storeBlob(String l2Key, String clientId, String name, in Blob data,
+ IOnStatusListener listener);
+
+ /**
+ * Returns the best L2 key associated with the attributes.
+ *
+ * This will find a record that would be in the same group as the passed attributes. This is
+ * useful to choose the key for storing a sample or private data when the L2 key is not known.
+ * If multiple records are group-close to these attributes, the closest match is returned.
+ * If multiple records have the same closeness, the one with the smaller (unicode codepoint
+ * order) L2 key is returned.
+ * If no record matches these attributes, null is returned.
+ *
+ * @param attributes The attributes of the network to find.
+ * @param listener The listener that will be invoked to return the answer.
+ * @return (through the listener) The L2 key if one matched, or null.
+ */
+ void findL2Key(in NetworkAttributesParcelable attributes, IOnL2KeyResponseListener listener);
+
+ /**
+ * Returns whether, to the best of the store's ability to tell, the two specified L2 keys point
+ * to the same L3 network. Group-closeness is used to determine this.
+ *
+ * @param l2Key1 The key for the first network.
+ * @param l2Key2 The key for the second network.
+ * @param listener The listener that will be invoked to return the answer.
+ * @return (through the listener) A SameL3NetworkResponse containing the answer and confidence.
+ */
+ void isSameNetwork(String l2Key1, String l2Key2, IOnSameL3NetworkResponseListener listener);
+
+ /**
+ * Retrieve the network attributes for a key.
+ * If no record is present for this key, this will return null attributes.
+ *
+ * @param l2Key The key of the network to query.
+ * @param listener The listener that will be invoked to return the answer.
+ * @return (through the listener) The network attributes and the L2 key associated with
+ * the query.
+ */
+ void retrieveNetworkAttributes(String l2Key, IOnNetworkAttributesRetrievedListener listener);
+
+ /**
+ * Retrieve previously stored private data.
+ * If no data was stored for this L2 key and name this will return null.
+ *
+ * @param l2Key The L2 key.
+ * @param clientId The id of the client that stored this data.
+ * @param name The name of the data.
+ * @param listener The listener that will be invoked to return the answer.
+ * @return (through the listener) The private data (or null), with the L2 key
+ * and the name of the data associated with the query.
+ */
+ void retrieveBlob(String l2Key, String clientId, String name,
+ IOnBlobRetrievedListener listener);
+
+ /**
+ * Delete all data because a factory reset operation is in progress.
+ */
+ void factoryReset();
+}
diff --git a/common/networkstackclient/src/android/net/IIpMemoryStoreCallbacks.aidl b/common/networkstackclient/src/android/net/IIpMemoryStoreCallbacks.aidl
new file mode 100644
index 0000000..53108db
--- /dev/null
+++ b/common/networkstackclient/src/android/net/IIpMemoryStoreCallbacks.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 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.IIpMemoryStore;
+
+/** {@hide} */
+oneway interface IIpMemoryStoreCallbacks {
+ void onIpMemoryStoreFetched(in IIpMemoryStore ipMemoryStore);
+}
diff --git a/common/networkstackclient/src/android/net/INetworkMonitor.aidl b/common/networkstackclient/src/android/net/INetworkMonitor.aidl
new file mode 100644
index 0000000..3fc81a3
--- /dev/null
+++ b/common/networkstackclient/src/android/net/INetworkMonitor.aidl
@@ -0,0 +1,68 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
+import android.net.PrivateDnsConfigParcel;
+
+/** @hide */
+oneway interface INetworkMonitor {
+ // After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
+ // The network should be used as a default internet connection. It was found to be:
+ // 1. a functioning network providing internet access, or
+ // 2. a captive portal and the user decided to use it as is.
+ const int NETWORK_TEST_RESULT_VALID = 0;
+
+ // After a network has been tested this result can be sent with EVENT_NETWORK_TESTED.
+ // The network should not be used as a default internet connection. It was found to be:
+ // 1. a captive portal and the user is prompted to sign-in, or
+ // 2. a captive portal and the user did not want to use it, or
+ // 3. a broken network (e.g. DNS failed, connect failed, HTTP request failed).
+ const int NETWORK_TEST_RESULT_INVALID = 1;
+
+ // After a network has been tested, this result can be sent with EVENT_NETWORK_TESTED.
+ // The network may be used as a default internet connection, but it was found to be a partial
+ // connectivity network which can get the pass result for http probe but get the failed result
+ // for https probe.
+ const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+
+ // Network validation flags indicate probe result and types. If no NETWORK_VALIDATION_RESULT_*
+ // are set, then it's equal to NETWORK_TEST_RESULT_INVALID. If NETWORK_VALIDATION_RESULT_VALID
+ // is set, then the network validates and equal to NETWORK_TEST_RESULT_VALID. If
+ // NETWORK_VALIDATION_RESULT_PARTIAL is set, then the network has partial connectivity which
+ // is equal to NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY. NETWORK_VALIDATION_PROBE_* is set
+ // when the specific probe result of the network is resolved.
+ const int NETWORK_VALIDATION_RESULT_VALID = 0x01;
+ const int NETWORK_VALIDATION_RESULT_PARTIAL = 0x02;
+ const int NETWORK_VALIDATION_PROBE_DNS = 0x04;
+ const int NETWORK_VALIDATION_PROBE_HTTP = 0x08;
+ const int NETWORK_VALIDATION_PROBE_HTTPS = 0x10;
+ const int NETWORK_VALIDATION_PROBE_FALLBACK = 0x20;
+ const int NETWORK_VALIDATION_PROBE_PRIVDNS = 0x40;
+
+ void start();
+ void launchCaptivePortalApp();
+ void notifyCaptivePortalAppFinished(int response);
+ void setAcceptPartialConnectivity();
+ void forceReevaluation(int uid);
+ void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config);
+ void notifyDnsResponse(int returnCode);
+ void notifyNetworkConnected(in LinkProperties lp, in NetworkCapabilities nc);
+ void notifyNetworkDisconnected();
+ void notifyLinkPropertiesChanged(in LinkProperties lp);
+ void notifyNetworkCapabilitiesChanged(in NetworkCapabilities nc);
+}
diff --git a/common/networkstackclient/src/android/net/INetworkMonitorCallbacks.aidl b/common/networkstackclient/src/android/net/INetworkMonitorCallbacks.aidl
new file mode 100644
index 0000000..2c61511
--- /dev/null
+++ b/common/networkstackclient/src/android/net/INetworkMonitorCallbacks.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+import android.net.INetworkMonitor;
+import android.net.PrivateDnsConfigParcel;
+
+/** @hide */
+oneway interface INetworkMonitorCallbacks {
+ void onNetworkMonitorCreated(in INetworkMonitor networkMonitor);
+ void notifyNetworkTested(int testResult, @nullable String redirectUrl);
+ void notifyPrivateDnsConfigResolved(in PrivateDnsConfigParcel config);
+ void showProvisioningNotification(String action, String packageName);
+ void hideProvisioningNotification();
+}
\ No newline at end of file
diff --git a/common/networkstackclient/src/android/net/INetworkStackConnector.aidl b/common/networkstackclient/src/android/net/INetworkStackConnector.aidl
new file mode 100644
index 0000000..3751c36
--- /dev/null
+++ b/common/networkstackclient/src/android/net/INetworkStackConnector.aidl
@@ -0,0 +1,32 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import android.net.IIpMemoryStoreCallbacks;
+import android.net.INetworkMonitorCallbacks;
+import android.net.Network;
+import android.net.dhcp.DhcpServingParamsParcel;
+import android.net.dhcp.IDhcpServerCallbacks;
+import android.net.ip.IIpClientCallbacks;
+
+/** @hide */
+oneway interface INetworkStackConnector {
+ void makeDhcpServer(in String ifName, in DhcpServingParamsParcel params,
+ in IDhcpServerCallbacks cb);
+ void makeNetworkMonitor(in Network network, String name, in INetworkMonitorCallbacks cb);
+ void makeIpClient(in String ifName, in IIpClientCallbacks callbacks);
+ void fetchIpMemoryStore(in IIpMemoryStoreCallbacks cb);
+}
diff --git a/common/networkstackclient/src/android/net/INetworkStackStatusCallback.aidl b/common/networkstackclient/src/android/net/INetworkStackStatusCallback.aidl
new file mode 100644
index 0000000..51032d8
--- /dev/null
+++ b/common/networkstackclient/src/android/net/INetworkStackStatusCallback.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+/** @hide */
+oneway interface INetworkStackStatusCallback {
+ void onStatusAvailable(int statusCode);
+}
\ No newline at end of file
diff --git a/common/networkstackclient/src/android/net/InitialConfigurationParcelable.aidl b/common/networkstackclient/src/android/net/InitialConfigurationParcelable.aidl
new file mode 100644
index 0000000..3fa88c3
--- /dev/null
+++ b/common/networkstackclient/src/android/net/InitialConfigurationParcelable.aidl
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 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.IpPrefix;
+import android.net.LinkAddress;
+
+parcelable InitialConfigurationParcelable {
+ LinkAddress[] ipAddresses;
+ IpPrefix[] directlyConnectedRoutes;
+ String[] dnsServers;
+ String gateway;
+}
\ No newline at end of file
diff --git a/common/networkstackclient/src/android/net/IpMemoryStoreClient.java b/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
new file mode 100644
index 0000000..014b528
--- /dev/null
+++ b/common/networkstackclient/src/android/net/IpMemoryStoreClient.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2019 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.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.ipmemorystore.Blob;
+import android.net.ipmemorystore.NetworkAttributes;
+import android.net.ipmemorystore.OnBlobRetrievedListener;
+import android.net.ipmemorystore.OnL2KeyResponseListener;
+import android.net.ipmemorystore.OnNetworkAttributesRetrievedListener;
+import android.net.ipmemorystore.OnSameL3NetworkResponseListener;
+import android.net.ipmemorystore.OnStatusListener;
+import android.net.ipmemorystore.Status;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.concurrent.ExecutionException;
+import java.util.function.Consumer;
+
+/**
+ * service used to communicate with the ip memory store service in network stack,
+ * which is running in a separate module.
+ * @hide
+ */
+public abstract class IpMemoryStoreClient {
+ private static final String TAG = IpMemoryStoreClient.class.getSimpleName();
+ private final Context mContext;
+
+ public IpMemoryStoreClient(@NonNull final Context context) {
+ if (context == null) throw new IllegalArgumentException("missing context");
+ mContext = context;
+ }
+
+ protected abstract void runWhenServiceReady(Consumer<IIpMemoryStore> cb)
+ throws ExecutionException;
+
+ @FunctionalInterface
+ private interface ThrowingRunnable {
+ void run() throws RemoteException;
+ }
+
+ private void ignoringRemoteException(ThrowingRunnable r) {
+ ignoringRemoteException("Failed to execute remote procedure call", r);
+ }
+
+ private void ignoringRemoteException(String message, ThrowingRunnable r) {
+ try {
+ r.run();
+ } catch (RemoteException e) {
+ Log.e(TAG, message, e);
+ }
+ }
+
+ /**
+ * Store network attributes for a given L2 key.
+ * If L2Key is null, choose automatically from the attributes ; passing null is equivalent to
+ * calling findL2Key with the attributes and storing in the returned value.
+ *
+ * @param l2Key The L2 key for the L2 network. Clients that don't know or care about the L2
+ * key and only care about grouping can pass a unique ID here like the ones
+ * generated by {@code java.util.UUID.randomUUID()}, but keep in mind the low
+ * relevance of such a network will lead to it being evicted soon if it's not
+ * refreshed. Use findL2Key to try and find a similar L2Key to these attributes.
+ * @param attributes The attributes for this network.
+ * @param listener A listener that will be invoked to inform of the completion of this call,
+ * or null if the client is not interested in learning about success/failure.
+ * Through the listener, returns the L2 key. This is useful if the L2 key was not specified.
+ * If the call failed, the L2 key will be null.
+ */
+ public void storeNetworkAttributes(@NonNull final String l2Key,
+ @NonNull final NetworkAttributes attributes,
+ @Nullable final OnStatusListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeNetworkAttributes(l2Key, attributes.toParcelable(),
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error storing network attributes",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
+ }
+ }
+
+ /**
+ * Store a binary blob associated with an L2 key and a name.
+ *
+ * @param l2Key The L2 key for this network.
+ * @param clientId The ID of the client.
+ * @param name The name of this data.
+ * @param data The data to store.
+ * @param listener A listener to inform of the completion of this call, or null if the client
+ * is not interested in learning about success/failure.
+ * Through the listener, returns a status to indicate success or failure.
+ */
+ public void storeBlob(@NonNull final String l2Key, @NonNull final String clientId,
+ @NonNull final String name, @NonNull final Blob data,
+ @Nullable final OnStatusListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.storeBlob(l2Key, clientId, name, data,
+ OnStatusListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error storing blob",
+ () -> listener.onComplete(new Status(Status.ERROR_UNKNOWN)));
+ }
+ }
+
+ /**
+ * Returns the best L2 key associated with the attributes.
+ *
+ * This will find a record that would be in the same group as the passed attributes. This is
+ * useful to choose the key for storing a sample or private data when the L2 key is not known.
+ * If multiple records are group-close to these attributes, the closest match is returned.
+ * If multiple records have the same closeness, the one with the smaller (unicode codepoint
+ * order) L2 key is returned.
+ * If no record matches these attributes, null is returned.
+ *
+ * @param attributes The attributes of the network to find.
+ * @param listener The listener that will be invoked to return the answer.
+ * Through the listener, returns the L2 key if one matched, or null.
+ */
+ public void findL2Key(@NonNull final NetworkAttributes attributes,
+ @NonNull final OnL2KeyResponseListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.findL2Key(attributes.toParcelable(),
+ OnL2KeyResponseListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error finding L2 Key",
+ () -> listener.onL2KeyResponse(new Status(Status.ERROR_UNKNOWN), null));
+ }
+ }
+
+ /**
+ * Returns whether, to the best of the store's ability to tell, the two specified L2 keys point
+ * to the same L3 network. Group-closeness is used to determine this.
+ *
+ * @param l2Key1 The key for the first network.
+ * @param l2Key2 The key for the second network.
+ * @param listener The listener that will be invoked to return the answer.
+ * Through the listener, a SameL3NetworkResponse containing the answer and confidence.
+ */
+ public void isSameNetwork(@NonNull final String l2Key1, @NonNull final String l2Key2,
+ @NonNull final OnSameL3NetworkResponseListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.isSameNetwork(l2Key1, l2Key2,
+ OnSameL3NetworkResponseListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error checking for network sameness",
+ () -> listener.onSameL3NetworkResponse(new Status(Status.ERROR_UNKNOWN), null));
+ }
+ }
+
+ /**
+ * Retrieve the network attributes for a key.
+ * If no record is present for this key, this will return null attributes.
+ *
+ * @param l2Key The key of the network to query.
+ * @param listener The listener that will be invoked to return the answer.
+ * Through the listener, returns the network attributes and the L2 key associated with
+ * the query.
+ */
+ public void retrieveNetworkAttributes(@NonNull final String l2Key,
+ @NonNull final OnNetworkAttributesRetrievedListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveNetworkAttributes(l2Key,
+ OnNetworkAttributesRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving network attributes",
+ () -> listener.onNetworkAttributesRetrieved(new Status(Status.ERROR_UNKNOWN),
+ null, null));
+ }
+ }
+
+ /**
+ * Retrieve previously stored private data.
+ * If no data was stored for this L2 key and name this will return null.
+ *
+ * @param l2Key The L2 key.
+ * @param clientId The id of the client that stored this data.
+ * @param name The name of the data.
+ * @param listener The listener that will be invoked to return the answer.
+ * Through the listener, returns the private data (or null), with the L2 key
+ * and the name of the data associated with the query.
+ */
+ public void retrieveBlob(@NonNull final String l2Key, @NonNull final String clientId,
+ @NonNull final String name, @NonNull final OnBlobRetrievedListener listener) {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.retrieveBlob(l2Key, clientId, name,
+ OnBlobRetrievedListener.toAIDL(listener))));
+ } catch (ExecutionException m) {
+ ignoringRemoteException("Error retrieving blob",
+ () -> listener.onBlobRetrieved(new Status(Status.ERROR_UNKNOWN),
+ null, null, null));
+ }
+ }
+
+ /**
+ * Wipe the data in the database upon network factory reset.
+ */
+ public void factoryReset() {
+ try {
+ runWhenServiceReady(service -> ignoringRemoteException(
+ () -> service.factoryReset()));
+ } catch (ExecutionException m) {
+ Log.e(TAG, "Error executing factory reset", m);
+ }
+ }
+}
diff --git a/common/networkstackclient/src/android/net/NattKeepalivePacketDataParcelable.aidl b/common/networkstackclient/src/android/net/NattKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..6f006d4
--- /dev/null
+++ b/common/networkstackclient/src/android/net/NattKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 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 NattKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+}
+
diff --git a/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl b/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl
new file mode 100644
index 0000000..b52fce6
--- /dev/null
+++ b/common/networkstackclient/src/android/net/PrivateDnsConfigParcel.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+parcelable PrivateDnsConfigParcel {
+ String hostname;
+ String[] ips;
+}
diff --git a/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
new file mode 100644
index 0000000..99606fb
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ProvisioningConfigurationParcelable.aidl
@@ -0,0 +1,38 @@
+/*
+**
+** Copyright (C) 2019 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.InitialConfigurationParcelable;
+import android.net.Network;
+import android.net.StaticIpConfiguration;
+import android.net.apf.ApfCapabilities;
+
+parcelable ProvisioningConfigurationParcelable {
+ boolean enableIPv4;
+ boolean enableIPv6;
+ boolean usingMultinetworkPolicyTracker;
+ boolean usingIpReachabilityMonitor;
+ int requestedPreDhcpActionMs;
+ InitialConfigurationParcelable initialConfig;
+ StaticIpConfiguration staticIpConfig;
+ ApfCapabilities apfCapabilities;
+ int provisioningTimeoutMs;
+ int ipv6AddrGenMode;
+ Network network;
+ String displayName;
+}
diff --git a/common/networkstackclient/src/android/net/TcpKeepalivePacketDataParcelable.aidl b/common/networkstackclient/src/android/net/TcpKeepalivePacketDataParcelable.aidl
new file mode 100644
index 0000000..e25168d
--- /dev/null
+++ b/common/networkstackclient/src/android/net/TcpKeepalivePacketDataParcelable.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 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 TcpKeepalivePacketDataParcelable {
+ byte[] srcAddress;
+ int srcPort;
+ byte[] dstAddress;
+ int dstPort;
+ int seq;
+ int ack;
+ int rcvWnd;
+ int rcvWndScale;
+ int tos;
+ int ttl;
+}
diff --git a/common/networkstackclient/src/android/net/dhcp/DhcpServingParamsParcel.aidl b/common/networkstackclient/src/android/net/dhcp/DhcpServingParamsParcel.aidl
new file mode 100644
index 0000000..7b8b9ee
--- /dev/null
+++ b/common/networkstackclient/src/android/net/dhcp/DhcpServingParamsParcel.aidl
@@ -0,0 +1,30 @@
+/**
+ *
+ * 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.dhcp;
+
+parcelable DhcpServingParamsParcel {
+ int serverAddr;
+ int serverAddrPrefixLength;
+ int[] defaultRouters;
+ int[] dnsServers;
+ int[] excludedAddrs;
+ long dhcpLeaseTimeSecs;
+ int linkMtu;
+ boolean metered;
+}
+
diff --git a/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl b/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl
new file mode 100644
index 0000000..559433b
--- /dev/null
+++ b/common/networkstackclient/src/android/net/dhcp/IDhcpServer.aidl
@@ -0,0 +1,32 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.net.INetworkStackStatusCallback;
+import android.net.dhcp.DhcpServingParamsParcel;
+
+/** @hide */
+oneway interface IDhcpServer {
+ const int STATUS_UNKNOWN = 0;
+ const int STATUS_SUCCESS = 1;
+ const int STATUS_INVALID_ARGUMENT = 2;
+ const int STATUS_UNKNOWN_ERROR = 3;
+
+ void start(in INetworkStackStatusCallback cb);
+ void updateParams(in DhcpServingParamsParcel params, in INetworkStackStatusCallback cb);
+ void stop(in INetworkStackStatusCallback cb);
+}
diff --git a/common/networkstackclient/src/android/net/dhcp/IDhcpServerCallbacks.aidl b/common/networkstackclient/src/android/net/dhcp/IDhcpServerCallbacks.aidl
new file mode 100644
index 0000000..7ab4dcd
--- /dev/null
+++ b/common/networkstackclient/src/android/net/dhcp/IDhcpServerCallbacks.aidl
@@ -0,0 +1,24 @@
+/**
+ * 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 perNmissions and
+ * limitations under the License.
+ */
+
+package android.net.dhcp;
+
+import android.net.dhcp.IDhcpServer;
+
+/** @hide */
+oneway interface IDhcpServerCallbacks {
+ void onDhcpServerCreated(int statusCode, in IDhcpServer server);
+}
diff --git a/common/networkstackclient/src/android/net/ip/IIpClient.aidl b/common/networkstackclient/src/android/net/ip/IIpClient.aidl
new file mode 100644
index 0000000..9989c52
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IIpClient.aidl
@@ -0,0 +1,38 @@
+/**
+ * Copyright (c) 2019, 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 perNmissions and
+ * limitations under the License.
+ */
+package android.net.ip;
+
+import android.net.ProxyInfo;
+import android.net.ProvisioningConfigurationParcelable;
+import android.net.NattKeepalivePacketDataParcelable;
+import android.net.TcpKeepalivePacketDataParcelable;
+
+/** @hide */
+oneway interface IIpClient {
+ void completedPreDhcpAction();
+ void confirmConfiguration();
+ void readPacketFilterComplete(in byte[] data);
+ void shutdown();
+ void startProvisioning(in ProvisioningConfigurationParcelable req);
+ void stop();
+ void setTcpBufferSizes(in String tcpBufferSizes);
+ void setHttpProxy(in ProxyInfo proxyInfo);
+ void setMulticastFilter(boolean enabled);
+ void addKeepalivePacketFilter(int slot, in TcpKeepalivePacketDataParcelable pkt);
+ void removeKeepalivePacketFilter(int slot);
+ void setL2KeyAndGroupHint(in String l2Key, in String groupHint);
+ void addNattKeepalivePacketFilter(int slot, in NattKeepalivePacketDataParcelable pkt);
+}
diff --git a/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl b/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl
new file mode 100644
index 0000000..3681416
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IIpClientCallbacks.aidl
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2019, 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 perNmissions and
+ * limitations under the License.
+ */
+package android.net.ip;
+
+import android.net.LinkProperties;
+import android.net.ip.IIpClient;
+import android.net.DhcpResultsParcelable;
+
+/** @hide */
+oneway interface IIpClientCallbacks {
+ void onIpClientCreated(in IIpClient ipClient);
+
+ void onPreDhcpAction();
+ void onPostDhcpAction();
+
+ // This is purely advisory and not an indication of provisioning
+ // success or failure. This is only here for callers that want to
+ // expose DHCPv4 results to other APIs (e.g., WifiInfo#setInetAddress).
+ // DHCPv4 or static IPv4 configuration failure or success can be
+ // determined by whether or not the passed-in DhcpResults object is
+ // null or not.
+ void onNewDhcpResults(in DhcpResultsParcelable dhcpResults);
+
+ void onProvisioningSuccess(in LinkProperties newLp);
+ void onProvisioningFailure(in LinkProperties newLp);
+
+ // Invoked on LinkProperties changes.
+ void onLinkPropertiesChange(in LinkProperties newLp);
+
+ // Called when the internal IpReachabilityMonitor (if enabled) has
+ // detected the loss of a critical number of required neighbors.
+ void onReachabilityLost(in String logMsg);
+
+ // Called when the IpClient state machine terminates.
+ void onQuit();
+
+ // Install an APF program to filter incoming packets.
+ void installPacketFilter(in byte[] filter);
+
+ // Asynchronously read back the APF program & data buffer from the wifi driver.
+ // Due to Wifi HAL limitations, the current implementation only supports dumping the entire
+ // buffer. In response to this request, the driver returns the data buffer asynchronously
+ // by sending an IpClient#EVENT_READ_PACKET_FILTER_COMPLETE message.
+ void startReadPacketFilter();
+
+ // If multicast filtering cannot be accomplished with APF, this function will be called to
+ // actuate multicast filtering using another means.
+ void setFallbackMulticastFilter(boolean enabled);
+
+ // Enabled/disable Neighbor Discover offload functionality. This is
+ // called, for example, whenever 464xlat is being started or stopped.
+ void setNeighborDiscoveryOffload(boolean enable);
+}
\ No newline at end of file
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/Blob.aidl b/common/networkstackclient/src/android/net/ipmemorystore/Blob.aidl
new file mode 100644
index 0000000..9dbef11
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/Blob.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.ipmemorystore;
+
+/**
+ * A blob of data opaque to the memory store. The client mutates this at its own risk,
+ * and it is strongly suggested to never do it at all and treat this as immutable.
+ * {@hide}
+ */
+parcelable Blob {
+ byte[] data;
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl b/common/networkstackclient/src/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
new file mode 100644
index 0000000..4926feb
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/IOnBlobRetrievedListener.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.ipmemorystore;
+
+import android.net.ipmemorystore.Blob;
+import android.net.ipmemorystore.StatusParcelable;
+
+/** {@hide} */
+oneway interface IOnBlobRetrievedListener {
+ /**
+ * Private data was retrieved for the L2 key and name specified.
+ * Note this does not return the client ID, as clients are expected to only ever use one ID.
+ */
+ void onBlobRetrieved(in StatusParcelable status, in String l2Key, in String name,
+ in Blob data);
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl b/common/networkstackclient/src/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
new file mode 100644
index 0000000..dea0cc4
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/IOnL2KeyResponseListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.ipmemorystore;
+
+import android.net.ipmemorystore.StatusParcelable;
+
+/** {@hide} */
+oneway interface IOnL2KeyResponseListener {
+ /**
+ * The operation completed with the specified L2 key.
+ */
+ void onL2KeyResponse(in StatusParcelable status, in String l2Key);
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl b/common/networkstackclient/src/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
new file mode 100644
index 0000000..870e217
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/IOnNetworkAttributesRetrievedListener.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.ipmemorystore;
+
+import android.net.ipmemorystore.NetworkAttributesParcelable;
+import android.net.ipmemorystore.StatusParcelable;
+
+/** {@hide} */
+oneway interface IOnNetworkAttributesRetrievedListener {
+ /**
+ * Network attributes were fetched for the specified L2 key. While the L2 key will never
+ * be null, the attributes may be if no data is stored about this L2 key.
+ */
+ void onNetworkAttributesRetrieved(in StatusParcelable status, in String l2Key,
+ in NetworkAttributesParcelable attributes);
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl b/common/networkstackclient/src/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
new file mode 100644
index 0000000..b8ccfb9
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/IOnSameL3NetworkResponseListener.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.ipmemorystore;
+
+import android.net.ipmemorystore.SameL3NetworkResponseParcelable;
+import android.net.ipmemorystore.StatusParcelable;
+
+/** {@hide} */
+oneway interface IOnSameL3NetworkResponseListener {
+ /**
+ * The memory store has come up with the answer to a query that was sent.
+ */
+ void onSameL3NetworkResponse(in StatusParcelable status,
+ in SameL3NetworkResponseParcelable response);
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/IOnStatusListener.aidl b/common/networkstackclient/src/android/net/ipmemorystore/IOnStatusListener.aidl
new file mode 100644
index 0000000..5d07504
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/IOnStatusListener.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.ipmemorystore;
+
+import android.net.ipmemorystore.StatusParcelable;
+
+/** {@hide} */
+oneway interface IOnStatusListener {
+ /**
+ * The operation has completed with the specified status.
+ */
+ void onComplete(in StatusParcelable status);
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java b/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java
new file mode 100644
index 0000000..818515a
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributes.java
@@ -0,0 +1,371 @@
+/*
+ * 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.ipmemorystore;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+/**
+ * A POD object to represent attributes of a single L2 network entry.
+ * @hide
+ */
+public class NetworkAttributes {
+ private static final boolean DBG = true;
+
+ // Weight cutoff for grouping. To group, a similarity score is computed with the following
+ // algorithm : if both fields are non-null and equals() then add their assigned weight, else if
+ // both are null then add a portion of their assigned weight (see NULL_MATCH_WEIGHT),
+ // otherwise add nothing.
+ // As a guideline, this should be something like 60~75% of the total weights in this class. The
+ // design states "in essence a reader should imagine that if two important columns don't match,
+ // or one important and several unimportant columns don't match then the two records are
+ // considered a different group".
+ private static final float TOTAL_WEIGHT_CUTOFF = 520.0f;
+ // The portion of the weight that is earned when scoring group-sameness by having both columns
+ // being null. This is because some networks rightfully don't have some attributes (e.g. a
+ // V6-only network won't have an assigned V4 address) and both being null should count for
+ // something, but attributes may also be null just because data is unavailable.
+ private static final float NULL_MATCH_WEIGHT = 0.25f;
+
+ // The v4 address that was assigned to this device the last time it joined this network.
+ // This typically comes from DHCP but could be something else like static configuration.
+ // This does not apply to IPv6.
+ // TODO : add a list of v6 prefixes for the v6 case.
+ @Nullable
+ public final Inet4Address assignedV4Address;
+ private static final float WEIGHT_ASSIGNEDV4ADDR = 300.0f;
+
+ // The lease expiry timestamp of v4 address allocated from DHCP server, in milliseconds.
+ @Nullable
+ public final Long assignedV4AddressExpiry;
+ // lease expiry doesn't imply any correlation between "the same lease expiry value" and "the
+ // same L3 network".
+ private static final float WEIGHT_ASSIGNEDV4ADDREXPIRY = 0.0f;
+
+ // Optionally supplied by the client if it has an opinion on L3 network. For example, this
+ // could be a hash of the SSID + security type on WiFi.
+ @Nullable
+ public final String groupHint;
+ private static final float WEIGHT_GROUPHINT = 300.0f;
+
+ // The list of DNS server addresses.
+ @Nullable
+ public final List<InetAddress> dnsAddresses;
+ private static final float WEIGHT_DNSADDRESSES = 200.0f;
+
+ // The mtu on this network.
+ @Nullable
+ public final Integer mtu;
+ private static final float WEIGHT_MTU = 50.0f;
+
+ // The sum of all weights in this class. Tests ensure that this stays equal to the total of
+ // all weights.
+ /** @hide */
+ @VisibleForTesting
+ public static final float TOTAL_WEIGHT = WEIGHT_ASSIGNEDV4ADDR
+ + WEIGHT_ASSIGNEDV4ADDREXPIRY
+ + WEIGHT_GROUPHINT
+ + WEIGHT_DNSADDRESSES
+ + WEIGHT_MTU;
+
+ /** @hide */
+ @VisibleForTesting
+ public NetworkAttributes(
+ @Nullable final Inet4Address assignedV4Address,
+ @Nullable final Long assignedV4AddressExpiry,
+ @Nullable final String groupHint,
+ @Nullable final List<InetAddress> dnsAddresses,
+ @Nullable final Integer mtu) {
+ if (mtu != null && mtu < 0) throw new IllegalArgumentException("MTU can't be negative");
+ if (assignedV4AddressExpiry != null && assignedV4AddressExpiry <= 0) {
+ throw new IllegalArgumentException("lease expiry can't be negative or zero");
+ }
+ this.assignedV4Address = assignedV4Address;
+ this.assignedV4AddressExpiry = assignedV4AddressExpiry;
+ this.groupHint = groupHint;
+ this.dnsAddresses = null == dnsAddresses ? null :
+ Collections.unmodifiableList(new ArrayList<>(dnsAddresses));
+ this.mtu = mtu;
+ }
+
+ @VisibleForTesting
+ public NetworkAttributes(@NonNull final NetworkAttributesParcelable parcelable) {
+ // The call to the other constructor must be the first statement of this constructor,
+ // so everything has to be inline
+ this((Inet4Address) getByAddressOrNull(parcelable.assignedV4Address),
+ parcelable.assignedV4AddressExpiry > 0
+ ? parcelable.assignedV4AddressExpiry : null,
+ parcelable.groupHint,
+ blobArrayToInetAddressList(parcelable.dnsAddresses),
+ parcelable.mtu >= 0 ? parcelable.mtu : null);
+ }
+
+ @Nullable
+ private static InetAddress getByAddressOrNull(@Nullable final byte[] address) {
+ if (null == address) return null;
+ try {
+ return InetAddress.getByAddress(address);
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+ @Nullable
+ private static List<InetAddress> blobArrayToInetAddressList(@Nullable final Blob[] blobs) {
+ if (null == blobs) return null;
+ final ArrayList<InetAddress> list = new ArrayList<>(blobs.length);
+ for (final Blob b : blobs) {
+ final InetAddress addr = getByAddressOrNull(b.data);
+ if (null != addr) list.add(addr);
+ }
+ return list;
+ }
+
+ @Nullable
+ private static Blob[] inetAddressListToBlobArray(@Nullable final List<InetAddress> addresses) {
+ if (null == addresses) return null;
+ final ArrayList<Blob> blobs = new ArrayList<>();
+ for (int i = 0; i < addresses.size(); ++i) {
+ final InetAddress addr = addresses.get(i);
+ if (null == addr) continue;
+ final Blob b = new Blob();
+ b.data = addr.getAddress();
+ blobs.add(b);
+ }
+ return blobs.toArray(new Blob[0]);
+ }
+
+ /** Converts this NetworkAttributes to a parcelable object */
+ @NonNull
+ public NetworkAttributesParcelable toParcelable() {
+ final NetworkAttributesParcelable parcelable = new NetworkAttributesParcelable();
+ parcelable.assignedV4Address =
+ (null == assignedV4Address) ? null : assignedV4Address.getAddress();
+ parcelable.assignedV4AddressExpiry =
+ (null == assignedV4AddressExpiry) ? 0 : assignedV4AddressExpiry;
+ parcelable.groupHint = groupHint;
+ parcelable.dnsAddresses = inetAddressListToBlobArray(dnsAddresses);
+ parcelable.mtu = (null == mtu) ? -1 : mtu;
+ return parcelable;
+ }
+
+ private float samenessContribution(final float weight,
+ @Nullable final Object o1, @Nullable final Object o2) {
+ if (null == o1) {
+ return (null == o2) ? weight * NULL_MATCH_WEIGHT : 0f;
+ }
+ return Objects.equals(o1, o2) ? weight : 0f;
+ }
+
+ /** @hide */
+ public float getNetworkGroupSamenessConfidence(@NonNull final NetworkAttributes o) {
+ final float samenessScore =
+ samenessContribution(WEIGHT_ASSIGNEDV4ADDR, assignedV4Address, o.assignedV4Address)
+ + samenessContribution(WEIGHT_ASSIGNEDV4ADDREXPIRY, assignedV4AddressExpiry,
+ o.assignedV4AddressExpiry)
+ + samenessContribution(WEIGHT_GROUPHINT, groupHint, o.groupHint)
+ + samenessContribution(WEIGHT_DNSADDRESSES, dnsAddresses, o.dnsAddresses)
+ + samenessContribution(WEIGHT_MTU, mtu, o.mtu);
+ // The minimum is 0, the max is TOTAL_WEIGHT and should be represented by 1.0, and
+ // TOTAL_WEIGHT_CUTOFF should represent 0.5, but there is no requirement that
+ // TOTAL_WEIGHT_CUTOFF would be half of TOTAL_WEIGHT (indeed, it should not be).
+ // So scale scores under the cutoff between 0 and 0.5, and the scores over the cutoff
+ // between 0.5 and 1.0.
+ if (samenessScore < TOTAL_WEIGHT_CUTOFF) {
+ return samenessScore / (TOTAL_WEIGHT_CUTOFF * 2);
+ } else {
+ return (samenessScore - TOTAL_WEIGHT_CUTOFF) / (TOTAL_WEIGHT - TOTAL_WEIGHT_CUTOFF) / 2
+ + 0.5f;
+ }
+ }
+
+ /** @hide */
+ public static class Builder {
+ @Nullable
+ private Inet4Address mAssignedAddress;
+ @Nullable
+ private Long mAssignedAddressExpiry;
+ @Nullable
+ private String mGroupHint;
+ @Nullable
+ private List<InetAddress> mDnsAddresses;
+ @Nullable
+ private Integer mMtu;
+
+ /**
+ * Set the assigned address.
+ * @param assignedV4Address The assigned address.
+ * @return This builder.
+ */
+ public Builder setAssignedV4Address(@Nullable final Inet4Address assignedV4Address) {
+ mAssignedAddress = assignedV4Address;
+ return this;
+ }
+
+ /**
+ * Set the lease expiry timestamp of assigned v4 address. Long.MAX_VALUE is used
+ * to represent "infinite lease".
+ *
+ * @param assignedV4AddressExpiry The lease expiry timestamp of assigned v4 address.
+ * @return This builder.
+ */
+ public Builder setAssignedV4AddressExpiry(
+ @Nullable final Long assignedV4AddressExpiry) {
+ if (null != assignedV4AddressExpiry && assignedV4AddressExpiry <= 0) {
+ throw new IllegalArgumentException("lease expiry can't be negative or zero");
+ }
+ mAssignedAddressExpiry = assignedV4AddressExpiry;
+ return this;
+ }
+
+ /**
+ * Set the group hint.
+ * @param groupHint The group hint.
+ * @return This builder.
+ */
+ public Builder setGroupHint(@Nullable final String groupHint) {
+ mGroupHint = groupHint;
+ return this;
+ }
+
+ /**
+ * Set the DNS addresses.
+ * @param dnsAddresses The DNS addresses.
+ * @return This builder.
+ */
+ public Builder setDnsAddresses(@Nullable final List<InetAddress> dnsAddresses) {
+ if (DBG && null != dnsAddresses) {
+ // Parceling code crashes if one of the addresses is null, therefore validate
+ // them when running in debug.
+ for (final InetAddress address : dnsAddresses) {
+ if (null == address) throw new IllegalArgumentException("Null DNS address");
+ }
+ }
+ this.mDnsAddresses = dnsAddresses;
+ return this;
+ }
+
+ /**
+ * Set the MTU.
+ * @param mtu The MTU.
+ * @return This builder.
+ */
+ public Builder setMtu(@Nullable final Integer mtu) {
+ if (null != mtu && mtu < 0) throw new IllegalArgumentException("MTU can't be negative");
+ mMtu = mtu;
+ return this;
+ }
+
+ /**
+ * Return the built NetworkAttributes object.
+ * @return The built NetworkAttributes object.
+ */
+ public NetworkAttributes build() {
+ return new NetworkAttributes(mAssignedAddress, mAssignedAddressExpiry,
+ mGroupHint, mDnsAddresses, mMtu);
+ }
+ }
+
+ /** @hide */
+ public boolean isEmpty() {
+ return (null == assignedV4Address) && (null == assignedV4AddressExpiry)
+ && (null == groupHint) && (null == dnsAddresses) && (null == mtu);
+ }
+
+ @Override
+ public boolean equals(@Nullable final Object o) {
+ if (!(o instanceof NetworkAttributes)) return false;
+ final NetworkAttributes other = (NetworkAttributes) o;
+ return Objects.equals(assignedV4Address, other.assignedV4Address)
+ && Objects.equals(assignedV4AddressExpiry, other.assignedV4AddressExpiry)
+ && Objects.equals(groupHint, other.groupHint)
+ && Objects.equals(dnsAddresses, other.dnsAddresses)
+ && Objects.equals(mtu, other.mtu);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(assignedV4Address, assignedV4AddressExpiry,
+ groupHint, dnsAddresses, mtu);
+ }
+
+ /** Pretty print */
+ @Override
+ public String toString() {
+ final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
+ final ArrayList<String> nullFields = new ArrayList<>();
+
+ if (null != assignedV4Address) {
+ resultJoiner.add("assignedV4Addr :");
+ resultJoiner.add(assignedV4Address.toString());
+ } else {
+ nullFields.add("assignedV4Addr");
+ }
+
+ if (null != assignedV4AddressExpiry) {
+ resultJoiner.add("assignedV4AddressExpiry :");
+ resultJoiner.add(assignedV4AddressExpiry.toString());
+ } else {
+ nullFields.add("assignedV4AddressExpiry");
+ }
+
+ if (null != groupHint) {
+ resultJoiner.add("groupHint :");
+ resultJoiner.add(groupHint);
+ } else {
+ nullFields.add("groupHint");
+ }
+
+ if (null != dnsAddresses) {
+ resultJoiner.add("dnsAddr : [");
+ for (final InetAddress addr : dnsAddresses) {
+ resultJoiner.add(addr.getHostAddress());
+ }
+ resultJoiner.add("]");
+ } else {
+ nullFields.add("dnsAddr");
+ }
+
+ if (null != mtu) {
+ resultJoiner.add("mtu :");
+ resultJoiner.add(mtu.toString());
+ } else {
+ nullFields.add("mtu");
+ }
+
+ if (!nullFields.isEmpty()) {
+ resultJoiner.add("; Null fields : [");
+ for (final String field : nullFields) {
+ resultJoiner.add(field);
+ }
+ resultJoiner.add("]");
+ }
+
+ return resultJoiner.toString();
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributesParcelable.aidl b/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
new file mode 100644
index 0000000..997eb2b
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/NetworkAttributesParcelable.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.ipmemorystore;
+
+// Blob[] is used to represent an array of byte[], as structured AIDL does not support arrays
+// of arrays.
+import android.net.ipmemorystore.Blob;
+
+/**
+ * An object to represent attributes of a single L2 network entry.
+ * See NetworkAttributes.java for a description of each field. The types used in this class
+ * are structured parcelable types instead of the richer types of the NetworkAttributes object,
+ * but they have the same purpose. The NetworkAttributes.java file also contains the code
+ * to convert the richer types to the parcelable types and back.
+ * @hide
+ */
+parcelable NetworkAttributesParcelable {
+ byte[] assignedV4Address;
+ long assignedV4AddressExpiry;
+ String groupHint;
+ Blob[] dnsAddresses;
+ int mtu;
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnBlobRetrievedListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnBlobRetrievedListener.java
new file mode 100644
index 0000000..a17483a
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnBlobRetrievedListener.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.ipmemorystore;
+
+import android.annotation.NonNull;
+
+/**
+ * A listener for the IpMemoryStore to return a blob.
+ * @hide
+ */
+public interface OnBlobRetrievedListener {
+ /**
+ * The memory store has come up with the answer to a query that was sent.
+ */
+ void onBlobRetrieved(Status status, String l2Key, String name, Blob blob);
+
+ /** Converts this OnBlobRetrievedListener to a parcelable object */
+ @NonNull
+ static IOnBlobRetrievedListener toAIDL(@NonNull final OnBlobRetrievedListener listener) {
+ return new IOnBlobRetrievedListener.Stub() {
+ @Override
+ public void onBlobRetrieved(final StatusParcelable statusParcelable, final String l2Key,
+ final String name, final Blob blob) {
+ // NonNull, but still don't crash the system server if null
+ if (null != listener) {
+ listener.onBlobRetrieved(new Status(statusParcelable), l2Key, name, blob);
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+ };
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnL2KeyResponseListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnL2KeyResponseListener.java
new file mode 100644
index 0000000..e608aec
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnL2KeyResponseListener.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2019 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.ipmemorystore;
+
+import android.annotation.NonNull;
+
+/**
+ * A listener for the IpMemoryStore to return a L2 key.
+ * @hide
+ */
+public interface OnL2KeyResponseListener {
+ /**
+ * The operation has completed with the specified status.
+ */
+ void onL2KeyResponse(Status status, String l2Key);
+
+ /** Converts this OnL2KeyResponseListener to a parcelable object */
+ @NonNull
+ static IOnL2KeyResponseListener toAIDL(@NonNull final OnL2KeyResponseListener listener) {
+ return new IOnL2KeyResponseListener.Stub() {
+ @Override
+ public void onL2KeyResponse(final StatusParcelable statusParcelable,
+ final String l2Key) {
+ // NonNull, but still don't crash the system server if null
+ if (null != listener) {
+ listener.onL2KeyResponse(new Status(statusParcelable), l2Key);
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+ };
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
new file mode 100644
index 0000000..395ad98
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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.ipmemorystore;
+
+import android.annotation.NonNull;
+
+/**
+ * A listener for the IpMemoryStore to return network attributes.
+ * @hide
+ */
+public interface OnNetworkAttributesRetrievedListener {
+ /**
+ * The memory store has come up with the answer to a query that was sent.
+ */
+ void onNetworkAttributesRetrieved(Status status, String l2Key, NetworkAttributes attributes);
+
+ /** Converts this OnNetworkAttributesRetrievedListener to a parcelable object */
+ @NonNull
+ static IOnNetworkAttributesRetrievedListener toAIDL(
+ @NonNull final OnNetworkAttributesRetrievedListener listener) {
+ return new IOnNetworkAttributesRetrievedListener.Stub() {
+ @Override
+ public void onNetworkAttributesRetrieved(final StatusParcelable statusParcelable,
+ final String l2Key,
+ final NetworkAttributesParcelable networkAttributesParcelable) {
+ // NonNull, but still don't crash the system server if null
+ if (null != listener) {
+ listener.onNetworkAttributesRetrieved(
+ new Status(statusParcelable), l2Key, null == networkAttributesParcelable
+ ? null : new NetworkAttributes(networkAttributesParcelable));
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+ };
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
new file mode 100644
index 0000000..67f8da8
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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.ipmemorystore;
+
+import android.annotation.NonNull;
+
+/**
+ * A listener for the IpMemoryStore to return a response about network sameness.
+ * @hide
+ */
+public interface OnSameL3NetworkResponseListener {
+ /**
+ * The memory store has come up with the answer to a query that was sent.
+ */
+ void onSameL3NetworkResponse(Status status, SameL3NetworkResponse response);
+
+ /** Converts this OnSameL3NetworkResponseListener to a parcelable object */
+ @NonNull
+ static IOnSameL3NetworkResponseListener toAIDL(
+ @NonNull final OnSameL3NetworkResponseListener listener) {
+ return new IOnSameL3NetworkResponseListener.Stub() {
+ @Override
+ public void onSameL3NetworkResponse(final StatusParcelable statusParcelable,
+ final SameL3NetworkResponseParcelable sameL3NetworkResponseParcelable) {
+ // NonNull, but still don't crash the system server if null
+ if (null != listener) {
+ listener.onSameL3NetworkResponse(
+ new Status(statusParcelable),
+ new SameL3NetworkResponse(sameL3NetworkResponseParcelable));
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+ };
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/OnStatusListener.java b/common/networkstackclient/src/android/net/ipmemorystore/OnStatusListener.java
new file mode 100644
index 0000000..4262efd
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/OnStatusListener.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 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.ipmemorystore;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+/**
+ * A listener for the IpMemoryStore to return a status to a client.
+ * @hide
+ */
+public interface OnStatusListener {
+ /**
+ * The operation has completed with the specified status.
+ */
+ void onComplete(Status status);
+
+ /** Converts this OnStatusListener to a parcelable object */
+ @NonNull
+ static IOnStatusListener toAIDL(@Nullable final OnStatusListener listener) {
+ return new IOnStatusListener.Stub() {
+ @Override
+ public void onComplete(final StatusParcelable statusParcelable) {
+ if (null != listener) {
+ listener.onComplete(new Status(statusParcelable));
+ }
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+ };
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/SameL3NetworkResponse.java b/common/networkstackclient/src/android/net/ipmemorystore/SameL3NetworkResponse.java
new file mode 100644
index 0000000..291aca8
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/SameL3NetworkResponse.java
@@ -0,0 +1,147 @@
+/*
+ * 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.ipmemorystore;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * An object representing the answer to a query whether two given L2 networks represent the
+ * same L3 network. Parcels as a SameL3NetworkResponseParceled object.
+ * @hide
+ */
+public class SameL3NetworkResponse {
+ @IntDef(prefix = "NETWORK_",
+ value = {NETWORK_SAME, NETWORK_DIFFERENT, NETWORK_NEVER_CONNECTED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NetworkSameness {}
+
+ /**
+ * Both L2 networks represent the same L3 network.
+ */
+ public static final int NETWORK_SAME = 1;
+
+ /**
+ * The two L2 networks represent a different L3 network.
+ */
+ public static final int NETWORK_DIFFERENT = 2;
+
+ /**
+ * The device has never connected to at least one of these two L2 networks, or data
+ * has been wiped. Therefore the device has never seen the L3 network behind at least
+ * one of these two L2 networks, and can't evaluate whether it's the same as the other.
+ */
+ public static final int NETWORK_NEVER_CONNECTED = 3;
+
+ /**
+ * The first L2 key specified in the query.
+ */
+ @NonNull
+ public final String l2Key1;
+
+ /**
+ * The second L2 key specified in the query.
+ */
+ @NonNull
+ public final String l2Key2;
+
+ /**
+ * A confidence value indicating whether the two L2 networks represent the same L3 network.
+ *
+ * If both L2 networks were known, this value will be between 0.0 and 1.0, with 0.0
+ * representing complete confidence that the given L2 networks represent a different
+ * L3 network, and 1.0 representing complete confidence that the given L2 networks
+ * represent the same L3 network.
+ * If at least one of the L2 networks was not known, this value will be outside of the
+ * 0.0~1.0 range.
+ *
+ * Most apps should not be interested in this, and are encouraged to use the collapsing
+ * {@link #getNetworkSameness()} function below.
+ */
+ public final float confidence;
+
+ /**
+ * @return whether the two L2 networks represent the same L3 network. Either
+ * {@code NETWORK_SAME}, {@code NETWORK_DIFFERENT} or {@code NETWORK_NEVER_CONNECTED}.
+ */
+ @NetworkSameness
+ public final int getNetworkSameness() {
+ if (confidence > 1.0 || confidence < 0.0) return NETWORK_NEVER_CONNECTED;
+ return confidence > 0.5 ? NETWORK_SAME : NETWORK_DIFFERENT;
+ }
+
+ /** @hide */
+ public SameL3NetworkResponse(@NonNull final String l2Key1, @NonNull final String l2Key2,
+ final float confidence) {
+ this.l2Key1 = l2Key1;
+ this.l2Key2 = l2Key2;
+ this.confidence = confidence;
+ }
+
+ /** Builds a SameL3NetworkResponse from a parcelable object */
+ @VisibleForTesting
+ public SameL3NetworkResponse(@NonNull final SameL3NetworkResponseParcelable parceled) {
+ this(parceled.l2Key1, parceled.l2Key2, parceled.confidence);
+ }
+
+ /** Converts this SameL3NetworkResponse to a parcelable object */
+ @NonNull
+ public SameL3NetworkResponseParcelable toParcelable() {
+ final SameL3NetworkResponseParcelable parcelable = new SameL3NetworkResponseParcelable();
+ parcelable.l2Key1 = l2Key1;
+ parcelable.l2Key2 = l2Key2;
+ parcelable.confidence = confidence;
+ return parcelable;
+ }
+
+ // Note key1 and key2 have to match each other for this to return true. If
+ // key1 matches o.key2 and the other way around this returns false.
+ @Override
+ public boolean equals(@Nullable final Object o) {
+ if (!(o instanceof SameL3NetworkResponse)) return false;
+ final SameL3NetworkResponse other = (SameL3NetworkResponse) o;
+ return l2Key1.equals(other.l2Key1) && l2Key2.equals(other.l2Key2)
+ && confidence == other.confidence;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(l2Key1, l2Key2, confidence);
+ }
+
+ @Override
+ /** Pretty print */
+ public String toString() {
+ switch (getNetworkSameness()) {
+ case NETWORK_SAME:
+ return "\"" + l2Key1 + "\" same L3 network as \"" + l2Key2 + "\"";
+ case NETWORK_DIFFERENT:
+ return "\"" + l2Key1 + "\" different L3 network from \"" + l2Key2 + "\"";
+ case NETWORK_NEVER_CONNECTED:
+ return "\"" + l2Key1 + "\" can't be tested against \"" + l2Key2 + "\"";
+ default:
+ return "Buggy sameness value ? \"" + l2Key1 + "\", \"" + l2Key2 + "\"";
+ }
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl b/common/networkstackclient/src/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
new file mode 100644
index 0000000..7196699
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/SameL3NetworkResponseParcelable.aidl
@@ -0,0 +1,24 @@
+/*
+ * 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.ipmemorystore;
+
+/** {@hide} */
+parcelable SameL3NetworkResponseParcelable {
+ String l2Key1;
+ String l2Key2;
+ float confidence;
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/Status.java b/common/networkstackclient/src/android/net/ipmemorystore/Status.java
new file mode 100644
index 0000000..13242c0
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/Status.java
@@ -0,0 +1,74 @@
+/*
+ * 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.ipmemorystore;
+
+import android.annotation.NonNull;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * A parcelable status representing the result of an operation.
+ * Parcels as StatusParceled.
+ * @hide
+ */
+public class Status {
+ public static final int SUCCESS = 0;
+
+ public static final int ERROR_GENERIC = -1;
+ public static final int ERROR_ILLEGAL_ARGUMENT = -2;
+ public static final int ERROR_DATABASE_CANNOT_BE_OPENED = -3;
+ public static final int ERROR_STORAGE = -4;
+ public static final int ERROR_UNKNOWN = -5;
+
+ public final int resultCode;
+
+ public Status(final int resultCode) {
+ this.resultCode = resultCode;
+ }
+
+ @VisibleForTesting
+ public Status(@NonNull final StatusParcelable parcelable) {
+ this(parcelable.resultCode);
+ }
+
+ /** Converts this Status to a parcelable object */
+ @NonNull
+ public StatusParcelable toParcelable() {
+ final StatusParcelable parcelable = new StatusParcelable();
+ parcelable.resultCode = resultCode;
+ return parcelable;
+ }
+
+ public boolean isSuccess() {
+ return SUCCESS == resultCode;
+ }
+
+ /** Pretty print */
+ @Override
+ public String toString() {
+ switch (resultCode) {
+ case SUCCESS: return "SUCCESS";
+ case ERROR_GENERIC: return "GENERIC ERROR";
+ case ERROR_ILLEGAL_ARGUMENT: return "ILLEGAL ARGUMENT";
+ case ERROR_DATABASE_CANNOT_BE_OPENED: return "DATABASE CANNOT BE OPENED";
+ // "DB storage error" is not very helpful but SQLite does not provide specific error
+ // codes upon store failure. Thus this indicates SQLite returned some error upon store
+ case ERROR_STORAGE: return "DATABASE STORAGE ERROR";
+ default: return "Unknown value ?!";
+ }
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ipmemorystore/StatusParcelable.aidl b/common/networkstackclient/src/android/net/ipmemorystore/StatusParcelable.aidl
new file mode 100644
index 0000000..fb36ef4
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ipmemorystore/StatusParcelable.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.ipmemorystore;
+
+/** {@hide} */
+parcelable StatusParcelable {
+ int resultCode;
+}
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
new file mode 100644
index 0000000..b9d5337
--- /dev/null
+++ b/res/values/overlayable.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2019 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.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <overlayable name="NetworkStackConfig">
+ <policy type="product|system|vendor">
+ <!-- Configuration values for NetworkMonitor -->
+ <item type="integer" name="config_captive_portal_dns_probe_timeout"/>
+ <item type="string" name="config_captive_portal_http_url"/>
+ <item type="string" name="config_captive_portal_https_url"/>
+ <item type="array" name="config_captive_portal_fallback_urls"/>
+ <!-- Configuration value for DhcpResults -->
+ <item type="array" name="config_default_dns_servers"/>
+ </policy>
+ </overlayable>
+</resources>
diff --git a/src/android/net/apf/ApfFilter.java b/src/android/net/apf/ApfFilter.java
index 6075f69..1d3421c 100644
--- a/src/android/net/apf/ApfFilter.java
+++ b/src/android/net/apf/ApfFilter.java
@@ -31,6 +31,7 @@
import static com.android.server.util.NetworkStackConstants.ICMPV6_NEIGHBOR_ADVERTISEMENT;
import static com.android.server.util.NetworkStackConstants.ICMPV6_ROUTER_ADVERTISEMENT;
import static com.android.server.util.NetworkStackConstants.ICMPV6_ROUTER_SOLICITATION;
+import static com.android.server.util.NetworkStackConstants.IPV6_ADDR_LEN;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -548,6 +549,9 @@
// For debugging only. Offsets into the packet where RDNSS options are.
private final ArrayList<Integer> mRdnssOptionOffsets = new ArrayList<>();
+ // For debugging only. Offsets into the packet where RIO options are.
+ private final ArrayList<Integer> mRioOptionOffsets = new ArrayList<>();
+
// For debugging only. How many times this RA was seen.
int seenCount = 0;
@@ -598,6 +602,28 @@
for (int server = 0; server < numServers; server++) {
sb.append(" ").append(IPv6AddresstoString(offset + 8 + 16 * server));
}
+ sb.append(" ");
+ }
+
+ private void rioOptionToString(StringBuffer sb, int offset) {
+ int optLen = getUint8(mPacket, offset + 1) * 8;
+ if (optLen < 8 || optLen > 24) return; // Malformed or empty.
+ int prefixLen = getUint8(mPacket, offset + 2);
+ long lifetime = getUint32(mPacket, offset + 4);
+
+ // This read is variable length because the prefix can be 0, 8 or 16 bytes long.
+ // We can't use any of the ByteBuffer#get methods here because they all start reading
+ // from the buffer's current position.
+ byte[] prefix = new byte[IPV6_ADDR_LEN];
+ System.arraycopy(mPacket.array(), offset + 8, prefix, 0, optLen - 8);
+ sb.append("RIO ").append(lifetime).append("s ");
+ try {
+ InetAddress address = (Inet6Address) InetAddress.getByAddress(prefix);
+ sb.append(address.getHostAddress());
+ } catch (UnknownHostException impossible) {
+ sb.append("???");
+ }
+ sb.append("/").append(prefixLen).append(" ");
}
public String toString() {
@@ -613,6 +639,9 @@
for (int i: mRdnssOptionOffsets) {
rdnssOptionToString(sb, i);
}
+ for (int i: mRioOptionOffsets) {
+ rioOptionToString(sb, i);
+ }
return sb.toString();
} catch (BufferUnderflowException|IndexOutOfBoundsException e) {
return "<Malformed RA>";
@@ -649,7 +678,7 @@
// specifications.
Ra(byte[] packet, int length) throws InvalidRaException {
if (length < ICMP6_RA_OPTION_OFFSET) {
- throw new InvalidRaException("Not an ICMP6 router advertisement");
+ throw new InvalidRaException("Not an ICMP6 router advertisement: too short");
}
mPacket = ByteBuffer.wrap(Arrays.copyOf(packet, length));
@@ -716,6 +745,7 @@
builder.updateRdnssLifetime(lifetime);
break;
case ICMP6_ROUTE_INFO_OPTION_TYPE:
+ mRioOptionOffsets.add(position);
lastNonLifetimeStart = addNonLifetimeU32(lastNonLifetimeStart);
lifetime = getUint32(mPacket, position + ICMP6_4_BYTE_LIFETIME_OFFSET);
builder.updateRouteInfoLifetime(lifetime);
@@ -1559,7 +1589,11 @@
for (Ra ra : mRas) {
ra.generateFilterLocked(gen);
// Stop if we get too big.
- if (gen.programLengthOverEstimate() > maximumApfProgramSize) break;
+ if (gen.programLengthOverEstimate() > maximumApfProgramSize) {
+ if (VDBG) Log.d(TAG, "Past maximum program size, skipping RAs");
+ break;
+ }
+
rasToFilter.add(ra);
}
diff --git a/src/android/net/dhcp/DhcpClient.java b/src/android/net/dhcp/DhcpClient.java
index a140f4d..bf63c1c 100644
--- a/src/android/net/dhcp/DhcpClient.java
+++ b/src/android/net/dhcp/DhcpClient.java
@@ -31,6 +31,7 @@
import static android.net.dhcp.DhcpPacket.INFINITE_LEASE;
import static android.net.util.NetworkStackUtils.closeSocketQuietly;
import static android.net.util.SocketUtils.makePacketSocketAddress;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_PACKET;
import static android.system.OsConstants.ETH_P_IP;
@@ -361,7 +362,7 @@
*
*/
public boolean isDhcpLeaseCacheEnabled() {
- return mDependencies.getBooleanDeviceConfig(NetworkStackUtils.NAMESPACE_CONNECTIVITY,
+ return mDependencies.getBooleanDeviceConfig(NAMESPACE_CONNECTIVITY,
NetworkStackUtils.DHCP_INIT_REBOOT_ENABLED);
}
@@ -369,7 +370,7 @@
* check whether or not to support DHCP Rapid Commit option.
*/
public boolean isDhcpRapidCommitEnabled() {
- return mDependencies.getBooleanDeviceConfig(NetworkStackUtils.NAMESPACE_CONNECTIVITY,
+ return mDependencies.getBooleanDeviceConfig(NAMESPACE_CONNECTIVITY,
NetworkStackUtils.DHCP_RAPID_COMMIT_ENABLED);
}
diff --git a/src/android/net/dhcp/DhcpServer.java b/src/android/net/dhcp/DhcpServer.java
index b8ab94c..f75fe18 100644
--- a/src/android/net/dhcp/DhcpServer.java
+++ b/src/android/net/dhcp/DhcpServer.java
@@ -20,8 +20,6 @@
import static android.net.dhcp.DhcpPacket.DHCP_HOST_NAME;
import static android.net.dhcp.DhcpPacket.DHCP_SERVER;
import static android.net.dhcp.DhcpPacket.ENCAP_BOOTP;
-import static android.net.dhcp.IDhcpServer.STATUS_INVALID_ARGUMENT;
-import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
import static android.net.shared.Inet4AddressUtils.getBroadcastAddress;
import static android.net.shared.Inet4AddressUtils.getPrefixMaskAsInet4Address;
import static android.system.OsConstants.AF_INET;
@@ -36,7 +34,7 @@
import static com.android.server.util.NetworkStackConstants.INFINITE_LEASE;
import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ALL;
import static com.android.server.util.NetworkStackConstants.IPV4_ADDR_ANY;
-import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
+import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;
import static java.lang.Integer.toUnsignedLong;
@@ -213,7 +211,7 @@
@Override
public void checkCaller() {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
}
}
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index 799184e..98e1e49 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -19,7 +19,7 @@
import static android.net.RouteInfo.RTN_UNICAST;
import static android.net.shared.IpConfigurationParcelableUtil.toStableParcelable;
-import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
+import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;
import android.annotation.NonNull;
import android.content.Context;
@@ -48,6 +48,7 @@
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.LocalLog;
@@ -514,67 +515,67 @@
class IpClientConnector extends IIpClient.Stub {
@Override
public void completedPreDhcpAction() {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.completedPreDhcpAction();
}
@Override
public void confirmConfiguration() {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.confirmConfiguration();
}
@Override
public void readPacketFilterComplete(byte[] data) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.readPacketFilterComplete(data);
}
@Override
public void shutdown() {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.shutdown();
}
@Override
public void startProvisioning(ProvisioningConfigurationParcelable req) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.startProvisioning(ProvisioningConfiguration.fromStableParcelable(req));
}
@Override
public void stop() {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.stop();
}
@Override
public void setL2KeyAndGroupHint(String l2Key, String groupHint) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.setL2KeyAndGroupHint(l2Key, groupHint);
}
@Override
public void setTcpBufferSizes(String tcpBufferSizes) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.setTcpBufferSizes(tcpBufferSizes);
}
@Override
public void setHttpProxy(ProxyInfo proxyInfo) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.setHttpProxy(proxyInfo);
}
@Override
public void setMulticastFilter(boolean enabled) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.setMulticastFilter(enabled);
}
@Override
public void addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.addKeepalivePacketFilter(slot, pkt);
}
@Override
public void addNattKeepalivePacketFilter(int slot, NattKeepalivePacketDataParcelable pkt) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.addNattKeepalivePacketFilter(slot, pkt);
}
@Override
public void removeKeepalivePacketFilter(int slot) {
- checkNetworkStackCallingPermission();
+ enforceNetworkStackCallingPermission();
IpClient.this.removeKeepalivePacketFilter(slot);
}
@@ -850,10 +851,12 @@
return shouldLog;
}
+ private void logError(String fmt, Throwable e, Object... args) {
+ mLog.e(String.format(fmt, args), e);
+ }
+
private void logError(String fmt, Object... args) {
- final String msg = "ERROR " + String.format(fmt, args);
- Log.e(mTag, msg);
- mLog.log(msg);
+ logError(fmt, null, args);
}
// This needs to be called with care to ensure that our LinkProperties
@@ -948,7 +951,7 @@
// accompanying code in IpReachabilityMonitor) is unreachable.
final boolean ignoreIPv6ProvisioningLoss =
mConfiguration != null && mConfiguration.mUsingMultinetworkPolicyTracker
- && mCm.shouldAvoidBadWifi();
+ && !mCm.shouldAvoidBadWifi();
// Additionally:
//
@@ -1274,6 +1277,28 @@
// TODO : implement this
}
+ private void maybeRestoreInterfaceMtu() {
+ InterfaceParams params = mDependencies.getInterfaceParams(mInterfaceName);
+ if (params == null) {
+ Log.w(mTag, "interface: " + mInterfaceName + " is gone");
+ return;
+ }
+
+ if (params.index != mInterfaceParams.index) {
+ Log.w(mTag, "interface: " + mInterfaceName + " has a different index: " + params.index);
+ return;
+ }
+
+ if (params.defaultMtu == mInterfaceParams.defaultMtu) return;
+
+ try {
+ mNetd.interfaceSetMtu(mInterfaceName, mInterfaceParams.defaultMtu);
+ } catch (RemoteException | ServiceSpecificException e) {
+ logError("Couldn't reset MTU on " + mInterfaceName + " from "
+ + params.defaultMtu + " to " + mInterfaceParams.defaultMtu, e);
+ }
+ }
+
class StoppedState extends State {
@Override
public void enter() {
@@ -1351,6 +1376,9 @@
// There's no DHCPv4 for which to wait; proceed to stopped.
deferMessage(obtainMessage(CMD_JUMP_STOPPING_TO_STOPPED));
}
+
+ // Restore the interface MTU to initial value if it has changed.
+ maybeRestoreInterfaceMtu();
}
@Override
diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java
index 4afc34b..0a18c0e 100644
--- a/src/android/net/util/NetworkStackUtils.java
+++ b/src/android/net/util/NetworkStackUtils.java
@@ -18,6 +18,10 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.provider.DeviceConfig;
+import android.util.Log;
import android.util.SparseArray;
import java.io.FileDescriptor;
@@ -33,8 +37,7 @@
* Collection of utilities for the network stack.
*/
public class NetworkStackUtils {
- // TODO: Refer to DeviceConfig definition.
- public static final String NAMESPACE_CONNECTIVITY = "connectivity";
+ private static final String TAG = "NetworkStackUtils";
/**
* A list of captive portal detection specifications used in addition to the fallback URLs.
@@ -183,8 +186,8 @@
@Nullable
public static String getDeviceConfigProperty(@NonNull String namespace, @NonNull String name,
@Nullable String defaultValue) {
- // TODO: Link to DeviceConfig API once it is ready.
- return defaultValue;
+ String value = DeviceConfig.getProperty(namespace, name);
+ return value != null ? value : defaultValue;
}
/**
@@ -218,6 +221,30 @@
}
/**
+ * Check whether or not one specific experimental feature for a particular namespace from
+ * {@link DeviceConfig} is enabled by comparing NetworkStack module version {@link NetworkStack}
+ * with current version of property. If this property version is valid, the corresponding
+ * experimental feature would be enabled, otherwise disabled.
+ * @param context The global context information about an app environment.
+ * @param namespace The namespace containing the property to look up.
+ * @param name The name of the property to look up.
+ * @return true if this feature is enabled, or false if disabled.
+ */
+ public static boolean isFeatureEnabled(@NonNull Context context, @NonNull String namespace,
+ @NonNull String name) {
+ try {
+ final int propertyVersion = getDeviceConfigPropertyInt(namespace, name,
+ 0 /* default value */);
+ final long packageVersion = context.getPackageManager().getPackageInfo(
+ context.getPackageName(), 0).getLongVersionCode();
+ return (propertyVersion != 0 && packageVersion >= (long) propertyVersion);
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not find the package name", e);
+ return false;
+ }
+ }
+
+ /**
* Attaches a socket filter that accepts DHCP packets to the given socket.
*/
public static native void attachDhcpFilter(FileDescriptor fd) throws SocketException;
diff --git a/src/com/android/networkstack/apishim/SocketUtilsShim.java b/src/com/android/networkstack/apishim/SocketUtilsShim.java
new file mode 100644
index 0000000..34b5f40
--- /dev/null
+++ b/src/com/android/networkstack/apishim/SocketUtilsShim.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.networkstack.apishim;
+
+import androidx.annotation.NonNull;
+
+import java.net.SocketAddress;
+
+/**
+ * Interface used to access API methods in {@link android.net.util.SocketUtils}, with appropriate
+ * fallbacks if the methods are not yet part of the released API.
+ *
+ * <p>This interface makes it easier for callers to use SocketUtilsShimImpl, as it's more obvious
+ * what methods must be implemented on each API level, and it abstracts from callers the need to
+ * reference classes that have different implementations (which also does not work well with IDEs).
+ */
+public interface SocketUtilsShim {
+ /**
+ * Create a new instance of SocketUtilsShim.
+ */
+ @NonNull
+ static SocketUtilsShim newInstance() {
+ // TODO: when the R API is finalized, rename the API 29 shim to SocketUtilsCompat, and
+ // return it here instead of SocketUtilsShimImpl for devices with Build.VERSION <= 29.
+ // For now, the switch between implementations is done at build time (swapping the java file
+ // with another), since production modules should not be built with a non-finalized API.
+ return new SocketUtilsShimImpl();
+ }
+
+ /**
+ * @see android.net.util.SocketUtils#makePacketSocketAddress(int, int, byte[])
+ */
+ @NonNull
+ SocketAddress makePacketSocketAddress(int protocol, int ifIndex, @NonNull byte[] hwAddr);
+}
diff --git a/src/com/android/networkstack/metrics/DataStallStatsUtils.java b/src/com/android/networkstack/metrics/DataStallStatsUtils.java
index 9308901..59e8fd3 100644
--- a/src/com/android/networkstack/metrics/DataStallStatsUtils.java
+++ b/src/com/android/networkstack/metrics/DataStallStatsUtils.java
@@ -21,6 +21,8 @@
import android.net.captiveportal.CaptivePortalProbeResult;
import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
import com.android.internal.util.HexDump;
import com.android.server.connectivity.nano.DataStallEventProto;
@@ -38,7 +40,11 @@
private static final String TAG = DataStallStatsUtils.class.getSimpleName();
private static final boolean DBG = false;
- private static int probeResultToEnum(@Nullable final CaptivePortalProbeResult result) {
+ /**
+ * Map {@link CaptivePortalProbeResult} to {@link DataStallEventProto}.
+ */
+ @VisibleForTesting
+ public static int probeResultToEnum(@Nullable final CaptivePortalProbeResult result) {
if (result == null) return DataStallEventProto.INVALID;
if (result.isSuccessful()) {
diff --git a/src/com/android/server/NetworkStackService.java b/src/com/android/server/NetworkStackService.java
index 91cc8c3..9e5ed74 100644
--- a/src/com/android/server/NetworkStackService.java
+++ b/src/com/android/server/NetworkStackService.java
@@ -21,14 +21,12 @@
import static android.net.dhcp.IDhcpServer.STATUS_UNKNOWN_ERROR;
import static com.android.server.util.PermissionUtil.checkDumpPermission;
-import static com.android.server.util.PermissionUtil.checkNetworkStackCallingPermission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.net.ConnectivityManager;
import android.net.IIpMemoryStore;
import android.net.IIpMemoryStoreCallbacks;
import android.net.INetd;
@@ -49,11 +47,15 @@
import android.net.util.SharedLog;
import android.os.IBinder;
import android.os.RemoteException;
+import android.util.ArraySet;
+
+import androidx.annotation.VisibleForTesting;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.connectivity.NetworkMonitor;
import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
+import com.android.server.util.PermissionUtil;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -62,7 +64,6 @@
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicInteger;
/**
* Android service used to start the network stack when bound to via an intent.
@@ -81,7 +82,8 @@
*/
public static synchronized IBinder makeConnector(Context context) {
if (sConnector == null) {
- sConnector = new NetworkStackConnector(context);
+ sConnector = new NetworkStackConnector(
+ context, new NetworkStackConnector.PermissionChecker());
}
return sConnector;
}
@@ -103,13 +105,17 @@
IIpMemoryStore getIpMemoryStoreService();
}
- private static class NetworkStackConnector extends INetworkStackConnector.Stub
+ /**
+ * Connector implementing INetworkStackConnector for clients.
+ */
+ @VisibleForTesting
+ public static class NetworkStackConnector extends INetworkStackConnector.Stub
implements NetworkStackServiceManager {
private static final int NUM_VALIDATION_LOG_LINES = 20;
private final Context mContext;
+ private final PermissionChecker mPermChecker;
private final INetd mNetd;
private final NetworkObserverRegistry mObserverRegistry;
- private final ConnectivityManager mCm;
@GuardedBy("mIpClients")
private final ArrayList<WeakReference<IpClient>> mIpClients = new ArrayList<>();
private final IpMemoryStoreService mIpMemoryStoreService;
@@ -118,14 +124,25 @@
@GuardedBy("mValidationLogs")
private final ArrayDeque<SharedLog> mValidationLogs = new ArrayDeque<>(MAX_VALIDATION_LOGS);
- private static final int VERSION_UNKNOWN = 0;
private static final String DUMPSYS_ARG_VERSION = "version";
- /** Version of the AIDL interfaces observed on the system */
- private final AtomicInteger mSystemAidlVersion = new AtomicInteger(VERSION_UNKNOWN);
+ /** Version of the framework AIDL interfaces observed. Should hold only one value. */
+ @GuardedBy("mFrameworkAidlVersions")
+ private final ArraySet<Integer> mFrameworkAidlVersions = new ArraySet<>(1);
+ private final int mNetdAidlVersion;
- /** Whether different versions have been observed on interfaces provided by the system */
- private volatile boolean mConflictingSystemAidlVersions = false;
+ /**
+ * Permission checking dependency of the connector, useful for testing.
+ */
+ @VisibleForTesting
+ public static class PermissionChecker {
+ /**
+ * @see PermissionUtil#enforceNetworkStackCallingPermission()
+ */
+ public void enforceNetworkStackCallingPermission() {
+ PermissionUtil.enforceNetworkStackCallingPermission();
+ }
+ }
private SharedLog addValidationLogs(Network network, String name) {
final SharedLog log = new SharedLog(NUM_VALIDATION_LOG_LINES, network + " - " + name);
@@ -138,14 +155,25 @@
return log;
}
- NetworkStackConnector(Context context) {
+ @VisibleForTesting
+ public NetworkStackConnector(
+ @NonNull Context context, @NonNull PermissionChecker permChecker) {
mContext = context;
+ mPermChecker = permChecker;
mNetd = INetd.Stub.asInterface(
(IBinder) context.getSystemService(Context.NETD_SERVICE));
mObserverRegistry = new NetworkObserverRegistry();
- mCm = context.getSystemService(ConnectivityManager.class);
mIpMemoryStoreService = new IpMemoryStoreService(context);
+ int netdVersion;
+ try {
+ netdVersion = mNetd.getInterfaceVersion();
+ } catch (RemoteException e) {
+ mLog.e("Error obtaining INetd version", e);
+ netdVersion = -1;
+ }
+ mNetdAidlVersion = netdVersion;
+
try {
mObserverRegistry.register(mNetd);
} catch (RemoteException e) {
@@ -154,9 +182,8 @@
}
private void updateSystemAidlVersion(final int version) {
- final int previousVersion = mSystemAidlVersion.getAndSet(version);
- if (previousVersion != VERSION_UNKNOWN && previousVersion != version) {
- mConflictingSystemAidlVersions = true;
+ synchronized (mFrameworkAidlVersions) {
+ mFrameworkAidlVersions.add(version);
}
}
@@ -166,7 +193,7 @@
@Override
public void makeDhcpServer(@NonNull String ifName, @NonNull DhcpServingParamsParcel params,
@NonNull IDhcpServerCallbacks cb) throws RemoteException {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
final DhcpServer server;
try {
@@ -189,16 +216,16 @@
@Override
public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)
throws RemoteException {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
final SharedLog log = addValidationLogs(network, name);
final NetworkMonitor nm = new NetworkMonitor(mContext, cb, network, log);
- cb.onNetworkMonitorCreated(new NetworkMonitorImpl(nm));
+ cb.onNetworkMonitorCreated(new NetworkMonitorConnector(nm, mPermChecker));
}
@Override
public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
final IpClient ipClient = new IpClient(mContext, ifName, cb, mObserverRegistry, this);
@@ -224,7 +251,7 @@
@Override
public void fetchIpMemoryStore(@NonNull final IIpMemoryStoreCallbacks cb)
throws RemoteException {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
cb.onIpMemoryStoreFetched(mIpMemoryStoreService);
}
@@ -233,12 +260,16 @@
protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
@Nullable String[] args) {
checkDumpPermission();
+
+ final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
+ pw.println("NetworkStack version:");
+ dumpVersion(pw);
+ pw.println();
+
if (args != null && args.length >= 1 && DUMPSYS_ARG_VERSION.equals(args[0])) {
- dumpVersion(fout);
return;
}
- final IndentingPrintWriter pw = new IndentingPrintWriter(fout, " ");
pw.println("NetworkStack logs:");
mLog.dump(fd, pw, args);
@@ -286,86 +317,100 @@
*/
private void dumpVersion(@NonNull PrintWriter fout) {
fout.println("NetworkStackConnector: " + this.VERSION);
- fout.println("SystemServer: " + mSystemAidlVersion);
- fout.println("SystemServerConflicts: " + mConflictingSystemAidlVersions);
+ synchronized (mFrameworkAidlVersions) {
+ fout.println("SystemServer: " + mFrameworkAidlVersions);
+ }
+ fout.println("Netd: " + mNetdAidlVersion);
}
+ /**
+ * Get the version of the AIDL interface.
+ */
@Override
public int getInterfaceVersion() {
return this.VERSION;
}
}
- private static class NetworkMonitorImpl extends INetworkMonitor.Stub {
+ /**
+ * Proxy for {@link NetworkMonitor} that implements {@link INetworkMonitor}.
+ */
+ @VisibleForTesting
+ public static class NetworkMonitorConnector extends INetworkMonitor.Stub {
+ @NonNull
private final NetworkMonitor mNm;
+ @NonNull
+ private final NetworkStackConnector.PermissionChecker mPermChecker;
- NetworkMonitorImpl(NetworkMonitor nm) {
+ public NetworkMonitorConnector(@NonNull NetworkMonitor nm,
+ @NonNull NetworkStackConnector.PermissionChecker permChecker) {
mNm = nm;
+ mPermChecker = permChecker;
}
@Override
public void start() {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.start();
}
@Override
public void launchCaptivePortalApp() {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.launchCaptivePortalApp();
}
@Override
public void notifyCaptivePortalAppFinished(int response) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyCaptivePortalAppFinished(response);
}
@Override
public void setAcceptPartialConnectivity() {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.setAcceptPartialConnectivity();
}
@Override
public void forceReevaluation(int uid) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.forceReevaluation(uid);
}
@Override
public void notifyPrivateDnsChanged(PrivateDnsConfigParcel config) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyPrivateDnsSettingsChanged(PrivateDnsConfig.fromParcel(config));
}
@Override
public void notifyDnsResponse(int returnCode) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyDnsResponse(returnCode);
}
@Override
public void notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyNetworkConnected(lp, nc);
}
@Override
public void notifyNetworkDisconnected() {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyNetworkDisconnected();
}
@Override
public void notifyLinkPropertiesChanged(LinkProperties lp) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyLinkPropertiesChanged(lp);
}
@Override
public void notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) {
- checkNetworkStackCallingPermission();
+ mPermChecker.enforceNetworkStackCallingPermission();
mNm.notifyNetworkCapabilitiesChanged(nc);
}
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index 6122d98..585e38e 100644
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -62,8 +62,8 @@
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_OTHER_FALLBACK_URLS;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USER_AGENT;
import static android.net.util.NetworkStackUtils.CAPTIVE_PORTAL_USE_HTTPS;
-import static android.net.util.NetworkStackUtils.NAMESPACE_CONNECTIVITY;
import static android.net.util.NetworkStackUtils.isEmpty;
+import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static com.android.networkstack.util.DnsUtils.PRIVATE_DNS_PROBE_HOST_SUFFIX;
import static com.android.networkstack.util.DnsUtils.TYPE_ADDRCONFIG;
@@ -379,7 +379,7 @@
}
@VisibleForTesting
- protected NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
+ public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
IpConnectivityLog logger, SharedLog validationLogs,
Dependencies deps, DataStallStatsUtils detectionStatsUtils) {
// Add suffix indicating which NetworkMonitor we're talking about.
@@ -1843,8 +1843,7 @@
latencyBroadcast.putExtra(NetworkMonitorUtils.EXTRA_RESPONSE_TIMESTAMP_MS,
responseTimestampMs);
}
- mContext.sendBroadcastAsUser(latencyBroadcast, UserHandle.CURRENT,
- NetworkMonitorUtils.PERMISSION_ACCESS_NETWORK_CONDITIONS);
+ mDependencies.sendNetworkConditionsBroadcast(mContext, latencyBroadcast);
}
private void logNetworkEvent(int evtype) {
@@ -1889,7 +1888,7 @@
}
@VisibleForTesting
- static class Dependencies {
+ public static class Dependencies {
public Network getPrivateDnsBypassNetwork(Network network) {
return new OneAddressPerFamilyNetwork(network);
}
@@ -1948,6 +1947,15 @@
return NetworkStackUtils.getDeviceConfigPropertyInt(namespace, name, defaultValue);
}
+ /**
+ * Send a broadcast indicating network conditions.
+ */
+ public void sendNetworkConditionsBroadcast(@NonNull Context context,
+ @NonNull Intent broadcast) {
+ context.sendBroadcastAsUser(broadcast, UserHandle.CURRENT,
+ NetworkMonitorUtils.PERMISSION_ACCESS_NETWORK_CONDITIONS);
+ }
+
public static final Dependencies DEFAULT = new Dependencies();
}
diff --git a/src/com/android/server/util/NetworkStackConstants.java b/src/com/android/server/util/NetworkStackConstants.java
index 804765e..3174a9b 100644
--- a/src/com/android/server/util/NetworkStackConstants.java
+++ b/src/com/android/server/util/NetworkStackConstants.java
@@ -54,6 +54,7 @@
public static final int ETHER_TYPE_IPV4 = 0x0800;
public static final int ETHER_TYPE_IPV6 = 0x86dd;
public static final int ETHER_HEADER_LEN = 14;
+ public static final int ETHER_MTU = 1500;
/**
* ARP constants.
@@ -97,6 +98,7 @@
public static final int IPV6_PROTOCOL_OFFSET = 6;
public static final int IPV6_SRC_ADDR_OFFSET = 8;
public static final int IPV6_DST_ADDR_OFFSET = 24;
+ public static final int IPV6_MIN_MTU = 1280;
/**
* ICMPv6 constants.
diff --git a/src/com/android/server/util/PermissionUtil.java b/src/com/android/server/util/PermissionUtil.java
index c4d736b..28dad25 100644
--- a/src/com/android/server/util/PermissionUtil.java
+++ b/src/com/android/server/util/PermissionUtil.java
@@ -34,7 +34,7 @@
* Check that the caller is allowed to communicate with the network stack.
* @throws SecurityException The caller is not allowed to communicate with the network stack.
*/
- public static void checkNetworkStackCallingPermission() {
+ public static void enforceNetworkStackCallingPermission() {
final int caller = getCallingUid();
if (caller == Process.SYSTEM_UID) {
checkConsistentSystemPid();
diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp
index ec8257f..89b3968 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -23,7 +23,8 @@
"androidx.annotation_annotation",
"androidx.test.rules",
"mockito-target-extended-minus-junit4",
- "NetworkStackBase",
+ "net-tests-utils",
+ "NetworkStackApiCurrentLib",
"testables",
],
libs: [
diff --git a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
index 16e92ef..cb7d418 100644
--- a/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
+++ b/tests/integration/src/android/net/ip/IpClientIntegrationTest.java
@@ -34,6 +34,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.timeout;
@@ -49,6 +50,7 @@
import android.net.ConnectivityManager;
import android.net.INetd;
import android.net.InetAddresses;
+import android.net.LinkProperties;
import android.net.NetworkStackIpMemoryStore;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
@@ -68,6 +70,8 @@
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
+import android.system.ErrnoException;
+import android.system.Os;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
@@ -77,6 +81,7 @@
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService.NetworkStackServiceManager;
import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
+import com.android.testutils.HandlerUtilsKt;
import org.junit.After;
import org.junit.Before;
@@ -91,6 +96,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.Inet4Address;
+import java.net.NetworkInterface;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
@@ -112,7 +118,7 @@
@Mock private Context mContext;
@Mock private ConnectivityManager mCm;
- @Mock private INetd mNetd;
+ @Mock private INetd mMockNetd;
@Mock private Resources mResources;
@Mock private IIpClientCallbacks mCb;
@Mock private AlarmManager mAlarm;
@@ -122,6 +128,7 @@
@Mock private IpMemoryStoreService mIpMemoryStoreService;
private String mIfaceName;
+ private INetd mNetd;
private HandlerThread mPacketReaderThread;
private TapPacketReader mPacketReader;
private IpClient mIpc;
@@ -158,7 +165,8 @@
private static final Inet4Address BROADCAST_ADDR = getBroadcastAddress(
SERVER_ADDR, PREFIX_LENGTH);
private static final String HOSTNAME = "testhostname";
- private static final short MTU = 1500;
+ private static final int TEST_DEFAULT_MTU = 1500;
+ private static final int TEST_MIN_MTU = 1280;
private static class TapPacketReader extends PacketReader {
private final ParcelFileDescriptor mTapFd;
@@ -214,7 +222,7 @@
@Override
public INetd getNetd(Context context) {
- return mNetd;
+ return mMockNetd;
}
@Override
@@ -287,7 +295,6 @@
inst.getUiAutomation().dropShellPermissionIdentity();
}
mIfaceName = iface.getInterfaceName();
-
mPacketReaderThread = new HandlerThread(IpClientIntegrationTest.class.getSimpleName());
mPacketReaderThread.start();
@@ -300,12 +307,12 @@
final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
final IBinder netdIBinder =
(IBinder) inst.getContext().getSystemService(Context.NETD_SERVICE);
- final INetd netd = INetd.Stub.asInterface(netdIBinder);
+ mNetd = INetd.Stub.asInterface(netdIBinder);
when(mContext.getSystemService(eq(Context.NETD_SERVICE))).thenReturn(netdIBinder);
- assertNotNull(netd);
+ assertNotNull(mNetd);
final NetworkObserverRegistry reg = new NetworkObserverRegistry();
- reg.register(netd);
+ reg.register(mNetd);
mIpc = new IpClient(mContext, mIfaceName, mCb, reg, mNetworkStackServiceManager,
mDependencies);
}
@@ -345,7 +352,7 @@
}
private static ByteBuffer buildDhcpOfferPacket(final DhcpPacket packet,
- final Integer leaseTimeSec) {
+ final Integer leaseTimeSec, final short mtu) {
return DhcpPacket.buildOfferPacket(DhcpPacket.ENCAP_L2, packet.getTransactionId(),
false /* broadcast */, SERVER_ADDR, INADDR_ANY /* relayIp */,
CLIENT_ADDR /* yourIp */, packet.getClientMac(), leaseTimeSec,
@@ -353,11 +360,11 @@
Collections.singletonList(SERVER_ADDR) /* gateways */,
Collections.singletonList(SERVER_ADDR) /* dnsServers */,
SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, HOSTNAME,
- false /* metered */, MTU);
+ false /* metered */, mtu);
}
private static ByteBuffer buildDhcpAckPacket(final DhcpPacket packet,
- final Integer leaseTimeSec) {
+ final Integer leaseTimeSec, final short mtu) {
return DhcpPacket.buildAckPacket(DhcpPacket.ENCAP_L2, packet.getTransactionId(),
false /* broadcast */, SERVER_ADDR, INADDR_ANY /* relayIp */,
CLIENT_ADDR /* yourIp */, CLIENT_ADDR /* requestIp */, packet.getClientMac(),
@@ -365,7 +372,7 @@
Collections.singletonList(SERVER_ADDR) /* gateways */,
Collections.singletonList(SERVER_ADDR) /* dnsServers */,
SERVER_ADDR /* dhcpServerIdentifier */, null /* domainName */, HOSTNAME,
- false /* metered */, MTU);
+ false /* metered */, mtu);
}
private static ByteBuffer buildDhcpNakPacket(final DhcpPacket packet) {
@@ -391,13 +398,13 @@
mDependencies.setDhcpRapidCommitEnabled(isDhcpRapidCommitEnabled);
mIpc.setL2KeyAndGroupHint(TEST_L2KEY, TEST_GROUPHINT);
mIpc.startProvisioning(config);
- verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
- verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
+ verify(mCb).setNeighborDiscoveryOffload(true);
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).setFallbackMulticastFilter(false);
verify(mCb, never()).onProvisioningFailure(any());
}
private void assertIpMemoryStoreNetworkAttributes(final Integer leaseTimeSec,
- final long startTime) {
+ final long startTime, final int mtu) {
final ArgumentCaptor<NetworkAttributes> networkAttributes =
ArgumentCaptor.forClass(NetworkAttributes.class);
@@ -416,7 +423,7 @@
assertTrue(lowerBound < expiry);
}
assertEquals(Collections.singletonList(SERVER_ADDR), naValueCaptured.dnsAddresses);
- assertEquals(new Integer((int) MTU), naValueCaptured.mtu);
+ assertEquals(new Integer(mtu), naValueCaptured.mtu);
}
private void assertIpMemoryNeverStoreNetworkAttributes() {
@@ -426,20 +433,20 @@
// Helper method to complete DHCP 2-way or 4-way handshake
private void performDhcpHandshake(final boolean isSuccessLease,
final Integer leaseTimeSec, final boolean isDhcpLeaseCacheEnabled,
- final boolean isDhcpRapidCommitEnabled) throws Exception {
+ final boolean isDhcpRapidCommitEnabled, final int mtu) throws Exception {
startIpClientProvisioning(isDhcpLeaseCacheEnabled, isDhcpRapidCommitEnabled);
DhcpPacket packet;
while ((packet = getNextDhcpPacket()) != null) {
if (packet instanceof DhcpDiscoverPacket) {
if (isDhcpRapidCommitEnabled) {
- sendResponse(buildDhcpAckPacket(packet, leaseTimeSec));
+ sendResponse(buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu));
} else {
- sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec));
+ sendResponse(buildDhcpOfferPacket(packet, leaseTimeSec, (short) mtu));
}
} else if (packet instanceof DhcpRequestPacket) {
final ByteBuffer byteBuffer = isSuccessLease
- ? buildDhcpAckPacket(packet, leaseTimeSec)
+ ? buildDhcpAckPacket(packet, leaseTimeSec, (short) mtu)
: buildDhcpNakPacket(packet);
sendResponse(byteBuffer);
} else {
@@ -474,6 +481,53 @@
return getNextDhcpPacket();
}
+ private void removeTapInterface(final FileDescriptor fd) {
+ try {
+ Os.close(fd);
+ } catch (ErrnoException e) {
+ fail("Fail to close file descriptor: " + e);
+ }
+ }
+
+ private void verifyAfterIpClientShutdown() throws RemoteException {
+ final LinkProperties emptyLp = new LinkProperties();
+ emptyLp.setInterfaceName(mIfaceName);
+ verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(emptyLp);
+ }
+
+ private void doRestoreInitialMtuTest(final boolean shouldChangeMtu,
+ final boolean shouldRemoveTapInterface) throws Exception {
+ final long currentTime = System.currentTimeMillis();
+ int mtu = TEST_DEFAULT_MTU;
+
+ if (shouldChangeMtu) mtu = TEST_MIN_MTU;
+ performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
+ true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */, mtu);
+ assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, mtu);
+
+ if (shouldChangeMtu) {
+ // Pretend that ConnectivityService set the MTU.
+ mNetd.interfaceSetMtu(mIfaceName, mtu);
+ assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), mtu);
+ }
+
+ if (shouldRemoveTapInterface) removeTapInterface(mPacketReader.createFd());
+ try {
+ mIpc.shutdown();
+ HandlerUtilsKt.waitForIdle(mIpc.getHandler(), TEST_TIMEOUT_MS);
+ if (shouldRemoveTapInterface) {
+ verify(mMockNetd, never()).interfaceSetMtu(mIfaceName, TEST_DEFAULT_MTU);
+ } else {
+ // Verify that MTU indeed has been restored or not.
+ verify(mMockNetd, times(shouldChangeMtu ? 1 : 0))
+ .interfaceSetMtu(mIfaceName, TEST_DEFAULT_MTU);
+ }
+ verifyAfterIpClientShutdown();
+ } catch (Exception e) {
+ fail("Exception should not have been thrown after shutdown: " + e);
+ }
+ }
+
@Test
public void testDhcpInit() throws Exception {
startIpClientProvisioning(false /* isDhcpLeaseCacheEnabled */,
@@ -486,14 +540,16 @@
public void testHandleSuccessDhcpLease() throws Exception {
final long currentTime = System.currentTimeMillis();
performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
- true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */);
- assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime);
+ true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU);
+ assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_DEFAULT_MTU);
}
@Test
public void testHandleFailureDhcpLease() throws Exception {
performDhcpHandshake(false /* isSuccessLease */, TEST_LEASE_DURATION_S,
- true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */);
+ true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU);
assertIpMemoryNeverStoreNetworkAttributes();
}
@@ -501,22 +557,25 @@
public void testHandleInfiniteLease() throws Exception {
final long currentTime = System.currentTimeMillis();
performDhcpHandshake(true /* isSuccessLease */, INFINITE_LEASE,
- true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */);
- assertIpMemoryStoreNetworkAttributes(INFINITE_LEASE, currentTime);
+ true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU);
+ assertIpMemoryStoreNetworkAttributes(INFINITE_LEASE, currentTime, TEST_DEFAULT_MTU);
}
@Test
public void testHandleNoLease() throws Exception {
final long currentTime = System.currentTimeMillis();
performDhcpHandshake(true /* isSuccessLease */, null /* no lease time */,
- true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */);
- assertIpMemoryStoreNetworkAttributes(null, currentTime);
+ true /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU);
+ assertIpMemoryStoreNetworkAttributes(null, currentTime, TEST_DEFAULT_MTU);
}
@Test
public void testHandleDisableInitRebootState() throws Exception {
performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
- false /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */);
+ false /* isDhcpLeaseCacheEnabled */, false /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU);
assertIpMemoryNeverStoreNetworkAttributes();
}
@@ -526,8 +585,9 @@
// TODO: remove @Ignore after supporting rapid commit option in DHCP server
final long currentTime = System.currentTimeMillis();
performDhcpHandshake(true /* isSuccessLease */, TEST_LEASE_DURATION_S,
- true /* isDhcpLeaseCacheEnabled */, true /* isDhcpRapidCommitEnabled */);
- assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime);
+ true /* isDhcpLeaseCacheEnabled */, true /* isDhcpRapidCommitEnabled */,
+ TEST_DEFAULT_MTU);
+ assertIpMemoryStoreNetworkAttributes(TEST_LEASE_DURATION_S, currentTime, TEST_DEFAULT_MTU);
}
@Test
@@ -536,7 +596,7 @@
new NetworkAttributes.Builder()
.setAssignedV4Address(CLIENT_ADDR)
.setAssignedV4AddressExpiry(Long.MAX_VALUE) // lease is always valid
- .setMtu(new Integer(MTU))
+ .setMtu(new Integer(TEST_DEFAULT_MTU))
.setGroupHint(TEST_GROUPHINT)
.setDnsAddresses(Collections.singletonList(SERVER_ADDR))
.build(), false /* timeout */);
@@ -549,7 +609,7 @@
new NetworkAttributes.Builder()
.setAssignedV4Address(CLIENT_ADDR)
.setAssignedV4AddressExpiry(EXPIRED_LEASE)
- .setMtu(new Integer(MTU))
+ .setMtu(new Integer(TEST_DEFAULT_MTU))
.setGroupHint(TEST_GROUPHINT)
.setDnsAddresses(Collections.singletonList(SERVER_ADDR))
.build(), false /* timeout */);
@@ -568,7 +628,7 @@
new NetworkAttributes.Builder()
.setAssignedV4Address(CLIENT_ADDR)
.setAssignedV4AddressExpiry(System.currentTimeMillis() + 3_600_000)
- .setMtu(new Integer(MTU))
+ .setMtu(new Integer(TEST_DEFAULT_MTU))
.setGroupHint(TEST_GROUPHINT)
.setDnsAddresses(Collections.singletonList(SERVER_ADDR))
.build(), true /* timeout */);
@@ -579,7 +639,7 @@
public void testDhcpClientStartWithCachedLeaseWithoutIPAddress() throws Exception {
final DhcpPacket packet = getReplyFromDhcpLease(
new NetworkAttributes.Builder()
- .setMtu(new Integer(MTU))
+ .setMtu(new Integer(TEST_DEFAULT_MTU))
.setGroupHint(TEST_GROUPHINT)
.setDnsAddresses(Collections.singletonList(SERVER_ADDR))
.build(), false /* timeout */);
@@ -593,4 +653,42 @@
final DhcpPacket packet = getNextDhcpPacket();
assertTrue(DhcpDiscoverPacket.class.isInstance(packet));
}
+
+ @Test
+ public void testRestoreInitialInterfaceMtu() throws Exception {
+ doRestoreInitialMtuTest(true /* shouldChangeMtu */, false /* shouldRemoveTapInterface */);
+ }
+
+ @Test
+ public void testRestoreInitialInterfaceMtu_WithoutMtuChange() throws Exception {
+ doRestoreInitialMtuTest(false /* shouldChangeMtu */, false /* shouldRemoveTapInterface */);
+ }
+
+ @Test
+ public void testRestoreInitialInterfaceMtu_WithException() throws Exception {
+ doThrow(new RemoteException("NetdNativeService::interfaceSetMtu")).when(mMockNetd)
+ .interfaceSetMtu(mIfaceName, TEST_DEFAULT_MTU);
+
+ doRestoreInitialMtuTest(true /* shouldChangeMtu */, false /* shouldRemoveTapInterface */);
+ assertEquals(NetworkInterface.getByName(mIfaceName).getMTU(), TEST_MIN_MTU);
+ }
+
+ @Test
+ public void testRestoreInitialInterfaceMtu_NotFoundInterfaceWhenStopping() throws Exception {
+ doRestoreInitialMtuTest(true /* shouldChangeMtu */, true /* shouldRemoveTapInterface */);
+ }
+
+ @Test
+ public void testRestoreInitialInterfaceMtu_NotFoundInterfaceWhenStartingProvisioning()
+ throws Exception {
+ removeTapInterface(mPacketReader.createFd());
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIpReachabilityMonitor()
+ .withoutIPv6()
+ .build();
+
+ mIpc.startProvisioning(config);
+ verify(mCb).onProvisioningFailure(any());
+ verify(mCb, never()).setNeighborDiscoveryOffload(true);
+ }
}
diff --git a/tests/lib/Android.bp b/tests/lib/Android.bp
index 1d52fa0..1db4054 100644
--- a/tests/lib/Android.bp
+++ b/tests/lib/Android.bp
@@ -23,6 +23,7 @@
defaults: ["lib_mockito_extended"],
static_libs: [
"kotlin-test",
+ "junit",
],
}
diff --git a/tests/lib/src/com/android/testutils/ConcurrentIntepreter.kt b/tests/lib/src/com/android/testutils/ConcurrentIntepreter.kt
index 5e1e005..25b1e0f 100644
--- a/tests/lib/src/com/android/testutils/ConcurrentIntepreter.kt
+++ b/tests/lib/src/com/android/testutils/ConcurrentIntepreter.kt
@@ -4,6 +4,7 @@
import java.util.concurrent.CyclicBarrier
import kotlin.system.measureTimeMillis
import kotlin.test.assertEquals
+import kotlin.test.assertFails
import kotlin.test.assertNull
import kotlin.test.assertTrue
@@ -64,7 +65,15 @@
// Spins as many threads as needed by the test spec and interpret each program concurrently,
// having all threads waiting on a CyclicBarrier after each line.
- fun interpretTestSpec(spec: String, initial: T, threadTransform: (T) -> T = { it }) {
+ // |lineShift| says how many lines after the call the spec starts. This is used for error
+ // reporting. Unfortunately AFAICT there is no way to get the line of an argument rather
+ // than the line at which the expression starts.
+ fun interpretTestSpec(
+ spec: String,
+ initial: T,
+ lineShift: Int = 0,
+ threadTransform: (T) -> T = { it }
+ ) {
// For nice stack traces
val callSite = getCallingMethod()
val lines = spec.trim().trim('\n').split("\n").map { it.split("|") }
@@ -91,7 +100,8 @@
// testing. Instead, catch the exception, cancel other threads, and report
// nicely. Catch throwable because fail() is AssertionError, which inherits
// from Error.
- crash = InterpretException(threadIndex, callSite.lineNumber + lineNum,
+ crash = InterpretException(threadIndex, it,
+ callSite.lineNumber + lineNum + lineShift,
callSite.className, callSite.methodName, callSite.fileName, e)
}
barrier.await()
@@ -103,18 +113,29 @@
}
// Helper to get the stack trace for a calling method
- protected fun getCallingMethod(depth: Int): StackTraceElement {
+ private fun getCallingStackTrace(): Array<StackTraceElement> {
try {
throw RuntimeException()
} catch (e: RuntimeException) {
- return e.stackTrace[depth]
+ return e.stackTrace
}
}
- // Override this if you don't call interpretTestSpec directly to get the correct file
- // and line for failure in the error message.
- // 0 is this method here, 1 is getCallingMethod(int), 2 is interpretTestSpec, 3 the lambda
- open fun getCallingMethod() = getCallingMethod(4)
+ // Find the calling method. This is the first method in the stack trace that is annotated
+ // with @Test.
+ fun getCallingMethod(): StackTraceElement {
+ val stackTrace = getCallingStackTrace()
+ return stackTrace.find { element ->
+ val clazz = Class.forName(element.className)
+ // Because the stack trace doesn't list the formal arguments, find all methods with
+ // this name and return this name if any of them is annotated with @Test.
+ clazz.declaredMethods
+ .filter { method -> method.name == element.methodName }
+ .any { method -> method.getAnnotation(org.junit.Test::class.java) != null }
+ } ?: stackTrace[3]
+ // If no method is annotated return the 4th one, because that's what it usually is :
+ // 0 is getCallingStackTrace, 1 is this method, 2 is ConcurrentInterpreter#interpretTestSpec
+ }
}
private fun <T> getDefaultInstructions() = listOf<InterpretMatcher<T>>(
@@ -124,7 +145,8 @@
Regex("(.*)//.*") to { i, t, r -> i.interpret(r.strArg(1), t) },
// Interpret "XXX time x..y" : run XXX and check it took at least x and not more than y
Regex("""(.*)\s*time\s*(\d+)\.\.(\d+)""") to { i, t, r ->
- assertTrue(measureTimeMillis { i.interpret(r.strArg(1), t) } in r.timeArg(2)..r.timeArg(3))
+ val time = measureTimeMillis { i.interpret(r.strArg(1), t) }
+ assertTrue(time in r.timeArg(2)..r.timeArg(3), "$time not in ${r.timeArg(2)..r.timeArg(3)}")
},
// Interpret "XXX = YYY" : run XXX and assert its return value is equal to YYY. "null" supported
Regex("""(.*)\s*=\s*(null|\d+)""") to { i, t, r ->
@@ -135,18 +157,22 @@
// Interpret sleep. Optional argument for the count, in INTERPRET_TIME_UNIT units.
Regex("""sleep(\((\d+)\))?""") to { i, t, r ->
SystemClock.sleep(if (r.strArg(2).isEmpty()) i.interpretTimeUnit else r.timeArg(2))
+ },
+ Regex("""(.*)\s*fails""") to { i, t, r ->
+ assertFails { i.interpret(r.strArg(1), t) }
}
)
class SyntaxException(msg: String, cause: Throwable? = null) : RuntimeException(msg, cause)
class InterpretException(
threadIndex: Int,
+ instr: String,
lineNum: Int,
className: String,
methodName: String,
fileName: String,
cause: Throwable
-) : RuntimeException(cause) {
+) : RuntimeException("Failure: $instr", cause) {
init {
stackTrace = arrayOf(StackTraceElement(
className,
diff --git a/tests/lib/src/com/android/testutils/TestableNetworkCallback.kt b/tests/lib/src/com/android/testutils/TestableNetworkCallback.kt
index 1cc1168..bbb279e 100644
--- a/tests/lib/src/com/android/testutils/TestableNetworkCallback.kt
+++ b/tests/lib/src/com/android/testutils/TestableNetworkCallback.kt
@@ -21,11 +21,15 @@
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
-import com.android.testutils.RecorderCallback.CallbackRecord.Available
-import com.android.testutils.RecorderCallback.CallbackRecord.BlockedStatus
-import com.android.testutils.RecorderCallback.CallbackRecord.CapabilitiesChanged
-import com.android.testutils.RecorderCallback.CallbackRecord.LinkPropertiesChanged
-import com.android.testutils.RecorderCallback.CallbackRecord.Lost
+import com.android.testutils.RecorderCallback.CallbackEntry.Available
+import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
+import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
+import com.android.testutils.RecorderCallback.CallbackEntry.Losing
+import com.android.testutils.RecorderCallback.CallbackEntry.Lost
+import com.android.testutils.RecorderCallback.CallbackEntry.Resumed
+import com.android.testutils.RecorderCallback.CallbackEntry.Suspended
+import com.android.testutils.RecorderCallback.CallbackEntry.Unavailable
import kotlin.reflect.KClass
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@@ -35,38 +39,43 @@
private val Int.capabilityName get() = NetworkCapabilities.capabilityNameOf(this)
-open class RecorderCallback : NetworkCallback() {
- sealed class CallbackRecord {
+open class RecorderCallback private constructor(
+ private val backingRecord: ArrayTrackRecord<CallbackEntry>
+) : NetworkCallback() {
+ public constructor() : this(ArrayTrackRecord())
+ protected constructor(src: RecorderCallback?): this(src?.backingRecord ?: ArrayTrackRecord())
+
+ sealed class CallbackEntry {
// To get equals(), hashcode(), componentN() etc for free, the child classes of
// this class are data classes. But while data classes can inherit from other classes,
// they may only have visible members in the constructors, so they couldn't declare
- // a constructor with a non-val arg to pass to CallbackRecord. Instead, force all
+ // a constructor with a non-val arg to pass to CallbackEntry. Instead, force all
// subclasses to implement a `network' property, which can be done in a data class
// constructor by specifying override.
abstract val network: Network
- data class Available(override val network: Network) : CallbackRecord()
+ data class Available(override val network: Network) : CallbackEntry()
data class CapabilitiesChanged(
override val network: Network,
val caps: NetworkCapabilities
- ) : CallbackRecord()
+ ) : CallbackEntry()
data class LinkPropertiesChanged(
override val network: Network,
val lp: LinkProperties
- ) : CallbackRecord()
- data class Suspended(override val network: Network) : CallbackRecord()
- data class Resumed(override val network: Network) : CallbackRecord()
- data class Losing(override val network: Network, val maxMsToLive: Int) : CallbackRecord()
- data class Lost(override val network: Network) : CallbackRecord()
+ ) : CallbackEntry()
+ data class Suspended(override val network: Network) : CallbackEntry()
+ data class Resumed(override val network: Network) : CallbackEntry()
+ data class Losing(override val network: Network, val maxMsToLive: Int) : CallbackEntry()
+ data class Lost(override val network: Network) : CallbackEntry()
data class Unavailable private constructor(
override val network: Network
- ) : CallbackRecord() {
+ ) : CallbackEntry() {
constructor() : this(NULL_NETWORK)
}
data class BlockedStatus(
override val network: Network,
val blocked: Boolean
- ) : CallbackRecord()
+ ) : CallbackEntry()
// Convenience constants for expecting a type
companion object {
@@ -91,12 +100,15 @@
}
}
- protected val history = ArrayTrackRecord<CallbackRecord>().newReadHead()
+ protected val history = backingRecord.newReadHead()
override fun onAvailable(network: Network) {
history.add(Available(network))
}
+ // PreCheck is not used in the tests today. For backward compatibility with existing tests that
+ // expect the callbacks not to record this, do not listen to PreCheck here.
+
override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
history.add(CapabilitiesChanged(network, caps))
}
@@ -110,39 +122,46 @@
}
override fun onNetworkSuspended(network: Network) {
- history.add(CallbackRecord.Suspended(network))
+ history.add(Suspended(network))
}
override fun onNetworkResumed(network: Network) {
- history.add(CallbackRecord.Resumed(network))
+ history.add(Resumed(network))
}
override fun onLosing(network: Network, maxMsToLive: Int) {
- history.add(CallbackRecord.Losing(network, maxMsToLive))
+ history.add(Losing(network, maxMsToLive))
}
override fun onLost(network: Network) {
- history.add(CallbackRecord.Lost(network))
+ history.add(Lost(network))
}
override fun onUnavailable() {
- history.add(CallbackRecord.Unavailable())
+ history.add(Unavailable())
}
}
-typealias CallbackType = KClass<out RecorderCallback.CallbackRecord>
-const val DEFAULT_TIMEOUT = 200L // ms
+private const val DEFAULT_TIMEOUT = 200L // ms
-open class TestableNetworkCallback(val defaultTimeoutMs: Long = DEFAULT_TIMEOUT)
- : RecorderCallback() {
- // The last available network. Null if the last available network was lost since.
+open class TestableNetworkCallback private constructor(
+ src: TestableNetworkCallback?,
+ val defaultTimeoutMs: Long = DEFAULT_TIMEOUT
+) : RecorderCallback(src) {
+ @JvmOverloads
+ constructor(timeoutMs: Long = DEFAULT_TIMEOUT): this(null, timeoutMs)
+
+ fun createLinkedCopy() = TestableNetworkCallback(this, defaultTimeoutMs)
+
+ // The last available network, or null if any network was lost since the last call to
+ // onAvailable. TODO : fix this by fixing the tests that rely on this behavior
val lastAvailableNetwork: Network?
get() = when (val it = history.lastOrNull { it is Available || it is Lost }) {
is Available -> it.network
else -> null
}
- fun pollForNextCallback(timeoutMs: Long = defaultTimeoutMs): CallbackRecord {
+ fun pollForNextCallback(timeoutMs: Long = defaultTimeoutMs): CallbackEntry {
return history.poll(timeoutMs) ?: fail("Did not receive callback after ${timeoutMs}ms")
}
@@ -153,7 +172,7 @@
if (null != cb) fail("Expected no callback but got $cb")
}
- inline fun <reified T : CallbackRecord> expectCallback(
+ inline fun <reified T : CallbackEntry> expectCallback(
network: Network,
timeoutMs: Long = defaultTimeoutMs
): T = pollForNextCallback(timeoutMs).let {
@@ -166,7 +185,7 @@
fun expectCallbackThat(
timeoutMs: Long = defaultTimeoutMs,
- valid: (CallbackRecord) -> Boolean
+ valid: (CallbackEntry) -> Boolean
) = pollForNextCallback(timeoutMs).also { assertTrue(valid(it), "Unexpected callback : $it") }
fun expectCapabilitiesThat(
@@ -209,7 +228,7 @@
) {
expectCallback<Available>(net, tmt)
if (suspended) {
- expectCallback<CallbackRecord.Suspended>(net, tmt)
+ expectCallback<CallbackEntry.Suspended>(net, tmt)
}
expectCapabilitiesThat(net, tmt) { validated == it.hasCapability(NET_CAPABILITY_VALIDATED) }
expectCallback<LinkPropertiesChanged>(net, tmt)
@@ -257,7 +276,7 @@
}
@JvmOverloads
- open fun <T : CallbackRecord> expectCallback(
+ open fun <T : CallbackEntry> expectCallback(
type: KClass<T>,
n: HasNetwork?,
timeoutMs: Long = defaultTimeoutMs
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index 9c1c791..03bcf95 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -22,9 +22,10 @@
resource_dirs: ["res"],
static_libs: [
"androidx.test.rules",
+ "kotlin-reflect",
"mockito-target-extended-minus-junit4",
"net-tests-utils",
- "NetworkStackBase",
+ "NetworkStackApiCurrentLib",
"testables",
],
libs: [
@@ -60,8 +61,6 @@
"libdl_android",
"libhidl-gen-utils",
"libhidlbase",
- "libhidltransport",
- "libhwbinder",
"libjsoncpp",
"liblog",
"liblzma",
diff --git a/tests/unit/src/android/net/apf/ApfTest.java b/tests/unit/src/android/net/apf/ApfTest.java
index 8f2b968..8b02b49 100644
--- a/tests/unit/src/android/net/apf/ApfTest.java
+++ b/tests/unit/src/android/net/apf/ApfTest.java
@@ -28,6 +28,7 @@
import static com.android.internal.util.BitUtils.bytesToBEInt;
import static com.android.server.util.NetworkStackConstants.ICMPV6_ECHO_REQUEST_TYPE;
+import static com.android.server.util.NetworkStackConstants.IPV6_ADDR_LEN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -38,6 +39,7 @@
import static org.mockito.Mockito.verify;
import android.content.Context;
+import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NattKeepalivePacketDataParcelable;
@@ -85,6 +87,7 @@
import java.io.OutputStream;
import java.net.InetAddress;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.List;
import java.util.Random;
@@ -119,7 +122,7 @@
private static final int MIN_PKT_SIZE = 15;
private static final ApfCapabilities MOCK_APF_CAPABILITIES =
- new ApfCapabilities(2, 1700, ARPHRD_ETHER);
+ new ApfCapabilities(2, 4096, ARPHRD_ETHER);
private static final boolean DROP_MULTICAST = true;
private static final boolean ALLOW_MULTICAST = false;
@@ -184,7 +187,7 @@
private void assertProgramEquals(byte[] expected, byte[] program) throws AssertionError {
// assertArrayEquals() would only print one byte, making debugging difficult.
- if (!java.util.Arrays.equals(expected, program)) {
+ if (!Arrays.equals(expected, program)) {
throw new AssertionError(
"\nexpected: " + HexDump.toHexString(expected) +
"\nactual: " + HexDump.toHexString(program));
@@ -197,7 +200,7 @@
assertReturnCodesEqual(expected, apfSimulate(program, packet, data, 0 /* filterAge */));
// assertArrayEquals() would only print one byte, making debugging difficult.
- if (!java.util.Arrays.equals(expected_data, data)) {
+ if (!Arrays.equals(expected_data, data)) {
throw new Exception(
"\nprogram: " + HexDump.toHexString(program) +
"\ndata memory: " + HexDump.toHexString(data) +
@@ -1030,6 +1033,7 @@
{(byte) 255, (byte) 255, (byte) 255, (byte) 255};
private static final int IPV6_HEADER_LEN = 40;
+ private static final int IPV6_PAYLOAD_LENGTH_OFFSET = ETH_HEADER_LEN + 4;
private static final int IPV6_NEXT_HEADER_OFFSET = ETH_HEADER_LEN + 6;
private static final int IPV6_SRC_ADDR_OFFSET = ETH_HEADER_LEN + 8;
private static final int IPV6_DEST_ADDR_OFFSET = ETH_HEADER_LEN + 24;
@@ -1799,6 +1803,111 @@
return packet.array();
}
+ private void addRdnssOption(ByteBuffer packet, int lifetime, String... servers)
+ throws Exception {
+ int optionLength = 1 + 2 * servers.length; // In 8-byte units
+ packet.put((byte) ICMP6_RDNSS_OPTION_TYPE); // Type
+ packet.put((byte) optionLength); // Length
+ packet.putShort((short) 0); // Reserved
+ packet.putInt(lifetime); // Lifetime
+ for (String server : servers) {
+ packet.put(InetAddress.getByName(server).getAddress());
+ }
+ }
+
+ private void addRioOption(ByteBuffer packet, int lifetime, String prefixString)
+ throws Exception {
+ IpPrefix prefix = new IpPrefix(prefixString);
+
+ int optionLength;
+ if (prefix.getPrefixLength() == 0) {
+ optionLength = 1;
+ } else if (prefix.getPrefixLength() <= 64) {
+ optionLength = 2;
+ } else {
+ optionLength = 3;
+ }
+
+ packet.put((byte) ICMP6_ROUTE_INFO_OPTION_TYPE); // Type
+ packet.put((byte) optionLength); // Length in 8-byte units
+ packet.put((byte) prefix.getPrefixLength()); // Prefix length
+ packet.put((byte) 0b00011000); // Pref = high
+ packet.putInt(lifetime); // Lifetime
+
+ byte[] prefixBytes = prefix.getRawAddress();
+ packet.put(prefixBytes, 0, (optionLength - 1) * 8);
+ }
+
+ private void addPioOption(ByteBuffer packet, int valid, int preferred, String prefixString) {
+ IpPrefix prefix = new IpPrefix(prefixString);
+ packet.put((byte) ICMP6_PREFIX_OPTION_TYPE); // Type
+ packet.put((byte) 4); // Length in 8-byte units
+ packet.put((byte) prefix.getPrefixLength()); // Prefix length
+ packet.put((byte) 0b11000000); // L = 1, A = 1
+ packet.putInt(valid);
+ packet.putInt(preferred);
+ packet.putInt(0); // Reserved
+ packet.put(prefix.getRawAddress());
+ }
+
+ private byte[] buildLargeRa() throws Exception {
+ InetAddress src = InetAddress.getByName("fe80::1234:abcd");
+
+ ByteBuffer packet = ByteBuffer.wrap(new byte[1514]);
+ packet.putShort(ETH_ETHERTYPE_OFFSET, (short) ETH_P_IPV6);
+ packet.position(ETH_HEADER_LEN);
+
+ packet.putInt(0x60012345); // Version, tclass, flowlabel
+ packet.putShort((short) 0); // Payload length; updated later
+ packet.put((byte) IPPROTO_ICMPV6); // Next header
+ packet.put((byte) 0xff); // Hop limit
+ packet.put(src.getAddress()); // Source address
+ packet.put(IPV6_ALL_NODES_ADDRESS); // Destination address
+
+ packet.put((byte) ICMP6_ROUTER_ADVERTISEMENT); // Type
+ packet.put((byte) 0); // Code (0)
+ packet.putShort((short) 0); // Checksum (ignored)
+ packet.put((byte) 64); // Hop limit
+ packet.put((byte) 0); // M/O, reserved
+ packet.putShort((short) 1800); // Router lifetime
+ packet.putInt(30_000); // Reachable time
+ packet.putInt(1000); // Retrans timer
+
+ addRioOption(packet, 1200, "64:ff9b::/96");
+ addRdnssOption(packet, 7200, "2001:db8:1::1", "2001:db8:1::2");
+ addRioOption(packet, 2100, "2000::/3");
+ addRioOption(packet, 2400, "::/0");
+ addPioOption(packet, 600, 300, "2001:db8:a::/64");
+ addRioOption(packet, 1500, "2001:db8:c:d::/64");
+ addPioOption(packet, 86400, 43200, "fd95:d1e:12::/64");
+
+ int length = packet.position();
+ packet.putShort(IPV6_PAYLOAD_LENGTH_OFFSET, (short) length);
+
+ // Don't pass the Ra constructor a packet that is longer than the actual RA.
+ // This relies on the fact that all the relative writes to the byte buffer are at the end.
+ byte[] packetArray = new byte[length];
+ packet.rewind();
+ packet.get(packetArray);
+ return packetArray;
+ }
+
+ @Test
+ public void testRaToString() throws Exception {
+ MockIpClientCallback cb = new MockIpClientCallback();
+ ApfConfiguration config = getDefaultConfig();
+ TestApfFilter apfFilter = new TestApfFilter(mContext, config, cb, mLog);
+
+ byte[] packet = buildLargeRa();
+ ApfFilter.Ra ra = apfFilter.new Ra(packet, packet.length);
+ String expected = "RA fe80::1234:abcd -> ff02::1 1800s "
+ + "2001:db8:a::/64 600s/300s fd95:d1e:12::/64 86400s/43200s "
+ + "DNS 7200s 2001:db8:1::1 2001:db8:1::2 "
+ + "RIO 1200s 64:ff9b::/96 RIO 2100s 2000::/3 "
+ + "RIO 2400s ::/0 RIO 1500s 2001:db8:c:d::/64 ";
+ assertEquals(expected, ra.toString());
+ }
+
// Verify that the last program pushed to the IpClient.Callback properly filters the
// given packet for the given lifetime.
private void verifyRaLifetime(byte[] program, ByteBuffer packet, int lifetime) {
@@ -1934,38 +2043,27 @@
new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_LEN]);
basePacket.clear();
prefixOptionPacket.put(basePacket);
- prefixOptionPacket.put((byte)ICMP6_PREFIX_OPTION_TYPE);
- prefixOptionPacket.put((byte)(ICMP6_PREFIX_OPTION_LEN / 8));
- prefixOptionPacket.putInt(
- ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_PREFERRED_LIFETIME_OFFSET,
- PREFIX_PREFERRED_LIFETIME);
- prefixOptionPacket.putInt(
- ICMP6_RA_OPTION_OFFSET + ICMP6_PREFIX_OPTION_VALID_LIFETIME_OFFSET,
- PREFIX_VALID_LIFETIME);
+ addPioOption(prefixOptionPacket, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME,
+ "2001:db8::/64");
verifyRaLifetime(
apfFilter, ipClientCallback, prefixOptionPacket, PREFIX_PREFERRED_LIFETIME);
verifyRaEvent(new RaEvent(
ROUTER_LIFETIME, PREFIX_VALID_LIFETIME, PREFIX_PREFERRED_LIFETIME, -1, -1, -1));
ByteBuffer rdnssOptionPacket = ByteBuffer.wrap(
- new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
+ new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + 2 * IPV6_ADDR_LEN]);
basePacket.clear();
rdnssOptionPacket.put(basePacket);
- rdnssOptionPacket.put((byte)ICMP6_RDNSS_OPTION_TYPE);
- rdnssOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
- rdnssOptionPacket.putInt(
- ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, RDNSS_LIFETIME);
+ addRdnssOption(rdnssOptionPacket, RDNSS_LIFETIME,
+ "2001:4860:4860::8888", "2001:4860:4860::8844");
verifyRaLifetime(apfFilter, ipClientCallback, rdnssOptionPacket, RDNSS_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, RDNSS_LIFETIME, -1));
ByteBuffer routeInfoOptionPacket = ByteBuffer.wrap(
- new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN]);
+ new byte[ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_OPTION_LEN + IPV6_ADDR_LEN]);
basePacket.clear();
routeInfoOptionPacket.put(basePacket);
- routeInfoOptionPacket.put((byte)ICMP6_ROUTE_INFO_OPTION_TYPE);
- routeInfoOptionPacket.put((byte)(ICMP6_4_BYTE_OPTION_LEN / 8));
- routeInfoOptionPacket.putInt(
- ICMP6_RA_OPTION_OFFSET + ICMP6_4_BYTE_LIFETIME_OFFSET, ROUTE_LIFETIME);
+ addRioOption(routeInfoOptionPacket, ROUTE_LIFETIME, "64:ff9b::/96");
verifyRaLifetime(apfFilter, ipClientCallback, routeInfoOptionPacket, ROUTE_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, ROUTE_LIFETIME, -1, -1));
@@ -1980,7 +2078,11 @@
verifyRaLifetime(apfFilter, ipClientCallback, dnsslOptionPacket, ROUTER_LIFETIME);
verifyRaEvent(new RaEvent(ROUTER_LIFETIME, -1, -1, -1, -1, DNSSL_LIFETIME));
- // Verify that current program filters all five RAs:
+ ByteBuffer largeRaPacket = ByteBuffer.wrap(buildLargeRa());
+ verifyRaLifetime(apfFilter, ipClientCallback, largeRaPacket, 300);
+ verifyRaEvent(new RaEvent(1800, 600, 300, 1200, 7200, -1));
+
+ // Verify that current program filters all the RAs:
program = ipClientCallback.getApfProgram();
verifyRaLifetime(program, basePacket, ROUTER_LIFETIME);
verifyRaLifetime(program, newFlowLabelPacket, ROUTER_LIFETIME);
@@ -1988,6 +2090,7 @@
verifyRaLifetime(program, rdnssOptionPacket, RDNSS_LIFETIME);
verifyRaLifetime(program, routeInfoOptionPacket, ROUTE_LIFETIME);
verifyRaLifetime(program, dnsslOptionPacket, ROUTER_LIFETIME);
+ verifyRaLifetime(program, largeRaPacket, 300);
apfFilter.shutdown();
}
diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java
index 1d6ce6e..b3e652e 100644
--- a/tests/unit/src/android/net/ip/IpClientTest.java
+++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -16,6 +16,8 @@
package android.net.ip;
+import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -31,12 +33,15 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
+import static java.util.Collections.emptySet;
+
import android.app.AlarmManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.INetd;
+import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -51,11 +56,11 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.R;
import com.android.server.NetworkObserver;
import com.android.server.NetworkObserverRegistry;
import com.android.server.NetworkStackService;
import com.android.server.connectivity.ipmemorystore.IpMemoryStoreService;
+import com.android.testutils.HandlerUtilsKt;
import org.junit.Before;
import org.junit.Test;
@@ -64,6 +69,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.HashSet;
@@ -77,8 +84,6 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpClientTest {
- private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
-
private static final String VALID = "VALID";
private static final String INVALID = "INVALID";
private static final String TEST_IFNAME = "test_wlan0";
@@ -89,6 +94,19 @@
private static final String TEST_L2KEY = "some l2key";
private static final String TEST_GROUPHINT = "some grouphint";
+ private static final String TEST_GLOBAL_ADDRESS = "1234:4321::548d:2db2:4fcf:ef75/64";
+ private static final String[] TEST_LOCAL_ADDRESSES = {
+ "fe80::a4be:f92:e1f7:22d1/64",
+ "fe80::f04a:8f6:6a32:d756/64",
+ "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"
+ };
+ private static final String TEST_IPV4_LINKADDRESS = "192.168.42.24/24";
+ private static final String[] TEST_PREFIXES = { "fe80::/64", "fd2c:4e57:8e3c::/64" };
+ private static final String[] TEST_DNSES = { "fd2c:4e57:8e3c::42" };
+ private static final String TEST_IPV6_GATEWAY = "fd2c:4e57:8e3c::43";
+ private static final String TEST_IPV4_GATEWAY = "192.168.42.11";
+ private static final long TEST_DNS_LIFETIME = 3600;
+
@Mock private Context mContext;
@Mock private ConnectivityManager mCm;
@Mock private NetworkObserverRegistry mObserverRegistry;
@@ -114,8 +132,7 @@
when(mContext.getSystemService(eq(ConnectivityManager.class))).thenReturn(mCm);
when(mContext.getResources()).thenReturn(mResources);
when(mDependencies.getNetd(any())).thenReturn(mNetd);
- when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
- .thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
+ when(mCm.shouldAvoidBadWifi()).thenReturn(true);
when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mNetworkStackServiceManager.getIpMemoryStoreService())
.thenReturn(mIpMemoryStoreService);
@@ -209,10 +226,20 @@
ipc.shutdown();
}
- @Test
- public void testDefaultProvisioningConfiguration() throws Exception {
- final String iface = TEST_IFNAME;
- final IpClient ipc = makeIpClient(iface);
+ private LinkProperties makeIPv6ProvisionedLinkProperties() {
+ // Add local addresses, and a global address with global scope
+ final Set<LinkAddress> addresses = links(TEST_LOCAL_ADDRESSES);
+ addresses.add(new LinkAddress(TEST_GLOBAL_ADDRESS, 0, RT_SCOPE_UNIVERSE));
+
+ // Add a route on the interface for each prefix, and a global route
+ final Set<RouteInfo> routes = routes(TEST_PREFIXES);
+ routes.add(defaultIPV6Route(TEST_IPV6_GATEWAY));
+
+ return linkproperties(addresses, routes, ips(TEST_DNSES));
+ }
+
+ private IpClient doProvisioningWithDefaultConfiguration() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
.withoutIPv4()
@@ -224,34 +251,115 @@
ipc.startProvisioning(config);
verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
+
+ final LinkProperties lp = makeIPv6ProvisionedLinkProperties();
+ lp.getRoutes().forEach(mObserver::onRouteUpdated);
+ lp.getLinkAddresses().forEach(la -> mObserver.onInterfaceAddressUpdated(la, TEST_IFNAME));
+ mObserver.onInterfaceDnsServerInfo(TEST_IFNAME, TEST_DNS_LIFETIME,
+ lp.getDnsServers().stream().map(InetAddress::getHostAddress)
+ .toArray(String[]::new));
+
+ HandlerUtilsKt.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS);
verify(mCb, never()).onProvisioningFailure(any());
verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any());
- ipc.shutdown();
- verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
- verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
- verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
- .onLinkPropertiesChange(makeEmptyLinkProperties(iface));
+ verify(mCb).onProvisioningSuccess(lp);
+ return ipc;
+ }
+
+ private void addIPv4Provisioning(LinkProperties lp) {
+ final LinkAddress la = new LinkAddress(TEST_IPV4_LINKADDRESS);
+ final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
+ InetAddresses.parseNumericAddress(TEST_IPV4_GATEWAY), TEST_IFNAME);
+ mObserver.onInterfaceAddressUpdated(la, TEST_IFNAME);
+ mObserver.onRouteUpdated(defaultRoute);
+
+ lp.addLinkAddress(la);
+ lp.addRoute(defaultRoute);
+ }
+
+ /**
+ * Simulate loss of IPv6 provisioning (default route lost).
+ *
+ * @return The expected new LinkProperties.
+ */
+ private void doIPv6ProvisioningLoss(LinkProperties lp) {
+ final RouteInfo defaultRoute = defaultIPV6Route(TEST_IPV6_GATEWAY);
+ mObserver.onRouteRemoved(defaultRoute);
+
+ lp.removeRoute(defaultRoute);
+ }
+
+ private void doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(boolean avoidBadWifi)
+ throws Exception {
+ when(mCm.shouldAvoidBadWifi()).thenReturn(avoidBadWifi);
+ final IpClient ipc = doProvisioningWithDefaultConfiguration();
+ final LinkProperties lp = makeIPv6ProvisionedLinkProperties();
+
+ reset(mCb);
+ doIPv6ProvisioningLoss(lp);
+ HandlerUtilsKt.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS);
+ verify(mCb).onProvisioningFailure(lp);
+ verify(mCb).onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME));
+
+ verifyShutdown(ipc);
}
@Test
+ public void testDefaultIPv6ProvisioningConfiguration_AvoidBadWifi() throws Exception {
+ doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(true /* avoidBadWifi */);
+ }
+
+ @Test
+ public void testDefaultIPv6ProvisioningConfiguration_StayOnBadWifi() throws Exception {
+ // Even when avoidBadWifi=false, if IPv6 only, loss of all provisioning causes
+ // onProvisioningFailure to be called.
+ doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(false /* avoidBadWifi */);
+ }
+
+ private void doDefaultDualStackProvisioningConfigurationTest(
+ boolean avoidBadWifi) throws Exception {
+ when(mCm.shouldAvoidBadWifi()).thenReturn(avoidBadWifi);
+ final IpClient ipc = doProvisioningWithDefaultConfiguration();
+ final LinkProperties lp = makeIPv6ProvisionedLinkProperties();
+ addIPv4Provisioning(lp);
+ HandlerUtilsKt.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS);
+
+ reset(mCb);
+ doIPv6ProvisioningLoss(lp);
+ HandlerUtilsKt.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS);
+ if (avoidBadWifi) { // Provisioning failure is expected only when avoidBadWifi is true
+ verify(mCb).onProvisioningFailure(lp);
+ verify(mCb).onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME));
+ } else {
+ verify(mCb, never()).onProvisioningFailure(any());
+ verify(mCb).onLinkPropertiesChange(lp);
+ }
+
+ verifyShutdown(ipc);
+ }
+
+ @Test
+ public void testDefaultDualStackProvisioningConfiguration_AvoidBadWifi() throws Exception {
+ doDefaultDualStackProvisioningConfigurationTest(true /* avoidBadWifi */);
+ }
+
+ @Test
+ public void testDefaultDualStackProvisioningConfiguration_StayOnBadWifi() throws Exception {
+ doDefaultDualStackProvisioningConfigurationTest(false /* avoidBadWifi */);
+ }
+
public void testProvisioningWithInitialConfiguration() throws Exception {
final String iface = TEST_IFNAME;
final IpClient ipc = makeIpClient(iface);
final String l2Key = TEST_L2KEY;
final String groupHint = TEST_GROUPHINT;
- String[] addresses = {
- "fe80::a4be:f92:e1f7:22d1/64",
- "fe80::f04a:8f6:6a32:d756/64",
- "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"
- };
- String[] prefixes = { "fe80::/64", "fd2c:4e57:8e3c::/64" };
-
ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
.withoutIPv4()
.withoutIpReachabilityMonitor()
- .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
+ .withInitialConfiguration(
+ conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips()))
.build();
ipc.startProvisioning(config);
@@ -260,35 +368,38 @@
verify(mCb, never()).onProvisioningFailure(any());
ipc.setL2KeyAndGroupHint(l2Key, groupHint);
- for (String addr : addresses) {
+ for (String addr : TEST_LOCAL_ADDRESSES) {
String[] parts = addr.split("/");
verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1))
.interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1]));
}
- final int lastAddr = addresses.length - 1;
+ final int lastAddr = TEST_LOCAL_ADDRESSES.length - 1;
// Add N - 1 addresses
for (int i = 0; i < lastAddr; i++) {
- mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[i]), iface);
+ mObserver.onInterfaceAddressUpdated(new LinkAddress(TEST_LOCAL_ADDRESSES[i]), iface);
verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(any());
reset(mCb);
}
// Add Nth address
- mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[lastAddr]), iface);
- LinkProperties want = linkproperties(links(addresses), routes(prefixes));
+ mObserver.onInterfaceAddressUpdated(new LinkAddress(TEST_LOCAL_ADDRESSES[lastAddr]), iface);
+ LinkProperties want = linkproperties(links(TEST_LOCAL_ADDRESSES),
+ routes(TEST_PREFIXES), emptySet() /* dnses */);
want.setInterfaceName(iface);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(want);
verifyNetworkAttributesStored(l2Key, new NetworkAttributes.Builder()
.setGroupHint(groupHint)
.build());
+ }
+ private void verifyShutdown(IpClient ipc) throws Exception {
ipc.shutdown();
- verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
- verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
+ verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(TEST_IFNAME, false);
+ verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(TEST_IFNAME);
verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
- .onLinkPropertiesChange(makeEmptyLinkProperties(iface));
+ .onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME));
verifyNoMoreInteractions(mIpMemoryStore);
}
@@ -360,7 +471,7 @@
Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) {
IsProvisionedTestCase testcase = new IsProvisionedTestCase();
testcase.isProvisioned = isProvisioned;
- testcase.lp = new LinkProperties();
+ testcase.lp = makeEmptyLinkProperties(TEST_IFNAME);
testcase.lp.setLinkAddresses(lpAddrs);
for (RouteInfo route : lpRoutes) {
testcase.lp.addRoute(route);
@@ -456,12 +567,12 @@
return testcase;
}
- static LinkProperties linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes) {
- LinkProperties lp = new LinkProperties();
+ static LinkProperties linkproperties(Set<LinkAddress> addresses,
+ Set<RouteInfo> routes, Set<InetAddress> dnses) {
+ LinkProperties lp = makeEmptyLinkProperties(TEST_IFNAME);
lp.setLinkAddresses(addresses);
- for (RouteInfo route : routes) {
- lp.addRoute(route);
- }
+ routes.forEach(lp::addRoute);
+ dnses.forEach(lp::addDnsServer);
return lp;
}
@@ -479,7 +590,13 @@
}
static Set<RouteInfo> routes(String... routes) {
- return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r)));
+ return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r), null /* gateway */,
+ TEST_IFNAME));
+ }
+
+ static RouteInfo defaultIPV6Route(String gateway) {
+ return new RouteInfo(new IpPrefix(Inet6Address.ANY, 0),
+ InetAddresses.parseNumericAddress(gateway), TEST_IFNAME);
}
static Set<IpPrefix> prefixes(String... prefixes) {
diff --git a/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt b/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
new file mode 100644
index 0000000..4e4d25a
--- /dev/null
+++ b/tests/unit/src/android/net/testutils/TestableNetworkCallbackTest.kt
@@ -0,0 +1,293 @@
+package android.net.testutils
+
+import android.net.LinkAddress
+import android.net.LinkProperties
+import android.net.Network
+import android.net.NetworkCapabilities
+import com.android.testutils.ConcurrentIntepreter
+import com.android.testutils.InterpretMatcher
+import com.android.testutils.RecorderCallback.CallbackEntry
+import com.android.testutils.RecorderCallback.CallbackEntry.Available
+import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
+import com.android.testutils.TestableNetworkCallback
+import com.android.testutils.intArg
+import com.android.testutils.strArg
+import com.android.testutils.timeArg
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import kotlin.reflect.KClass
+import kotlin.test.assertEquals
+import kotlin.test.assertFails
+import kotlin.test.assertNull
+import kotlin.test.assertTrue
+import kotlin.test.fail
+
+const val SHORT_TIMEOUT_MS = 20L
+const val DEFAULT_LINGER_DELAY_MS = 30000
+const val NOT_METERED = NetworkCapabilities.NET_CAPABILITY_NOT_METERED
+const val WIFI = NetworkCapabilities.TRANSPORT_WIFI
+const val CELLULAR = NetworkCapabilities.TRANSPORT_CELLULAR
+const val TEST_INTERFACE_NAME = "testInterfaceName"
+
+@RunWith(JUnit4::class)
+class TestableNetworkCallbackTest {
+ private lateinit var mCallback: TestableNetworkCallback
+
+ private fun makeHasNetwork(netId: Int) = object : TestableNetworkCallback.HasNetwork {
+ override val network: Network = Network(netId)
+ }
+
+ @Before
+ fun setUp() {
+ mCallback = TestableNetworkCallback()
+ }
+
+ @Test
+ fun testLastAvailableNetwork() {
+ // Make sure there is no last available network at first, then the last available network
+ // is returned after onAvailable is called.
+ val net2097 = Network(2097)
+ assertNull(mCallback.lastAvailableNetwork)
+ mCallback.onAvailable(net2097)
+ assertEquals(mCallback.lastAvailableNetwork, net2097)
+
+ // Make sure calling onCapsChanged/onLinkPropertiesChanged don't affect the last available
+ // network.
+ mCallback.onCapabilitiesChanged(net2097, NetworkCapabilities())
+ mCallback.onLinkPropertiesChanged(net2097, LinkProperties())
+ assertEquals(mCallback.lastAvailableNetwork, net2097)
+
+ // Make sure onLost clears the last available network.
+ mCallback.onLost(net2097)
+ assertNull(mCallback.lastAvailableNetwork)
+
+ // Do the same but with a different network after onLost : make sure the last available
+ // network is the new one, not the original one.
+ val net2098 = Network(2098)
+ mCallback.onAvailable(net2098)
+ mCallback.onCapabilitiesChanged(net2098, NetworkCapabilities())
+ mCallback.onLinkPropertiesChanged(net2098, LinkProperties())
+ assertEquals(mCallback.lastAvailableNetwork, net2098)
+
+ // Make sure onAvailable changes the last available network even if onLost was not called.
+ val net2099 = Network(2099)
+ mCallback.onAvailable(net2099)
+ assertEquals(mCallback.lastAvailableNetwork, net2099)
+
+ // For legacy reasons, lastAvailableNetwork is null as soon as any is lost, not necessarily
+ // the last available one. Check that behavior.
+ mCallback.onLost(net2098)
+ assertNull(mCallback.lastAvailableNetwork)
+
+ // Make sure that losing the really last available one still results in null.
+ mCallback.onLost(net2099)
+ assertNull(mCallback.lastAvailableNetwork)
+
+ // Make sure multiple onAvailable in a row then onLost still results in null.
+ mCallback.onAvailable(net2097)
+ mCallback.onAvailable(net2098)
+ mCallback.onAvailable(net2099)
+ mCallback.onLost(net2097)
+ assertNull(mCallback.lastAvailableNetwork)
+ }
+
+ @Test
+ fun testAssertNoCallback() {
+ mCallback.assertNoCallback(SHORT_TIMEOUT_MS)
+ mCallback.onAvailable(Network(100))
+ assertFails { mCallback.assertNoCallback(SHORT_TIMEOUT_MS) }
+ }
+
+ @Test
+ fun testCapabilitiesWithAndWithout() {
+ val net = Network(101)
+ val matcher = makeHasNetwork(101)
+ val meteredNc = NetworkCapabilities()
+ val unmeteredNc = NetworkCapabilities().addCapability(NOT_METERED)
+ // Check that expecting caps (with or without) fails when no callback has been received.
+ assertFails { mCallback.expectCapabilitiesWith(NOT_METERED, matcher, SHORT_TIMEOUT_MS) }
+ assertFails { mCallback.expectCapabilitiesWithout(NOT_METERED, matcher, SHORT_TIMEOUT_MS) }
+
+ // Add NOT_METERED and check that With succeeds and Without fails.
+ mCallback.onCapabilitiesChanged(net, unmeteredNc)
+ mCallback.expectCapabilitiesWith(NOT_METERED, matcher)
+ mCallback.onCapabilitiesChanged(net, unmeteredNc)
+ assertFails { mCallback.expectCapabilitiesWithout(NOT_METERED, matcher, SHORT_TIMEOUT_MS) }
+
+ // Don't add NOT_METERED and check that With fails and Without succeeds.
+ mCallback.onCapabilitiesChanged(net, meteredNc)
+ assertFails { mCallback.expectCapabilitiesWith(NOT_METERED, matcher, SHORT_TIMEOUT_MS) }
+ mCallback.onCapabilitiesChanged(net, meteredNc)
+ mCallback.expectCapabilitiesWithout(NOT_METERED, matcher)
+ }
+
+ @Test
+ fun testExpectCallbackThat() {
+ val net = Network(193)
+ val netCaps = NetworkCapabilities().addTransportType(CELLULAR)
+ // Check that expecting callbackThat anything fails when no callback has been received.
+ assertFails { mCallback.expectCallbackThat(SHORT_TIMEOUT_MS) { true } }
+
+ // Basic test for true and false
+ mCallback.onAvailable(net)
+ mCallback.expectCallbackThat { true }
+ mCallback.onAvailable(net)
+ assertFails { mCallback.expectCallbackThat(SHORT_TIMEOUT_MS) { false } }
+
+ // Try a positive and a negative case
+ mCallback.onBlockedStatusChanged(net, true)
+ mCallback.expectCallbackThat { cb -> cb is BlockedStatus && cb.blocked }
+ mCallback.onCapabilitiesChanged(net, netCaps)
+ assertFails { mCallback.expectCallbackThat(SHORT_TIMEOUT_MS) { cb ->
+ cb is CapabilitiesChanged && cb.caps.hasTransport(WIFI)
+ } }
+ }
+
+ @Test
+ fun testCapabilitiesThat() {
+ val net = Network(101)
+ val netCaps = NetworkCapabilities().addCapability(NOT_METERED).addTransportType(WIFI)
+ // Check that expecting capabilitiesThat anything fails when no callback has been received.
+ assertFails { mCallback.expectCapabilitiesThat(net, SHORT_TIMEOUT_MS) { true } }
+
+ // Basic test for true and false
+ mCallback.onCapabilitiesChanged(net, netCaps)
+ mCallback.expectCapabilitiesThat(net) { true }
+ mCallback.onCapabilitiesChanged(net, netCaps)
+ assertFails { mCallback.expectCapabilitiesThat(net, SHORT_TIMEOUT_MS) { false } }
+
+ // Try a positive and a negative case
+ mCallback.onCapabilitiesChanged(net, netCaps)
+ mCallback.expectCapabilitiesThat(net) { caps ->
+ caps.hasCapability(NOT_METERED) &&
+ caps.hasTransport(WIFI) &&
+ !caps.hasTransport(CELLULAR)
+ }
+ mCallback.onCapabilitiesChanged(net, netCaps)
+ assertFails { mCallback.expectCapabilitiesThat(net, SHORT_TIMEOUT_MS) { caps ->
+ caps.hasTransport(CELLULAR)
+ } }
+
+ // Try a matching callback on the wrong network
+ mCallback.onCapabilitiesChanged(net, netCaps)
+ assertFails { mCallback.expectCapabilitiesThat(Network(100), SHORT_TIMEOUT_MS) { true } }
+ }
+
+ @Test
+ fun testLinkPropertiesThat() {
+ val net = Network(112)
+ val linkAddress = LinkAddress("fe80::ace:d00d/64")
+ val mtu = 1984
+ val linkProps = LinkProperties().apply {
+ this.mtu = mtu
+ interfaceName = TEST_INTERFACE_NAME
+ addLinkAddress(linkAddress)
+ }
+
+ // Check that expecting linkPropsThat anything fails when no callback has been received.
+ assertFails { mCallback.expectLinkPropertiesThat(net, SHORT_TIMEOUT_MS) { true } }
+
+ // Basic test for true and false
+ mCallback.onLinkPropertiesChanged(net, linkProps)
+ mCallback.expectLinkPropertiesThat(net) { true }
+ mCallback.onLinkPropertiesChanged(net, linkProps)
+ assertFails { mCallback.expectLinkPropertiesThat(net, SHORT_TIMEOUT_MS) { false } }
+
+ // Try a positive and negative case
+ mCallback.onLinkPropertiesChanged(net, linkProps)
+ mCallback.expectLinkPropertiesThat(net) { lp ->
+ lp.interfaceName == TEST_INTERFACE_NAME &&
+ lp.linkAddresses.contains(linkAddress) &&
+ lp.mtu == mtu
+ }
+ mCallback.onLinkPropertiesChanged(net, linkProps)
+ assertFails { mCallback.expectLinkPropertiesThat(net, SHORT_TIMEOUT_MS) { lp ->
+ lp.interfaceName != TEST_INTERFACE_NAME
+ } }
+
+ // Try a matching callback on the wrong network
+ mCallback.onLinkPropertiesChanged(net, linkProps)
+ assertFails { mCallback.expectLinkPropertiesThat(Network(114), SHORT_TIMEOUT_MS) { lp ->
+ lp.interfaceName == TEST_INTERFACE_NAME
+ } }
+ }
+
+ @Test
+ fun testExpectCallback() {
+ val net = Network(103)
+ // Test expectCallback fails when nothing was sent.
+ assertFails { mCallback.expectCallback<BlockedStatus>(net, SHORT_TIMEOUT_MS) }
+
+ // Test onAvailable is seen and can be expected
+ mCallback.onAvailable(net)
+ mCallback.expectCallback<Available>(net, SHORT_TIMEOUT_MS)
+
+ // Test onAvailable won't return calls with a different network
+ mCallback.onAvailable(Network(106))
+ assertFails { mCallback.expectCallback<Available>(net, SHORT_TIMEOUT_MS) }
+
+ // Test onAvailable won't return calls with a different callback
+ mCallback.onAvailable(net)
+ assertFails { mCallback.expectCallback<BlockedStatus>(net, SHORT_TIMEOUT_MS) }
+ }
+
+ @Test
+ fun testPollForNextCallback() {
+ assertFails { mCallback.pollForNextCallback(SHORT_TIMEOUT_MS) }
+ TNCInterpreter.interpretTestSpec(initial = mCallback, lineShift = 1,
+ threadTransform = { cb -> cb.createLinkedCopy() }, spec = """
+ sleep; onAvailable(133) | poll(2) = Available(133) time 1..4
+ | poll(1) fails
+ onCapabilitiesChanged(108) | poll(1) = CapabilitiesChanged(108) time 0..3
+ onBlockedStatus(199) | poll(1) = BlockedStatus(199) time 0..3
+ """)
+ }
+}
+
+private object TNCInterpreter : ConcurrentIntepreter<TestableNetworkCallback>(interpretTable)
+
+val EntryList = CallbackEntry::class.sealedSubclasses.map { it.simpleName }.joinToString("|")
+private fun callbackEntryFromString(name: String): KClass<out CallbackEntry> {
+ return CallbackEntry::class.sealedSubclasses.first { it.simpleName == name }
+}
+
+private val interpretTable = listOf<InterpretMatcher<TestableNetworkCallback>>(
+ // Interpret "Available(xx)" as "call to onAvailable with netId xx", and likewise for
+ // all callback types. This is implemented above by enumerating the subclasses of
+ // CallbackEntry and reading their simpleName.
+ Regex("""(.*)\s+=\s+($EntryList)\((\d+)\)""") to { i, cb, t ->
+ val record = i.interpret(t.strArg(1), cb)
+ assertTrue(callbackEntryFromString(t.strArg(2)).isInstance(record))
+ // Strictly speaking testing for is CallbackEntry is useless as it's been tested above
+ // but the compiler can't figure things out from the isInstance call. It does understand
+ // from the assertTrue(is CallbackEntry) that this is true, which allows to access
+ // the 'network' member below.
+ assertTrue(record is CallbackEntry)
+ assertEquals(record.network.netId, t.intArg(3))
+ },
+ // Interpret "onAvailable(xx)" as calling "onAvailable" with a netId of xx, and likewise for
+ // all callback types. NetworkCapabilities and LinkProperties just get an empty object
+ // as their argument. Losing gets the default linger timer. Blocked gets false.
+ Regex("""on($EntryList)\((\d+)\)""") to { i, cb, t ->
+ val net = Network(t.intArg(2))
+ when (t.strArg(1)) {
+ "Available" -> cb.onAvailable(net)
+ // PreCheck not used in tests. Add it here if it becomes useful.
+ "CapabilitiesChanged" -> cb.onCapabilitiesChanged(net, NetworkCapabilities())
+ "LinkPropertiesChanged" -> cb.onLinkPropertiesChanged(net, LinkProperties())
+ "Suspended" -> cb.onNetworkSuspended(net)
+ "Resumed" -> cb.onNetworkResumed(net)
+ "Losing" -> cb.onLosing(net, DEFAULT_LINGER_DELAY_MS)
+ "Lost" -> cb.onLost(net)
+ "Unavailable" -> cb.onUnavailable()
+ "BlockedStatus" -> cb.onBlockedStatusChanged(net, false)
+ else -> fail("Unknown callback type")
+ }
+ },
+ Regex("""poll\((\d+)\)""") to { i, cb, t ->
+ cb.pollForNextCallback(t.timeArg(1))
+ }
+)
diff --git a/tests/unit/src/android/net/testutils/TrackRecordTest.kt b/tests/unit/src/android/net/testutils/TrackRecordTest.kt
index f9d3558..995d537 100644
--- a/tests/unit/src/android/net/testutils/TrackRecordTest.kt
+++ b/tests/unit/src/android/net/testutils/TrackRecordTest.kt
@@ -352,12 +352,11 @@
private object TRTInterpreter : ConcurrentIntepreter<TrackRecord<Int>>(interpretTable) {
fun interpretTestSpec(spec: String, useReadHeads: Boolean) = if (useReadHeads) {
- interpretTestSpec(spec, ArrayTrackRecord(), { (it as ArrayTrackRecord).newReadHead() })
+ interpretTestSpec(spec, initial = ArrayTrackRecord(),
+ threadTransform = { (it as ArrayTrackRecord).newReadHead() })
} else {
interpretTestSpec(spec, ArrayTrackRecord())
}
-
- override fun getCallingMethod() = getCallingMethod(4)
}
/*
diff --git a/tests/unit/src/android/net/util/NetworkStackUtilsTest.java b/tests/unit/src/android/net/util/NetworkStackUtilsTest.java
new file mode 100644
index 0000000..806054d
--- /dev/null
+++ b/tests/unit/src/android/net/util/NetworkStackUtilsTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2019 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.util;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.provider.DeviceConfig;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+
+
+/**
+ * Tests for NetworkStackUtils.
+ *
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkStackUtilsTest {
+ private static final String TEST_NAME_SPACE = "connectivity";
+ private static final String TEST_EXPERIMENT_FLAG = "experiment_flag";
+ private static final int TEST_FLAG_VERSION = 28;
+ private static final String TEST_FLAG_VERSION_STRING = "28";
+ private static final int TEST_DEFAULT_FLAG_VERSION = 0;
+ private static final long TEST_PACKAGE_VERSION = 290000000;
+ private static final String TEST_PACKAGE_NAME = "NetworkStackUtilsTest";
+ private MockitoSession mSession;
+
+ @Mock private Context mContext;
+ @Mock private PackageManager mPm;
+ @Mock private PackageInfo mPi;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mSession = mockitoSession().spyStatic(DeviceConfig.class).startMocking();
+
+ final PackageInfo pi = new PackageInfo();
+ pi.setLongVersionCode(TEST_PACKAGE_VERSION);
+
+ doReturn(mPm).when(mContext).getPackageManager();
+ doReturn(TEST_PACKAGE_NAME).when(mContext).getPackageName();
+ doReturn(pi).when(mPm).getPackageInfo(anyString(), anyInt());
+ }
+
+ @After
+ public void tearDown() {
+ mSession.finishMocking();
+ }
+
+ @Test
+ public void testGetDeviceConfigPropertyInt_Null() {
+ doReturn(null).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ assertEquals(TEST_DEFAULT_FLAG_VERSION, NetworkStackUtils.getDeviceConfigPropertyInt(
+ TEST_NAME_SPACE, TEST_EXPERIMENT_FLAG,
+ TEST_DEFAULT_FLAG_VERSION /* default value */));
+ }
+
+ @Test
+ public void testGetDeviceConfigPropertyInt_NotNull() {
+ doReturn(TEST_FLAG_VERSION_STRING).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ assertEquals(TEST_FLAG_VERSION, NetworkStackUtils.getDeviceConfigPropertyInt(
+ TEST_NAME_SPACE, TEST_EXPERIMENT_FLAG,
+ TEST_DEFAULT_FLAG_VERSION /* default value */));
+ }
+
+ @Test
+ public void testGetDeviceConfigPropertyBoolean_Null() {
+ doReturn(null).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ assertFalse(NetworkStackUtils.getDeviceConfigPropertyBoolean(
+ TEST_NAME_SPACE, TEST_EXPERIMENT_FLAG,
+ false /* default value */));
+ }
+
+ @Test
+ public void testGetDeviceConfigPropertyBoolean_NotNull() {
+ doReturn("true").when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ assertTrue(NetworkStackUtils.getDeviceConfigPropertyBoolean(
+ TEST_NAME_SPACE, TEST_EXPERIMENT_FLAG,
+ false /* default value */));
+ }
+
+ @Test
+ public void testFeatureIsEnabledWithExceptionsEnabled() {
+ doReturn(TEST_FLAG_VERSION_STRING).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ assertTrue(NetworkStackUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ TEST_EXPERIMENT_FLAG));
+ }
+
+ @Test
+ public void testFeatureIsNotEnabled() {
+ doReturn(null).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ assertFalse(NetworkStackUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ TEST_EXPERIMENT_FLAG));
+ }
+
+ @Test
+ public void testFeatureIsEnabledWithException() throws Exception {
+ doReturn(TEST_FLAG_VERSION_STRING).when(() -> DeviceConfig.getProperty(eq(TEST_NAME_SPACE),
+ eq(TEST_EXPERIMENT_FLAG)));
+ doThrow(NameNotFoundException.class).when(mPm).getPackageInfo(anyString(), anyInt());
+ assertFalse(NetworkStackUtils.isFeatureEnabled(mContext, TEST_NAME_SPACE,
+ TEST_EXPERIMENT_FLAG));
+ }
+}
diff --git a/tests/unit/src/android/networkstack/metrics/DataStallStatsUtilsTest.kt b/tests/unit/src/android/networkstack/metrics/DataStallStatsUtilsTest.kt
new file mode 100644
index 0000000..3b53b5f
--- /dev/null
+++ b/tests/unit/src/android/networkstack/metrics/DataStallStatsUtilsTest.kt
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 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.networkstack.metrics
+
+import android.net.captiveportal.CaptivePortalProbeResult
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.networkstack.metrics.DataStallStatsUtils
+import com.android.server.connectivity.nano.DataStallEventProto
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class DataStallStatsUtilsTest {
+ @Test
+ fun testProbeResultToEnum() {
+ assertEquals(DataStallStatsUtils.probeResultToEnum(null), DataStallEventProto.INVALID)
+ assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult.FAILED),
+ DataStallEventProto.INVALID)
+ assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult.SUCCESS),
+ DataStallEventProto.VALID)
+ assertEquals(DataStallStatsUtils.probeResultToEnum(CaptivePortalProbeResult.PARTIAL),
+ DataStallEventProto.PARTIAL)
+ assertEquals(DataStallStatsUtils.probeResultToEnum(
+ CaptivePortalProbeResult(CaptivePortalProbeResult.PORTAL_CODE)),
+ DataStallEventProto.PORTAL)
+ }
+}