[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 230e1fb647 -s ours
am skip reason: subject contains skip directive
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/NetworkStack/+/15433152
Change-Id: I2648feec26ee30d2d923e92a15ba6ecb87e4fc80
diff --git a/Android.bp b/Android.bp
index cce44b0..367c542 100644
--- a/Android.bp
+++ b/Android.bp
@@ -45,10 +45,6 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-// Whether to enable the targets in this file that target current SDKs.
-// Set to false in branches like mainline-prod where API classes are too old to build current code.
-enable_current_sdk_targets = false
-
java_defaults {
name: "NetworkStackDevApiLevel",
min_sdk_version: "29",
@@ -57,9 +53,14 @@
java_defaults {
name: "NetworkStackReleaseApiLevel",
- sdk_version: "system_30",
+ sdk_version: "module_31",
min_sdk_version: "29",
- target_sdk_version: "30",
+ target_sdk_version: "31",
+ libs: [
+ "framework-connectivity",
+ "framework-statsd",
+ "framework-wifi",
+ ]
}
// Libraries for the API shims
@@ -127,7 +128,6 @@
// integer so if the next SDK release happens to use that integer, we don't need to rename them.
java_library {
name: "NetworkStackApi31Shims",
- enabled: enable_current_sdk_targets,
defaults: ["NetworkStackShimsDefaults"],
srcs: [
"apishim/31/**/*.java",
@@ -138,6 +138,27 @@
"NetworkStackApi30Shims",
"framework-connectivity",
],
+ sdk_version: "module_31",
+ visibility: ["//visibility:private"],
+}
+
+
+// Shims for APIs being added to the current development version of Android. These APIs are not
+// stable and have no defined version number. These could be called 10000, but they use the next
+// integer so if the next SDK release happens to use that integer, we don't need to rename them.
+java_library {
+ name: "NetworkStackApi32Shims",
+ defaults: ["NetworkStackShimsDefaults"],
+ srcs: [
+ "apishim/32/**/*.java",
+ ],
+ libs: [
+ "NetworkStackShimsCommon",
+ "NetworkStackApi29Shims",
+ "NetworkStackApi30Shims",
+ "NetworkStackApi31Shims",
+ "framework-connectivity",
+ ],
sdk_version: "module_current",
visibility: ["//visibility:private"],
}
@@ -147,13 +168,13 @@
// called directly by the networkstack code.
java_library {
name: "NetworkStackApiCurrentShims",
- enabled: enable_current_sdk_targets,
defaults: ["NetworkStackShimsDefaults"],
static_libs: [
"NetworkStackShimsCommon",
"NetworkStackApi29Shims",
"NetworkStackApi30Shims",
"NetworkStackApi31Shims",
+ "NetworkStackApi32Shims",
],
sdk_version: "module_current",
visibility: [
@@ -172,9 +193,10 @@
"NetworkStackShimsCommon",
"NetworkStackApi29Shims",
"NetworkStackApi30Shims",
+ "NetworkStackApi31Shims",
],
jarjar_rules: "apishim/jarjar-rules-compat.txt",
- sdk_version: "system_30",
+ sdk_version: "module_31",
visibility: [
"//packages/modules/Connectivity/Tethering",
"//packages/modules/Connectivity/tests/cts/net",
@@ -215,7 +237,6 @@
],
static_libs: ["NetworkStackApiCurrentShims"],
manifest: "AndroidManifestBase.xml",
- enabled: enable_current_sdk_targets,
visibility: [
"//frameworks/base/tests/net/integration",
"//packages/modules/Connectivity/Tethering/tests/integration",
@@ -290,8 +311,10 @@
// 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"],
- enabled: enable_current_sdk_targets,
+ required: [
+ "PlatformNetworkPermissionConfig",
+ "PlatformCaptivePortalLogin",
+ ],
}
// Pre-merge the AndroidManifest for NetworkStackNext, so that its manifest can be merged on top
@@ -299,8 +322,7 @@
name: "NetworkStackNextManifestBase",
defaults: ["NetworkStackAppDefaults", "NetworkStackDevApiLevel"],
static_libs: ["NetworkStackApiCurrentLib"],
- manifest: "AndroidManifest.xml",
- enabled: enable_current_sdk_targets,
+ manifest: "AndroidManifest.xml"
}
// NetworkStack build targeting the current API release, for testing on in-development SDK
@@ -311,8 +333,10 @@
certificate: "networkstack",
manifest: "AndroidManifest_Next.xml",
// The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
- enabled: enable_current_sdk_targets,
+ required: [
+ "NetworkPermissionConfig",
+ "privapp_whitelist_com.android.networkstack",
+ ],
}
// Updatable network stack for finalized API
@@ -323,7 +347,10 @@
certificate: "networkstack",
manifest: "AndroidManifest.xml",
// The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
+ required: [
+ "NetworkPermissionConfig",
+ "privapp_whitelist_com.android.networkstack",
+ ],
updatable: true,
}
@@ -400,7 +427,10 @@
certificate: "networkstack",
manifest: ":NetworkStackTestAndroidManifest",
// The permission configuration *must* be included to ensure security of the device
- required: ["NetworkPermissionConfig"],
+ required: [
+ "NetworkPermissionConfig",
+ "privapp_whitelist_com.android.networkstack",
+ ],
}
// When adding or modifying protos, the jarjar rules and possibly proguard rules need
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 55357a8..6a11b2c 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,8 +19,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack"
android:sharedUserId="android.uid.networkstack"
- android:versionCode="309999900"
- android:versionName="r_aml_309999900"
+ android:versionCode="319999900"
+ android:versionName="s_aml_319999900"
>
<!-- 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
diff --git a/AndroidManifest_Next.xml b/AndroidManifest_Next.xml
index 02fcb64..9ad69ae 100644
--- a/AndroidManifest_Next.xml
+++ b/AndroidManifest_Next.xml
@@ -17,6 +17,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.networkstack"
android:sharedUserId="android.uid.networkstack"
- android:versionCode="300000000"
- android:versionName="R-next">
+ android:versionCode="320000000"
+ android:versionName="T-next">
</manifest>
diff --git a/TEST_MAPPING b/TEST_MAPPING
index ed6a1a8..2bb0e61 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -40,7 +40,8 @@
// We must specify at least one module here or the tests won't run. Use the same set as CTS
// so in theory the infra would not need to reinstall/reboot devices to run both.
{
- "name": "NetworkStackTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex]"
+ // TODO: add back tethering when it is updatable in this branch
+ "name": "NetworkStackTests[CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex]"
}
],
"mainline-postsubmit": [
diff --git a/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
similarity index 98%
rename from apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
index 5af7412..5ae006b 100644
--- a/apishim/31/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/CaptivePortalDataShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import android.net.CaptivePortalData;
import android.net.Uri;
diff --git a/apishim/31/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
similarity index 98%
rename from apishim/31/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
index 0e01c98..46de698 100644
--- a/apishim/31/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/ConnectivityManagerShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
diff --git a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java b/apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
similarity index 96%
rename from apishim/31/com/android/networkstack/apishim/ConstantsShim.java
rename to apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
index 0184845..95ff072 100644
--- a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/ConstantsShim.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import androidx.annotation.VisibleForTesting;
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
similarity index 94%
rename from apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
index d2615e6..a5c9a71 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkInformationShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/NetworkInformationShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
@@ -50,7 +50,7 @@
if (!useApiAboveR()) {
return com.android.networkstack.apishim.api30.NetworkInformationShimImpl.newInstance();
}
- return new com.android.networkstack.apishim.NetworkInformationShimImpl();
+ return new NetworkInformationShimImpl();
}
@Nullable
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkRequestShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
similarity index 87%
rename from apishim/31/com/android/networkstack/apishim/NetworkRequestShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
index ccc8f70..2dc5d72 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkRequestShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/NetworkRequestShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
@@ -58,6 +58,13 @@
}
@Override
+ public NetworkRequest.Builder setIncludeOtherUidNetworks(NetworkRequest.Builder builder,
+ boolean include) {
+ builder.setIncludeOtherUidNetworks(include);
+ return builder;
+ }
+
+ @Override
public NetworkRequest.Builder newBuilder(@NonNull NetworkRequest request) {
return new NetworkRequest.Builder(request);
}
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
similarity index 95%
rename from apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
index 0c92391..eda8e27 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/NetworkShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import android.net.Network;
diff --git a/apishim/31/com/android/networkstack/apishim/SettingsShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
similarity index 87%
rename from apishim/31/com/android/networkstack/apishim/SettingsShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
index e15872f..1b5cbae 100644
--- a/apishim/31/com/android/networkstack/apishim/SettingsShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/SettingsShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
import android.content.Context;
import android.os.Build;
@@ -48,9 +48,7 @@
public boolean checkAndNoteWriteSettingsOperation(@NonNull Context context, int uid,
@NonNull String callingPackage, @Nullable String callingAttributionTag,
boolean throwException) {
- // Since checkAndNoteWriteSettingsOperation with callingAttributionTag (S method) is not
- // available in AOSP, calling R method (same as API 30 shim) temporary.
return Settings.checkAndNoteWriteSettingsOperation(context, uid, callingPackage,
- throwException);
+ callingAttributionTag, throwException);
}
}
diff --git a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
similarity index 94%
rename from apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
rename to apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
index 483bde0..f5aa80b 100644
--- a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
+++ b/apishim/31/com/android/networkstack/apishim/api31/SocketUtilsShimImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.networkstack.apishim;
+package com.android.networkstack.apishim.api31;
/**
* Implementation of {@link NetworkShim} for API 30.
diff --git a/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java b/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
new file mode 100644
index 0000000..2056b1b
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/CaptivePortalDataShimImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.CaptivePortalData;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.CaptivePortalDataShim;
+
+/**
+ * Compatibility implementation of {@link CaptivePortalDataShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class CaptivePortalDataShimImpl
+ extends com.android.networkstack.apishim.api31.CaptivePortalDataShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ public CaptivePortalDataShimImpl(@NonNull CaptivePortalData data) {
+ super(data);
+ }
+}
diff --git a/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java b/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
new file mode 100644
index 0000000..a7aa0c8
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/ConnectivityManagerShimImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.content.Context;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.ConnectivityManagerShim;
+
+/**
+ * Compatibility implementation of {@link ConnectivityManagerShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class ConnectivityManagerShimImpl
+ extends com.android.networkstack.apishim.api31.ConnectivityManagerShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected ConnectivityManagerShimImpl(Context context) {
+ super(context);
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java b/apishim/32/com/android/networkstack/apishim/ConstantsShim.java
similarity index 76%
copy from apishim/31/com/android/networkstack/apishim/ConstantsShim.java
copy to apishim/32/com/android/networkstack/apishim/ConstantsShim.java
index 0184845..0a5b555 100644
--- a/apishim/31/com/android/networkstack/apishim/ConstantsShim.java
+++ b/apishim/32/com/android/networkstack/apishim/ConstantsShim.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -21,7 +21,7 @@
/**
* Utility class for defining and importing constants from the Android platform.
*/
-public class ConstantsShim extends com.android.networkstack.apishim.api30.ConstantsShim {
+public class ConstantsShim extends com.android.networkstack.apishim.api31.ConstantsShim {
/**
* Constant that callers can use to determine what version of the shim they are using.
* Must be the same as the version of the shims.
@@ -29,9 +29,5 @@
* the shimmed objects and methods themselves.
*/
@VisibleForTesting
- public static final int VERSION = 31;
-
- // When removing this shim, the version in NetworkMonitorUtils should be removed too.
- // TODO: add TRANSPORT_TEST to system API in API 31 (it is only a test API as of R)
- public static final int TRANSPORT_TEST = 7;
+ public static final int VERSION = 32;
}
diff --git a/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java
new file mode 100644
index 0000000..28aa75c
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/NetworkInformationShimImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.NetworkInformationShim;
+
+/**
+ * Compatibility implementation of {@link NetworkInformationShim}.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class NetworkInformationShimImpl
+ extends com.android.networkstack.apishim.api31.NetworkInformationShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected NetworkInformationShimImpl() {}
+}
diff --git a/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java
new file mode 100644
index 0000000..95ae5ba
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/NetworkRequestShimImpl.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.NetworkRequestShim;
+
+/**
+ * Implementation of {@link NetworkRequestShim} for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class NetworkRequestShimImpl
+ extends com.android.networkstack.apishim.api31.NetworkRequestShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected NetworkRequestShimImpl() {
+ super();
+ }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java b/apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
similarity index 70%
copy from apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
copy to apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
index 0c92391..2e31a78 100644
--- a/apishim/31/com/android/networkstack/apishim/NetworkShimImpl.java
+++ b/apishim/32/com/android/networkstack/apishim/NetworkShimImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -17,14 +17,17 @@
package com.android.networkstack.apishim;
import android.net.Network;
+import android.os.Build;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
/**
- * Implementation of {@link NetworkShim} for API 30.
+ * Compatibility implementation of {@link com.android.networkstack.apishim.common.NetworkShim}.
*/
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
public class NetworkShimImpl extends com.android.networkstack.apishim.api30.NetworkShimImpl {
- // Currently, this is the same as the API 30 shim, so inherit everything from that.
+ // Currently, this is the same as the API 31 shim, so inherit everything from that.
protected NetworkShimImpl(@NonNull Network network) {
super(network);
}
diff --git a/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java b/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java
new file mode 100644
index 0000000..46d2102
--- /dev/null
+++ b/apishim/32/com/android/networkstack/apishim/SettingsShimImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.os.Build;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.networkstack.apishim.common.SettingsShim;
+
+/**
+ * Compatibility implementation of {@link SettingsShim} for API 31.
+ */
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
+public class SettingsShimImpl
+ extends com.android.networkstack.apishim.api30.SettingsShimImpl {
+ // Currently identical to the API 31 shim, so inherit everything
+ protected SettingsShimImpl() { }
+}
diff --git a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java b/apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
similarity index 68%
copy from apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
copy to apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
index 483bde0..2f4e500 100644
--- a/apishim/31/com/android/networkstack/apishim/SocketUtilsShimImpl.java
+++ b/apishim/32/com/android/networkstack/apishim/SocketUtilsShimImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -16,11 +16,16 @@
package com.android.networkstack.apishim;
+import android.os.Build;
+
+import androidx.annotation.RequiresApi;
+
/**
- * Implementation of {@link NetworkShim} for API 30.
+ * Implementation of {@link com.android.networkstack.apishim.common.SocketUtilsShim}.
*/
+@RequiresApi(Build.VERSION_CODES.S) // Change to T when version code available, and adding T methods
public class SocketUtilsShimImpl
extends com.android.networkstack.apishim.api30.SocketUtilsShimImpl {
- // Currently, this is the same as the API 30 shim, so inherit everything from that.
+ // Currently, this is the same as the API 31 shim, so inherit everything from that.
protected SocketUtilsShimImpl() {}
}
diff --git a/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java b/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
index 7d6d7bf..d07d1ae 100644
--- a/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
+++ b/apishim/common/com/android/networkstack/apishim/common/NetworkRequestShim.java
@@ -37,6 +37,14 @@
@Nullable Set<Range<Integer>> uids) throws UnsupportedApiLevelException;
/**
+ * See android.net.NetworkRequest.Builder#setIncludeOtherUidNetworks.
+ */
+ default NetworkRequest.Builder setIncludeOtherUidNetworks(NetworkRequest.Builder builder,
+ boolean include) throws UnsupportedApiLevelException {
+ throw new UnsupportedApiLevelException("Not supported before API 31.");
+ }
+
+ /**
* See android.net.NetworkRequest.Builder(NetworkRequest).
* @throws UnsupportedApiLevelException if API is not available in the API level.
*/
diff --git a/apishim/jarjar-rules-compat.txt b/apishim/jarjar-rules-compat.txt
index dba2b49..4f34ccb 100644
--- a/apishim/jarjar-rules-compat.txt
+++ b/apishim/jarjar-rules-compat.txt
@@ -1,7 +1,7 @@
# jarjar rules to use on API stable builds.
# Use the latest stable apishim package as the main apishim package, to replace and avoid building
# the unstable, non-compatibility shims.
-# Once API 31 is stable, apishim/31/com.android.networkstack.apishim should be moved to the
-# com.android.networkstack.apishim.api31 package, a new apishim/32/com.android.networkstack.apishim
-# package should be created, and this rule should reference api31.
-rule com.android.networkstack.apishim.api30.** com.android.networkstack.apishim.@1
\ No newline at end of file
+# Once API 32 is stable, apishim/32/com.android.networkstack.apishim should be moved to the
+# com.android.networkstack.apishim.api32 package, a new apishim/33/com.android.networkstack.apishim
+# package should be created, and this rule should reference api32.
+rule com.android.networkstack.apishim.api31.** com.android.networkstack.apishim.@1
\ No newline at end of file
diff --git a/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
index 2ba1dcc..8b388ad 100755
--- a/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
+++ b/common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java
@@ -103,11 +103,22 @@
}
public boolean isSuccessful() {
- return mHttpResponseCode == SUCCESS_CODE;
+ return isSuccessCode(mHttpResponseCode);
}
public boolean isPortal() {
- return !isSuccessful() && (mHttpResponseCode >= 200) && (mHttpResponseCode <= 399);
+ return isPortalCode(mHttpResponseCode);
+ }
+
+ private static boolean isSuccessCode(int responseCode) {
+ return responseCode == SUCCESS_CODE;
+ }
+
+ /**
+ * @return Whether the specified HTTP return code indicates a captive portal.
+ */
+ public static boolean isPortalCode(int responseCode) {
+ return !isSuccessCode(responseCode) && (responseCode >= 200) && (responseCode <= 399);
}
public boolean isFailed() {
diff --git a/common/moduleutils/Android.bp b/common/moduleutils/Android.bp
index 5d1c9e3..54f4b22 100644
--- a/common/moduleutils/Android.bp
+++ b/common/moduleutils/Android.bp
@@ -25,20 +25,15 @@
name: "net-module-utils-srcs",
srcs: [
"src/android/net/util/SharedLog.java",
- "src/android/net/shared/InitialConfiguration.java",
- "src/android/net/shared/Layer2Information.java",
- "src/android/net/shared/LinkPropertiesParcelableUtil.java",
- "src/android/net/shared/ParcelableUtil.java",
"src/android/net/shared/NetdUtils.java",
"src/android/net/shared/NetworkMonitorUtils.java",
- "src/android/net/shared/ParcelableUtil.java",
- "src/android/net/shared/PrivateDnsConfig.java",
- "src/android/net/shared/ProvisioningConfiguration.java",
"src/android/net/shared/RouteUtils.java",
"src/android/net/util/InterfaceParams.java",
],
visibility: [
"//frameworks/base/services/net",
+ "//frameworks/base/packages/Connectivity/service",
+ "//packages/modules/Connectivity/service",
]
}
diff --git a/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java b/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
index 981a576..18138a7 100644
--- a/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
+++ b/common/moduleutils/src/android/net/shared/NetworkMonitorUtils.java
@@ -19,6 +19,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.TRANSPORT_BLUETOOTH;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
@@ -36,6 +37,14 @@
// TODO: use NetworkCapabilities.TRANSPORT_TEST once NetworkStack builds against API 31.
private static final int TRANSPORT_TEST = 7;
+ // This class is used by both NetworkMonitor and ConnectivityService, so it cannot use
+ // NetworkStack shims, but at the same time cannot use non-system APIs.
+ // NET_CAPABILITY_NOT_VCN_MANAGED is system API as of S (so it is enforced to always be 28 and
+ // can't be changed).
+ // TODO: use NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED once NetworkStack builds against
+ // API 31.
+ public static final int NET_CAPABILITY_NOT_VCN_MANAGED = 28;
+
// Network conditions broadcast constants
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
@@ -59,11 +68,15 @@
public static boolean isPrivateDnsValidationRequired(NetworkCapabilities nc) {
if (nc == null) return false;
+ final boolean isVcnManaged = !nc.hasCapability(NET_CAPABILITY_NOT_VCN_MANAGED);
+ final boolean isOemPaid = nc.hasCapability(NET_CAPABILITY_OEM_PAID)
+ && nc.hasCapability(NET_CAPABILITY_TRUSTED);
+ final boolean isDefaultCapable = nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
+ && nc.hasCapability(NET_CAPABILITY_TRUSTED);
+
// TODO: Consider requiring validation for DUN networks.
if (nc.hasCapability(NET_CAPABILITY_INTERNET)
- && nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)
- && nc.hasCapability(NET_CAPABILITY_TRUSTED)) {
- // Real networks
+ && (isVcnManaged || isOemPaid || isDefaultCapable)) {
return true;
}
diff --git a/common/networkstackclient/Android.bp b/common/networkstackclient/Android.bp
index 96ff315..376ff89 100644
--- a/common/networkstackclient/Android.bp
+++ b/common/networkstackclient/Android.bp
@@ -72,7 +72,7 @@
// For framework parcelables.
"frameworks/base/core/java",
// For API parcelables in connectivity
- "frameworks/base/packages/Connectivity/framework/aidl-export",
+ "packages/modules/Connectivity/framework/aidl-export",
"frameworks/native/aidl/binder", // For PersistableBundle.aidl
],
srcs: [
@@ -145,25 +145,34 @@
java_library {
name: "networkstack-client",
sdk_version: "system_current",
- // this is part of updatable modules(NetworkStack) which targets 29(Q)
+ // this is part of updatable modules(NetworkStack) which runs on Q and above
min_sdk_version: "29",
srcs: [
":framework-annotations",
+ "src/android/net/ip/**/*.java",
+ "src/android/net/IpMemoryStore.java",
"src/android/net/IpMemoryStoreClient.java",
"src/android/net/ipmemorystore/**/*.java",
+ "src/android/net/NetworkMonitorManager.java",
"src/android/net/networkstack/**/*.java",
"src/android/net/networkstack/aidl/quirks/**/*.java",
"src/android/net/shared/**/*.java",
+ "src/android/net/util/**/*.java",
+ ],
+ libs: [
+ "net-utils-framework-common", // XXX for IpUtils.java only
],
static_libs: [
"ipmemorystore-aidl-interfaces-V10-java",
"networkstack-aidl-interfaces-V10-java",
],
visibility: [
- "//frameworks/base/packages/Tethering",
+ "//frameworks/base/packages/Connectivity/service",
"//packages/modules/Connectivity/Tethering",
+ "//packages/modules/Connectivity/service",
"//frameworks/base/services/net",
"//frameworks/opt/net/wifi/service",
+ "//packages/apps/Bluetooth",
"//packages/modules/NetworkStack",
],
apex_available: [
diff --git a/common/networkstackclient/src/android/net/IpMemoryStore.java b/common/networkstackclient/src/android/net/IpMemoryStore.java
new file mode 100644
index 0000000..f2c1d35
--- /dev/null
+++ b/common/networkstackclient/src/android/net/IpMemoryStore.java
@@ -0,0 +1,98 @@
+/*
+ * 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.content.Context;
+import android.net.networkstack.ModuleNetworkStackClient;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+/**
+ * Manager class used to communicate with the ip memory store service in the network stack,
+ * which is running in a separate module.
+ * @hide
+*/
+public class IpMemoryStore extends IpMemoryStoreClient {
+ private static final String TAG = IpMemoryStore.class.getSimpleName();
+ @NonNull private final CompletableFuture<IIpMemoryStore> mService;
+ @NonNull private final AtomicReference<CompletableFuture<IIpMemoryStore>> mTailNode;
+
+ public IpMemoryStore(@NonNull final Context context) {
+ super(context);
+ mService = new CompletableFuture<>();
+ mTailNode = new AtomicReference<CompletableFuture<IIpMemoryStore>>(mService);
+ getModuleNetworkStackClient(context).fetchIpMemoryStore(
+ new IIpMemoryStoreCallbacks.Stub() {
+ @Override
+ public void onIpMemoryStoreFetched(@NonNull final IIpMemoryStore memoryStore) {
+ mService.complete(memoryStore);
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ });
+ }
+
+ /*
+ * If the IpMemoryStore is ready, this function will run the request synchronously.
+ * Otherwise, it will enqueue the requests for execution immediately after the
+ * service becomes ready. The requests are guaranteed to be executed in the order
+ * they are sumbitted.
+ */
+ @Override
+ protected void runWhenServiceReady(Consumer<IIpMemoryStore> cb) throws ExecutionException {
+ mTailNode.getAndUpdate(future -> future.handle((store, exception) -> {
+ if (exception != null) {
+ // this should never happens since we also catch the exception below
+ Log.wtf(TAG, "Error fetching IpMemoryStore", exception);
+ return store;
+ }
+
+ try {
+ cb.accept(store);
+ } catch (Exception e) {
+ Log.wtf(TAG, "Exception occurred: " + e.getMessage());
+ }
+ return store;
+ }));
+ }
+
+ @VisibleForTesting
+ protected ModuleNetworkStackClient getModuleNetworkStackClient(Context context) {
+ return ModuleNetworkStackClient.getInstance(context);
+ }
+
+ /** Gets an instance of the memory store */
+ @NonNull
+ public static IpMemoryStore getMemoryStore(final Context context) {
+ return new IpMemoryStore(context);
+ }
+}
diff --git a/common/networkstackclient/src/android/net/NetworkMonitorManager.java b/common/networkstackclient/src/android/net/NetworkMonitorManager.java
new file mode 100644
index 0000000..0f66981
--- /dev/null
+++ b/common/networkstackclient/src/android/net/NetworkMonitorManager.java
@@ -0,0 +1,203 @@
+/*
+ * 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.Hide;
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for INetworkMonitor.
+ *
+ * Wraps INetworkMonitor calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on INetworkMonitor are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+@Hide
+public class NetworkMonitorManager {
+
+ @NonNull private final INetworkMonitor mNetworkMonitor;
+ @NonNull private final String mTag;
+
+ public NetworkMonitorManager(@NonNull INetworkMonitor networkMonitorManager,
+ @NonNull String tag) {
+ mNetworkMonitor = networkMonitorManager;
+ mTag = tag;
+ }
+
+ public NetworkMonitorManager(@NonNull INetworkMonitor networkMonitorManager) {
+ this(networkMonitorManager, NetworkMonitorManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ // CHECKSTYLE:OFF Generated code
+
+ public boolean start() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.start();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in start", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean launchCaptivePortalApp() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.launchCaptivePortalApp();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in launchCaptivePortalApp", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyCaptivePortalAppFinished(int response) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyCaptivePortalAppFinished(response);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyCaptivePortalAppFinished", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean setAcceptPartialConnectivity() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.setAcceptPartialConnectivity();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in setAcceptPartialConnectivity", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean forceReevaluation(int uid) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.forceReevaluation(uid);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in forceReevaluation", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyPrivateDnsChanged(PrivateDnsConfigParcel config) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyPrivateDnsChanged(config);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyPrivateDnsChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyDnsResponse(int returnCode) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyDnsResponse(returnCode);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyDnsResponse", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkConnected(lp, nc);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkConnected", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkDisconnected() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkDisconnected();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkDisconnected", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyLinkPropertiesChanged(LinkProperties lp) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyLinkPropertiesChanged(lp);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyLinkPropertiesChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkCapabilitiesChanged(nc);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkCapabilitiesChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // CHECKSTYLE:ON Generated code
+}
diff --git a/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java b/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
new file mode 100644
index 0000000..b17fcaa
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IpClientCallbacks.java
@@ -0,0 +1,136 @@
+/*
+ * 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.ip;
+
+import android.net.DhcpResultsParcelable;
+import android.net.Layer2PacketParcelable;
+import android.net.LinkProperties;
+
+import java.util.List;
+
+/**
+ * Callbacks for handling IpClient events.
+ *
+ * This is a convenience class to allow clients not to override all methods of IIpClientCallbacks,
+ * and avoid unparceling arguments.
+ * These methods are called asynchronously on a Binder thread, as IpClient lives in a different
+ * process.
+ * @hide
+ */
+public class IpClientCallbacks {
+
+ /**
+ * Callback called upon IpClient creation.
+ *
+ * @param ipClient The Binder token to communicate with IpClient.
+ */
+ public void onIpClientCreated(IIpClient ipClient) {}
+
+ /**
+ * Callback called prior to DHCP discovery/renewal.
+ *
+ * <p>In order to receive onPreDhcpAction(), call #withPreDhcpAction() when constructing a
+ * ProvisioningConfiguration.
+ *
+ * <p>Implementations of onPreDhcpAction() must call IpClient#completedPreDhcpAction() to
+ * indicate that DHCP is clear to proceed.
+ */
+ public void onPreDhcpAction() {}
+
+ /**
+ * Callback called after DHCP discovery/renewal.
+ */
+ public void onPostDhcpAction() {}
+
+ /**
+ * Callback called when new DHCP results are available.
+ *
+ * <p>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).
+ *
+ * <p>DHCPv4 or static IPv4 configuration failure or success can be determined by whether or not
+ * the passed-in DhcpResults object is null.
+ */
+ public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
+ // In general callbacks would not use a parcelable directly (DhcpResultsParcelable), and
+ // would use a wrapper instead, because of the lack of safety of stable parcelables. But
+ // there are already two classes in the tree for DHCP information: DhcpInfo and DhcpResults,
+ // and neither of them exposes an appropriate API (they are bags of mutable fields and can't
+ // be changed because they are public API and @UnsupportedAppUsage, being no better than the
+ // stable parcelable). Adding a third class would cost more than the gain considering that
+ // the only client of this callback is WiFi, which will end up converting the results to
+ // DhcpInfo anyway.
+ }
+
+ /**
+ * Indicates that provisioning was successful.
+ */
+ public void onProvisioningSuccess(LinkProperties newLp) {}
+
+ /**
+ * Indicates that provisioning failed.
+ */
+ public void onProvisioningFailure(LinkProperties newLp) {}
+
+ /**
+ * Invoked on LinkProperties changes.
+ */
+ public void onLinkPropertiesChange(LinkProperties newLp) {}
+
+ /**Called when the internal IpReachabilityMonitor (if enabled) has
+ * detected the loss of a critical number of required neighbors.
+ */
+ public void onReachabilityLost(String logMsg) {}
+
+ /**
+ * Called when the IpClient state machine terminates.
+ */
+ public void onQuit() {}
+
+ /**
+ * Called to indicate that a new APF program must be installed to filter incoming packets.
+ */
+ public void installPacketFilter(byte[] filter) {}
+
+ /**
+ * Called to indicate that the APF Program & data buffer must be read asynchronously from the
+ * wifi driver.
+ *
+ * <p>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.
+ */
+ public void startReadPacketFilter() {}
+
+ /**
+ * If multicast filtering cannot be accomplished with APF, this function will be called to
+ * actuate multicast filtering using another means.
+ */
+ public void setFallbackMulticastFilter(boolean enabled) {}
+
+ /**
+ * Enabled/disable Neighbor Discover offload functionality. This is called, for example,
+ * whenever 464xlat is being started or stopped.
+ */
+ public void setNeighborDiscoveryOffload(boolean enable) {}
+
+ /**
+ * Invoked on starting preconnection process.
+ */
+ public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {}
+}
diff --git a/common/networkstackclient/src/android/net/ip/IpClientManager.java b/common/networkstackclient/src/android/net/ip/IpClientManager.java
new file mode 100644
index 0000000..b45405f
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IpClientManager.java
@@ -0,0 +1,326 @@
+/*
+ * 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.ip;
+
+import android.annotation.Hide;
+import android.annotation.NonNull;
+import android.net.NattKeepalivePacketData;
+import android.net.ProxyInfo;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
+import android.net.shared.Layer2Information;
+import android.net.shared.ProvisioningConfiguration;
+import android.net.util.KeepalivePacketDataUtil;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for IpClient.
+ *
+ * Wraps IIpClient calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on IIpClient are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+@Hide
+public class IpClientManager {
+ @NonNull private final IIpClient mIpClient;
+ @NonNull private final String mTag;
+
+ public IpClientManager(@NonNull IIpClient ipClient, @NonNull String tag) {
+ mIpClient = ipClient;
+ mTag = tag;
+ }
+
+ public IpClientManager(@NonNull IIpClient ipClient) {
+ this(ipClient, IpClientManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ /**
+ * For clients using {@link ProvisioningConfiguration.Builder#withPreDhcpAction()}, must be
+ * called after {@link IIpClientCallbacks#onPreDhcpAction} to indicate that DHCP is clear to
+ * proceed.
+ */
+ public boolean completedPreDhcpAction() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.completedPreDhcpAction();
+ return true;
+ } catch (RemoteException e) {
+ log("Error completing PreDhcpAction", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Confirm the provisioning configuration.
+ */
+ public boolean confirmConfiguration() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.confirmConfiguration();
+ return true;
+ } catch (RemoteException e) {
+ log("Error confirming IpClient configuration", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Indicate that packet filter read is complete.
+ */
+ public boolean readPacketFilterComplete(byte[] data) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.readPacketFilterComplete(data);
+ return true;
+ } catch (RemoteException e) {
+ log("Error notifying IpClient of packet filter read", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Shut down this IpClient instance altogether.
+ */
+ public boolean shutdown() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.shutdown();
+ return true;
+ } catch (RemoteException e) {
+ log("Error shutting down IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Start provisioning with the provided parameters.
+ */
+ public boolean startProvisioning(ProvisioningConfiguration prov) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.startProvisioning(prov.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error starting IpClient provisioning", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Stop this IpClient.
+ *
+ * <p>This does not shut down the StateMachine itself, which is handled by {@link #shutdown()}.
+ */
+ public boolean stop() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.stop();
+ return true;
+ } catch (RemoteException e) {
+ log("Error stopping IpClient", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the TCP buffer sizes to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setTcpBufferSizes(String tcpBufferSizes) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setTcpBufferSizes(tcpBufferSizes);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient TCP buffer sizes", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the HTTP Proxy configuration to use.
+ *
+ * This may be called, repeatedly, at any time before or after a call to
+ * #startProvisioning(). The setting is cleared upon calling #stop().
+ */
+ public boolean setHttpProxy(ProxyInfo proxyInfo) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setHttpProxy(proxyInfo);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting IpClient proxy", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Enable or disable the multicast filter. Attempts to use APF to accomplish the filtering,
+ * if not, Callback.setFallbackMulticastFilter() is called.
+ */
+ public boolean setMulticastFilter(boolean enabled) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setMulticastFilter(enabled);
+ return true;
+ } catch (RemoteException e) {
+ log("Error setting multicast filter", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketData pkt) {
+ return addKeepalivePacketFilter(slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
+ }
+
+ /**
+ * Add a TCP keepalive packet filter before setting up keepalive offload.
+ * @deprecated This method is for use on pre-S platforms where TcpKeepalivePacketData is not
+ * system API. On newer platforms use
+ * addKeepalivePacketFilter(int, TcpKeepalivePacketData) instead.
+ */
+ @Deprecated
+ public boolean addKeepalivePacketFilter(int slot, TcpKeepalivePacketDataParcelable pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addKeepalivePacketFilter(slot, pkt);
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Add a NAT-T keepalive packet filter before setting up keepalive offload.
+ */
+ public boolean addKeepalivePacketFilter(int slot, NattKeepalivePacketData pkt) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.addNattKeepalivePacketFilter(
+ slot, KeepalivePacketDataUtil.toStableParcelable(pkt));
+ return true;
+ } catch (RemoteException e) {
+ log("Error adding NAT-T Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Remove a keepalive packet filter after stopping keepalive offload.
+ */
+ public boolean removeKeepalivePacketFilter(int slot) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.removeKeepalivePacketFilter(slot);
+ return true;
+ } catch (RemoteException e) {
+ log("Error removing Keepalive Packet Filter ", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Set the L2 key and group hint for storing info into the memory store.
+ */
+ public boolean setL2KeyAndGroupHint(String l2Key, String groupHint) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.setL2KeyAndGroupHint(l2Key, groupHint);
+ return true;
+ } catch (RemoteException e) {
+ log("Failed setL2KeyAndGroupHint", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Notify IpClient that preconnection is complete and that the link is ready for use.
+ * The success parameter indicates whether the packets passed in by 'onPreconnectionStart'
+ * were successfully sent to the network or not.
+ */
+ public boolean notifyPreconnectionComplete(boolean success) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.notifyPreconnectionComplete(success);
+ return true;
+ } catch (RemoteException e) {
+ log("Error notifying IpClient Preconnection completed", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Update the bssid, L2 key and group hint layer2 information.
+ */
+ public boolean updateLayer2Information(Layer2Information info) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mIpClient.updateLayer2Information(info.toStableParcelable());
+ return true;
+ } catch (RemoteException e) {
+ log("Error updating layer2 information", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+}
diff --git a/common/networkstackclient/src/android/net/ip/IpClientUtil.java b/common/networkstackclient/src/android/net/ip/IpClientUtil.java
new file mode 100644
index 0000000..1b55776
--- /dev/null
+++ b/common/networkstackclient/src/android/net/ip/IpClientUtil.java
@@ -0,0 +1,204 @@
+/*
+ * 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.ip;
+
+import android.content.Context;
+import android.net.DhcpResultsParcelable;
+import android.net.Layer2PacketParcelable;
+import android.net.LinkProperties;
+import android.net.networkstack.ModuleNetworkStackClient;
+import android.os.ConditionVariable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+
+/**
+ * Utilities and wrappers to simplify communication with IpClient, which lives in the NetworkStack
+ * process.
+ *
+ * @hide
+ */
+public class IpClientUtil {
+ // TODO: remove with its callers
+ public static final String DUMP_ARG = "ipclient";
+
+ /**
+ * Subclass of {@link IpClientCallbacks} allowing clients to block until provisioning is
+ * complete with {@link WaitForProvisioningCallbacks#waitForProvisioning()}.
+ */
+ public static class WaitForProvisioningCallbacks extends IpClientCallbacks {
+ private final ConditionVariable mCV = new ConditionVariable();
+ private LinkProperties mCallbackLinkProperties;
+
+ /**
+ * Block until either {@link #onProvisioningSuccess(LinkProperties)} or
+ * {@link #onProvisioningFailure(LinkProperties)} is called.
+ */
+ public LinkProperties waitForProvisioning() {
+ mCV.block();
+ return mCallbackLinkProperties;
+ }
+
+ @Override
+ public void onProvisioningSuccess(LinkProperties newLp) {
+ mCallbackLinkProperties = newLp;
+ mCV.open();
+ }
+
+ @Override
+ public void onProvisioningFailure(LinkProperties newLp) {
+ mCallbackLinkProperties = null;
+ mCV.open();
+ }
+ }
+
+ /**
+ * Create a new IpClient.
+ *
+ * <p>This is a convenience method to allow clients to use {@link IpClientCallbacks} instead of
+ * {@link IIpClientCallbacks}.
+ * @see {@link ModuleNetworkStackClient#makeIpClient(String, IIpClientCallbacks)}
+ */
+ public static void makeIpClient(Context context, String ifName, IpClientCallbacks callback) {
+ ModuleNetworkStackClient.getInstance(context)
+ .makeIpClient(ifName, new IpClientCallbacksProxy(callback));
+ }
+
+ /**
+ * Wrapper to relay calls from {@link IIpClientCallbacks} to {@link IpClientCallbacks}.
+ */
+ private static class IpClientCallbacksProxy extends IIpClientCallbacks.Stub {
+ protected final IpClientCallbacks mCb;
+
+ /**
+ * Create a new IpClientCallbacksProxy.
+ */
+ IpClientCallbacksProxy(IpClientCallbacks cb) {
+ mCb = cb;
+ }
+
+ @Override
+ public void onIpClientCreated(IIpClient ipClient) {
+ mCb.onIpClientCreated(ipClient);
+ }
+
+ @Override
+ public void onPreDhcpAction() {
+ mCb.onPreDhcpAction();
+ }
+
+ @Override
+ public void onPostDhcpAction() {
+ mCb.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.
+ @Override
+ public void onNewDhcpResults(DhcpResultsParcelable dhcpResults) {
+ mCb.onNewDhcpResults(dhcpResults);
+ }
+
+ @Override
+ public void onProvisioningSuccess(LinkProperties newLp) {
+ mCb.onProvisioningSuccess(newLp);
+ }
+ @Override
+ public void onProvisioningFailure(LinkProperties newLp) {
+ mCb.onProvisioningFailure(newLp);
+ }
+
+ // Invoked on LinkProperties changes.
+ @Override
+ public void onLinkPropertiesChange(LinkProperties newLp) {
+ mCb.onLinkPropertiesChange(newLp);
+ }
+
+ // Called when the internal IpReachabilityMonitor (if enabled) has
+ // detected the loss of a critical number of required neighbors.
+ @Override
+ public void onReachabilityLost(String logMsg) {
+ mCb.onReachabilityLost(logMsg);
+ }
+
+ // Called when the IpClient state machine terminates.
+ @Override
+ public void onQuit() {
+ mCb.onQuit();
+ }
+
+ // Install an APF program to filter incoming packets.
+ @Override
+ public void installPacketFilter(byte[] filter) {
+ mCb.installPacketFilter(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.
+ @Override
+ public void startReadPacketFilter() {
+ mCb.startReadPacketFilter();
+ }
+
+ // If multicast filtering cannot be accomplished with APF, this function will be called to
+ // actuate multicast filtering using another means.
+ @Override
+ public void setFallbackMulticastFilter(boolean enabled) {
+ mCb.setFallbackMulticastFilter(enabled);
+ }
+
+ // Enabled/disable Neighbor Discover offload functionality. This is
+ // called, for example, whenever 464xlat is being started or stopped.
+ @Override
+ public void setNeighborDiscoveryOffload(boolean enable) {
+ mCb.setNeighborDiscoveryOffload(enable);
+ }
+
+ // Invoked on starting preconnection process.
+ @Override
+ public void onPreconnectionStart(List<Layer2PacketParcelable> packets) {
+ mCb.onPreconnectionStart(packets);
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return this.VERSION;
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return this.HASH;
+ }
+ }
+
+ /**
+ * Dump logs for the specified IpClient.
+ * TODO: remove callers and delete
+ */
+ public static void dumpIpClient(
+ IIpClient connector, FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("IpClient logs have moved to dumpsys network_stack");
+ }
+}
diff --git a/common/moduleutils/src/android/net/shared/InitialConfiguration.java b/common/networkstackclient/src/android/net/shared/InitialConfiguration.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/InitialConfiguration.java
rename to common/networkstackclient/src/android/net/shared/InitialConfiguration.java
diff --git a/common/moduleutils/src/android/net/shared/Layer2Information.java b/common/networkstackclient/src/android/net/shared/Layer2Information.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/Layer2Information.java
rename to common/networkstackclient/src/android/net/shared/Layer2Information.java
diff --git a/common/moduleutils/src/android/net/shared/ParcelableUtil.java b/common/networkstackclient/src/android/net/shared/ParcelableUtil.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/ParcelableUtil.java
rename to common/networkstackclient/src/android/net/shared/ParcelableUtil.java
diff --git a/common/moduleutils/src/android/net/shared/PrivateDnsConfig.java b/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
similarity index 100%
rename from common/moduleutils/src/android/net/shared/PrivateDnsConfig.java
rename to common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
diff --git a/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java b/common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
similarity index 96%
rename from common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
rename to common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
index d3bc04d..6ee9b73 100644
--- a/common/moduleutils/src/android/net/shared/ProvisioningConfiguration.java
+++ b/common/networkstackclient/src/android/net/shared/ProvisioningConfiguration.java
@@ -21,7 +21,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.net.INetd;
import android.net.InformationElementParcelable;
import android.net.Network;
import android.net.ProvisioningConfigurationParcelable;
@@ -76,6 +75,13 @@
// allowing for 10% jitter.
private static final int DEFAULT_TIMEOUT_MS = 18 * 1000;
+ // TODO: These cannot be imported from INetd.aidl, because networkstack-client cannot depend on
+ // INetd, as there are users of IpClient that depend on INetd directly (potentially at a
+ // different version, which is not allowed by the build system).
+ // Find a better way to express these constants.
+ public static final int IPV6_ADDR_GEN_MODE_EUI64 = 0;
+ public static final int IPV6_ADDR_GEN_MODE_STABLE_PRIVACY = 2;
+
/**
* Builder to create a {@link ProvisioningConfiguration}.
*/
@@ -180,7 +186,7 @@
* Specify that IPv6 address generation should use a random MAC address.
*/
public Builder withRandomMacAddress() {
- mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_EUI64;
+ mConfig.mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_EUI64;
return this;
}
@@ -188,7 +194,7 @@
* Specify that IPv6 address generation should use a stable MAC address.
*/
public Builder withStableMacAddress() {
- mConfig.mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ mConfig.mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
return this;
}
@@ -437,7 +443,7 @@
public StaticIpConfiguration mStaticIpConfig;
public ApfCapabilities mApfCapabilities;
public int mProvisioningTimeoutMs = DEFAULT_TIMEOUT_MS;
- public int mIPv6AddrGenMode = INetd.IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
+ public int mIPv6AddrGenMode = IPV6_ADDR_GEN_MODE_STABLE_PRIVACY;
public Network mNetwork = null;
public String mDisplayName = null;
public ScanResultInfo mScanResultInfo;
diff --git a/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java b/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java
new file mode 100644
index 0000000..5666985
--- /dev/null
+++ b/common/networkstackclient/src/android/net/util/KeepalivePacketDataUtil.java
@@ -0,0 +1,223 @@
+/*
+ * 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 android.net.SocketKeepalive.ERROR_INVALID_IP_ADDRESS;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.InvalidPacketException;
+import android.net.KeepalivePacketData;
+import android.net.NattKeepalivePacketData;
+import android.net.NattKeepalivePacketDataParcelable;
+import android.net.TcpKeepalivePacketData;
+import android.net.TcpKeepalivePacketDataParcelable;
+import android.os.Build;
+import android.system.OsConstants;
+import android.util.Log;
+
+import com.android.net.module.util.IpUtils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+/**
+ * Utility class to convert to/from keepalive data parcelables.
+ *
+ * TODO: move to networkstack-client library when it is moved to frameworks/libs/net.
+ * This class cannot go into other shared libraries as it depends on NetworkStack AIDLs.
+ * @hide
+ */
+public final class KeepalivePacketDataUtil {
+ private static final int IPV4_HEADER_LENGTH = 20;
+ private static final int IPV6_HEADER_LENGTH = 40;
+ private static final int TCP_HEADER_LENGTH = 20;
+
+ private static final String TAG = KeepalivePacketDataUtil.class.getSimpleName();
+
+ /**
+ * Convert a NattKeepalivePacketData to a NattKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public static NattKeepalivePacketDataParcelable toStableParcelable(
+ @NonNull NattKeepalivePacketData pkt) {
+ final NattKeepalivePacketDataParcelable parcel = new NattKeepalivePacketDataParcelable();
+ final InetAddress srcAddress = pkt.getSrcAddress();
+ final InetAddress dstAddress = pkt.getDstAddress();
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = pkt.getSrcPort();
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = pkt.getDstPort();
+ return parcel;
+ }
+
+ /**
+ * Convert a TcpKeepalivePacketData to a TcpKeepalivePacketDataParcelable.
+ */
+ @NonNull
+ public static TcpKeepalivePacketDataParcelable toStableParcelable(
+ @NonNull TcpKeepalivePacketData pkt) {
+ final TcpKeepalivePacketDataParcelable parcel = new TcpKeepalivePacketDataParcelable();
+ final InetAddress srcAddress = pkt.getSrcAddress();
+ final InetAddress dstAddress = pkt.getDstAddress();
+ parcel.srcAddress = srcAddress.getAddress();
+ parcel.srcPort = pkt.getSrcPort();
+ parcel.dstAddress = dstAddress.getAddress();
+ parcel.dstPort = pkt.getDstPort();
+ parcel.seq = pkt.getTcpSeq();
+ parcel.ack = pkt.getTcpAck();
+ parcel.rcvWnd = pkt.getTcpWindow();
+ parcel.rcvWndScale = pkt.getTcpWindowScale();
+ parcel.tos = pkt.getIpTos();
+ parcel.ttl = pkt.getIpTtl();
+ return parcel;
+ }
+
+ /**
+ * Factory method to create tcp keepalive packet structure.
+ * @hide
+ */
+ public static TcpKeepalivePacketData fromStableParcelable(
+ TcpKeepalivePacketDataParcelable tcpDetails) throws InvalidPacketException {
+ final byte[] packet;
+ try {
+ if ((tcpDetails.srcAddress != null) && (tcpDetails.dstAddress != null)
+ && (tcpDetails.srcAddress.length == 4 /* V4 IP length */)
+ && (tcpDetails.dstAddress.length == 4 /* V4 IP length */)) {
+ packet = buildV4Packet(tcpDetails);
+ } else {
+ // TODO: support ipv6
+ throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+ }
+ return new TcpKeepalivePacketData(
+ InetAddress.getByAddress(tcpDetails.srcAddress),
+ tcpDetails.srcPort,
+ InetAddress.getByAddress(tcpDetails.dstAddress),
+ tcpDetails.dstPort,
+ packet,
+ tcpDetails.seq, tcpDetails.ack, tcpDetails.rcvWnd, tcpDetails.rcvWndScale,
+ tcpDetails.tos, tcpDetails.ttl);
+ } catch (UnknownHostException e) {
+ throw new InvalidPacketException(ERROR_INVALID_IP_ADDRESS);
+ }
+
+ }
+
+ /**
+ * Build ipv4 tcp keepalive packet, not including the link-layer header.
+ */
+ // TODO : if this code is ever moved to the network stack, factorize constants with the ones
+ // over there.
+ private static byte[] buildV4Packet(TcpKeepalivePacketDataParcelable tcpDetails) {
+ final int length = IPV4_HEADER_LENGTH + TCP_HEADER_LENGTH;
+ ByteBuffer buf = ByteBuffer.allocate(length);
+ buf.order(ByteOrder.BIG_ENDIAN);
+ buf.put((byte) 0x45); // IP version and IHL
+ buf.put((byte) tcpDetails.tos); // TOS
+ buf.putShort((short) length);
+ buf.putInt(0x00004000); // ID, flags=DF, offset
+ buf.put((byte) tcpDetails.ttl); // TTL
+ buf.put((byte) OsConstants.IPPROTO_TCP);
+ final int ipChecksumOffset = buf.position();
+ buf.putShort((short) 0); // IP checksum
+ buf.put(tcpDetails.srcAddress);
+ buf.put(tcpDetails.dstAddress);
+ buf.putShort((short) tcpDetails.srcPort);
+ buf.putShort((short) tcpDetails.dstPort);
+ buf.putInt(tcpDetails.seq); // Sequence Number
+ buf.putInt(tcpDetails.ack); // ACK
+ buf.putShort((short) 0x5010); // TCP length=5, flags=ACK
+ buf.putShort((short) (tcpDetails.rcvWnd >> tcpDetails.rcvWndScale)); // Window size
+ final int tcpChecksumOffset = buf.position();
+ buf.putShort((short) 0); // TCP checksum
+ // URG is not set therefore the urgent pointer is zero.
+ buf.putShort((short) 0); // Urgent pointer
+
+ buf.putShort(ipChecksumOffset, com.android.net.module.util.IpUtils.ipChecksum(buf, 0));
+ buf.putShort(tcpChecksumOffset, IpUtils.tcpChecksum(
+ buf, 0, IPV4_HEADER_LENGTH, TCP_HEADER_LENGTH));
+
+ return buf.array();
+ }
+
+ // TODO: add buildV6Packet.
+
+ /**
+ * Get a {@link TcpKeepalivePacketDataParcelable} from {@link KeepalivePacketData}, if the
+ * generic class actually contains TCP keepalive data.
+ *
+ * @deprecated This method is used on R platforms where android.net.TcpKeepalivePacketData was
+ * not yet system API. Newer platforms should use android.net.TcpKeepalivePacketData directly.
+ *
+ * @param data A {@link KeepalivePacketData} that may contain TCP keepalive data.
+ * @return A parcelable containing TCP keepalive data, or null if the input data does not
+ * contain TCP keepalive data.
+ */
+ @Deprecated
+ @SuppressWarnings("AndroidFrameworkCompatChange") // API version check used to Log.wtf
+ @Nullable
+ public static TcpKeepalivePacketDataParcelable parseTcpKeepalivePacketData(
+ @Nullable KeepalivePacketData data) {
+ if (data == null) return null;
+
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
+ Log.wtf(TAG, "parseTcpKeepalivePacketData should not be used after R, use "
+ + "TcpKeepalivePacketData instead.");
+ }
+
+ // Reconstruct TcpKeepalivePacketData from the packet contained in KeepalivePacketData
+ final ByteBuffer buffer = ByteBuffer.wrap(data.getPacket());
+ buffer.order(ByteOrder.BIG_ENDIAN);
+
+ // Most of the fields are accessible from the KeepalivePacketData superclass: instead of
+ // using Struct to parse everything, just extract the extra fields necessary for
+ // TcpKeepalivePacketData.
+ final int tcpSeq;
+ final int tcpAck;
+ final int wndSize;
+ final int ipTos;
+ final int ttl;
+ try {
+ // This only support IPv4, because TcpKeepalivePacketData only supports IPv4 for R and
+ // below, and this method should not be used on newer platforms.
+ tcpSeq = buffer.getInt(IPV4_HEADER_LENGTH + 4);
+ tcpAck = buffer.getInt(IPV4_HEADER_LENGTH + 8);
+ wndSize = buffer.getShort(IPV4_HEADER_LENGTH + 14);
+ ipTos = buffer.get(1);
+ ttl = buffer.get(8);
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+
+ final TcpKeepalivePacketDataParcelable p = new TcpKeepalivePacketDataParcelable();
+ p.srcAddress = data.getSrcAddress().getAddress();
+ p.srcPort = data.getSrcPort();
+ p.dstAddress = data.getDstAddress().getAddress();
+ p.dstPort = data.getDstPort();
+ p.seq = tcpSeq;
+ p.ack = tcpAck;
+ // TcpKeepalivePacketData could actually use non-zero wndScale, but this does not affect
+ // actual functionality as generated packets will be the same (no wndScale option added)
+ p.rcvWnd = wndSize;
+ p.rcvWndScale = 0;
+ p.tos = ipTos;
+ p.ttl = ttl;
+ return p;
+ }
+}
diff --git a/lint-baseline-current-lib.xml b/lint-baseline-current-lib.xml
index f7b00f2..e8cfe3e 100644
--- a/lint-baseline-current-lib.xml
+++ b/lint-baseline-current-lib.xml
@@ -3,83 +3,6 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1032"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1034"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1087"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1089"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#any`"
- errorLine1=" final boolean haveKeepaliveResponses = CollectionUtils.any(mKeepalivePackets,"
- errorLine2=" ~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1368"
- column="64"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toIntArray`"
- errorLine1=" CollectionUtils.toIntArray(mDnsReturnCode),"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
- line="302"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toLongArray`"
- errorLine1=" CollectionUtils.toLongArray(mDnsTimeStamp),"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
- line="303"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
errorLine1=" newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
errorLine2=" ~~~~~~~~~~~~~~">
@@ -102,50 +25,6 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" mStatsBuilder.setIpv4LatencyMicros(ConnectivityUtils.saturatedCast(mIpv4Watch.stop()));"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
- line="74"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" mStatsBuilder.setIpv6LatencyMicros(ConnectivityUtils.saturatedCast(mIpv6Watch.stop()));"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
- line="83"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#isEmpty`"
- errorLine1=" if (isEmpty(mCaptivePortalFallbackSpecs)) {"
- errorLine2=" ~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
- line="2279"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#isIPv6ULA`"
- errorLine1=" || isIPv6ULA(address)) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
- line="2447"
- column="24"/>
- </issue>
-
- <issue
- id="NewApi"
message="Call requires API level R (current min is 29): `android.telephony.NetworkRegistrationInfo#getCellIdentity`"
errorLine1=" nri == null ? null : nri.getCellIdentity());"
errorLine2=" ~~~~~~~~~~~~~~~">
@@ -155,48 +34,4 @@
column="46"/>
</issue>
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" int latencyUs = ConnectivityUtils.saturatedCast(durationUs);"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="198"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" .setRemainingTtlSecs(ConnectivityUtils.saturatedCast(secondsRemaining))"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="209"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" ConnectivityUtils.saturatedCast(capportData.getByteLimit() / 1000))"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="212"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" mStatsBuilder.setLatencyMicros(ConnectivityUtils.saturatedCast(mWatch.stop()));"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="237"
- column="58"/>
- </issue>
-
</issues>
diff --git a/lint-baseline-stable-lib.xml b/lint-baseline-stable-lib.xml
index f7b00f2..e8cfe3e 100644
--- a/lint-baseline-stable-lib.xml
+++ b/lint-baseline-stable-lib.xml
@@ -3,83 +3,6 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1032"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1034"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1087"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#addressAndPortToString`"
- errorLine1=" ConnectivityUtils.addressAndPortToString("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1089"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#any`"
- errorLine1=" final boolean haveKeepaliveResponses = CollectionUtils.any(mKeepalivePackets,"
- errorLine2=" ~~~">
- <location
- file="packages/modules/NetworkStack/src/android/net/apf/ApfFilter.java"
- line="1368"
- column="64"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toIntArray`"
- errorLine1=" CollectionUtils.toIntArray(mDnsReturnCode),"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
- line="302"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#toLongArray`"
- errorLine1=" CollectionUtils.toLongArray(mDnsTimeStamp),"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/DataStallDetectionStats.java"
- line="303"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
message="Call requires API level R (current min is 29): `android.net.LinkProperties#getNat64Prefix`"
errorLine1=" newLp.setNat64Prefix(netlinkLinkProperties.getNat64Prefix());"
errorLine2=" ~~~~~~~~~~~~~~">
@@ -102,50 +25,6 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" mStatsBuilder.setIpv4LatencyMicros(ConnectivityUtils.saturatedCast(mIpv4Watch.stop()));"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
- line="74"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" mStatsBuilder.setIpv6LatencyMicros(ConnectivityUtils.saturatedCast(mIpv6Watch.stop()));"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/IpProvisioningMetrics.java"
- line="83"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.CollectionUtils#isEmpty`"
- errorLine1=" if (isEmpty(mCaptivePortalFallbackSpecs)) {"
- errorLine2=" ~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
- line="2279"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#isIPv6ULA`"
- errorLine1=" || isIPv6ULA(address)) {"
- errorLine2=" ~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java"
- line="2447"
- column="24"/>
- </issue>
-
- <issue
- id="NewApi"
message="Call requires API level R (current min is 29): `android.telephony.NetworkRegistrationInfo#getCellIdentity`"
errorLine1=" nri == null ? null : nri.getCellIdentity());"
errorLine2=" ~~~~~~~~~~~~~~~">
@@ -155,48 +34,4 @@
column="46"/>
</issue>
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" int latencyUs = ConnectivityUtils.saturatedCast(durationUs);"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="198"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" .setRemainingTtlSecs(ConnectivityUtils.saturatedCast(secondsRemaining))"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="209"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" ConnectivityUtils.saturatedCast(capportData.getByteLimit() / 1000))"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="212"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `com.android.net.module.util.ConnectivityUtils#saturatedCast`"
- errorLine1=" mStatsBuilder.setLatencyMicros(ConnectivityUtils.saturatedCast(mWatch.stop()));"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/src/com/android/networkstack/metrics/NetworkValidationMetrics.java"
- line="237"
- column="58"/>
- </issue>
-
</issues>
diff --git a/res/values/config.xml b/res/values/config.xml
index d6a11ab..805ca04 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -105,4 +105,20 @@
increased until reaching the config_max_retry_timer. -->
<integer name="config_evaluating_bandwidth_min_retry_timer_ms"></integer>
<integer name="config_evaluating_bandwidth_max_retry_timer_ms"></integer>
+
+ <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
+ Those frames are identified by the field Eth-type having values
+ less than 0x600 -->
+ <bool name="config_apfDrop802_3Frames">true</bool>
+
+ <!-- An array of Denylisted EtherType, packets with EtherTypes within this array
+ will be dropped
+ TODO: need to put proper values, these are for testing purposes only -->
+ <integer-array name="config_apfEthTypeDenyList">
+ <item>0x88A2</item>
+ <item>0x88A4</item>
+ <item>0x88B8</item>
+ <item>0x88CD</item>
+ <item>0x88E3</item>
+ </integer-array>
</resources>
diff --git a/res/values/overlayable.xml b/res/values/overlayable.xml
index b2967b9..bfb450e 100644
--- a/res/values/overlayable.xml
+++ b/res/values/overlayable.xml
@@ -77,6 +77,13 @@
<item type="integer" name="config_evaluating_bandwidth_timeout_ms"/>
<item type="integer" name="config_evaluating_bandwidth_min_retry_timer_ms"/>
<item type="integer" name="config_evaluating_bandwidth_max_retry_timer_ms"/>
+
+ <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
+ Those frames are identified by the field Eth-type having values less than 0x600 -->
+ <item type="bool" name="config_apfDrop802_3Frames"/>
+ <!-- An array of Denylisted EtherType, packets with EtherTypes within this array
+ will be dropped -->
+ <item type="array" name="config_apfEthTypeDenyList"/>
</policy>
</overlayable>
</resources>
diff --git a/src/android/net/ip/IpClient.java b/src/android/net/ip/IpClient.java
index b03d653..a57e99d 100644
--- a/src/android/net/ip/IpClient.java
+++ b/src/android/net/ip/IpClient.java
@@ -36,6 +36,7 @@
import static com.android.server.util.PermissionUtil.enforceNetworkStackCallingPermission;
import android.content.Context;
+import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
import android.net.INetd;
@@ -94,6 +95,7 @@
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
import com.android.net.module.util.DeviceConfigUtils;
+import com.android.networkstack.R;
import com.android.networkstack.apishim.NetworkInformationShimImpl;
import com.android.networkstack.apishim.SocketUtilsShimImpl;
import com.android.networkstack.apishim.common.NetworkInformationShim;
@@ -605,6 +607,16 @@
return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name,
defaultEnabled);
}
+
+ /**
+ * Create an APF filter if apfCapabilities indicates support for packet filtering using
+ * APF programs.
+ * @see ApfFilter#maybeCreate
+ */
+ public ApfFilter maybeCreateApfFilter(Context context, ApfFilter.ApfConfiguration config,
+ InterfaceParams ifParams, IpClientCallbacksWrapper cb) {
+ return ApfFilter.maybeCreate(context, config, ifParams, cb);
+ }
}
public IpClient(Context context, String ifName, IIpClientCallbacks callback,
@@ -2195,10 +2207,19 @@
apfConfig.apfCapabilities = mConfiguration.mApfCapabilities;
apfConfig.multicastFilter = mMulticastFiltering;
// Get the Configuration for ApfFilter from Context
- apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
- apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
+ // Resource settings were moved from ApfCapabilities APIs to NetworkStack resources in S
+ if (ShimUtils.isReleaseOrDevelopmentApiAbove(Build.VERSION_CODES.R)) {
+ final Resources res = mContext.getResources();
+ apfConfig.ieee802_3Filter = res.getBoolean(R.bool.config_apfDrop802_3Frames);
+ apfConfig.ethTypeBlackList = res.getIntArray(R.array.config_apfEthTypeDenyList);
+ } else {
+ apfConfig.ieee802_3Filter = ApfCapabilities.getApfDrop8023Frames();
+ apfConfig.ethTypeBlackList = ApfCapabilities.getApfEtherTypeBlackList();
+ }
+
apfConfig.minRdnssLifetimeSec = mMinRdnssLifetimeSec;
- mApfFilter = ApfFilter.maybeCreate(mContext, apfConfig, mInterfaceParams, mCallback);
+ mApfFilter = mDependencies.maybeCreateApfFilter(mContext, apfConfig, mInterfaceParams,
+ mCallback);
// TODO: investigate the effects of any multicast filtering racing/interfering with the
// rest of this IP configuration startup.
if (mApfFilter == null) {
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index 7bc6a49..8950938 100755
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -33,6 +33,7 @@
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
import static android.net.captiveportal.CaptivePortalProbeSpec.parseCaptivePortalProbeSpecs;
import static android.net.metrics.ValidationProbeEvent.DNS_FAILURE;
import static android.net.metrics.ValidationProbeEvent.DNS_SUCCESS;
@@ -671,6 +672,7 @@
(Pair<LinkProperties, NetworkCapabilities>) connectedMsg.obj;
mLinkProperties = attrs.first;
mNetworkCapabilities = attrs.second;
+ suppressNotificationIfNetworkRestricted();
}
/**
@@ -735,6 +737,12 @@
return NetworkMonitorUtils.isPrivateDnsValidationRequired(mNetworkCapabilities);
}
+ private void suppressNotificationIfNetworkRestricted() {
+ if (!mNetworkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) {
+ mDontDisplaySigninNotification = true;
+ }
+ }
+
private void notifyNetworkTested(NetworkTestResultParcelable result) {
try {
if (mCallbackVersion <= 5) {
@@ -984,6 +992,7 @@
break;
case EVENT_NETWORK_CAPABILITIES_CHANGED:
mNetworkCapabilities = (NetworkCapabilities) message.obj;
+ suppressNotificationIfNetworkRestricted();
break;
default:
break;
@@ -2541,8 +2550,17 @@
final CaptivePortalProbeResult probeResult;
if (probeSpec == null) {
+ if (CaptivePortalProbeResult.isPortalCode(httpResponseCode)
+ && TextUtils.isEmpty(redirectUrl)
+ && ShimUtils.isAtLeastS()) {
+ // If a portal is a non-redirect portal (often portals that return HTTP 200 with a
+ // login page for all HTTP requests), report the probe URL as the login URL starting
+ // from S (b/172048052). This avoids breaking assumptions that
+ // [is a portal] is equivalent to [there is a login URL].
+ redirectUrl = url.toString();
+ }
probeResult = new CaptivePortalProbeResult(httpResponseCode, redirectUrl,
- url.toString(), 1 << probeType);
+ url.toString(), 1 << probeType);
} else {
probeResult = probeSpec.getResult(httpResponseCode, redirectUrl);
}
diff --git a/tests/integration/Android.bp b/tests/integration/Android.bp
index 43a0575..7a2a471 100644
--- a/tests/integration/Android.bp
+++ b/tests/integration/Android.bp
@@ -87,7 +87,6 @@
certificate: "networkstack",
platform_apis: true,
test_suites: ["device-tests"],
- enabled: false, // Disabled in mainline-prod
}
// The static lib needs to be jarjared by each module so they do not conflict with each other
diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp
index e308b96..64da600 100644
--- a/tests/unit/Android.bp
+++ b/tests/unit/Android.bp
@@ -36,7 +36,10 @@
"android.test.base",
"android.test.mock",
],
- defaults: ["libnetworkstackutilsjni_deps"],
+ defaults: [
+ "framework-connectivity-test-defaults",
+ "libnetworkstackutilsjni_deps"
+ ],
jni_libs: [
// For mockito extended
"libdexmakerjvmtiagent",
@@ -54,11 +57,13 @@
min_sdk_version: "29",
srcs: [], // TODO: tests that only apply to the current, non-stable API can be added here
test_suites: ["general-tests"],
- test_mainline_modules: ["CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex"],
+ test_mainline_modules: [
+ "CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex",
+ "CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex"
+ ],
defaults: ["NetworkStackTestsDefaults"],
static_libs: ["NetworkStackApiCurrentLib"],
compile_multilib: "both", // Workaround for b/147785146 for mainline-presubmit
- enabled: false, // Disabled in mainline-prod
}
// Library containing the unit tests. This is used by the coverage test target to pull in the
@@ -71,8 +76,8 @@
static_libs: ["NetworkStackApiStableLib"],
visibility: [
"//packages/modules/NetworkStack/tests/integration",
- "//frameworks/base/packages/Tethering/tests/integration",
- "//packages/modules/Connectivity/Tethering/tests/integration",
+ "//packages/modules/Connectivity/tests:__subpackages__",
+ "//packages/modules/Connectivity/Tethering/tests:__subpackages__",
]
}
@@ -81,7 +86,10 @@
min_sdk_version: "29",
target_sdk_version: "30",
test_suites: ["general-tests", "mts"],
- test_mainline_modules: ["CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex"],
+ test_mainline_modules: [
+ "CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex",
+ "CaptivePortalLoginGoogle.apk+NetworkStackGoogle.apk+com.google.android.resolv.apex+com.google.android.tethering.apex"
+ ],
defaults: ["NetworkStackTestsDefaults"],
static_libs: ["NetworkStackApiStableLib"],
compile_multilib: "both",
diff --git a/tests/unit/lint-baseline.xml b/tests/unit/lint-baseline.xml
index ededbea..0812c2d 100644
--- a/tests/unit/lint-baseline.xml
+++ b/tests/unit/lint-baseline.xml
@@ -3,105 +3,6 @@
<issue
id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" private static final NetworkCapabilities CELL_METERED_CAPABILITIES = new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="297"
- column="74"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="302"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="308"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" new NetworkCapabilities().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="314"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" final NetworkCapabilities nc = new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="670"
- column="40"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" final NetworkCapabilities nc = new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="690"
- column="40"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" final NetworkCapabilities meteredCap = new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="726"
- column="48"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" final NetworkCapabilities nonMeteredCap = new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="746"
- column="51"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `new android.net.NetworkCapabilities`"
- errorLine1=" final NetworkCapabilities nc = new NetworkCapabilities()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/modules/NetworkStack/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java"
- line="2149"
- column="40"/>
- </issue>
-
- <issue
- id="NewApi"
message="Call requires API level R (current min is 29): `android.net.NetworkCapabilities()`"
errorLine1=" private val EMPTY_CAPABILITIES = NetworkCapabilities()"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
diff --git a/tests/unit/src/android/net/ip/IpClientTest.java b/tests/unit/src/android/net/ip/IpClientTest.java
index e991ea7..7260332 100644
--- a/tests/unit/src/android/net/ip/IpClientTest.java
+++ b/tests/unit/src/android/net/ip/IpClientTest.java
@@ -18,12 +18,14 @@
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -48,22 +50,30 @@
import android.net.MacAddress;
import android.net.NetworkStackIpMemoryStore;
import android.net.RouteInfo;
+import android.net.apf.ApfCapabilities;
+import android.net.apf.ApfFilter.ApfConfiguration;
import android.net.ipmemorystore.NetworkAttributes;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.InitialConfiguration;
import android.net.shared.ProvisioningConfiguration;
import android.net.util.InterfaceParams;
+import android.os.Build;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.networkstack.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.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.HandlerUtils;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -85,6 +95,9 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
public class IpClientTest {
+ @Rule
+ public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule();
+
private static final String VALID = "VALID";
private static final String INVALID = "INVALID";
private static final String TEST_IFNAME = "test_wlan0";
@@ -631,6 +644,71 @@
return out;
}
+ private ApfConfiguration verifyApfFilterCreatedOnStart(IpClient ipc) {
+ ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
+ .withoutIPv4()
+ .withoutIpReachabilityMonitor()
+ .withInitialConfiguration(
+ conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips()))
+ .withApfCapabilities(new ApfCapabilities(
+ 4 /* version */, 4096 /* maxProgramSize */, 4 /* format */))
+ .build();
+
+ ipc.startProvisioning(config);
+ final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass(
+ ApfConfiguration.class);
+ verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter(
+ any(), configCaptor.capture(), any(), any());
+
+ return configCaptor.getValue();
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.R)
+ public void testApfConfiguration_R() throws Exception {
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc);
+
+ assertEquals(ApfCapabilities.getApfDrop8023Frames(), config.ieee802_3Filter);
+ assertArrayEquals(ApfCapabilities.getApfEtherTypeBlackList(), config.ethTypeBlackList);
+
+ verify(mResources, never()).getBoolean(R.bool.config_apfDrop802_3Frames);
+ verify(mResources, never()).getIntArray(R.array.config_apfEthTypeDenyList);
+
+ verifyShutdown(ipc);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testApfConfiguration() throws Exception {
+ doReturn(true).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames);
+ final int[] ethTypeDenyList = new int[] { 0x88A2, 0x88A4 };
+ doReturn(ethTypeDenyList).when(mResources).getIntArray(
+ R.array.config_apfEthTypeDenyList);
+
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc);
+
+ assertTrue(config.ieee802_3Filter);
+ assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList);
+
+ verifyShutdown(ipc);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testApfConfiguration_NoApfDrop8023Frames() throws Exception {
+ doReturn(false).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames);
+ final int[] ethTypeDenyList = new int[] { 0x88A3, 0x88A5 };
+ doReturn(ethTypeDenyList).when(mResources).getIntArray(
+ R.array.config_apfEthTypeDenyList);
+
+ final IpClient ipc = makeIpClient(TEST_IFNAME);
+ final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc);
+
+ assertFalse(config.ieee802_3Filter);
+ assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList);
+
+ verifyShutdown(ipc);
+ }
+
interface Fn<A,B> {
B call(A a) throws Exception;
}
diff --git a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
index f010007..3a1bde4 100644
--- a/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/tests/unit/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -28,6 +28,8 @@
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -91,6 +93,7 @@
import static java.util.stream.Collectors.toList;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.ContextWrapper;
@@ -112,6 +115,7 @@
import android.net.Uri;
import android.net.captiveportal.CaptivePortalProbeResult;
import android.net.metrics.IpConnectivityLog;
+import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.SharedLog;
import android.net.wifi.WifiInfo;
@@ -155,6 +159,7 @@
import com.android.server.connectivity.nano.DnsEvent;
import com.android.server.connectivity.nano.WifiData;
import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.HandlerUtils;
@@ -201,6 +206,7 @@
@RunWith(AndroidJUnit4.class)
@SmallTest
+@SuppressLint("NewApi") // Uses hidden APIs, which the linter would identify as missing APIs.
public class NetworkMonitorTest {
private static final String LOCATION_HEADER = "location";
private static final String CONTENT_TYPE_HEADER = "Content-Type";
@@ -315,6 +321,14 @@
private static final NetworkCapabilities CELL_NO_INTERNET_CAPABILITIES =
new NetworkCapabilities().addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ private static final NetworkCapabilities WIFI_OEM_PAID_CAPABILITIES =
+ new NetworkCapabilities()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .addCapability(NET_CAPABILITY_OEM_PAID)
+ .removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+
/**
* Fakes DNS responses.
*
@@ -1068,6 +1082,34 @@
runPortalNetworkTest();
}
+ @Test
+ public void testIsCaptivePortal_Http200EmptyResponse() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 200);
+ // Invalid if there is no content (can't login to an empty page)
+ runNetworkTest(VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null);
+ verify(mCallbacks, never()).showProvisioningNotification(any(), any());
+ }
+
+ private void doCaptivePortal200ResponseTest(String expectedRedirectUrl) throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 200);
+ doReturn(100L).when(mHttpConnection).getContentLengthLong();
+ // Redirect URL was null before S
+ runNetworkTest(VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */, expectedRedirectUrl);
+ verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS)).showProvisioningNotification(any(), any());
+ }
+
+ @Test @IgnoreAfter(Build.VERSION_CODES.R)
+ public void testIsCaptivePortal_HttpProbeIs200Portal_R() throws Exception {
+ doCaptivePortal200ResponseTest(null);
+ }
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testIsCaptivePortal_HttpProbeIs200Portal() throws Exception {
+ doCaptivePortal200ResponseTest(TEST_HTTP_URL);
+ }
+
private void setupPrivateIpResponse(String privateAddr) throws Exception {
setSslException(mHttpsConnection);
setPortal302(mHttpConnection);
@@ -1758,6 +1800,47 @@
verify(mCleartextDnsNetwork, never()).openConnection(any());
}
+ private NetworkCapabilities getVcnUnderlyingCarrierWifiCaps() {
+ // Must be called from within the test because NOT_VCN_MANAGED is an invalid capability
+ // value up to Android R. Thus, this must be guarded by an SDK check in tests that use this.
+ return new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .removeCapability(NetworkMonitorUtils.NET_CAPABILITY_NOT_VCN_MANAGED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ .addCapability(NET_CAPABILITY_INTERNET)
+ .build();
+ }
+
+ @Test
+ public void testVcnUnderlyingNetwork() throws Exception {
+ assumeTrue(ShimUtils.isAtLeastS());
+ setStatus(mHttpsConnection, 204);
+ setStatus(mHttpConnection, 204);
+
+ final NetworkMonitor nm = runNetworkTest(
+ TEST_LINK_PROPERTIES, getVcnUnderlyingCarrierWifiCaps(),
+ NETWORK_VALIDATION_RESULT_VALID,
+ NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
+ null /* redirectUrl */);
+ assertEquals(NETWORK_VALIDATION_RESULT_VALID,
+ nm.getEvaluationState().getEvaluationResult());
+ }
+
+ @Test
+ public void testVcnUnderlyingNetworkBadNetwork() throws Exception {
+ assumeTrue(ShimUtils.isAtLeastS());
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 500);
+ setStatus(mFallbackConnection, 404);
+
+ final NetworkMonitor nm = runNetworkTest(
+ TEST_LINK_PROPERTIES, getVcnUnderlyingCarrierWifiCaps(),
+ VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
+ assertEquals(VALIDATION_RESULT_INVALID,
+ nm.getEvaluationState().getEvaluationResult());
+ }
+
@Test
public void testLaunchCaptivePortalApp() throws Exception {
setSslException(mHttpsConnection);
@@ -2604,6 +2687,61 @@
ConnectivityManager.EXTRA_NETWORK)).netId));
}
+ @Test
+ public void testOemPaidNetworkValidated() throws Exception {
+ setValidProbes();
+
+ final NetworkMonitor nm = runNetworkTest(TEST_LINK_PROPERTIES,
+ WIFI_OEM_PAID_CAPABILITIES,
+ NETWORK_VALIDATION_RESULT_VALID,
+ NETWORK_VALIDATION_PROBE_DNS | NETWORK_VALIDATION_PROBE_HTTPS,
+ null /* redirectUrl */);
+ assertEquals(NETWORK_VALIDATION_RESULT_VALID,
+ nm.getEvaluationState().getEvaluationResult());
+ }
+
+ @Test
+ public void testOemPaidNetwork_AllProbesFailed() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 500);
+ setStatus(mFallbackConnection, 404);
+
+ runNetworkTest(TEST_LINK_PROPERTIES,
+ WIFI_OEM_PAID_CAPABILITIES,
+ VALIDATION_RESULT_INVALID, 0 /* probesSucceeded */, null /* redirectUrl */);
+ }
+
+ @Test
+ public void testOemPaidNetworkNoInternetCapabilityValidated() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mHttpConnection, 500);
+ setStatus(mFallbackConnection, 404);
+
+ final NetworkCapabilities networkCapabilities =
+ new NetworkCapabilities(WIFI_OEM_PAID_CAPABILITIES);
+ networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
+ runNetworkTest(TEST_LINK_PROPERTIES, networkCapabilities,
+ NETWORK_VALIDATION_RESULT_VALID, 0 /* probesSucceeded */, null /* redirectUrl */);
+
+ verify(mCleartextDnsNetwork, never()).openConnection(any());
+ verify(mHttpsConnection, never()).getResponseCode();
+ verify(mHttpConnection, never()).getResponseCode();
+ verify(mFallbackConnection, never()).getResponseCode();
+ }
+
+ @Test
+ public void testOemPaidNetwork_CaptivePortalNotLaunched() throws Exception {
+ setSslException(mHttpsConnection);
+ setStatus(mFallbackConnection, 404);
+ setPortal302(mHttpConnection);
+
+ runNetworkTest(TEST_LINK_PROPERTIES, WIFI_OEM_PAID_CAPABILITIES,
+ VALIDATION_RESULT_PORTAL, 0 /* probesSucceeded */,
+ TEST_LOGIN_URL);
+
+ verify(mCallbacks, never()).showProvisioningNotification(any(), any());
+ }
+
private void setupResourceForMultipleProbes() {
// Configure the resource to send multiple probe.
when(mResources.getStringArray(R.array.config_captive_portal_https_urls))